Skip to content

Commit

Permalink
ARMmbed#62 Take ADC measurements for VIN and battery
Browse files Browse the repository at this point in the history
  • Loading branch information
gerargz authored and gaborcsapo committed Jun 29, 2022
1 parent cf43537 commit 4239434
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 23 deletions.
8 changes: 5 additions & 3 deletions source/board/microbitv2/microbitv2.c
Original file line number Diff line number Diff line change
Expand Up @@ -638,9 +638,11 @@ static void i2c_write_comms_callback(uint8_t* pData, uint8_t size) {
memcpy(&i2cResponse.cmdData.readRspCmd.data, &power_source, sizeof(power_source));
break;
case gPowerConsumption_c: {
uint32_t power_consumption = 1;
i2cResponse.cmdData.readRspCmd.dataSize = sizeof(power_consumption);
memcpy(&i2cResponse.cmdData.readRspCmd.data, &power_consumption, sizeof(power_consumption));
uint32_t vin_voltage_uv = pwr_mon_get_vin_mv() * 1000;
uint32_t vbat_voltage_uv = pwr_mon_get_vbat_mv() * 1000;
i2cResponse.cmdData.readRspCmd.dataSize = sizeof(vin_voltage_uv) + sizeof(vbat_voltage_uv);
memcpy(&i2cResponse.cmdData.readRspCmd.data[0], &vbat_voltage_uv, sizeof(vbat_voltage_uv));
memcpy(&i2cResponse.cmdData.readRspCmd.data[sizeof(vbat_voltage_uv)], &vin_voltage_uv, sizeof(vin_voltage_uv));
}
break;
case gUSBEnumerationState_c:
Expand Down
47 changes: 28 additions & 19 deletions source/board/microbitv2/pwr_mon.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
#define BATT_MIN_VOLTAGE 1500

void pwr_mon_bandgap_init(void);
uint32_t pwr_mon_read_vbg(uint32_t channelGroup);
uint32_t pwr_mon_adc_to_mv(uint32_t raw_adc);
static uint32_t pwr_mon_read_vbg(uint32_t channelGroup);
static uint32_t pwr_mon_adc_to_mv(uint32_t raw_adc);

void pwr_mon_init(void)
{
Expand All @@ -40,21 +40,14 @@ void pwr_mon_init(void)
power_source_t pwr_mon_get_power_source(void) {
power_source_t power_source = PWR_SOURCE_NONE;
uint32_t bat_voltage_mv = 0;
// Detect if device is battery powered
GPIO_PinWrite(PIN_RUN_VBAT_SENSE_GPIO, PIN_RUN_VBAT_SENSE_BIT, 1);
// Add a ~3ms delay to allow the 100nF capacitors to charge to about 3*RC.
// 3 clock cycles per loop at -O2 ARMCC optimization
for (uint32_t count = 48000; count > 0UL; count--);
uint32_t bat_adc = adc_read_channel(0, PIN_VMON_BAT_ADC_CH, PIN_VMON_BAT_ADC_MUX);
GPIO_PinWrite(PIN_RUN_VBAT_SENSE_GPIO, PIN_RUN_VBAT_SENSE_BIT, 0);


// Read WAKE_ON_EDGE pin for detecting if board is USB powered
bool usb_on = (((PIN_WAKE_ON_EDGE_GPIO->PDIR) >> PIN_WAKE_ON_EDGE_BIT) & 0x01U) ? false : true;

// Compensate for voltage divider with ratio of 11
bat_adc = bat_adc * 11;

bat_voltage_mv = pwr_mon_adc_to_mv(bat_adc);
// Read battery voltage
bat_voltage_mv = pwr_mon_get_vbat_mv();

// Get power source based on battery and USB
if (usb_on == true && bat_voltage_mv < (BATT_MIN_VOLTAGE)) {
power_source = PWR_USB_ONLY;
} else if (usb_on == true && bat_voltage_mv >= (BATT_MIN_VOLTAGE)) {
Expand All @@ -68,23 +61,39 @@ power_source_t pwr_mon_get_power_source(void) {
return power_source;
}

uint32_t pwr_mon_vcc_mv(void) {
// ADC read the Vref (same as Vcc) and the Vbg 1V internal reference
uint32_t pwr_mon_get_vbat_mv(void) {
// Enable voltage divider to take measurement
GPIO_PinWrite(PIN_RUN_VBAT_SENSE_GPIO, PIN_RUN_VBAT_SENSE_BIT, 1);
// Add a ~3ms delay to allow the 100nF capacitors to charge to about 3*RC.
// 3 clock cycles per loop at -O2 ARMCC optimization
for (uint32_t count = 48000; count > 0UL; count--);
uint32_t bat_adc = adc_read_channel(0, PIN_VMON_BAT_ADC_CH, PIN_VMON_BAT_ADC_MUX);
// Disable voltage divider
GPIO_PinWrite(PIN_RUN_VBAT_SENSE_GPIO, PIN_RUN_VBAT_SENSE_BIT, 0);

// Compensate for voltage divider with ratio of 11
bat_adc = bat_adc * 11;

return pwr_mon_adc_to_mv(bat_adc);
}

uint32_t pwr_mon_get_vin_mv(void) {
// ADC read the Vref (same as Vdda) and the Vbg 1V internal reference
uint32_t vref_high = adc_read_channel(0, ADC_VREFH_CHANNEL, ADC_VREFH_MUX);
uint32_t ref_volt = pwr_mon_read_vbg(0);

// Reference voltage is 1V, scale to millivolts
return vref_high * 1000 / ref_volt;
}

void pwr_mon_bandgap_init(void) {
static void pwr_mon_bandgap_init(void) {
pmc_bandgap_buffer_config_t pmcBandgapConfig;
pmcBandgapConfig.enable = true;
pmcBandgapConfig.enableInLowPowerMode = false;
PMC_ConfigureBandgapBuffer(PMC, &pmcBandgapConfig);
}

uint32_t pwr_mon_read_vbg(uint32_t channelGroup) {
static uint32_t pwr_mon_read_vbg(uint32_t channelGroup) {
// Ensure the Vbg is enabled from first use only
static bool bandgap_enabled = false;
if (!bandgap_enabled) {
Expand All @@ -94,7 +103,7 @@ uint32_t pwr_mon_read_vbg(uint32_t channelGroup) {
return adc_read_channel(channelGroup, ADC_VBG_CHANNEL, ADC_VBG_MUX);
}

uint32_t pwr_mon_adc_to_mv(uint32_t raw_adc)
static uint32_t pwr_mon_adc_to_mv(uint32_t raw_adc)
{
// ADC read Vbg, a 1V internal reference
uint32_t ref_volt_read = pwr_mon_read_vbg(0);
Expand Down
3 changes: 2 additions & 1 deletion source/board/microbitv2/pwr_mon.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ typedef enum {

void pwr_mon_init(void);
power_source_t pwr_mon_get_power_source(void);
uint32_t pwr_mon_vcc_mv(void);
uint32_t pwr_mon_get_vin_mv(void);
uint32_t pwr_mon_get_vbat_mv(void);


#ifdef __cplusplus
Expand Down

0 comments on commit 4239434

Please sign in to comment.