QG8 ADC with current sensor help

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

QG8 ADC with current sensor help

Jump to solution
4,480 Views
abicash
Contributor III

 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

Message Edited by abicash on 2009-06-17 12:15 PM
Labels (1)
0 Kudos
Reply
1 Solution
1,516 Views
bigmac
Specialist III

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

View solution in original post

0 Kudos
Reply
26 Replies
1,423 Views
abicash
Contributor III

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

Message Edited by abicash on 2009-06-17 12:43 PM
0 Kudos
Reply
1,423 Views
abicash
Contributor III

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 :smileysad:

 

Thanks and regards 

0 Kudos
Reply
1,423 Views
celsoken
Contributor V

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

0 Kudos
Reply
1,423 Views
abicash
Contributor III

 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

0 Kudos
Reply
1,423 Views
bigmac
Specialist III

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

 

0 Kudos
Reply
1,423 Views
abicash
Contributor III

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

0 Kudos
Reply
1,517 Views
bigmac
Specialist III

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

0 Kudos
Reply
1,423 Views
abicash
Contributor III

Hello Mac  :smileyvery-happy:

 

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

0 Kudos
Reply
1,423 Views
bigmac
Specialist III

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

0 Kudos
Reply
1,423 Views
abicash
Contributor III

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

Message Edited by abicash on 2009-06-25 09:21 AM
0 Kudos
Reply
1,423 Views
bigmac
Specialist III

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

0 Kudos
Reply
1,423 Views
abicash
Contributor III

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

Message Edited by abicash on 2009-06-29 07:40 AM
Message Edited by abicash on 2009-06-29 07:41 AM
0 Kudos
Reply
1,423 Views
bigmac
Specialist III

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

0 Kudos
Reply
1,423 Views
abicash
Contributor III

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

0 Kudos
Reply
1,423 Views
bigmac
Specialist III

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

 

0 Kudos
Reply
1,423 Views
abicash
Contributor III

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

Message Edited by abicash on 2009-07-03 09:27 AM
0 Kudos
Reply
1,423 Views
bigmac
Specialist III

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

0 Kudos
Reply
1,421 Views
abicash
Contributor III

 Hello Mac :smileyhappy:

 

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

0 Kudos
Reply
1,419 Views
abicash
Contributor III

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 

0 Kudos
Reply
1,419 Views
bigmac
Specialist III

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

 

Message Edited by bigmac on 2009-07-17 01:04 PM
0 Kudos
Reply