Skip to content

Commit c12333f

Browse files
committed
Add an example to read VBUS and VSYS
The process is different on Pico and Pico W so demonstrate how to do it. Fixes #324
1 parent 42ffd51 commit c12333f

File tree

5 files changed

+174
-0
lines changed

5 files changed

+174
-0
lines changed

adc/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ if (NOT PICO_NO_HARDWARE)
55
add_subdirectory(joystick_display)
66
add_subdirectory(onboard_temperature)
77
add_subdirectory(microphone_adc)
8+
add_subdirectory(read_vsys)
89
endif ()

adc/read_vsys/CMakeLists.txt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
add_library(power_status_adc INTERFACE)
2+
target_sources(power_status_adc INTERFACE
3+
${CMAKE_CURRENT_LIST_DIR}/power_status.c
4+
)
5+
target_include_directories(power_status_adc INTERFACE
6+
${CMAKE_CURRENT_LIST_DIR}
7+
)
8+
target_link_libraries(power_status_adc INTERFACE
9+
hardware_adc
10+
hardware_gpio
11+
)
12+
13+
add_executable(read_vsys
14+
read_vsys.c
15+
)
16+
target_include_directories(read_vsys PRIVATE
17+
${CMAKE_CURRENT_LIST_DIR}
18+
)
19+
target_link_libraries(read_vsys
20+
pico_stdlib
21+
power_status_adc
22+
)
23+
if (PICO_CYW43_SUPPORTED)
24+
target_link_libraries(read_vsys
25+
pico_cyw43_arch_none
26+
)
27+
endif()
28+
29+
pico_add_extra_outputs(read_vsys)
30+
example_auto_set_url(read_vsys)

adc/read_vsys/power_status.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/**
2+
* Copyright (c) 2023 Raspberry Pi (Trading) Ltd.
3+
*
4+
* SPDX-License-Identifier: BSD-3-Clause
5+
*/
6+
7+
#include "stdbool.h"
8+
#include "hardware/adc.h"
9+
#include "power_status.h"
10+
11+
#if CYW43_USES_VSYS_GPIO_PIN
12+
#include "pico/cyw43_arch.h"
13+
#endif
14+
15+
// Get power status
16+
// Must have called adc_init
17+
// On Pico W must also have called cyw43_arch_init
18+
void power_status(bool *mains_powered, float *voltage_result) {
19+
#if defined CYW43_WL_GPIO_VBUS_PIN
20+
*mains_powered = cyw43_arch_gpio_get(CYW43_WL_GPIO_VBUS_PIN);
21+
#elif defined PICO_VBUS_GPIO_PIN
22+
gpio_set_function(PICO_VBUS_GPIO_PIN, GPIO_FUNC_SIO);
23+
*mains_powered = gpio_get(PICO_VBUS_GPIO_PIN);
24+
#else
25+
#error No vbus pin defined
26+
#endif
27+
28+
#if CYW43_USES_VSYS_GPIO_PIN
29+
cyw43_thread_enter();
30+
#endif
31+
32+
adc_gpio_init(PICO_VSYS_GPIO_PIN);
33+
adc_select_input(PICO_VSYS_ADC_NUM);
34+
35+
uint16_t vsys = 0;
36+
const int sample_count = 3;
37+
for(int i = 0; i < sample_count; i++) {
38+
vsys += adc_read();
39+
}
40+
vsys /= sample_count;
41+
42+
#if CYW43_USES_VSYS_GPIO_PIN
43+
cyw43_thread_exit();
44+
#endif
45+
46+
const float conversion_factor = 3.3f / (1 << 12);
47+
*voltage_result = vsys * 3 * conversion_factor;
48+
}

adc/read_vsys/power_status.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/**
2+
* Copyright (c) 2023 Raspberry Pi (Trading) Ltd.
3+
*
4+
* SPDX-License-Identifier: BSD-3-Clause
5+
*/
6+
7+
#ifndef POWER_STATUS_H
8+
#define POWER_STATUS_H
9+
10+
/*!
11+
* \brief Get power status
12+
*
13+
* Returns whether mains or battery powered and the mains or battery voltage
14+
* \note Must have called adc_init and on Pico W must also have called cyw43_arch_init
15+
*
16+
* \param mains_powered True if powered, False if running off a battery
17+
* \param voltage Calculated voltage
18+
*/
19+
void power_status(bool *mains_powered, float *voltage);
20+
21+
#endif

adc/read_vsys/read_vsys.c

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/**
2+
* Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
3+
*
4+
* SPDX-License-Identifier: BSD-3-Clause
5+
*/
6+
7+
#include <stdio.h>
8+
#include <pico/stdlib.h>
9+
#include <power_status.h>
10+
#include "hardware/adc.h"
11+
#include "pico/float.h"
12+
13+
#if CYW43_USES_VSYS_GPIO_PIN
14+
#include "pico/cyw43_arch.h"
15+
#endif
16+
17+
int main() {
18+
stdio_init_all();
19+
20+
adc_init();
21+
adc_set_temp_sensor_enabled(true);
22+
23+
// Pico W uses a CYW43 pin to get VBUS so we need to initialise it
24+
#if CYW43_USES_VSYS_GPIO_PIN
25+
if (cyw43_arch_init()) {
26+
printf("failed to initialise\n");
27+
return 1;
28+
}
29+
#endif
30+
31+
bool old_mains_power;
32+
float old_voltage;
33+
34+
while(true) {
35+
36+
const float min_battery_volts = 3.0f;
37+
const float max_battery_volts = 4.2f;
38+
39+
// Get power status
40+
bool mains_power;
41+
float voltage;
42+
power_status(&mains_power, &voltage);
43+
voltage = floorf(voltage * 100) / 100;
44+
45+
// Display power if it's changed
46+
if (old_mains_power != mains_power || old_voltage != voltage) {
47+
const char *power_str = mains_power ? "MAINS" : "BATTERY";
48+
char percent_buf[10];
49+
if (mains_power) {
50+
percent_buf[0] = 0;
51+
} else {
52+
int percent_val = ((voltage - min_battery_volts) / (max_battery_volts - min_battery_volts)) * 100;
53+
snprintf(percent_buf, sizeof(percent_buf), " (%d%%)", percent_val);
54+
}
55+
56+
// Also get the temperature
57+
adc_select_input(4);
58+
const float conversionFactor = 3.3f / (1 << 12);
59+
float adc = (float)adc_read() * conversionFactor;
60+
float tempC = 27.0f - (adc - 0.706f) / 0.001721f;
61+
62+
// Display power and remember old vales
63+
printf("Power %s, %.2fV%s, temp %.1f DegC\n", power_str, voltage, percent_buf, tempC);
64+
old_mains_power = mains_power;
65+
old_voltage = voltage;
66+
}
67+
sleep_ms(3000);
68+
}
69+
70+
#if CYW43_USES_VSYS_GPIO_PIN
71+
cyw43_arch_deinit();
72+
#endif
73+
return 0;
74+
}

0 commit comments

Comments
 (0)