-
Notifications
You must be signed in to change notification settings - Fork 971
Add an example to read VBUS and VSYS #331
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
d534ada
27c3b5a
731cea2
c834ce4
fcb4de4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| add_library(power_status_adc INTERFACE) | ||
| target_sources(power_status_adc INTERFACE | ||
| ${CMAKE_CURRENT_LIST_DIR}/power_status.c | ||
| ) | ||
| target_include_directories(power_status_adc INTERFACE | ||
| ${CMAKE_CURRENT_LIST_DIR} | ||
| ) | ||
| target_link_libraries(power_status_adc INTERFACE | ||
| hardware_adc | ||
| hardware_gpio | ||
| ) | ||
|
|
||
| add_executable(read_vsys | ||
| read_vsys.c | ||
| ) | ||
| target_include_directories(read_vsys PRIVATE | ||
| ${CMAKE_CURRENT_LIST_DIR} | ||
| ) | ||
| target_link_libraries(read_vsys | ||
| pico_stdlib | ||
| power_status_adc | ||
| ) | ||
| if (PICO_CYW43_SUPPORTED) | ||
| target_link_libraries(read_vsys | ||
| pico_cyw43_arch_none | ||
| ) | ||
| endif() | ||
|
|
||
| pico_add_extra_outputs(read_vsys) | ||
| example_auto_set_url(read_vsys) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,78 @@ | ||
| /** | ||
| * Copyright (c) 2023 Raspberry Pi (Trading) Ltd. | ||
| * | ||
| * SPDX-License-Identifier: BSD-3-Clause | ||
| */ | ||
|
|
||
| #include "stdbool.h" | ||
| #include "hardware/adc.h" | ||
| #include "power_status.h" | ||
|
|
||
| #if CYW43_USES_VSYS_PIN | ||
| #include "pico/cyw43_arch.h" | ||
| #endif | ||
|
|
||
| #ifndef PICO_POWER_SAMPLE_COUNT | ||
| #define PICO_POWER_SAMPLE_COUNT 3 | ||
| #endif | ||
|
|
||
| // Pin used for ADC 0 | ||
| #define PICO_FIRST_ADC_PIN 26 | ||
|
|
||
| int power_source(bool *battery_powered) { | ||
| #if defined CYW43_WL_GPIO_VBUS_PIN | ||
| *battery_powered = !cyw43_arch_gpio_get(CYW43_WL_GPIO_VBUS_PIN); | ||
| return PICO_OK; | ||
| #elif defined PICO_VBUS_GPIO_PIN | ||
| gpio_set_function(PICO_VBUS_GPIO_PIN, GPIO_FUNC_SIO); | ||
| *battery_powered = !gpio_get(PICO_VBUS_GPIO_PIN); | ||
| return PICO_OK; | ||
| #else | ||
| return PICO_ERROR_NO_DATA; | ||
| #endif | ||
| } | ||
|
|
||
| int power_voltage(float *voltage_result) { | ||
| #ifndef PICO_VSYS_PIN | ||
| return PICO_ERROR_NO_DATA; | ||
| #endif | ||
| #if CYW43_USES_VSYS_PIN | ||
| cyw43_thread_enter(); | ||
| // Make sure cyw43 is awake | ||
| cyw43_arch_gpio_get(CYW43_WL_GPIO_VBUS_PIN); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Would that not cause conflicts and or release our lock too soon?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are you seeing an issue? You can nest calls to enter and exit so I wouldn't expect this to be a problem. |
||
| #endif | ||
|
|
||
| // setup adc | ||
| adc_gpio_init(PICO_VSYS_PIN); | ||
| adc_select_input(PICO_VSYS_PIN - PICO_FIRST_ADC_PIN); | ||
|
|
||
| adc_fifo_setup(true, false, 0, false, false); | ||
| adc_run(true); | ||
|
|
||
| #if CYW43_USES_VSYS_PIN | ||
| // We seem to read low values from cyw43 sometimes - this seems to fix it | ||
| int ignore_count = PICO_POWER_SAMPLE_COUNT; | ||
| while (!adc_fifo_is_empty() || ignore_count-- > 0) { | ||
| (void)adc_fifo_get_blocking(); | ||
| } | ||
| #endif | ||
|
|
||
| // read vsys | ||
| uint32_t vsys = 0; | ||
| for(int i = 0; i < PICO_POWER_SAMPLE_COUNT; i++) { | ||
| uint16_t val = adc_fifo_get_blocking(); | ||
| vsys += val; | ||
| } | ||
|
|
||
| adc_run(false); | ||
| adc_fifo_drain(); | ||
|
|
||
| vsys /= PICO_POWER_SAMPLE_COUNT; | ||
| #if CYW43_USES_VSYS_PIN | ||
| cyw43_thread_exit(); | ||
| #endif | ||
| // Generate voltage | ||
| const float conversion_factor = 3.3f / (1 << 12); | ||
| *voltage_result = vsys * 3 * conversion_factor; | ||
| return PICO_OK; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| /** | ||
| * Copyright (c) 2023 Raspberry Pi (Trading) Ltd. | ||
| * | ||
| * SPDX-License-Identifier: BSD-3-Clause | ||
| */ | ||
|
|
||
| #ifndef POWER_STATUS_H | ||
| #define POWER_STATUS_H | ||
|
|
||
| /*! | ||
| * \brief Get power source | ||
| * | ||
| * Returns whether battery powered | ||
| * \note On Pico W must have called cyw43_arch_init | ||
| * | ||
| * \param battery_powered True if powered by battery, False if powered by USB or another means | ||
| * \return Zero if the battery status can be determined, an error code otherwise \see pico_error_codes | ||
| */ | ||
|
|
||
| int power_source(bool *battery_powered); | ||
|
|
||
| /*! | ||
| * \brief Get system voltage | ||
| * | ||
| * Returns the system voltage | ||
| * \note Must have called adc_init | ||
| * | ||
| * \param voltage Calculated voltage | ||
| * \return Zero if the voltage can be determined, an error code otherwise \see pico_error_codes | ||
| */ | ||
| int power_voltage(float *voltage); | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| /** | ||
| * Copyright (c) 2022 Raspberry Pi (Trading) Ltd. | ||
| * | ||
| * SPDX-License-Identifier: BSD-3-Clause | ||
| */ | ||
|
|
||
| #include <stdio.h> | ||
| #include <pico/stdlib.h> | ||
| #include <power_status.h> | ||
| #include "hardware/adc.h" | ||
| #include "pico/float.h" | ||
|
|
||
| #if CYW43_USES_VSYS_PIN | ||
| #include "pico/cyw43_arch.h" | ||
| #endif | ||
|
|
||
| int main() { | ||
| stdio_init_all(); | ||
|
|
||
| adc_init(); | ||
| adc_set_temp_sensor_enabled(true); | ||
|
|
||
| // Pico W uses a CYW43 pin to get VBUS so we need to initialise it | ||
| #if CYW43_USES_VSYS_PIN | ||
| if (cyw43_arch_init()) { | ||
| printf("failed to initialise\n"); | ||
| return 1; | ||
| } | ||
| #endif | ||
|
|
||
| bool old_battery_status; | ||
| float old_voltage; | ||
| bool battery_status = true; | ||
| char *power_str = "UNKNOWN"; | ||
|
|
||
| while(true) { | ||
| // Get battery status | ||
| if (power_source(&battery_status) == PICO_OK) { | ||
| power_str = battery_status ? "BATTERY" : "POWERED"; | ||
| } | ||
|
|
||
| // Get voltage | ||
| float voltage = 0; | ||
| int voltage_return = power_voltage(&voltage); | ||
| voltage = floorf(voltage * 100) / 100; | ||
|
|
||
| // Display power if it's changed | ||
| if (old_battery_status != battery_status || old_voltage != voltage) { | ||
| char percent_buf[10] = {0}; | ||
| if (battery_status && voltage_return == PICO_OK) { | ||
| const float min_battery_volts = 3.0f; | ||
| const float max_battery_volts = 4.2f; | ||
| int percent_val = ((voltage - min_battery_volts) / (max_battery_volts - min_battery_volts)) * 100; | ||
| snprintf(percent_buf, sizeof(percent_buf), " (%d%%)", percent_val); | ||
| } | ||
|
|
||
| // Also get the temperature | ||
| adc_select_input(4); | ||
| const float conversionFactor = 3.3f / (1 << 12); | ||
| float adc = (float)adc_read() * conversionFactor; | ||
| float tempC = 27.0f - (adc - 0.706f) / 0.001721f; | ||
|
|
||
| // Display power and remember old vales | ||
| printf("Power %s, %.2fV%s, temp %.1f DegC\n", power_str, voltage, percent_buf, tempC); | ||
| old_battery_status = battery_status; | ||
| old_voltage = voltage; | ||
| } | ||
| sleep_ms(1000); | ||
| } | ||
|
|
||
| #if CYW43_USES_VSYS_PIN | ||
| cyw43_arch_deinit(); | ||
| #endif | ||
| return 0; | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.