ADC measures over time

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

ADC measures over time

ソリューションへジャンプ
689件の閲覧回数
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

ラベル(1)
タグ(3)
0 件の賞賛
1 解決策
487件の閲覧回数
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 件の賞賛
1 返信
488件の閲覧回数
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 件の賞賛