Values wont update

RP2040 based microcontroller boards running MicroPython.
Target audience: MicroPython users with an RP2040 boards.
This does not include conventional Linux-based Raspberry Pi boards.
Post Reply
soggycashew
Posts: 55
Joined: Sat Sep 18, 2021 10:21 pm

Values wont update

Post by soggycashew » Sat Mar 19, 2022 3:18 pm

Hello, I have a 4 plant moisture and humidity meter on a Pico and everything runs fine when the btn_show_display is pressed BUT my values never update on the oled (Unless I stop the program and rerun). What it does when I press the button it displays temp and humidity then shows each plants capacitive soil sensors moisture percent based off the Wet/Dry Baseline Readings in the code and loops twice and shuts off oled until I press the button again and it loops again displaying the values.

What in the code do I need to change to update the values on the fly OR when the button is pressed? Please give me an example I'm new to this... Thanks!

Attached is the .py in a .zip
Moisture_And_OLED.zip
(1.56 KiB) Downloaded 79 times

Code: Select all

import machine, time, uasyncio
from primitives.pushbutton import Pushbutton
from machine import I2C
from ads1x15 import ADS1115
from sh1106 import SH1106_I2C
from dht22 import DHT22

# ------------------------------------------------------------------------
# Define/Initialize GPIO Pins

i2c2 = I2C(0, sda=machine.Pin(0), scl=machine.Pin(1), freq=400000)
dht22 = DHT22(machine.Pin(2,machine.Pin.IN,machine.Pin.PULL_UP))
btn_show_display = machine.Pin(3, machine.Pin.IN, machine.Pin.PULL_DOWN)
led = machine.Pin(25, machine.Pin.OUT)

# ------------------------------------------------------------------------
#  Define Functions

# Calculate the percentage between the wet/dry values
def percentage_value(value, in_min, out_max, out_min):
        percentage_value = (value - in_min) / (out_max - out_min) * 100
        return (str(round(percentage_value))) + "%"

# Scroll in OLED screen vertically
def scroll_in_screen_v(screen):
  for i in range (0, (oled_height+1), 1):
    for line in screen:
      oled.text(line[2], line[0], -oled_height+i+line[1])
    oled.show()
    if i!= oled_height:
      oled.fill(0)

# Scroll out OLED screen vertically
def scroll_out_screen_v(speed):
  for i in range ((oled_height+1)/speed):
    for j in range (oled_width):
      oled.pixel(j, i, 0)
    oled.scroll(0,speed)
    oled.show()
 
# ------------------------------------------------------------------------
# Define Variables

wet = 11344  # Wet Baseline Reading 
dry = 22283  # Dry Baseline Reading 

# -----------------------------------ADC Converter

adc0 = ADS1115(i2c2, 0x48, 1)  # Pins, 1st ADC Address, Gain = 1

# -----------------------------------OLED Display

oled_width = 128 # Width of OLED screen
oled_height = 64 # Height of OLED screen

oled = SH1106_I2C(oled_width, oled_height, i2c2)
    
# -----------------------------------Temperature & Humidity Sensor

T, H = dht22.read() # Gets Temp & Hum from dht22.py library
temp_f = T * (9/5) + 32.0 # Converts the (T) temperature to Fahrenheit degrees

# -----------------------------------ADC Converter
  
# Analog-to-Digital ADC PGA Converter ADS1115--------------
adc0_result_A0 = percentage_value(adc0.read(0, 0), dry, wet, dry)
adc0_result_A1 = percentage_value(adc0.read(0, 1), dry, wet, dry)
adc0_result_A2 = percentage_value(adc0.read(0, 2), dry, wet, dry)
adc0_result_A3 = percentage_value(adc0.read(0, 3), dry, wet, dry)

# -----------------------------------OLED Display

    # %m.kf Converts a value of type float (or double) to m decimal positions with k digits after the period.
OLED_screen1 = [[0, 18 , "Temp: %3.0fF" %temp_f], [0, 34, "Humidity: %3.0f%%" %H]]
OLED_screen2 = [[0, 2 , "Pot 1: " + str(adc0_result_A0)],
                [0, 18, "Pot 2: " + str(adc0_result_A1)],
                [0, 34, "Pot 3: " + str(adc0_result_A2)],
                [0, 50, "Pot 4: " + str(adc0_result_A3)]]

# -----------------------------------uasyncio Coroutine

# Coroutine: blink on a timer
async def blink(delay):
    while True:
        led.toggle()
        await uasyncio.sleep(delay)

async def wake_oled():  # Runs when button pressed
    for i in range(2):
    # Scroll in, stop, scroll out (vertical)
        scroll_in_screen_v(OLED_screen1)
        await uasyncio.sleep(5) # Sleep for 5 seconds (must use async sleep)
        scroll_out_screen_v(2)

        scroll_in_screen_v(OLED_screen2)
        await uasyncio.sleep(5) # Sleep for 5 seconds
        scroll_out_screen_v(2)

# Coroutine: entry point for asyncio program
async def main():
    pb = Pushbutton(btn_show_display)  # Create pushbutton instance
    pb.press_func(wake_oled)
    
    # Start coroutine as a task and immediately return
    uasyncio.create_task(blink(0.2))
    
    while True:
        await uasyncio.sleep(1)  # You can run other code here

# Start event loop and run entry point coroutine
uasyncio.run(main())
# -----------------------------------


User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Values wont update

Post by pythoncoder » Sun Mar 20, 2022 10:35 am

I'm not sure I fully understand this. I take it that the program works as designed, updating the display each time you press the button, and you want it to update continuously. If this is what you want, the button becomes redundant - hence my confusion.

If this is what you want your main routine would look something like this:

Code: Select all

async def run():
    while True:
        await wake_oled()

async def main():
    uasyncio.create_task(run())
    # No need to launch blink and wait forever: this does the same
    await blink(0.2)
Peter Hinch
Index to my micropython libraries.

soggycashew
Posts: 55
Joined: Sat Sep 18, 2021 10:21 pm

Re: Values wont update

Post by soggycashew » Sun Mar 20, 2022 2:37 pm

Peter, the button is there so it shows the values twice and shuts off screen otherwise it would just run and run and run when not needed, It works as in that's correct but the values don't update for whatever reason and that's what I need.

What its doing is when I press the button it loops through the temp, humidity and the 4 soil sensors values and it does this twice as its supposed to BUT the values never change ever UNLESS I stop the program and restart it or unplug and plug back in and it updates the values if they had changed but again it wont update unless I stop the program and restart it or unplug it as I did before.

I hope I explained this better.... Thanks!

Peter, the only way I can get data to update without having to cut power or stop/start thonny is getting rid of the uasyncio all together and adding the while True: and moving code to below that then it works EXCEPT now I don't have it loop twice and the button is useless and I wanted it to loop twice and turn off oled.

Code: Select all

import machine, utime
from machine import I2C
from ads1x15 import ADS1115
from sh1106 import SH1106_I2C
from dht22 import DHT22

# ------------------------------------------------------------------------
# Define/Initialize GPIO Pins

i2c2 = I2C(0, sda=machine.Pin(0), scl=machine.Pin(1), freq=400000)
dht22 = DHT22(machine.Pin(2,machine.Pin.IN,machine.Pin.PULL_UP))
btn_show_display = machine.Pin(3, machine.Pin.IN, machine.Pin.PULL_DOWN)
led = machine.Pin(25, machine.Pin.OUT)

# ------------------------------------------------------------------------
#  Define Functions

# Calculate the percentage between the wet/dry values
def percentage_value(value, in_min, out_max, out_min):
        percentage_value = (value - in_min) / (out_max - out_min) * 100
        return (str(round(percentage_value)))

# Scroll in OLED screen vertically
def scroll_in_screen_v(screen):
  for i in range (0, (oled_height+1), 1):
    for line in screen:
      oled.text(line[2], line[0], -oled_height+i+line[1])
    oled.show()
    if i!= oled_height:
      oled.fill(0)

# Scroll out OLED screen vertically
def scroll_out_screen_v(speed):
  for i in range ((oled_height+1)/speed):
    for j in range (oled_width):
      oled.pixel(j, i, 0)
    oled.scroll(0,speed)
    oled.show()
 
# ------------------------------------------------------------------------
# Define Variables

wet = 11344  # Wet Baseline Reading 
dry = 22486  # Dry Baseline Reading 

# -----------------------------------ADC Converter

adc0 = ADS1115(i2c2, 0x48, 1)  # Pins, 1st ADC Address, Gain = 1

# -----------------------------------OLED Display

oled_width = 128 # Width of OLED screen
oled_height = 64 # Height of OLED screen

oled = SH1106_I2C(oled_width, oled_height, i2c2)

while True:
    
    # -----------------------------------Temperature & Humidity Sensor

    T, H = dht22.read() # Gets Temp & Hum from dht22.py library
    temp_f = T * (9/5) + 32.0 # Converts the (T) temperature to Fahrenheit degrees
 
    # -----------------------------------ADC Converter
  
    # Analog-to-Digital ADC PGA Converter ADS1115--------------
    adc0_result_A0 = percentage_value(adc0.read(0, 0), dry, wet, dry)
    adc0_result_A1 = percentage_value(adc0.read(0, 1), dry, wet, dry)
    adc0_result_A2 = percentage_value(adc0.read(0, 2), dry, wet, dry)
    adc0_result_A3 = percentage_value(adc0.read(0, 3), dry, wet, dry)
    
    # -----------------------------------OLED Display

    # %m.kf Converts a value of type float (or double) to m decimal positions with k digits after the period.
    OLED_screen1 = [[0, 18 , "Temp: %3.0fF" %temp_f], [0, 34, "Humidity: %3.0f%%" %H]]
    OLED_screen2 = [[0, 2 , "Pot 1: " + str(adc0_result_A0) + "%"],
                    [0, 18, "Pot 2: " + str(adc0_result_A1) + "%"],
                    [0, 34, "Pot 3: " + str(adc0_result_A2) + "%"],
                    [0, 50, "Pot 4: " + str(adc0_result_A3) + "%"]]
    
 
    # Scroll in, stop, scroll out (vertical)
    scroll_in_screen_v(OLED_screen1)
    utime.sleep(5)
    scroll_out_screen_v(2)

    scroll_in_screen_v(OLED_screen2)
    utime.sleep(5)
    scroll_out_screen_v(2)






User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Values wont update

Post by pythoncoder » Mon Mar 21, 2022 8:57 am

OK, now I've got it. The reason is simple. In your original uasyncio code you read the values once only, for example

Code: Select all

adc0_result_A0 = percentage_value(adc0.read(0, 0), dry, wet, dry)
adc0_result_A1 = percentage_value(adc0.read(0, 1), dry, wet, dry)
adc0_result_A2 = percentage_value(adc0.read(0, 2), dry, wet, dry)
adc0_result_A3 = percentage_value(adc0.read(0, 3), dry, wet, dry)
If you want these values to update, this must be done in a function or a coroutine. For example:

Code: Select all

async def main():
    global T, H, temp_f, adc0_result_A0, adc0_result_A1, adc0_result_A2, adc0_result_A3
    pb = Pushbutton(btn_show_display)  # Create pushbutton instance
    pb.press_func(wake_oled)
    # Start coroutine as a task and immediately return
    uasyncio.create_task(blink(0.2))

    while True:
        T, H = dht22.read() # Gets Temp & Hum from dht22.py library
        temp_f = T * (9/5) + 32.0 # Converts the (T) temperature to Fahrenheit degrees

        adc0_result_A0 = percentage_value(adc0.read(0, 0), dry, wet, dry)
        adc0_result_A1 = percentage_value(adc0.read(0, 1), dry, wet, dry)
        adc0_result_A2 = percentage_value(adc0.read(0, 2), dry, wet, dry)
        adc0_result_A3 = percentage_value(adc0.read(0, 3), dry, wet, dry)
        await asyncio.sleep(5)
This should fix the problem, but it's ugly code with lots of needless globals. It would be much nicer to implement the same logic with a class, using bound variables instead of the globals.

Rather than continuously reading as above, an alternative would be to do the update as a synchronous function called immediately prior to display.
Peter Hinch
Index to my micropython libraries.

Post Reply