Skip to content
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

Reinstatement of voltage monitor #145

Open
Julia7676 opened this issue Jan 23, 2023 · 3 comments
Open

Reinstatement of voltage monitor #145

Julia7676 opened this issue Jan 23, 2023 · 3 comments

Comments

@Julia7676
Copy link

I am attracted to the range of Enviro boards by there ability to operate for months unattended using AA cells. in addition to reliability (see issue #119) battery monitoring is essential for my application. I have been considering a HW workaround consisting of a pair of external resistor feeding VSYS /3 to ADC(2). A far better solution would be to get the PICO W voltage monitor working on ADC(3) as intended.

This is notoriously difficult and may require changes to the micropython firmware outside of the scope of the enviro software. The difficulties arise because the RP2040 pin used for the voltage monitor is shared with the WiFi chip.

The following code from 0.0.8 show the code that needed to be removed to improve stability.

# all the other imports, so many shiny modules
import machine, sys, os, json
from machine import RTC, ADC
import phew
from pcf85063a import PCF85063A
import enviro.helpers as helpers


# all the other imports, so many shiny modules
import machine, sys, os, json
from machine import RTC, ADC
import phew
from pcf85063a import PCF85063A
import enviro.helpers as helpers

# read battery voltage - we have to toggle the wifi chip select
# pin to take the reading - this is probably not ideal but doesn't
# seem to cause issues. there is no obvious way to shut down the
# wifi for a while properly to do this (wlan.disonnect() and
# wlan.active(False) both seem to mess things up big style..)
old_state = Pin(WIFI_CS_PIN).value()
Pin(WIFI_CS_PIN, Pin.OUT, value=True)
sample_count = 50
battery_voltage = 0
for i in range(0, sample_count):
  battery_voltage += (ADC(29).read_u16() * 3.3 / 65535) * 3
battery_voltage /= sample_count
battery_voltage = round(battery_voltage, 3)
Pin(WIFI_CS_PIN).value(old_state)

# set up the button, external trigger, and rtc alarm pins
rtc_alarm_pin = Pin(RTC_ALARM_PIN, Pin.IN, Pin.PULL_DOWN)
external_trigger_pin = Pin(EXTERNAL_INTERRUPT_PIN, Pin.IN, Pin.PULL_DOWN)

There is nothing wrong with the code that reads the voltage except that 50 reads is a bit excessive. The problem is how it interacts with WiFi.

  1. The code should not touch the WIFI_CS_PIN. If WIFI_CS_PIN is ever False during a ADC read it is a indication that WiFi is active. We must ensure that WiFI is inactive (easier said than done).

  2. The digital drivers connected to GPIO29 need to be completely disabled. (see dection 2.19.4. Pads of the RP2040 datasheet).

  3. Extreme measures needed to be implement to endure that WiFi is off. It appears to be active whilst using Thonny even before import network.

The following code is showing promise but given the nature of past issues needs further testing.

WIFI_CLK_ADC_PIN              = 29  # add to constants 

import network
wlan=network.WLAN()
wlan.disconnect()
wlan.active(False)
wlan.deinit()

def setPadCtr(gpio, value):
    mem32[0x4001c000 | (4 + (4 * gpio))] = value

def getPadCtr(gpio):
    return mem32[0x4001c000 | (4 + (4 * gpio))]

padCtrSave = getPadCtr(WIFI_CLK_ADC_PIN)
setPadCtr(WIFI_CLK_ADC_PIN, 0x80)

sample_count = 4
battery_voltage = 0
for i in range(0, sample_count):
    battery_voltage += (ADC(WIFI_CLK_ADC_PIN).read_u16() * 3.3 / 65535) * 3
battery_voltage /= sample_count
battery_voltage = round(battery_voltage, 3)

setPadCtr(WIFI_CLK_ADC_PIN,padCtrSave)
@ZodiusInfuser
Copy link
Member

Good luck with this! Not to put a downer on it already, but that second set of code looks similar to some that I tried months back from either reddit or the pi forum, which sadly still caused issues.

I hope you can get somewhere with it though, as I feel like it will benefit a lot of people if you do. The Micropython system solution I talked about in the other thread, though it would work, is only really applicable to Enviro (and our other RTC equipped Pico W Aboard products), and only gives you that single reading at bootup.

@Gadgetoid
Copy link
Member

Related - raspberrypi/pico-examples#331

I'm not above rolling a C module for us to accomplish this, while we wait for an official solution.

@Julia7676
Copy link
Author

It has been a while since I visited this topic.

IMPORTANT: I found that after switching the battery voltage to the ADC pin it is necessary to allow time for the voltage to settle. I used a delay of 1 ms and have not investigated whether a shorter delay would suffice.

The following code has been successfully working on my enviro for some time:-


def setPadCtr(gpio, value):
    mem32[0x4001c000 | (4 + (4 * gpio))] = value

def getPadCtr(gpio):
    return mem32[0x4001c000 | (4 + (4 * gpio))]

padCtrSave = getPadCtr(WIFI_CLK_ADC_PIN)
setPadCtr(WIFI_CLK_ADC_PIN, 0x80)
time.sleep_us(1000)  ## alow voltage to settle after reconnect
sample_count = 4
battery_voltage = 0
for i in range(0, sample_count):
    battery_voltage += (ADC(WIFI_CLK_ADC_PIN).read_u16() * 3.3 / 65535) * 3
battery_voltage /= sample_count
battery_voltage = round(battery_voltage, 3)
setPadCtr(WIFI_CLK_ADC_PIN,padCtrSave)

I now understand that whilst PYTHON runs there are other higher priority tasks that can unexpectedly interrupt the python script. Since there is no way from PYTHON to 'disable interrupts' great care is needed to ensure that WIFI and anything this else that may affect the WIFI_CLK_ADC_PIN pin is dormant. Presumably a C module would be able to prevent interruption by other processes however I beleive my suggested code adequately prevent interuption by the wifi.

I mention the following since not working with Thonny was one of the original reasons for removal.
I have found, in general, that activity from Thonny can cause unexpected hiccups in my python scripts. To avoid this when debugging using Thonny I always execute my application by using a soft reset.

from machine import reset
reset()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants