ADC measures over time

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

ADC measures over time

Jump to solution
858 Views
GMVS
Contributor III

hi

 

i need to check the voltage level of 2 lines

 

but i need to send a warning if the level drops or goes too high in either of them

 

i'm using 8 bit ADC

 

should i make a histeresis window or a buffer to compare, or both?

 

and if use a buffer, what would be the best way to compare the values stored?

 

thanks

Labels (1)
Tags (3)
0 Kudos
Reply
1 Solution
656 Views
bigmac
Specialist III

Hello,

The approach taken may depend on how quickly you need to respond to an alarm state, and the sensitivity of the project to alarm "chattering".  If the alarm state needs to be based on a single ADC reading, and the analog signal is subject to significant variation due to noise, a large hysteresis value is required.

However, if your project requirements will allow a longer time frame to sense an alarm state, you can take the average value from multiple readings for each channel.  This will reduce the effects of random noise, and allow a smaller hysteresis range to be used to determine when the warning is cancelled.  Ideally, you would take the average over a full mains frequency cycle to minimize the effects of mains hum.

To "pace" the multiple ADC readings, I would make use of a periodic tick interrupt associated with a timer.  For example, using a tick period of 1 millisecond, you might alternate readings for each of the two channels, giving 8 readings per channel over a period of 16 milliseconds (a total of 16 ADC readings per measurement cycle).

Using simple averaging, you do not need to store individual readings, but simply sum the readings for each channel.  In fact, it is unnecessary to divide the sum by 8, for the above example, since you can simply multiply the comparison threshold values by 8.

#define MIN_VAL    50*8   // Sum of 8 readings

#define MAX_VAL   150*8

#define HYST        3*8   // Hysteresis value

#define MIN_VALH  MIN_VAL + HYST

#define MAX_VALH  MAX_VAL - HYST

#define CH_OFFSET 0       // Use ADC channels 0 & 1

// Global variables:

byte AD_count;

word result0;

word result1;

Within the ADC initialisation, and following the ADC register initialisation, would be needed -

  AD_count = 0;

  result0 = 0;

  result1 = 0;

  ADCSC1 = CH_OFFSET;  // Commence first ADC reading

The following code could be placed within the timer ISR code -

  if (AD_count & 1) result1 += ADCR;

  else              result0 += ADCR;

  AD_count++;

  if (AD_count >= 16) { // End of measurement cycle

    AD_count = 0;       // Start of new measurement cycle

    if ((result0 < MIN_VAL) || (result0 > MAX_VAL))   show_warning0();

    if ((result0 > MIN_VALH) || (result0 < MAX_VALH)) clear_warning0();

    if ((result1 < MIN_VAL) || (result1 > MAX_VAL))   show_warning1();

    if ((result1 > MIN_VALH) || (result1 < MAX_VALH)) clear_warning1();

    result0 = 0;

    result1 = 0;

  }

  ADCSC1 = (AD_count & 1) + CH_OFFSET; // Start next ADC reading

Regards,

Mac

View solution in original post

0 Kudos
Reply
1 Reply
657 Views
bigmac
Specialist III

Hello,

The approach taken may depend on how quickly you need to respond to an alarm state, and the sensitivity of the project to alarm "chattering".  If the alarm state needs to be based on a single ADC reading, and the analog signal is subject to significant variation due to noise, a large hysteresis value is required.

However, if your project requirements will allow a longer time frame to sense an alarm state, you can take the average value from multiple readings for each channel.  This will reduce the effects of random noise, and allow a smaller hysteresis range to be used to determine when the warning is cancelled.  Ideally, you would take the average over a full mains frequency cycle to minimize the effects of mains hum.

To "pace" the multiple ADC readings, I would make use of a periodic tick interrupt associated with a timer.  For example, using a tick period of 1 millisecond, you might alternate readings for each of the two channels, giving 8 readings per channel over a period of 16 milliseconds (a total of 16 ADC readings per measurement cycle).

Using simple averaging, you do not need to store individual readings, but simply sum the readings for each channel.  In fact, it is unnecessary to divide the sum by 8, for the above example, since you can simply multiply the comparison threshold values by 8.

#define MIN_VAL    50*8   // Sum of 8 readings

#define MAX_VAL   150*8

#define HYST        3*8   // Hysteresis value

#define MIN_VALH  MIN_VAL + HYST

#define MAX_VALH  MAX_VAL - HYST

#define CH_OFFSET 0       // Use ADC channels 0 & 1

// Global variables:

byte AD_count;

word result0;

word result1;

Within the ADC initialisation, and following the ADC register initialisation, would be needed -

  AD_count = 0;

  result0 = 0;

  result1 = 0;

  ADCSC1 = CH_OFFSET;  // Commence first ADC reading

The following code could be placed within the timer ISR code -

  if (AD_count & 1) result1 += ADCR;

  else              result0 += ADCR;

  AD_count++;

  if (AD_count >= 16) { // End of measurement cycle

    AD_count = 0;       // Start of new measurement cycle

    if ((result0 < MIN_VAL) || (result0 > MAX_VAL))   show_warning0();

    if ((result0 > MIN_VALH) || (result0 < MAX_VALH)) clear_warning0();

    if ((result1 < MIN_VAL) || (result1 > MAX_VAL))   show_warning1();

    if ((result1 > MIN_VALH) || (result1 < MAX_VALH)) clear_warning1();

    result0 = 0;

    result1 = 0;

  }

  ADCSC1 = (AD_count & 1) + CH_OFFSET; // Start next ADC reading

Regards,

Mac

0 Kudos
Reply