Hello
I am using a Qg8 with other 5v devices.The simplest & cheapest approach to get 3.3v on QG8 was to lift its ground by 3 diode drops (schem attached)
I am measuring current with the help of a Hall sensor,which o/p's corresponding voltage(VIOut) scaled to 5v.
Now the rectified and filtered VIOut is fed to the ADC input.The voltage measured here is some 0.9v w.r.t MCU GND,whereas the current sensor o/ps some 3v.I ask the ADC to take action when this threshold is crossed.
Now I have a question that ,will the ADC consider the voltage at its pins as 0.9v or 3v (with different grounds)..since when i run the code ,the ADC behaves as if the threshold is crossed even when i set the compare value at 1023 (10 bit).
I dont know if i am clear enough.Please someone reply so that i can take it further.
Thanks and regards
Solved! Go to Solution.
Hello,
There are two major problems with your code, that are likely to prevent proper operation, and a number of other issues. Firstly, it appears that you have enabled the ADC interrupt, but are then proceeding to poll the COCO flag within the main loop. This will not work! You must either use polling without interrupts, or use the interrupt without polling. Since the COCO flag will be cleared within the ISR, the wait loop within the main loop will never exit when using single conversion mode.
Secondly, within your ISR code you are explicitly disabling interrupts, which will do no harm, but is superfluous because the I-bit within the CCR will already be set when the ISR is entered. However, your code also re-enables interrupts prior to exiting the ISR. This is very bad. If any other interrupt is pending, this will result in a nested interrupt occurring, and will potentially result in stack overflow problems.
If you are going to use interrupts, you need to understand exactly what occurs when an interrupt is entered and exited. The HCS08 reference manual is probably a good starting point.
Your ADC initialisation approach is very inefficient. The code efficiency will be much improved if all bits of each ADC register are simultaneously written. There is no good reason to separately write individual bits. In fact, for the ADCSC1 register, there will be side effects unless all bits are written to their correct values in a single hit. Any write to this register (with the exception of a value of 0x1F) will result in any current conversion being aborted, and a new conversion commencing. So better to do this only once with the bit values that are required.
Consider the following modified code snippets -
The first one is the version for polled operation.
word ADC_Read, ADC_CNT;
void main( void)
{
...
// Initialise ADC
ADCSC1 = 0x1F; // No ADC channel selected during config
ADCCFG = 0xB8; // Bus clk, 10-bit, long samp, clock/2 & low power
ADCSC2 = 0x00; // S/w trigger, no compare
APCTL1_ADPC2 = 1; // Pin I/O disabled for ADP2
for ( ; ; ) {
__RESET_WATCHDOG();
ADCSC1 = 0x02; // Commence single conversion ADP2 (no interrupt)
while (!ADCSC1_COCO); // Wait for conversion complete
ADC_Read = ADCR; // Read value & clear flag
// Process result
if (( ADC_Read >= 300) && (PTAD_PTAD1 == 0)) {
PTBD_PTBD1 = ~PTBD_PTBD1; // Toggle red led
ADC_CNT = ADC_CNT + 3;
}
else {
PTBD_PTBD0 = ~PTBD_PTBD0; // Toggle green led
ADC_CNT = ADC_CNT - 1;
if (ADC_CNT <= 1)
ADC_CNT = 4;
}
if (ADC_CNT > 500) {
if ((ADC_Read >= 300) && (PTAD_PTAD1 == 0)) {
PTAD_PTAD1 = 1;
PTBD_PTBD1 = 1; //red LED on
}
ADC_CNT = 0;
ADC_Read = 0;
}
}
The second code snippet is the suggested approach using interrupts.
word ADC_Read, ADC_CNT;
void main( void)
{
...
// Initialise ADC
ADCSC1 = 0x1F; // No ADC channel selected during config
ADCCFG = 0xB8; // Bus clk, 10-bit, long samp, clock/2 & low power
ADCSC2 = 0x00; // S/w trigger, no compare
APCTL1_ADPC2 = 1; // Pin I/O disabled for ADP2
ADCSC1 = 0x42; // Commence ADP2 single conversion (interrupt enabled)
for ( ; ; ) {
__RESET_WATCHDOG();
}
}
interrupt 19 void ADC_ISR(void)
{
ADC_Read = ADCR; // Read value & clear flag
// Process result
if ((ADC_Read >= 300) && (PTAD_PTAD1 == 0)) {
PTBD_PTBD1 = ~PTBD_PTBD1; // Toggle red led
ADC_CNT = ADC_CNT + 3;
}
else {
PTBD_PTBD0 = ~PTBD_PTBD0; // Toggle green led
ADC_CNT = ADC_CNT - 1;
if (ADC_CNT <= 1)
ADC_CNT = 4;
}
if (ADC_CNT > 500) {
if ((ADC_Read >= 300) && (PTAD_PTAD1 == 0)) {
PTAD_PTAD1 = 1;
PTBD_PTBD1 = 1; //red LED on
}
ADC_CNT = 0;
ADC_Read = 0;
ADCSC1 = 0x42; // New ADP2 single conversion (interrupt enabled)
}
Regards,
Mac
Hello
Actually the ADC is not crossing the threshold as i see now.I have a window comparator running,where the MCU is turning the TRIAC on above a min threshold and below a max threshold.Beyond these thresholds,the TRIAC is turned off and appropriate LED glows.
I am getting the error of <min threshold when i try switching on the TRIAC.
During turn on there is min voltage developed on the filter of the current sensor.How can i take care of these situations?
Awaiting precious reply
Thanks and regards
Hello
After migrating from QD4(with some mod) to QG8 i am having a very bad time measuring a voltage on the ADC input pin.
The initialisation and ISR of the ADC is below.
void Init_ADC(void){ ADCSC1_ADCH = 0x1f; // all channels selected disables the ADC during config ADCCFG_ADICLK = 0b00; // clock source, 00=bus clock, 11 = async. clock,01=bus/2 ADCCFG_MODE = 0b10; // conversion mode, 00 = 8 bit, 10 = 10 bit mode ADCCFG_ADLSMP = 1; // sample time, 1 = long sample time ADCCFG_ADIV = 0b01; // clock divide, 1 = input clock/2 ,10=i/p clk/4 ADCCFG_ADLPC = 1; // low power config, 1 = low power ADCSC2_ADTRG = 0; // trigger select, 0 = software trigger ADCSC2_ACFE = 0; // compare function, 1 = enable compare function ADCSC2_ACFGT = 0; // 1 = compare function greater than ADCSC1_ADCO = 1; // enable single conversion, 1 is continuous conversion ADCSC1_AIEN = 1; // enable ADC interrupt APCTL1_ADPC2 = 1; // disable I/O control on pin //ADCCVL = 100; // set a compare value ADCSC1_ADCH = 0x02; //ADP2 enable} //-------------------------------------------------------------------------------------interrupt 19 void ADC_ISR(void) { ADC_Read= ADCR; //Acknowledge the Read Value to disable COCO Flag if (( ADC_Read>=1000) && (PTAD_PTAD1==0)) { PTBD_PTBD1 = ~PTBD_PTBD1 ; //********TESTING ADC_CNT = ADC_CNT+2; } else { PTBD_PTBD0 = ~PTBD_PTBD0 ; //********TESTING ADC_CNT = ADC_CNT-1; if(ADC_CNT<=1) ADC_CNT=4; } if (ADC_CNT>700) { if (( ADC_Read>=1000) && (PTAD_PTAD1==0))//*********CHANGED FOR ACSTRIAC { PTAD_PTAD1 = SET; //************CHANGED FOR ACSTRIAC PTBD_PTBD1 = SET ; //red LED on } ADC_CNT=0; ADC_Read=0; } }
The ADC is in continous conversion mode with long sample time.My Bus freq is 8Mhz.
With this setting only my ADC ISR is executed and no other s/w part is executed.It is ONLY running in loops around the ADC_ISR as if no other code is present.
I tried using single conversion but the same thing is happening.Earlier I didn't have so many decision making instructions in the ISR and this problem wasn't there,which has risen after the 'if' statements are added.
I am yet to address the actual problem but now i am stuck in this never ending loop of the ADC_ISR which i am not able to solve and losing my mind over it..
Where could the problem be?
Please someone help..I am going nowhere
Thanks and regards
Abi,
Did you consider using the processor expert? It seems that the problems you are facing are due to lack of familiarity to the hardware you're working with. PE is an elegant way of getting it to work.
Cheers,
Celso
Hello Celso
Thanks for replying..I had earlier used PE for initialising (this was some 2 months back)..i saw what the PE did and corected my code according to that and also with help of the datasheet and some app notes.I really don't think current problems are due to lack of familiarity with the h/w
As you can see in my previous post ,i have initialised the ADC as it should've been!
When i use a demo ADC i/p thru a preset the i never run into problems.Since i used the hall effect current sensor, am i facing the same problems again.
Can you modify/add to the existing init routine or the ISR routine.
That would be a heap of help..
Currently i am trying single conversion of the ADC but the ADC will enter the ISR when the load is removed from the current sensor..
Please help.
Thanks and regards
Hello,
It might be possible that the ISR processing cycles exceeds the ADC conversion cycles, and this may contribute to what you are observing. I think that your current attempt to use single conversion mode is probably more appropriate, where you do not start the next conversion until the previous one has been processed.
Additionally, try and get your code to work by polling the COCO bit within the main loop, rather than using interrupts. Once you get it working correctly in this manner, you might then introduce interrupt operation.
You seem to be saying that you have placed series diodes in the Vss lead of the MCU, in order to reduce the supply voltage to the MCU. I do not particularly like this approach because of sensitivity of ADC operation to MCU generated noise. You will likely need a large tantalum bypass capacitor between Vss and "ground", plus some additional high frequency bypass.
To further allow for the presence of noise, perhaps the ADC result should be derived from the average of multiple ADC readings.
Regards,
Mac
Hello Mac and thanks for replying
I had modified my code yesterday after i replied (before your reply) and somewhat same as what you are suggesting.Also i have already removed the diodes and introduced a TL431 2.5v reference at the Vss of the MCU.There is a 10uf capacitor across the 2.5v ref.So now the Vdd w.r.t Vss is +2.6v and is quite stable.
Here is my modified code
for(;;) //forever loop{******************SOME CODE*********************************** ADCSC1_ADCO = 0; // enable single conversion, 1 is continuous conversion ADCSC1_ADCH = 0x02; //ADP2 enable ADCSC1_AIEN = 1; // enable ADC interrupt while(!ADCSC1_COCO) ; } //End of Superloop//---------------------------------------------------------------------------------------//void Init_ADC(void){ ADCSC1_ADCH = 0x1f; // all channels selected disables the ADC during config ADCCFG_ADICLK = 0b00; // clock source, 00=bus clock, 11 = async. clock,01=bus/2 ADCCFG_MODE = 0b10; // conversion mode, 00 = 8 bit, 10 = 10 bit mode ADCCFG_ADLSMP = 1; // sample time, 1 = long sample time ADCCFG_ADIV = 0b01; // clock divide, 1 = input clock/2 ,10=i/p clk/4 ADCCFG_ADLPC = 1; // low power config, 1 = low power ADCSC2_ADTRG = 0; // trigger select, 0 = software trigger ADCSC2_ACFE = 0; // compare function, 1 = enable compare function ADCSC2_ACFGT = 0; // 1 = compare function greater than ADCSC1_ADCO = 0; // enable single conversion, 1 is continuous conversion ADCSC1_AIEN = 1; // enable ADC interrupt APCTL1_ADPC2 = 1; // disable I/O control on pin ADCSC1_ADCH = 0x02; //ADP2 enable} //-------------------------------------------------------------------------------------interrupt 19 void ADC_ISR(void) { DisableInterrupts; ADCSC1_AIEN = 0; // disable ADC interrupt ADC_Read= ADCR; //Acknowledge the Read Value to disable COCO Flag if (( ADC_Read>=300) && (PTAD_PTAD1==0)) { PTBD_PTBD1 = ~PTBD_PTBD1 ; //red led ********TESTING ADC_CNT = ADC_CNT+3; } else { PTBD_PTBD0 = ~PTBD_PTBD0 ; //green led ********TESTING ADC_CNT = ADC_CNT-1; if(ADC_CNT<=1) ADC_CNT=4; } if (ADC_CNT>500) { if (( ADC_Read>=300) && (PTAD_PTAD1==0))//*********CHANGED FOR ACSTRIAC { PTAD_PTAD1 = SET; //************CHANGED FOR ACSTRIAC PTBD_PTBD1 = SET ; //red LED on } ADC_CNT=0; ADC_Read=0; }EnableInterrupts; }
So this is a similar approach to what you are suggesting.Now only thing is that it has a long sample time and low power config for the ADC so this statement : "It might be possible that the ISR processing cycles exceeds the ADC conversion cycles" ..is because of the ADC setup?
Earlier i had also tried using averaging but the current approach acts like a software filter..where the ADC_CNT is incremented by 3 for OL and decremented by 1 for normal operation.Once a threshold (500) count is reached ,only then does it consider as actual OL.
Please get back.
Thanks & regards
Hello,
There are two major problems with your code, that are likely to prevent proper operation, and a number of other issues. Firstly, it appears that you have enabled the ADC interrupt, but are then proceeding to poll the COCO flag within the main loop. This will not work! You must either use polling without interrupts, or use the interrupt without polling. Since the COCO flag will be cleared within the ISR, the wait loop within the main loop will never exit when using single conversion mode.
Secondly, within your ISR code you are explicitly disabling interrupts, which will do no harm, but is superfluous because the I-bit within the CCR will already be set when the ISR is entered. However, your code also re-enables interrupts prior to exiting the ISR. This is very bad. If any other interrupt is pending, this will result in a nested interrupt occurring, and will potentially result in stack overflow problems.
If you are going to use interrupts, you need to understand exactly what occurs when an interrupt is entered and exited. The HCS08 reference manual is probably a good starting point.
Your ADC initialisation approach is very inefficient. The code efficiency will be much improved if all bits of each ADC register are simultaneously written. There is no good reason to separately write individual bits. In fact, for the ADCSC1 register, there will be side effects unless all bits are written to their correct values in a single hit. Any write to this register (with the exception of a value of 0x1F) will result in any current conversion being aborted, and a new conversion commencing. So better to do this only once with the bit values that are required.
Consider the following modified code snippets -
The first one is the version for polled operation.
word ADC_Read, ADC_CNT;
void main( void)
{
...
// Initialise ADC
ADCSC1 = 0x1F; // No ADC channel selected during config
ADCCFG = 0xB8; // Bus clk, 10-bit, long samp, clock/2 & low power
ADCSC2 = 0x00; // S/w trigger, no compare
APCTL1_ADPC2 = 1; // Pin I/O disabled for ADP2
for ( ; ; ) {
__RESET_WATCHDOG();
ADCSC1 = 0x02; // Commence single conversion ADP2 (no interrupt)
while (!ADCSC1_COCO); // Wait for conversion complete
ADC_Read = ADCR; // Read value & clear flag
// Process result
if (( ADC_Read >= 300) && (PTAD_PTAD1 == 0)) {
PTBD_PTBD1 = ~PTBD_PTBD1; // Toggle red led
ADC_CNT = ADC_CNT + 3;
}
else {
PTBD_PTBD0 = ~PTBD_PTBD0; // Toggle green led
ADC_CNT = ADC_CNT - 1;
if (ADC_CNT <= 1)
ADC_CNT = 4;
}
if (ADC_CNT > 500) {
if ((ADC_Read >= 300) && (PTAD_PTAD1 == 0)) {
PTAD_PTAD1 = 1;
PTBD_PTBD1 = 1; //red LED on
}
ADC_CNT = 0;
ADC_Read = 0;
}
}
The second code snippet is the suggested approach using interrupts.
word ADC_Read, ADC_CNT;
void main( void)
{
...
// Initialise ADC
ADCSC1 = 0x1F; // No ADC channel selected during config
ADCCFG = 0xB8; // Bus clk, 10-bit, long samp, clock/2 & low power
ADCSC2 = 0x00; // S/w trigger, no compare
APCTL1_ADPC2 = 1; // Pin I/O disabled for ADP2
ADCSC1 = 0x42; // Commence ADP2 single conversion (interrupt enabled)
for ( ; ; ) {
__RESET_WATCHDOG();
}
}
interrupt 19 void ADC_ISR(void)
{
ADC_Read = ADCR; // Read value & clear flag
// Process result
if ((ADC_Read >= 300) && (PTAD_PTAD1 == 0)) {
PTBD_PTBD1 = ~PTBD_PTBD1; // Toggle red led
ADC_CNT = ADC_CNT + 3;
}
else {
PTBD_PTBD0 = ~PTBD_PTBD0; // Toggle green led
ADC_CNT = ADC_CNT - 1;
if (ADC_CNT <= 1)
ADC_CNT = 4;
}
if (ADC_CNT > 500) {
if ((ADC_Read >= 300) && (PTAD_PTAD1 == 0)) {
PTAD_PTAD1 = 1;
PTBD_PTBD1 = 1; //red LED on
}
ADC_CNT = 0;
ADC_Read = 0;
ADCSC1 = 0x42; // New ADP2 single conversion (interrupt enabled)
}
Regards,
Mac
Hello Mac
Yes its doing great now..little things that i missed were actually very huge..and thanks for pointing that out to me... I used the polling approach.
Now since the ADC portion is reading the values well,let me move on to the original problem..
I have Voltage at Vdd w.r.t Vss =2.6v
The voltage measured at ADC i/p pin is 0.485v w.r.t Vss for an Overload condition. (which is stable)
The ripple on the Vdd is <10mV.
The current sensor operates on 5v and o/ps corresponding voltage (scaled to 5v) to an i/p AC current flow ,which i have rectified & filtered (pls refer schematic in this thread)
Simple math for the ADC_Read = (1023*0.485)/2.6=191 decimal.
Now the s/w filter will check sustained OL (overload) conditions for atleast 500 counts,meanwhile subtracting the ADC_CNT on every 'normal' condition...so as not to react to a transient OL.
I can see OL at even a 0.470v or 184 decimal value.Is it something to do with the ADC internal resitance (5k) at the pin?
Is what i am doing is correct or again i am missing something?
Please help as usual
Thanks & regards
Hello,
After examination of your circuit, I think that there will be problems maintaining accuracy and repeatability, particularly with small changes of Vcc and of operating temperature.
Firstly, the current sensing device has a ratiometric output, and with zero current, the output voltage will be Vcc/2. The output voltage will swing positively and negatively about this point, with the actual output directly proportional to Vcc. For 5.0 volt Vcc, and with full scale (5A) positive and negative current swing, the output voltage swing will approximate to 1.5 to 3.5 volts.
Since the operation of the ADC module is also ratiometric (with respect to Vdd - Vss), my suggestion is that there be a constant ratio between Vcc and (Vdd - Vss), with a design ratio of 0.6 suggested. This will give an applied MCU voltage of 3.0 volts when Vcc is 5.0 volts, with the Vss rail at +2.0 volts. I have purposely made the Vss voltage lower than the zero current output voltage from the current sensor.
To achieve the ratiometric setting of the Vss rail, in its simlest form, would be a resistive voltage divider driving an op amplifier (with voltage follower configuration). If the sink current capability of the op amplifier were to be insufficient, an additional PNP transistor may need to be incorporated in the output circuitry. When this is done correctly, the ADC reading for zero sensor current should remain constant (apart from fluctuations due to noise) for Vcc variation 4.5 to 5.5 volts. In fact, this value should be stored by the firmware, as a calibration constant to take into account resistor tolerances, etc.
A further problem with your existing circuit is that the output of current sensor is fed to a peak detector circuit consisting of R4, D7 and C6. The voltage drop across D7 (0.6-0.7 volts) is problematic because it is comparable with the voltage swing that you are attempting to measure, and it will be temperature dependent. I also notice that the peak detector does not have a discharge path other than the high-Z input to the ADC.
Assuming that the mains line frequency is 50/60 Hz, you might not need a peak detector provided your sampling is sufficiently frequent, i.e. many samples per half cycle. In this case, only R4 would remain (to provide protection against possible negative ADC input voltage during power up cycling).
If you feel that the peak detector is still required, it will need to be of the form that uses an op amplifier so that the diode voltage drop may be compensated. A capacitor discharge path will also need to be provided, and might be achieved in firmware, by transiently setting the ADC input as GPIO output.
A final comment about your LED connections. With the LEDs returned to the Vss rail, you allow very little voltage overhead, particularly for the green LED. The switching of the LED current may also affect the Vss rail voltage. A better solution would be to return the LEDs to ground. To do this will require the use of a PNP transistor to drive each LED. The method I would probably use would be to directly drive the base from the MCU ouput, and to place the current limiting resistor in the emitter circuit. This way a single resistor can limit both base current and LED current. With a Vss voltage of 2 volts, the voltage overhead should be about 2.5 volts, sufficient for most green LEDs.
Regards,
Mac
Hello Mac
Thanks for the immense support.Really appreciated.
I am contemplating adding a boost converter (TPS61222) 3v to 5v for the ACS712 sensor,so that all grounds are at same potential and no additional circuits to compensate for voltage dips are needed.
Please refer new schematic. The devices will be received on 27th june.
This will add a discharge path(R7) for C6 on the o/p & also calibrate it to 0v (or maybe i remove R7 so as to get higher potential on ADC INPUT wrt GND ?.Then the firmware approach can be incorporated to discharge the capacitor.what do you say? )
The 3.3v & the 5v will be very stable in this case.
With this scheme the LEDs too may be biased appropriately w/o affecting the Vss.
In my existing circuit ,the 5v is quite stable with about 2% tolerance.I was using a TL431 at the Vss pin.So both Vdd and Vcc were having ratiometric responses.But i think the D7 will be the main issue here which you have pointed out which i will remove and check with my existing scheme.
Anyhow i need some advice with the new scheme (attached).
PLease reply back soon.
[EDIT : D7 will be removed from where it is.Its stuck there by mistake]
Thanks and regards
Hello,
Using a boost switching converter for the Hall effect device may introduce additional noise that may affect ADC conversion results. With this non-ratiometric approach both supply voltages will ideally need to be stable to better than 3mV (one LSB for the ADC).
Accepting a generated output voltage range from the current sensor of 1.5 volts minimum (negative current peak) to 3.5 volts maximum (positive current peak), the positive peak will now be out of range for the ADC (previously the negative peaks were out of range).
For both positive and negative peaks to fall within the ADC conversion range you will need to shift the voltages, without reduction of the voltage swing. This will require an additional op amp. The simplest arrangement to do this is to use a standard unity gain inverting amplifier configuration (with equal input and feedback resistor values). The non-inverting input of the op amp should be set to a level of 2.0 volts, using a resistive voltage divider from the regulated 3 volt supply. The output of the op amp should then have a voltage swing from 0.5 volts to 2.5 volts, with a zero current value of 1.5 volts.
The positive peaks will now cause a negative swing, but may be corrected by reversing the input connections to the current sensor, if necessary.
I notice that your schematic still includes the D7 diode, and may account for your measured non-linearity if it was present for the measurements. With resistor R7 present, you now have a lossy peak detector. However, if R7 was put there to reduce the sensor output voltage (and sensitivity), I would still recommend the alternative use of an op amp to avoid the reduction of sensitivity. The presence of D7 is unacceptable, as previously discussed. If D7 is removed, C6 will also need to be removed.
Exactly what are you attempting to measure? My previous understanding was that you had an interest only in the peak (overload) current, on a cycle by cycle basis. Is this correct? Do you need to monitor both positive and negative current peaks, or will a single direction suffice?
Your currently attempt is to use a peak detect circuit, within analog hardware, for positive peaks only. This attempt failed primarily because of the non-linearity of the peak detector, although could be satisfactory with a more elaborate linear peak detector configuration, and additional control of the discharge of the storage capacitor. The minimum sampling rate for this method would be once or twice per input cycle.
The alternative approach is to implement the peak detection requirement within firmware, by rapid sampling of the current waveform, to detemine the maximum and minimum values associated with the positive and negative peak currents. The minimum number of samples per cycle, to obtain a measurement very close to to the peak value will depend, to a large extent, on the shape of the current waveform. The detection of very narrow spikes will need a higher sampling rate than a sinusoidal or a square waveform.
Regards,
Mac
Hello Mac
Thanks for the explanation.
I need to measure two current levels. Imax>=2.5A rms , Imin<125mA rms @230v 50Hz.
Yesterday while searching on the web i found this
He has used a peak detector w/o using any amplification on the signal and that too for very low currents (maybe <26w standby currents).
Coming back to my problem ,how would an LDO introduced at the Vss of the MCU behave?..(Earlier i had TL431 2.5v reference there.) Since you said that ratiometric responses will suffer upon using a boost converter for the hall sensor.
The range of 1.5v to 3.5v is for 0 to 5A.I am measuring 125mA to 2.5A which will be 2.96v max beyond which i anyways shut the current carrying device off.The main concern here is the lower current at 125mA where the sensed voltage will be 125mA*185mV=23.125mV+2.5v=2.523v
which will be only 8 counts variation with 3.3v & 10 bit ADC...which again is not substantial and can vary with temperature and noise.So i think the use of op-amp is imperative here .What do you think?
The measurements with nonlinearity which i have observed are with D7 removed and only R4 & C6. R7 was NOT yet put there.This i am planning to use to reduce the sensor o/p voltage as you correctly mentioned and also to discharge C6,but with the drawback of reduced sensitivity.So as mentioned by you, the op-amp may be mandatory here.OR i won't use R7 since i am not concerned about currents greater than 2.5A and provide discharge from firmware.
My sampling now is close to a 100 times in a half cycle if not more.The ADC sampling (with tremendous help from you) is done once in the continous loop.Only during some other action where i am processing an i/p IR remote protocol on the TPM channel interrupt ,will it take more than some 100ms,and that is not very often. My main worry is to switch off a device once it starts demanding greater current than 2.5A.I am not worried about the response as it may take action in 500ms or even 1 second. I just need it accurate and that too maybe within 1 or 2 ADC counts.
The current in question here is a sinusoidal waveform and sampled quite a number of times more than you suggested.
Please advise soon
Thanks & regards
Hello,
Firstly, all processes so far have been based on measurement of peak current, yet your threshold criteria specify rms current. If the current waveform is approximately sinusoidal, your threshold levels would need to be adjusted to an equivalent peak value.
With the sampling approach, it would be advantageous to derive the peak-to-peak value from each series of samples. You then would no longer need to be concerned about the zero current offset since you would be subtracting the minimum peak value from the maximum peak value. Your two threshold levels might then correspond to 350ma p-p and 7.1A p-p.
Perhaps the upper and lower thresholds should be handled by two different ADC channels. The upper threshold channel would have unity gain. However, the lower threshold channel might have a gain of, say 5, to improve the resolution of the lower threshold measurements. If you were to use an op amp with rail-to-rail output this would limit the voltage swing, and prevent any over-voltage problems at the ADC input.
It would seem that a suitable sampling rate would be 6000 samples per second (120 samples per cycle). The change in level near the peak of the sinusoid would be less than 1 LSB.
Regards,
Mac
Hello Mac
Thanks for replying
I was actually measuring the voltage at the ADC pin and converting that to respective counts.This voltage was the dc equivalent of the peak value or whatever the rms value.(or am i wrong?)
Why doesn't it work for that.Should i calculate the actual peaks in code this way? (2*[root]2*VIOUT)
and convert that to the count? I am sorry i am being very crude here..
The two ADC channel idea is a very good one.I can try that and i think that i sample some 100 samples for a cycle with my current approach.
Thanks & regards
Hello,
A sinusoidal current with an RMS value of 2.5A will have a peak value of 3.54A and a peak-to-peak value of 7.07A. The nominal output frim the sensor, under this condition, will be 1.31 volt p-p, i.e. 2.5 +/- 0.65 volts, cycling between the limits 1.85 to 3.15. For Vdd of 3.3 volts, the change of ADC reading samples, from minimum to maximum, will be 1.31 * 1024 / 3.3 = 406.
For the lower current threshold of 0.125A rms, the sinusoidal peak-to-peak current would be 0.354A, with a voltage swing at the sensor output of 0.065 volt p-p. When amplified by a factor of 5, this will become 0.327 volt p-p. and the change of ADC reading, from minimum to maximum would be 102. This assumes that the output of the amplifier is biased within the linear range of the ADC.
Regards,
Mac
Hello Mac
I am unable to understand one thing here.
To get a maximum and minimum value will i need a zcd where zero=2.5v ?
I am writing a generalised algorithm for peak (not peak-to-peak) of the upper limit
if(ADC_Read>2.5v){ if(ADC_Read>Max_ADC_Read) { Max_ADC_Read = ADC_Read; } if (Max_ADC_Read > overload_value) { take action;}}
is it correct?
Similar piece can be written for lower limit with another ADC i/p pin enabled.
Is this approach correct? if not then can you suggest a better approach?
Thanks & regards
Hello,
The whole point about using the peak-to-peak current is that the result will be unaffected by the zero current offset voltage from the sensor, and any change due to drift, supply change, etc.
You will firstly need to derive the peak-to-peak value, by testing each increasing sample until there is no further increase, and then testing each decreasing sample until there is no further decrease. Then subtract the minimum value from the maximum value.
Start with the low threshold channel, and should overflow (1023 reading) or underflow (0 reading) occur, then continue processing with the high threshold channel.
The second step would then be to compare the peak-to-peak value with the relevant threshold level (adjusted for peak-to-peak value).
Regards,
Mac
Hello Mac
Since there was a lot of problems with different GND's in my schematic,I have shifted to a 5v device ,SH8 (which was the customers suggestion as there is lesser component count) I have been migrating the code to SH8 and now I have successfully implemented the peak-to-peak approach for current reading.This is with the high threshold channel only,for now at least!!
I can get a very precise measurement within 43mA mains current.
The lower threshold will have to be amplified and then applied to another ADC channel,I will check that today.
Thanks and regards
Hello
I checked the current on an amplified channel as well on another ADC channel (ADP6)..and it is okay..
I now integrated both the channels and am measuring the lower channel first and if ADC reading goes beyond a set 'overflow' value ,the other channel is activated.
I am trouble realising one thing here.How should i go back to the amplified channel so that 'underloads' are taken care of ? I mean ,what should be the condition to switch to amplified channel
I had taken this condition
if ((RMS <= 20) && (Next_channel == 1))
where Next_channel is a flag to check which channel is active (1= normal ,0 =amplified)
With this even a normal load is considered as underload.
I am adding the part where i take the decision of which channel to activate
if ((RMS <= 50) && (RMS!=0) && (Next_channel == 0)) { PTAD_PTAD1 = 1 ; //Turn off TRIAC PTBD_PTBD0 = 1 ; //Turn on GREEN LED ADC_Read = 0; RMS=0 ; ADC_AVG_CNT=0; ADC_Avg =0; } else { if ((RMS >=100) && (Next_channel == 0)) //if this channel is overflow { Next_channel = 1; ADC_Read = 0; RMS=0 ; ADC_AVG_CNT=0; ADC_Avg =0; } }//-------------------------------------------------------------------------------------------------------// if ((RMS >= 70) && (Next_channel == 1)) //if actual overload on normal channel { PTAD_PTAD1 = 1 ; //Turn off TRIAC PTBD_PTBD1 = 1 ; //Turn on RED LED ADC_Read = 0; RMS=0 ; ADC_AVG_CNT=0; ADC_Avg =0; } else { if ((RMS <= 20) && (RMS!=0) && (Next_channel == 1)) //if underload on normal channel { Next_channel = 0; ADC_Read = 0; RMS=0 ; ADC_AVG_CNT=0; ADC_Avg =0; } } //------------------------------------------------------------------------------------------------------------//
RMS= actual RMS reading after sampling,averaging and converting the p-p to rms.
One more query.
Since i have an unisolated PSU for this board , i have two boards,of which one uses the debugger 5v supply to test and debug and the ACS712 on it isolates the mains side from this supply.But my actual board uses the mains unisolated power to generate the 5v so i am not able to connect the debugger to the board..This way i have become blind..any ideas how i can connect the debugger ,and PC to my board?
Thanks and regards
Hello,
I am not sure how the 'RMS' variable relates to your previous post where you state that you are measuring peak-to-peak values. I might have expected each threshold value to be most simply expressed as the equivalent peak-to-peak value, to avoid the unnecessary additional run time calculation of RMS value.
The determination of the peak-to-peak current should be an entirely separate process from the threshold test and control process. Therefore, at the commencement of the reading process for a new mains cycle, you simply revert to measuring the amplified channel until overflow or underflow occurs - exactly the same process for every cycle. A flag can be used to indicate whether the current reading is based on the direct or the amplified channel. If the amplified channel is output, only the low threshold is of interest.
Further to the suggestion by Celso, another possibility is to use a 1:1 mains isolation transformer during test and debug. In fact I would have thought this would be a necessity, to prevent a potential personal electrical hazard during the development process.
Regards,
Mac