Skip to main content
Tweeted twitter.com/StackElectronix/status/1300765353740587008
Became Hot Network Question
deleted 24 characters in body; edited title
Source Link
JRE
  • 73.6k
  • 10
  • 112
  • 195

This ADC code works, but I don't understand why?

I have the following code for reading a battery voltage on the ADC on a microcontroller (Atmel SAM D21 to be precise).) The reference voltage is 3.3v3.3V and the ADC is reading at 12 bit resolution:

/**
 * Union for Readings
 *
 */
typedef union u_reading {
    int16_t i;
    uint8_t c[2];
} reading;

/**
 * Read the main battery voltage.
 *
 */
static void read_battery_level()
{
    // Switch on the Control Pin
    gpio_set_pin_level(ADC_CONTROL, 1);
    
    // Battery Voltage
    float batt_voltage = 0.0f;
    
    // Array of Samples
    reading batt_readings[BATTERY_READINGS_COUNT];
    int x;
    
    // Loop through ad Average the Readings
    for (x = 0; x < BATTERY_READINGS_COUNT; x++)
    {
        // Read the ADC Channel
        adc_sync_read_channel(&ADC_BATTERY, 0, batt_readings[x].c, 2);
        delay_us(20);
    }
    
    // Counter for the Sum
    uint32_t sum = 0;
    
    // Loop through and Average the Readings
    for (x = 0; x < BATTERY_READINGS_COUNT; x++)
    {
        // Add the Sum
        sum += batt_readings[x].i;
    }
    
    // Calculate the Mean Reading
    batt_voltage = (sum / (float)BATTERY_READINGS_COUNT) * 0.8;
    
    // Set the Battery Level
    battery_level.i = (uint16_t)batt_voltage;
    
    // Switch off the Control Pin
    gpio_set_pin_level(ADC_CONTROL, 0);
}

The code works and gives me a very accurate reading for battery voltage - I've tried it with a pretty accurate power source and multiple voltages and the reading is good every time. When I switch the reference voltage to 5v5V, it's no longer accurate, unless I remove the * 0.8 multiplier.

I'm still wrapping my head around how ADCs work, and I was wondering if someone could explain what's going on here?.

Why does a multipler of 0.8 work for a 3.3v3V input and a multiplier of 1 work for 5v5V?

Thanks in advance!

This ADC code works, but I don't understand why?

I have the following code for reading a battery voltage on the ADC on a microcontroller (Atmel SAM D21 to be precise). The reference voltage is 3.3v and the ADC is reading at 12 bit resolution:

/**
 * Union for Readings
 *
 */
typedef union u_reading {
    int16_t i;
    uint8_t c[2];
} reading;

/**
 * Read the main battery voltage.
 *
 */
static void read_battery_level()
{
    // Switch on the Control Pin
    gpio_set_pin_level(ADC_CONTROL, 1);
    
    // Battery Voltage
    float batt_voltage = 0.0f;
    
    // Array of Samples
    reading batt_readings[BATTERY_READINGS_COUNT];
    int x;
    
    // Loop through ad Average the Readings
    for (x = 0; x < BATTERY_READINGS_COUNT; x++)
    {
        // Read the ADC Channel
        adc_sync_read_channel(&ADC_BATTERY, 0, batt_readings[x].c, 2);
        delay_us(20);
    }
    
    // Counter for the Sum
    uint32_t sum = 0;
    
    // Loop through and Average the Readings
    for (x = 0; x < BATTERY_READINGS_COUNT; x++)
    {
        // Add the Sum
        sum += batt_readings[x].i;
    }
    
    // Calculate the Mean Reading
    batt_voltage = (sum / (float)BATTERY_READINGS_COUNT) * 0.8;
    
    // Set the Battery Level
    battery_level.i = (uint16_t)batt_voltage;
    
    // Switch off the Control Pin
    gpio_set_pin_level(ADC_CONTROL, 0);
}

The code works and gives me a very accurate reading for battery voltage - I've tried it with a pretty accurate power source and multiple voltages and the reading is good every time. When I switch the reference voltage to 5v, it's no longer accurate, unless I remove the * 0.8 multiplier.

I'm still wrapping my head around how ADCs work, and I was wondering if someone could explain what's going on here? Why does a multipler of 0.8 work for a 3.3v input and a multiplier of 1 work for 5v?

Thanks in advance!

This ADC code works, but I don't understand why

I have the following code for reading a battery voltage on the ADC on a microcontroller (Atmel SAM D21 to be precise.) The reference voltage is 3.3V and the ADC is reading at 12 bit resolution:

/**
 * Union for Readings
 *
 */
typedef union u_reading {
    int16_t i;
    uint8_t c[2];
} reading;

/**
 * Read the main battery voltage.
 *
 */
static void read_battery_level()
{
    // Switch on the Control Pin
    gpio_set_pin_level(ADC_CONTROL, 1);
    
    // Battery Voltage
    float batt_voltage = 0.0f;
    
    // Array of Samples
    reading batt_readings[BATTERY_READINGS_COUNT];
    int x;
    
    // Loop through ad Average the Readings
    for (x = 0; x < BATTERY_READINGS_COUNT; x++)
    {
        // Read the ADC Channel
        adc_sync_read_channel(&ADC_BATTERY, 0, batt_readings[x].c, 2);
        delay_us(20);
    }
    
    // Counter for the Sum
    uint32_t sum = 0;
    
    // Loop through and Average the Readings
    for (x = 0; x < BATTERY_READINGS_COUNT; x++)
    {
        // Add the Sum
        sum += batt_readings[x].i;
    }
    
    // Calculate the Mean Reading
    batt_voltage = (sum / (float)BATTERY_READINGS_COUNT) * 0.8;
    
    // Set the Battery Level
    battery_level.i = (uint16_t)batt_voltage;
    
    // Switch off the Control Pin
    gpio_set_pin_level(ADC_CONTROL, 0);
}

The code works and gives me a very accurate reading for battery voltage - I've tried it with a pretty accurate power source and multiple voltages and the reading is good every time. When I switch the reference voltage to 5V, it's no longer accurate, unless I remove the * 0.8 multiplier.

I'm still wrapping my head around how ADCs work, and I was wondering if someone could explain what's going on here.

Why does a multipler of 0.8 work for a 3.3V input and a multiplier of 1 work for 5V?

Source Link

This ADC code works, but I don't understand why?

I have the following code for reading a battery voltage on the ADC on a microcontroller (Atmel SAM D21 to be precise). The reference voltage is 3.3v and the ADC is reading at 12 bit resolution:

/**
 * Union for Readings
 *
 */
typedef union u_reading {
    int16_t i;
    uint8_t c[2];
} reading;

/**
 * Read the main battery voltage.
 *
 */
static void read_battery_level()
{
    // Switch on the Control Pin
    gpio_set_pin_level(ADC_CONTROL, 1);
    
    // Battery Voltage
    float batt_voltage = 0.0f;
    
    // Array of Samples
    reading batt_readings[BATTERY_READINGS_COUNT];
    int x;
    
    // Loop through ad Average the Readings
    for (x = 0; x < BATTERY_READINGS_COUNT; x++)
    {
        // Read the ADC Channel
        adc_sync_read_channel(&ADC_BATTERY, 0, batt_readings[x].c, 2);
        delay_us(20);
    }
    
    // Counter for the Sum
    uint32_t sum = 0;
    
    // Loop through and Average the Readings
    for (x = 0; x < BATTERY_READINGS_COUNT; x++)
    {
        // Add the Sum
        sum += batt_readings[x].i;
    }
    
    // Calculate the Mean Reading
    batt_voltage = (sum / (float)BATTERY_READINGS_COUNT) * 0.8;
    
    // Set the Battery Level
    battery_level.i = (uint16_t)batt_voltage;
    
    // Switch off the Control Pin
    gpio_set_pin_level(ADC_CONTROL, 0);
}

The code works and gives me a very accurate reading for battery voltage - I've tried it with a pretty accurate power source and multiple voltages and the reading is good every time. When I switch the reference voltage to 5v, it's no longer accurate, unless I remove the * 0.8 multiplier.

I'm still wrapping my head around how ADCs work, and I was wondering if someone could explain what's going on here? Why does a multipler of 0.8 work for a 3.3v input and a multiplier of 1 work for 5v?

Thanks in advance!