Battery voltage and internal temperature reading together

hello, I am a beginner in AVR programming, and I am having a strange problem in reading the battery voltage and the internal temperature sensor.

In short words, both function works when called alone, but when I place them inside the main loop to run them one after another, the battery reading is wrong. I suspect I am missing something in the ADC part.

the test code is shown as below, please be aware that the temperature reading is commented out, you need to un-comment it to take effect. Any input on this problem is appreciated. thank you!

#include <Arduboy2.h>

Arduboy2 arduboy;

volatile long count = 0;
volatile int32_t temp = 0;

//read internal vcc voltage
uint16_t read_vcc()
{
    uint16_t vcc_mv;

    //reset
    //ADCSRA = 0;
    ADMUX  = 0;

    //read 1.1V band gap against AVcc
    ADMUX |= (1<<REFS0)|(1<<MUX4)|(1<<MUX3)|(1<<MUX2)|(1<<MUX1);
    
    _delay_ms(2);
    
    //10-bit resolution with ADC clock speed of 50 kHz to 200 kHz
    //Enable ADC, set prescaller to /64, ADC clock of 16mHz/64=125kHz
    ADCSRA |= (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
    
    //actual read
    ADCSRA |= (1<<ADSC);
    while ((ADCSRA & (1<<ADSC)) != 0);
    
    //calculate AVcc in mV, 1.1*1024*1000/ADC
    vcc_mv = (uint16_t)(1126400/ADC); 
    return vcc_mv;
}

//read internal temperature sensor
int32_t read_inter_temperature()
{
    int32_t temp_c;

    //reset
    ADMUX  = 0;
    
    //setup ADC to use internal 2.56V reference
    //ADC right adjust result
    ADMUX |= (1<<REFS1)|(1<<REFS0)|(1<<MUX2)|(1<<MUX1)|(1<<MUX0);
    ADCSRB |= (1<<MUX5);

    _delay_ms(2);
    
    //10-bit resolution with ADC clock speed of 50 kHz to 200 kHz
    //Enable ADC, set prescaller to /64, ADC clock of 16mHz/64=125kHz
    ADCSRA |= (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
    
    //dummy read
    ADCSRA |= (1<<ADSC);
    while ((ADCSRA & (1<<ADSC)) != 0);
    
    // start a new conversion
    ADCSRA |= (1<<ADSC);
    while ((ADCSRA & (1<<ADSC)) != 0);
    
    // Calculate the temperature in C, offset = 275
    temp_c = ADC - 275;

    
    return temp_c;
}

void setup()
{
  arduboy.begin();
  power_adc_enable();
  arduboy.setFrameRate(15);
}

void loop()
{
  // pause render until it's time for the next frame
  if (!(arduboy.nextFrame()))
    return;

  arduboy.clear();

  arduboy.setCursor(0, 0);
  uint16_t vcc = read_vcc();
  arduboy.print("VCC = ");
  arduboy.print(vcc, DEC);

  arduboy.setCursor(0, 20);
  //temp = read_inter_temperature();
  arduboy.print("TEMP = ");
  arduboy.print(temp, DEC);

  arduboy.setCursor(0, 40);
  arduboy.print("COUNT = ");
  arduboy.print(count, DEC);
  count++;
  // then we finaly we tell the arduboy to display what we just wrote to the display
  arduboy.display();

  delay(500);
}

Is it always wrong even if you switch the order?

I’m not sure if it has anything to do we aren’t properly using the AREF signal which should be tied to ground through a capacitor but it’s just left floating.

I just tried switching order, did not solve the issue…
but I think I’d like to try to add a capacitor though, is the AREF pin brought out ?

You can find a pad labelled AREF next to the rocket just above the Dinosaur to the right on the rear of the Arduboy PCD.

There’s also some related discussion about adding a capacitor in the linked post…

1 Like

thanks for the link, I just realized that I have an extra pro micro(https://www.sparkfun.com/products/12640) with the same cpu, and it has a capacitor on the AREF pin, unfortunately the problem remains, even with just serial output, without the arduboy library

Hmm, might be something with the code could also be errata from the chip. Since it also happens on the pro micro you might try posting about it the arduino or atmel forums and see if you get any advice. If you do be sure to drop it back in here! :slight_smile:

1 Like

read_vcc is not guaranteeing that ADCSRB is set correctly.