AdSense

Sunday 31 August 2014

Arduino, ATmega or ATtiny: monitor supply voltage

(Deutsche Version)
If you supply your Arduino or ATmega/ATtiny using a battery you might want to be warned, when the battery is almost empty so you can replace it. To do this you can monitor the supply voltage. If it drops below a defined threshold you can for example turn on a LED to be warned.

Monitoring the voltage can be done without any additional hardware by using the microcontrollers analog digital converter. As you might know, the value of the ADC is calculated using the following formula:
VALUE_ADC = V_INPUT * 1023/V_REF
Now you could think: "I'll just take my supply voltage as input voltage for the ADC" but that won't work since the supply voltage is also used as reference voltage. The value of the ADC would always be 1023.
But there is a trick: every microcontroller generates an internal reference voltage, the so called "bandgap voltage" V_BG. At the ATmega328 which is used in die Arduino Uno, the bandgap voltage is 1.1V. You can use this voltage as input für your ADC.
With V_INPUT = V_BG and V_REF = V_CC you get:
VALUE_ADC = V_BG * 1023/V_CC
or:
V_CC = V_BG * 1023/VALUE_ADC
With V_BG = 1100 (in mV) you get:
V_CC = 1100 * 1023/VALUE_ADC
Where V_CC is the value of your supply voltage in mV.

The code for the Arduino Uni is:

int led = 13;  //pin of the LED
int adc_low, adc_high;  //buffer for the results of the ADC
long adc_result;  //10bit result of measurement of ADC
long vcc;  //supply voltage

void setup() {    
  pinMode(led, OUTPUT);  

  ADMUX |= (1<<REFS0); //VCC as reference for ADC
  ADMUX |= (1<<MUX3) | (1<<MUX2) | (1<<MUX1);  //1.1V bandgap voltage as input of ADC 
  delay(10);  //wait until reference voltage is set
  ADCSRA |= (1<<ADEN);   //enable ADC
}

// the loop routine runs over and over again forever:
void loop() {    
  ADCSRA |= (1<<ADSC);  //start measurement

  while (bitRead(ADCSRA, ADSC));  //wait until measurement is completed
  //buffer results. Important: read ADCL first!
  adc_low = ADCL;
  adc_high = ADCH;

  adc_result = (adc_high<<8) | adc_low; //10bit result 
  vcc = 1125300L / adc_result;  //calculate supply voltage in mV (1100mV * 1023 = 1125300)

  //if supply voltage is lower then 5V
  if (vcc < 5000)
  {
    digitalWrite(led, HIGH);  //turn on LED
  }

  else 
  {
    digitalWrite(led, LOW);  //turn of LED
  }

  delay(500);
} 
 
In setup()-function the ADC is configured to use the supply voltage V_CC als referenz and the bandgap voltage V_BG as input. Then the ADC is enabled.
In loop() the measurement is started by setting the bit ADSC. When it's finished (bit ADSC is cleared) the result of the conversion is read from the registers ADCL (lower 8 bits) and ADCH (upper 2 bits) and merged to a 10-bit-result. Using this result, the supply voltage is calculated. If it is uner 5V, the LED is turned on.


This method works with every ATmega oder ATtiny. Depending on the µC you might have to set different bits in the registers of the ADC. Check the datasheet of your microcontroller.

Wednesday 20 August 2014

ATmega - measure the soil humidity

(Deutsche Version) Today, I want to present a humidity sensor. The basic idea is to measure the soil humidity at plants to know when you have to water the plants.

To construct the sensor, you don't need much stuff. I used a small piece of stripboard, two nails and some pin strips. The sensor looks like this:
The next step is to measure the resistivity in between the two nails (when the sensor is in the earth) and then you can estimate the soil humidity. The electrical wiring is the following:
If the earth is humid, the sensor conducts well, therefore the ATmega measures a high voltage, if the earth is dry, the measured voltage is small. You can now think about putting units on the axis, in my opinion, it is sufficient to simply plot the "humidity" from 0 to 5 V and then check the voltage which corresponds to dry earth which has to be watered. This can now be displayed by an LED or by sending an automatic e-mail.