uasyncio and display

Discuss development of drivers for external hardware and components, such as LCD screens, sensors, motor drivers, etc.
Target audience: Users and developers of drivers.
IHOXOHI
Posts: 119
Joined: Sat Apr 25, 2020 7:31 am

uasyncio and display

Post by IHOXOHI » Sat Jul 04, 2020 10:50 am

Hi,

I tried to use pms5003 wich give air quality data and need the uasyncio module.
I would like display data on a epaper.

I tried to add epaper code in the pms module in a simple definition (line 59) that I call in the def(print) of pms module (line 449). But after 2 rights cycles, nothing happen.

Is it possible to do it? Or usyncio means no more sensor or display? Maybe uasyncio need correct syntax, not like mine... with a new class... or maybe I could recall everything every 2 cycles wich have 60 sec of duration each one, with an other command of the run_forever command?


the code of my pms module:

Code: Select all

import uasyncio as asyncio
import time

###others datas of pms and epaper init
import epaper2in9
from pyb import SPI
#from pyb import LED
#from pyb import Switch
import pyb
#from machine import I2C, Pin
#from pycom_bme680 import *
from time import sleep
#import sgp30
#from ads1x15 import *
#import os

#sw = Switch()

#log = open('/sd/donnees/donnees.txt', 'wb')
###bmp680
#i2c=I2C(-1, Pin("X9"), Pin("X10"))
#bme=BME680_I2C(i2c)

####adc for 3 gas
#adc = ADS1115(i2c = i2c, address = 72, gain = 4)

###sgp
#sgp = sgp30.Adafruit_SGP30(i2c)

# SPI3 on Black STM32F407VET6
spi = SPI(2, SPI.MASTER, baudrate=2000000, polarity=0, phase=0)
cs = pyb.Pin('Y7')
dc = pyb.Pin('Y5')
rst = pyb.Pin('Y4')
busy = pyb.Pin('Y3')

e = epaper2in9.EPD(spi, cs, dc, rst, busy)
e.init()

w = 128
h = 296
x = 0
y = 0

import framebuf
buf = bytearray(128 * 296 // 8)
fb = framebuf.FrameBuffer(buf, 128, 296, framebuf.MONO_HLSB)
black = 0
white = 1


#global temp_affichage
#global temp_delay
#temp_delay = time.time()

def brut():
    #temp_affichage = time.time()
    #if (temp_affichage - temp_delay) >= 60:
     #   temp_delay = time.time()
    #if sw.value() == False:
        #date
    date_now = time.localtime()
    jour = date_now[2]
    mois = date_now[1]
    heure = date_now[3]
    minu = date_now[4]
    sec = date_now[5]

    jour = str(jour)
    mois = str(mois)
    heure = str(heure)
    minu = str(minu)
    sec = str(sec)
    
        #bme
 #       bmet = round(bme.temperature, 2)
  #      bmep = round(bme.pressure, 2)
   #     bmeh = round(bme.humidity - 10, 2)
            
    #    bmep = str(bmep)
     #   bmet = str(bmet)
      #  bmeh = str(bmeh)      

        #sgp
       # co2eq, tvoc = sgp.iaq_measure()

        ###recalibration
#        co2 = co2eq * 10 - 3600
 #       voc = tvoc * 8

  #      co2eq = str(co2eq)
   #     tvoc = str(tvoc)

        ###3 gas
   #     value_no2 = adc.read( rate=0, channel1=2 )
    #    value_nh3 = adc.read( rate=0, channel1=1 )
     #   value_co = adc.read( rate=0, channel1=0 )

      #  no2 =  value_no2 * (10*(0.512/32767)) 
       # nh3 = value_nh3 * (500*(0.512/32767))
    #    co = value_co * (1000*(0.512/32767))

     #   no2 = round(no2, 3)
      #  nh3 = round(nh3, 3)
   #     co = round(co, 3)
    #    no2 = str(no2)
     #   nh3 = str(nh3)
      #  co = str(co)

        #epaper
    fb.fill(white)

    fb.text(jour,5,5,black)
    fb.text("/",20,5,black)
    fb.text(mois,30,5,black)
    fb.text('--',40,5,black)
    fb.text(heure,57,5,black)
    fb.text(':',70,5,black)
    fb.text(minu,76,5,black)
    fb.text(':',90,5,black)
    fb.text(sec,95,5,black)

     #   fb.text('Temp = ',5,30,black)
      #  fb.text(bmet,55,30,black)
       # fb.text(' C',90,30,black)
        #fb.text('Pres= ',5,50,black)
#        fb.text(bmep,50,50,black)
 #       fb.text(' HPa',95,50,black)
  #      fb.text('Hum = ',5,70,black)
   #     fb.text(bmeh,55,70,black)
    #    fb.text(' %',90,70,black)
            
     #   fb.text('COV = ',5,130,black)
      #  fb.text(tvoc,55,130,black)
 #       fb.text(' ppb',80,130,black)
  #      fb.text('CO2 = ',5,150,black)
   #     fb.text(co2eq,55,150,black)
    #    fb.text(' ppm',80,150,black)
     #   fb.text('CO = ',5,170,black)
      #  fb.text(co,55,170,black)
       # fb.text(' ppm',90,170,black)
        #fb.text('NH3 = ',5,190,black)
#        fb.text(nh3,55,190,black)
 #       fb.text(' ppm',90,190,black)
  #      fb.text('NO2 = ',5,210,black)
   #     fb.text(no2,55,210,black)
    #    fb.text(' ppm',90,210,black)

    e.set_frame_memory(buf, x, y, w, h)
    e.display_frame()

#        LED(3).on()
 #       log.write('{},{},{},{},{},{},{},{},{},{},{},{}\n'.format(jour,mois,heure,minu,bmet,bmep,bmeh,tvoc,co2eq,no2,nh3,co))
  #      LED(3).off()

   # if sw.value() == True: 
    #    log.close()
     #   LED(2).on()
      #  time.sleep(10)
       # LED(2).off()

#########pms
try:
    import struct
except ImportError:
    import ustruct as struct

# Sensor settling after wakeup requires at least 30 seconds (sensor sepcifications).
WAIT_AFTER_WAKEUP = 40

# Normal data frame length.
DATA_FRAME_LENGTH = 28
# Command response frame length.
CMD_FRAME_LENGTH = 4

# Maximum tries after which the device is being reset, the actual tries are twice as much as library tries 2 times
MAX_COMMAND_FAILS = 3

DEBUG = False


def set_debug(debug):
    global DEBUG
    DEBUG = debug


class PMS5003_base:
    def __init__(self, uart, lock, set_pin=None, reset_pin=None, interval_passive_mode=None, event=None,
                 active_mode=True, eco_mode=True, assume_sleeping=True):
        self._uart = uart  # accepts a uart object
        self._set_pin = set_pin
        if set_pin is not None:
            set_pin.value(1)
        self._reset_pin = reset_pin
        if reset_pin is not None:
            reset_pin.value(1)
        self._active = True
        self._active_mode = active_mode  # passive mode will be set on first wakeUp() in _read()
        self._eco_mode = eco_mode  # only works with passive mode as sleep is not possible in active_mode
        self._sreader = asyncio.StreamReader(uart)
        self._interval_passive_mode = interval_passive_mode or 60  # in case someone forgets to set it
        if self._eco_mode and self._active_mode is False and self._interval_passive_mode < WAIT_AFTER_WAKEUP + 5:
            self._error(
                "interval_passive_mode can't be less than DEVICE_WAKEUP_TIME of {!s}s".format(WAIT_AFTER_WAKEUP + 5))
            self._interval_passive_mode = 60
        self._event = event
        self._lock = lock
        self._timestamp = None
        self._sleeping_state = assume_sleeping  # assume sleeping on start by default
        self._invalidateMeasurements()
        self._callback = None  # can be a short coroutine too; no args given
        asyncio.get_event_loop().create_task(self._read())

   [...........]

    def print(self):
        if self._active and self._timestamp is not None:
            print("")
            print("---------------------------------------------")
            t = time.localtime()
            print("Measurement {!s}ms ago at {}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}".format(
                time.ticks_ms() - self._timestamp, t[0], t[1], t[2], t[3], t[4], t[5]))
            print("---------------------------------------------")
            print("Concentration Units (standard)")
            print("---------------------------------------------")
            print("PM 1.0: %d\tPM2.5: %d\tPM10: %d" % (self._pm10_standard, self._pm25_standard, self._pm100_standard))
            print("Concentration Units (environmental)")
            print("---------------------------------------------")
            print("PM 1.0: %d\tPM2.5: %d\tPM10: %d" % (self._pm10_env, self._pm25_env, self._pm100_env))
            print("---------------------------------------------")
            print("Particles > 0.3um / 0.1L air:", self._particles_03um)
            print("Particles > 0.5um / 0.1L air:", self._particles_05um)
            print("Particles > 1.0um / 0.1L air:", self._particles_10um)
            print("Particles > 2.5um / 0.1L air:", self._particles_25um)
            print("Particles > 5.0um / 0.1L air:", self._particles_50um)
            print("Particles > 10 um / 0.1L air:", self._particles_100um)
            print("---------------------------------------------")
            print("")

            ####brut
            brut()
            time.sleep(30)
            ###

        else:
            print("PMS5003 Sensor not active")

    async def _read(self):
        woke_up = None
        if self._sleeping_state:
            await self.wakeUp()  # just in case controller rebooted and left device in sleep mode
            woke_up = time.ticks_ms()
        elif self._active_mode is False:
            await self.setPassiveMode()
        last_reading = time.ticks_ms()
        [........]
        

Thanks.
Last edited by IHOXOHI on Sat Jul 04, 2020 3:08 pm, edited 2 times in total.

kevinkk525
Posts: 969
Joined: Sat Feb 03, 2018 7:02 pm

Re: uasyncio and display

Post by kevinkk525 » Sat Jul 04, 2020 12:50 pm

I'm sorry but this is impossible to read..
1) Put code in code formatting so it is displayed correctly
2) Don't modify libraries like pms. It makes it very difficult to help you if someone doesn't know exactly how the library works. Only use the public methods of the library (like the callback or reading the values directly like pms.pm25_standard()). Then you can only post your code and not the complete pms library.
Kevin Köck
Micropython Smarthome Firmware (with Home-Assistant integration): https://github.com/kevinkk525/pysmartnode

IHOXOHI
Posts: 119
Joined: Sat Apr 25, 2020 7:31 am

Re: uasyncio and display

Post by IHOXOHI » Sat Jul 04, 2020 2:45 pm

Yes
Sorry
I have included the code in a balise code for good presentation but it dosen't happen what I was thinking...

Maybe I have to re-open a topic?
Could I destroy this?

IHOXOHI
Posts: 119
Joined: Sat Apr 25, 2020 7:31 am

Re: uasyncio and display

Post by IHOXOHI » Sat Jul 04, 2020 3:02 pm

Otherwise,

When I tried to add code in my "main" file for get other data than pms data, it doesn't works.
The line "loop.run_forever()" prevents further data collection.
It's why I tried to add code in the pms module wich call the uasyncio module... It works 2 cycles... but no more.

To simplify my aim, my code for epaper display:
"
import epaper2in9
from pyb import SPI
import pyb

# SPI3 on Black STM32F407VET6
spi = SPI(2, SPI.MASTER, baudrate=2000000, polarity=0, phase=0)
cs = pyb.Pin('Y7')
dc = pyb.Pin('Y5')
rst = pyb.Pin('Y4')
busy = pyb.Pin('Y3')

e = epaper2in9.EPD(spi, cs, dc, rst, busy)
e.init()

w = 128
h = 296
x = 0
y = 0

import framebuf
buf = bytearray(128 * 296 // 8)
fb = framebuf.FrameBuffer(buf, 128, 296, framebuf.MONO_HLSB)
black = 0
white = 1
fb.fill(white)
fb.text('pms.data',30,0,black)

e.set_frame_memory(buf, x, y, w, h)
e.display_frame()
"

Where can I add this code for display data from pms?

Thanks.

kevinkk525
Posts: 969
Joined: Sat Feb 03, 2018 7:02 pm

Re: uasyncio and display

Post by kevinkk525 » Sat Jul 04, 2020 7:02 pm

Code: Select all

import uasyncio as asyncio
uart = machine.UART(4, baudrate=9600)
pm = PMS5003(uart, lock) 
pm.registerCallback(display_values)


import epaper2in9
from pyb import SPI
import pyb

# SPI3 on Black STM32F407VET6
spi = SPI(2, SPI.MASTER, baudrate=2000000, polarity=0, phase=0)
cs = pyb.Pin('Y7')
dc = pyb.Pin('Y5')
rst = pyb.Pin('Y4')
busy = pyb.Pin('Y3')

e = epaper2in9.EPD(spi, cs, dc, rst, busy)
e.init()

w = 128
h = 296
x = 0
y = 0

import framebuf
buf = bytearray(128 * 296 // 8)
fb = framebuf.FrameBuffer(buf, 128, 296, framebuf.MONO_HLSB)
black = 0
white = 1
fb.fill(white)

def display_values():
    fb.text('PM2.5: {!s}'.format(pm.pm25_standard,30,0,black)
    e.set_frame_memory(buf, x, y, w, h)
    e.display_frame()

loop=asyncio.get_event_loop()
loop.run_forever()
This should work. Every new read should update the screen.

Alternatively you could do this, it will update every 30 seconds:

Code: Select all

import uasyncio as asyncio
uart = machine.UART(4, baudrate=9600)
pm = PMS5003(uart, lock) 


import epaper2in9
from pyb import SPI
import pyb

# SPI3 on Black STM32F407VET6
spi = SPI(2, SPI.MASTER, baudrate=2000000, polarity=0, phase=0)
cs = pyb.Pin('Y7')
dc = pyb.Pin('Y5')
rst = pyb.Pin('Y4')
busy = pyb.Pin('Y3')

e = epaper2in9.EPD(spi, cs, dc, rst, busy)
e.init()

w = 128
h = 296
x = 0
y = 0

import framebuf
buf = bytearray(128 * 296 // 8)
fb = framebuf.FrameBuffer(buf, 128, 296, framebuf.MONO_HLSB)
black = 0
white = 1
fb.fill(white)

async def display_values():
    await asyncio.sleep(50) # wait for sensor to start correctly
    while True:
        fb.text('PM2.5: {!s}'.format(pm.pm25_standard,30,0,black)
        e.set_frame_memory(buf, x, y, w, h)
        e.display_frame()
        await asyncio.sleep(30)

asyncio.run(display_values())
(General note: I have never worked with a display so the display methods might not be correct)


I would also suggest learning how to use uasyncio: https://github.com/peterhinch/micropyth ... UTORIAL.md
Kevin Köck
Micropython Smarthome Firmware (with Home-Assistant integration): https://github.com/kevinkk525/pysmartnode

IHOXOHI
Posts: 119
Joined: Sat Apr 25, 2020 7:31 am

Re: uasyncio and display

Post by IHOXOHI » Sat Jul 04, 2020 9:50 pm

Nice!

Thanks a lot again...

And I will study how to use uasyncio... and try the v3 version too. It looks a powerfull tool.

kevinkk525
Posts: 969
Joined: Sat Feb 03, 2018 7:02 pm

Re: uasyncio and display

Post by kevinkk525 » Sun Jul 05, 2020 5:22 am

uasyncio v3 would be even better, a tutorial for that can be found: https://github.com/peterhinch/micropyth ... /README.md

It is very similar to the asyncio module in Python on your computer, so most basic tutorials will work the same as on micropython.
Kevin Köck
Micropython Smarthome Firmware (with Home-Assistant integration): https://github.com/kevinkk525/pysmartnode

IHOXOHI
Posts: 119
Joined: Sat Apr 25, 2020 7:31 am

Re: uasyncio and display

Post by IHOXOHI » Sun Jul 05, 2020 7:11 am

Hi,

I have the return :
"AttributeError: 'module' object has no attribute 'run' "

I will try to replace the "loop_run_forever" command by " uasyncio.get_event_loop()" in a "while True" boucle...

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

Re: uasyncio and display

Post by pythoncoder » Sun Jul 05, 2020 7:47 am

The error suggests you're not running uasyncio V3. As stated at the start of the tutorial you need to install the latest daily build of firmware. Issue

Code: Select all

import uasyncio as asyncio
asyncio.__version__
If you get a tuple (3, 0, 0) then you're running V3. An exception means you're not.
Peter Hinch
Index to my micropython libraries.

kevinkk525
Posts: 969
Joined: Sat Feb 03, 2018 7:02 pm

Re: uasyncio and display

Post by kevinkk525 » Sun Jul 05, 2020 7:54 am

IHOXOHI wrote:
Sun Jul 05, 2020 7:11 am
Hi,

I have the return :
"AttributeError: 'module' object has no attribute 'run' "

I will try to replace the "loop_run_forever" command by " uasyncio.get_event_loop()" in a "while True" boucle...
Ah yes, sorry. the asyncio.run() works only with uasyncio version 3. For version 2 you need to use

Code: Select all

loop=asyncio.get_event_loop()
loop.run_until_complete(display_values())
Kevin Köck
Micropython Smarthome Firmware (with Home-Assistant integration): https://github.com/kevinkk525/pysmartnode

Post Reply