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
Solved! Go to Solution.
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
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