Replies: 42 comments 62 replies
-
In the your
or if you want to use same SPI bus for both display and touch
Default MISO for Not sure what ramifications with SD Card would be. |
Beta Was this translation helpful? Give feedback.
-
The ILI9341 is only capable of 240x320 pixels, not 240x380. |
Beta Was this translation helpful? Give feedback.
-
You would have any example of a push button through the 2.8 SPI TFT ILI9341 touch screen. I'm programming in micropython on a raspberry pi pico and I can't get this touch functionality. Thanks in advance. |
Beta Was this translation helpful? Give feedback.
-
No, I'm not sure if the screen supports TSC2007. With this configuration I have carried out the second test, without success. At first I used ili9341_xpt204y6_pico.py as hardware_setup.py, also without success. I understand that this is an SPI bus. |
Beta Was this translation helpful? Give feedback.
-
@tirejas
|
Beta Was this translation helpful? Give feedback.
-
@tirejas Please can you supply details of the exact display board that you have. It's hard to provide support without knowing what touch controller it uses and the board's pinout. |
Beta Was this translation helpful? Give feedback.
-
Thank you very much, Peter
Enviado desde Correo para Windows
De: Peter Hinch
Enviado: domingo, 21 de julio de 2024 19:31
Para: micropython/micropython
CC: tirejas; Mention
Asunto: Re: [micropython/micropython] Trouble setting up a SPI 240 x 380 V1.2TFT display (Discussion #14423)
See doc and this demo.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you were mentioned.Message ID: ***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
You will probably get some good guidance from Peter but when I read this I wondered if the following touch screen push button example I created is any use for your understanding. When confronted with the new touch screen libraries that Peter produced, to get to grips with it I like to break things down into small program snippets to test features out individually and serve as a useful reminder to me when building a proper program One such small program I did was to give myself an example of how to use the button widget with callback functions, where to place then in the code and the correct way to pass the args to the callback function. I knocked up a simple example for a rpi pico attached to an ili9341 screen. Its a very simple example that has 4 buttons, 2 of which control an LED widget placed on the screen, and the other 2 buttons control the pico's on board LED. To control the LED widget the callback function method I used was to use a class method placed in the baseScreen class. To illustrate calling 'normal' functions the buttons controlling the pico's on board LED call a function created outside of the class. Obviously for your case your functions will activate relays, valves or whatever, but the mechanism of using callbacks will be the same. Looking at my small example just now I see that for the buttons controlling the LED widget the callback args are provided as a List for one button and as a Tuple for the other. This was to remind me that either are suitable to pass the args to the callback function. So if this helps, then all well and good, but if it just confuses more then please disregard it.
|
Beta Was this translation helpful? Give feedback.
-
The button callback is defined here tbl = {"litcolor": WHITE, "height": 30, "width": 60, "callback": my_callback} calling this function def my_callback(button, arg):
print("Botón pulsado", arg) which looks fine, but there are problems:
The solution is simple. You need to do something like this: import hardware_setup # Create a display instance
from gui.core.tgui import Screen, Window, ssd, display
from gui.widgets import Label, Button,CloseButton, Pad
from gui.core.writer import CWriter
# Font for CWriter
import gui.fonts.font10 as font
from gui.core.colors import *
import machine
import utime
val_izq = machine.Pin(20, machine.Pin.OUT)
val_dch = machine.Pin(21, machine.Pin.OUT)
val_linea = machine.Pin(22, machine.Pin.OUT)
pres = 21.345
msgPSum = f' P.Sum. {pres:2.1f} bar'
msgPIzq = f'{pres:2.1f}'
msgPDch = f'{pres:2.1f}'
def cb(obj, txt):
print(f"Pad callback: text {txt}")
class BaseScreen(Screen):
def __init__(self):
def my_callback(button, arg):
print("Botón pulsado", arg)
if arg == "Izquierdo":
val_izq.on()
val_linea.on()
print("Válvula Ramal izquierdo activa")
#arg = ""
elif arg == "Derecho":
val_dch.on()
val_linea.on()
print("Válvula Ramal derecho activa")
#arg = ""
elif arg == "Parada":
val_izq.off()
val_dch.off()
val_linea.off()
print("Parada central de gases")
print(arg)
#arg = ""
else:
print("Nada")
super().__init__()
tbl = {"litcolor": WHITE, "height": 30, "width": 60, "callback": my_callback}
wri = CWriter(ssd, font, GREEN, BLACK, verbose=False)
col = 2
row = 2
Label(wri, row, col, "CENTRAL N2")
col =150
row =30
Label(wri, row, col, msgPSum)
row =50
Label(wri, row, col, "PRESION MUY ALTA", fgcolor=RED)
row =70
Label(wri, row, col, "SETA EMERGENCIA", fgcolor=RED)
col =50
row =90
Label(wri, row, col, msgPIzq)
row = 110
Label(wri, row, col, "bar")
row =130
Label(wri, row, col, "BAJA", fgcolor=RED)
col =150
row =90
Label(wri, row, col, msgPDch)
row = 110
Label(wri, row, col, "bar")
row =130
Label(wri, row, col, "BAJA", fgcolor=RED)
col =200
row =90
Label(wri, row, col, "CAMBIO DCH.", fgcolor=YELLOW)
row =110
Label(wri, row, col, "CAMBIO IZQ.", fgcolor=YELLOW)
col =170
row =150
Button(wri, row, col, text="Izq", args=("Izquierdo",), **tbl)
col += 80
Button(wri, row, col, text="Dch", args=("Derecho",), **tbl)
col =200
row =190
Button(wri, row, col, text="PARADA ", args=("Parada",), **tbl)
CloseButton(wri) # Quit the application
def after_open(self):
display.usegrey(False)
ssd.hline(20, 70, 100, WHITE)
ssd.vline(20, 70, 30, WHITE)
ssd.vline(120, 70, 30, WHITE)
ssd.vline(70, 40, 30, WHITE)
display.clip_rect(30, 60, 20, 20, WHITE)
display.clip_rect(90,60, 20, 20, WHITE)
ssd.hline(70, 40, 80, WHITE)
display.clip_rect(90, 30, 20, 20, WHITE)
display.fill_clip_rect(75, 25, 10, 10, RED)
display.fill_clip_rect(0, 90, 40, 150, GREEN)
display.fill_clip_rect(1, 91, 38, 75, BLACK)
display.fill_clip_rect(100, 90, 40, 150, WHITE)
ssd.pixel(70,200,GREEN)
def Control():
print("Control de presión")
Screen.change(BaseScreen)
print("Finishing") # To illustrate that this line does not run until the base screen is closed
Control() In this version the valve control is done in the callback. |
Beta Was this translation helpful? Give feedback.
-
As ever in programming there are many ways to achieve your desires, but you don't need need to use a second core to achieve this and I would not recommend you go down this route and it can be fraught with difficulties. Two questions to consider before considering a response are
|
Beta Was this translation helpful? Give feedback.
-
I agree with @beetlegigg - avoid using the second core. Achieving reliable results requires a considerable degree of expertise. In most cases, Demos such as various.py illustrate a continuously running loop here - with this line determining the polling interval and ensuring that the GUI remains responsive. This is another demo with a continuously running loop. For general guidance on asyncio, see the tutorial. |
Beta Was this translation helpful? Give feedback.
-
You can find the most excellent tutorial and examples of asynchronous programming in micropython written by our Peter Hinch the author of the touch screen library. I show you a very simple example below building on the previous example I posted. It now has an additional aysnc function to continually flash the on-board LED of the pico in a while loop, but the screen button can also turn the LED on or off as well, though of course the while loop will kick in again (set for a 10 second on/off period ) and override any current setting made by the manual pressing of the screen button. The micropython-touch starts the asyncio event loop when the baseScreen is instantiated so you don't have to do this, but you can only start the async function once the async event loop is running so the baseScreen class now creates an async task to run the async function when the screen starts up (if that makes sense, and if it does not, then by the end of reading through the micropython-async tutorial doc's you will probably be more of an expert than me ) You will need to read the asyncio tutorial . Happy reading :) And just before you glance as my short code example, and to indicate many ways to proceed with your project, I give you the following thought. You indicate the status check should run in a loop 'as fast as possible'. Well that indicates it may be checking the status faster than a fat finger can press an on screen button leaving one wondering why have buttons at all. You could consider running your program in a 'normal' syncronous loop and just update a screen with any changed status info when the status changes. Then you could consider using the excellent nano-gui to update your screen. micropython-nano-gui The example:
|
Beta Was this translation helpful? Give feedback.
-
Good morning, Peter, Bg, async def control_pressure(): It has been a very important step to move forward. However, I still have the problem of the exchange of information between the screen and the control_pressure() class BackScreen(Screen):
def __init__(self):
wri = CWriter(ssd, font, GREEN, BLACK, verbose=False)
# global rango_tp_izq_dch, histerisis_tp_izq_dch, rango_tp_linea, histerisis_tp_linea
# global presion_baja_izq_dch, presion_baja_izq_dch, presion_alta_linea, registro_parametro
def cb(lb, s):
print("Valor Parametro:", s)
Label(wri, 190, 2, f'Valor P.seleccionado: {s:2.1f} bar')
registro_parametro = s
def guardar(vi):
print("Guarda parámetro")
registro_parametro = vi
super().__init__()
wri = CWriter(ssd, font, GREEN, BLACK, verbose=False)
els = (
("Rango TP.botellas", cb, (rango_tp_izq_dch,)),
("Histerisis TP.botellas:", cb, (histerisis_tp_izq_dch,)),
("Rango TP.linea:", cb, (rango_tp_linea,)),
("Histerisis TP.linea:", cb, (histerisis_tp_linea,)),
("Presion baja botellas:", cb, (presion_baja_izq_dch,)),
("Presion alta linea:", cb, (presion_alta_linea,)),
("Presion baja linea:", cb, (presion_baja_linea,)),
("", cb, ()),
)
Label(wri, 2, 100, "PARAMETROS")
Listbox(wri, 35, 2, elements=els, dlines=8, bdcolor=BLACK, value=8)
#bdcolor = RED, fgcolor=RED, fontcolor = YELLOW, select_color=BLUE, value=1)
Label(wri, 210, 2, "Nuevo valor a guardar (bar): ")
global rango
if registro_parametro == (histerisis_tp_izq_dch or histerisis_tp_linea):
args = {"legends": ("0", "5", "10"),}
rango = 10
elif registro_parametro == (rango_tp_linea or presion_alta_linea or presion_baja_linea or presion_baja_izq_dch):
args = {"legends": ("0", "12,5", "25"),}
rango = 25
else:
args = {"legends": ("0", "150", "300"),}
rango = 300
self.lbl = Label(wri, 210, 220, "310")
# Instantiate Label first, because Slider callback will run now.
# See linked_sliders.py for another approach.
Slider(
wri,
70,
260,
width=20,
height=150,
callback=self.slider_cb,
bdcolor=BLACK,
slotcolor=BLUE,
value=0.5, **args,
)
tbl = {"litcolor": WHITE, "height": 30, "width": 60, "callback": guardar}
Button(wri, 120, 180, text="Guardar", **tbl)
CloseButton(wri)
def slider_cb(self, s):
# global vi
v = s.value()
vi = v*rango
# global valor_a_guardar
valor_a_guardar = vi
self.lbl.value("{:3.1f}".format(vi)) |
Beta Was this translation helpful? Give feedback.
-
Using global variables to pass data to the asynchronous task is valid, but a more object oriented approach is to define the coroutine as a bound method: async def control_pressure(self): then the task can read bound variables controlled by the on-screen widgets. def slider_cb(self, s):
v = s.value()
vi = v*self.rango # This would be a bound variable
self.valor_a_guardar = vi # self.valor_a_guardar could be accessed by the task
self.lbl.value("{:3.1f}".format(vi)) |
Beta Was this translation helpful? Give feedback.
-
Just a quick read of your last question before I turn in for the night, and I think your answer may depend on where your callback called my_callback is located. e.g.
run that and you get: Was that what you were asking, or am I too boggle eyed tonight :-). In the touch screen demo's the callback is often located in the class init. But where did you put it? But now its goodnight from me. |
Beta Was this translation helpful? Give feedback.
-
@beetlegigg I'm glad of any contributions to this discussion - and you've spotted something I missed :) @tirejas The variables such as my_global_variable = 0
def foo():
global my_global_variable
my_global_variable = 42 Note that if the function only needs to read the variable, the |
Beta Was this translation helpful? Give feedback.
-
Good evening, Peter, Bg, I have arranged the program in two parts, the first in the header # COMUNICACION WIFI
try:
import usocket as socket
except:
import socket
import network
ssid = 'VIRGIN-telco_3CDA'
password = '2thTcQzPRShCAy'
station = network.WLAN(network.STA_IF)
station.active(True)
station.connect(ssid, password)
while station.isconnected() == False:
pass
print('Conexion correcta')
print(station.ifconfig()) The second as part of the function: async def control_pressure(self): which is started by: class BaseScreen(Screen): def pagina_web():
global presion_izq
global presion_dch
global presion_linea
html = """<!DOCTYPE HTML><html>
<head>
<meta http-equiv=\"refresh\" content=\"10\">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
<style>
html {
font-family: Arial;
display: inline-block;
margin: 0px auto;
text-align: center;
}
h2 { font-size: 2.0rem; }
p { font-size: 2.0rem; }
.units { font-size: 1.2rem; }
.bme-labels{
font-size: 1.5rem;
vertical-align:middle;
padding-bottom: 15px;
}
</style>
</head>
<body>
<h2>CENTRAL DE PRESIONES</h2>
<p>
<i class="fas fa-tachometer-alt"></i>
<span class="bme-labels">Presion ramal izquierdo (bar):</span>
<span>"""+str(presion_izq)+"""</span>
</p>
<p>
<i class="fas fa-tachometer-alt"></i>
<span class="bme-labels">Presion ramal derecho (bar):</span>
<span>"""+str(presion_dch)+"""</span>
</p>
<p>
<i class="fas fa-tachometer-alt"></i>
<span class="bme-labels">Presion linea suministro (bar):</span>
<span>"""+str(presion_linea)+"""</span>
</p>
</body>
</html>"""
return html
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', 80))
s.listen(5)
#
while True:
conn, addr = s.accept()
request = conn.recv(1024)
presion_izq = tp_izq.read_u16() * factor_izq_dch
presion_dch = tp_dch.read_u16() * factor_izq_dch
presion_linea = tp_linea.read_u16() * factor_linea
respuesta = pagina_web()
conn.send('HTTP/1.1 200 OK\n')
conn.send('Content-Type: text/html\n')
conn.send('Connection: close\n\n')
conn.sendall(respuesta)
conn.close()
led.on()
await asyncio.sleep(1) # yeild to asyncio loop and shedule to proceed in 1 seconds.
led.off()
await asyncio.sleep(1) I am attaching the complete example program import hardware_setup # Create a display instance
from gui.core.tgui import Screen, Window, ssd, display
from gui.widgets import Label, Button,CloseButton, Pad, Meter, Region, LED, Listbox, Slider
from gui.core.writer import CWriter
import gui.fonts.font10 as font
from gui.core.colors import *
import machine
import utime
import asyncio
#
# COMUNICACION WIFI
try:
import usocket as socket
except:
import socket
import network
ssid = 'VIRGIN-telco_3CDA'
password = '2thTcQzPRShCAy'
station = network.WLAN(network.STA_IF)
station.active(True)
station.connect(ssid, password)
while station.isconnected() == False:
pass
print('Conexion correcta')
print(station.ifconfig())
#
#Define la interfase, entradas y salidas digitales, entradas analógicas
#
tp_izq = machine.ADC(26) #Transmisor presion ramal izquierdo
tp_dch = machine.ADC(27) #Transmisor presión ramal derecho
tp_linea = machine.ADC(28) # Transmisor presión de línea
led = machine.Pin('LED', machine.Pin.OUT)
#
global rango_tp_izq_dch # Parámetrod
global rango_tp_linea
global factor_izq_dch # factores de conversión
global factor_linea
global presion_izq
global presion_dch
global presion_linea
f5 = CWriter(ssd, font, WHITE, BLACK, verbose=False)
rango_tp_izq_dch = 200
rango_tp_linea = 25
factor_izq_dch = rango_tp_izq_dch / (65535)
factor_linea = rango_tp_linea / (65535)
#
# async function to continuously flash the on-board pico LED
#
async def control_presion(self):
#
# Variables globales
global rango_tp_izq_dch # Parámetrod
global rango_tp_linea
global factor_izq_dch # factores de conversión
global factor_linea
global presion_izq
global presion_dch
global presion_linea
#
def pagina_web():
global presion_izq
global presion_dch
global presion_linea
html = """<!DOCTYPE HTML><html>
<head>
<meta http-equiv=\"refresh\" content=\"10\">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
<style>
html {
font-family: Arial;
display: inline-block;
margin: 0px auto;
text-align: center;
}
h2 { font-size: 2.0rem; }
p { font-size: 2.0rem; }
.units { font-size: 1.2rem; }
.bme-labels{
font-size: 1.5rem;
vertical-align:middle;
padding-bottom: 15px;
}
</style>
</head>
<body>
<h2>CENTRAL DE PRESIONES</h2>
<p>
<i class="fas fa-tachometer-alt"></i>
<span class="bme-labels">Presion ramal izquierdo (bar):</span>
<span>"""+str(presion_izq)+"""</span>
</p>
<p>
<i class="fas fa-tachometer-alt"></i>
<span class="bme-labels">Presion ramal derecho (bar):</span>
<span>"""+str(presion_dch)+"""</span>
</p>
<p>
<i class="fas fa-tachometer-alt"></i>
<span class="bme-labels">Presion linea suministro (bar):</span>
<span>"""+str(presion_linea)+"""</span>
</p>
</body>
</html>"""
return html
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', 80))
s.listen(5)
#
while True:
conn, addr = s.accept()
request = conn.recv(1024)
presion_izq = tp_izq.read_u16() * factor_izq_dch
presion_dch = tp_dch.read_u16() * factor_izq_dch
presion_linea = tp_linea.read_u16() * factor_linea
respuesta = pagina_web()
conn.send('HTTP/1.1 200 OK\n')
conn.send('Content-Type: text/html\n')
conn.send('Connection: close\n\n')
conn.sendall(respuesta)
conn.close()
led.on()
await asyncio.sleep(1) # yeild to asyncio loop and shedule to proceed in 1 seconds.
led.off()
await asyncio.sleep(1)
# --------------------------------------------------------------------
class BaseScreen(Screen):
def __init__(self):
global ramal_izq_uso # estado ramales
global ramal_izq_reserva
global ramal_dch_uso
global ramal_dch_reserva
global alarma_baja_izq # alarmas
global alarma_baja_dch
global alarma_alta_alta_linea
global alarma_alta_linea
global alarma_baja_linea
global alarma_seta
global rango_tp_izq_dch # Parámetrod
global histerisis_tp_izq_dch
global rango_tp_linea
global histerisis_tp_linea
global presion_baja_izq_dch
global presion_alta_linea
global presion_baja_linea
global pc_presion_baja_izq # Consignas
global pc_presion_baja_dch
global pc_presion_baja_linea
global pc_presion_alta_linea
global factor_izq_dch # factores de conversión
global factor_linea
global registro_parametro
global rango
global cambio_dch
global cambio_izq
self.comando = 0
# set task control_presion() function running.
asyncio.create_task(control_presion(self))
super().__init__()
wri = CWriter(ssd, font, GREEN, BLACK, verbose=False)
col = 2
row = 2
Label(wri, row, col, "CENTRAL DE GASES")
col =50
row =90
self.data1 = Label(f5, 90, 50,"11111", "Data Value", fgcolor=GREEN, bgcolor=BLACK)
col =150
row =90
self.data2 = Label(f5, 90, 150, "11111", "Data Value", fgcolor=GREEN, bgcolor=BLACK)
Button(f5, 150, 180, height=30, width=45, text="Izq", bgcolor = BLACK, litcolor=WHITE,
callback=self.Pulsadores, args=("Izquierdo",))
#$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
asyncio.create_task(self.receive_data1())
asyncio.create_task(self.receive_data2())
#
def Pulsadores(self, button, args):
if args == "Izquierdo":
self.comando = 1
print("Boton pulsado")
#
async def receive_data1(self): # VALOR PRESION BOTELLA IZQUIERDA
while True:
presion_izq = tp_izq.read_u16() * factor_izq_dch
data1 = presion_izq
data1 = "{:.1f}".format(data1)
self.external_received1(data1)
await asyncio.sleep(1)
#
async def receive_data2(self): # VALOR PRESION BOTELLA DERECHA
while True:
presion_dch = tp_dch.read_u16() * factor_izq_dch
data2 = presion_dch
data2 = "{:.1f}".format(data2)
self.external_received2(data2)
await asyncio.sleep(1)
#
#
#
def external_received1(self,val): # VALOR PRESION BOTELLA IZQUIERDA
self.data1.value(str(val))
#
def external_received2(self,val): # NIVEL PRESION BOTELLA IZQUIERDA
self.data2.value(str(val))
#
#
def test():
print("Control de presión")
Screen.change(BaseScreen)
#
test() Could you tell me how I could make it work? |
Beta Was this translation helpful? Give feedback.
-
I can give you an example, but I find your code a bit too labyrinthine for my old eyes to suggest amendments to your code and I think you should try not to use globals so much if you can. As you are creating a program with lots of concurrent tasks you have to ensure that your web server, that listens for incoming web requests is not blocking the rest of the tasks. And bear in mind that the browser in which you issue your request will get the response, but that response is not dynamically updated, and a new request will have to be sent to get the up to date info. You can of course create your own web request program on you PC, possibly in javascript to keep sending requests thus keeping the web page updated. I prefer to use the mqtt subcribe and receive all publications rather then the request and then receive paradigm of a web server for this sort of task but that does mean you have to run a mqtt broker (typically on a rpi) and create a program to receive and display the messages on the PC. The little bit of http messaging I have done with the likes of the rpi pico is to use the very nice microdot library, which is an async type of application and save a lot of detailed coding you would have to do if rolling your own. In case its any help I've added a microdot web server to the example I showed some posts back where a label is being updated with data from a simulated sensor feed. The example connects to the wifi via an imported module (from picow_wifi_connect import wlan_connect) that I have not included, but of course you can substitute your own code to connect to a wifi. My wifi connection code prints out the ip address when its connected, and as you may see from the small microdot code in the example it uses port 5000. So if you fire up your browser and in put something like 192.168.0.1:5000 the latest value of the 'data' label And just a final point is that running the micodot and touch libraries and all the other stuff you may have in your program may mean you get to running out of the little pico's memory. You may have to freeze some or all of these modules and build your own micropython version. On my picow with its ili9341 screen I had allready frozen in the touch screen module so I have not got a good handle on how much the microdot an touch libraries may eat your RAM. But here is the snipped example running a touch screen example with a microdot web server. Have fun, but take all remarks and advice as being from one who has never been a professional programmer and I've only learnt python when I retired and only dabble as a hobby with this stuff, so I may spout some nonsense :) # Initialise hardware and framebuf before importing modules.
import hardware_setup # Create a display instance
from gui.core.tgui import Screen, ssd, display
from gui.widgets import Label, Button, CloseButton, LED, Listbox, HorizSlider
from gui.core.writer import CWriter
from gui.core.colors import *
# Fonts for CWriter
import gui.fonts.arial10 as arial10
import gui.fonts.font6 as font6
import gui.fonts.font14 as font14
# set up CWriter fonts -----------------------------
f1 = CWriter(ssd, arial10, GREEN, BLACK, verbose=False)
f3 = CWriter(ssd, font6, GREEN, BLACK, verbose=False)
f5 = CWriter(ssd, font14, GREEN, BLACK, verbose=False)
from picow_wifi_connect import wlan_connect
from microdot import Microdot
import asyncio
status = wlan_connect()
print('network status: ', status)
app = Microdot()
@app.route('/')
async def index(request):
return base_ref.get_label_values()
async def start_server():
app.run(port=5000)
# -----------------------------------------------------------------
class infoScreen(Screen):
def __init__(self, base_screen):
super().__init__()
Label(f5, 20, 2, "Infomation screen.")
# status
Label(f5, 50, 2, "Thing Status")
self.lbl_bs = Label(f5, 50, 150, 50, fgcolor=YELLOW)
CloseButton(f1)
self.reg_task(self.update(base_screen)) # *** infoScreen updates itself ***
async def update(self, bs):
while True:
self.lbl_bs.value(bs.status_value) # *** Get value from base screen ***
await asyncio.sleep_ms(100)
# ------------------------------------------------------------------
class baseScreen(Screen):
def __init__(self):
# initialise Screen (super) -----------------
super().__init__()
global base_ref
base_ref = self
self.status_value = 'On'
# Screen Layout ***********************************
# Heading ----------------------
Label(f5, 5, 5, "Change Colour", fgcolor=YELLOW)
# Sub heading -------------------
Label(f5, 30, 5, "Press Start to Commence")
# Info Screen button (infoScreen)
Button(f5, 65, 50, height=60, width=60, text="Info", bgcolor = BLUE,
litcolor=WHITE,
callback=self.info_screen, args=(infoScreen,))
# data label
self.data = Label(f5, 130, 50, "Data Value", fgcolor=BLACK, bgcolor=GREEN)
# Close Button -----------------
CloseButton(f1, 10)
print('async tasks started')
# start async funtion to mimic data being received
asyncio.create_task(self.receive_data())
asyncio.create_task(self.test_info())
asyncio.create_task(start_server())
# class methods
def info_screen(self, button, cls_screen):
Screen.change(cls_screen, args=(self,)) # *** Pass the base screen instance to the info screen ***
# function to simulate data received (e.g. a sensor or a transmitted message etc)
async def receive_data(self): # *** Make these coroutines bound methods. ***
data = 1
while True:
self.external_received(data)
data += 1
data %= 11
await asyncio.sleep(1)
def external_received(self,val):
self.data.value(str(val))
if val < 5:
self.data.bgcolor=RED
elif val >= 5 and val < 8:
self.data.bgcolor=GREEN
else:
self.data.bgcolor=YELLOW
async def test_info(self):
while True:
if self.status_value == 'On':
self.status_value = 'Off'
else:
self.status_value = 'On'
await asyncio.sleep(3)
def get_label_values(self):
return self.data.value()
# End of Class -------------------------------------------------------
print('program running')
Screen.change(baseScreen) # A class is passed here, not an instance. |
Beta Was this translation helpful? Give feedback.
-
And a brief addition to my post just made, you can find the microdot docs on: |
Beta Was this translation helpful? Give feedback.
-
hello @tirejas, the picow_wifi_connect.py is not a library but just my own micropython prorgram that I use to connect the picoW to the network. As I mentioned you can just as easily use your own connect code, but for what its worth here is my wifi connect module that I call picow_wifi_connect.py and its located in the pico from machine import soft_reset
import network
import time
# WiFi
ssid = 'YOUR SID'
pw = 'YOUR PASSWORD'
reboot_pause = 3
wlan = network.WLAN(network.STA_IF)
# connect to wifi
def wlan_connect():
# if allready connected print ip address and return
if wlan.isconnected():
print(wlan.ifconfig())
return wlan.status()
# commenct connecting to network
# wifi connect attempts
connect_tries = 0
# set network to active state
wlan.active(True)
# turn off wifi power saving mode
wlan.config(pm = 0xa11140)
# connect to wifi
wlan.connect(ssid, pw)
# loop until connected or network status shows error
while not wlan.isconnected():
"""
note network status values:
0 CYW43_LINK_DOWN
1 CYW43_LINK_JOIN
2 CYW43_LINK_NOIP
3 CYW43_LINK_UP
-1 CYW43_LINK_FAIL
-2 CYW43_LINK_NONET
-3 CYW43_LINK_BADAUTH
"""
connect_tries += 1
print('wifi has not connected')
print('wifi connection attempts: ',connect_tries)
status = wlan.status()
print('wlan status: ',status)
# if an error status <= 0 it wont recover so bail out and reboot
if status <= 0:
# for testing wait for 3 seconds, for real more like wait for 60++ seconds before next connetion attempt
# to allow for the router rebooting after a power outage.
print('error <=0 in connecting to wifi - maybe wifi network is not yet up')
print('will soft reboot in 3 seconds')
time.sleep(3)
soft_reset()
# else carry on trying to connect until no of tries indicate giving up rebooting for this run
time.sleep(1)
if connect_tries > 10:
print('Too many connect tries to wifi - sleep 10 seconds before rebooting to try again')
time.sleep(10)
soft_reset()
print('network is connected')
print( 'ip: ', wlan.ifconfig()[0] )
print('channel: ', wlan.config('channel'))
return wlan.status()
if __name__ == '__main__':
status = wlan_connect()
print('network status: ', status)
|
Beta Was this translation helpful? Give feedback.
-
Good morning Bg, Peter, MPY: soft reboot
|
Beta Was this translation helpful? Give feedback.
-
As indicated in my post yesterday where I mentioned you may run out of memory when using Touch and microdot for bigger programs, the same is certainly so when using Peters Touch and mqtt_as libraries together on a picoW. On my rpi picoW I froze both of these packages into a build of micropython which considerably reduces RAM use. Instead of freezing the modules into your own build you may find that cross compiling these libraries into .mpy files will suffice, but I've not tried this. |
Beta Was this translation helpful? Give feedback.
-
Re running a graph in the background the way to do this is to have an asynchronous task update the data set in the background. When the graph screen is displayed, plot the accumulated data. |
Beta Was this translation helpful? Give feedback.
-
Good afternoon Peter, MPY: soft reboot How can I get it running? I currently have a free account at the broker: 'io.adafruit.com' |
Beta Was this translation helpful? Give feedback.
-
Thank you, Peter. |
Beta Was this translation helpful? Give feedback.
-
Good afternoon Peter, async def lista_variables(self):
# Inicializar la lista con 20 valores
self.tspi1 = [0,] * 20
self.tspd1 = [0,] * 20
self.tspl1 = [0,] * 20
self.tsvi1 = [0,] * 20
self.tsvd1 = [0,] * 20
while True:
# Leer nuevo valor del sensor
presionizq = tp_izq.read_u16() * factor_izq_dch
presiondch = tp_dch.read_u16() * factor_izq_dch
presionlinea = tp_linea.read_u16() * factor_linea
evalizq = val_izq.value()
evaldch = val_dch.value()
# Añadir la nueva lectura
self.tspi1.insert(0, presionizq)
self.tspd1.insert(0, presiondch)
self.tspl1.insert(0, presionlinea)
self.tsvi1.insert(0, evalizq)
self.tsvd1.insert(0, evaldch)
# Eliminar el último valor (FIFO)
self.tspi1.pop()
self.tspd1.pop()
self.tspl1.pop()
self.tsvi1.pop()
self.tsvd1.pop()
#
# Imprimir la tupla para ver los valores
print(self.tspi1)
#print(tspd)
#print(tspl)
#print(tsvi)
#print(tsvd)
# Esperar 100 milisegundos
await asyncio.sleep(0.4)
#----------------------------------------------------
#
class GraficaScreen(Screen):
def __init__(self):
super().__init__()
#self.tspi1_list = []
#asyncio.create_task(lista_variables(self))
wri = CWriter(ssd, font, GREEN, BLACK, verbose=False)
Label(wri, 10, 60, "GRAFICAS")
Label(wri, 215, 2, "1 hora - 1 muestra/3 minutos")
Label(wri, 15, 225, "300")
Label(wri, 30, 225, " 25")
Label(wri, 120, 223, "-")
Label(wri, 200, 225, "0")
CloseButton(wri)
wri = CWriter(ssd, font, BLUE, BLACK, verbose=False)
Label(wri, 80, 250, "P.bot.I")
wri = CWriter(ssd, font, YELLOW, BLACK, verbose=False)
Label(wri,100, 250, "P.bot.D")
wri = CWriter(ssd, font, CYAN, BLACK, verbose=False)
Label(wri,120, 250, "P.linea")
wri = CWriter(ssd, font, WHITE, BLACK, verbose=False)
Label(wri,140, 250, "Val.I")
wri = CWriter(ssd, font, RED, BLACK, verbose=False)
Label(wri,160, 250, "Val.D")
wri = CWriter(ssd, font, BLACK, BLACK, verbose=False)
fwdbutton(wri, 200, 280, BackScreen)
self.g = CartesianGraph(
wri, 30, 2, xorigin=20, yorigin=0, height=180, width=220, xdivs=20, ydivs=20,
fgcolor=GREEN, gridcolor=LIGHTGREEN, bdcolor=False
)
def after_open(self): # After graph has been drawn
self.reg_task(self.run(self.g), True) # Cancel on screen change
async def run(self, g):
await asyncio.sleep_ms(100)
tspi = TSequence(g, BLUE, 20)
tspd = TSequence(g, YELLOW, 20)
tspl = TSequence(g, CYAN, 20)
tsvi = TSequence(g, WHITE, 20)
tsvd = TSequence(g, RED, 20)
t = 0
#
'''
# Mostrar los últimos 20 datos leídos al activar la gráfica
#
for dato in self.tspi1:
registro1 = dato
g.show() # sigue agregando lecturas a la gráfica
tspi.add(registro1)
t += 1
'''
while True:
presionizq = tp_izq.read_u16() * factor_izq_dch
presiondch = tp_dch.read_u16() * factor_izq_dch
presionlinea = tp_linea.read_u16() * factor_linea
evalizq = val_izq.value()
evaldch = val_dch.value()
g.show() # sigue agregando lecturas a la gráfica
tspi.add(presionizq/rango_tp_izq_dch)
tspd.add(presiondch/rango_tp_izq_dch)
tspl.add(presionlinea/rango_tp_linea)
tsvi.add(evalizq*0.5)
tsvd.add(evaldch*0.4)
await asyncio.sleep(0.4)
t += |
Beta Was this translation helpful? Give feedback.
-
I suggest you run the |
Beta Was this translation helpful? Give feedback.
-
@peterhinch The device, is a screen with dimensions of 320 x 240 landscape. Mikrokontroller: PicoW The device.show() function takes approximately 417 ms, with only one 36x36 object at row=1 x col=280 position is placed in the framebuffer using the fillrect and fillcircle functions from nanogui. I'm wondering if there is a way to refresh part of the screen using the device.show() method or similar function by providing coordinates? |
Beta Was this translation helpful? Give feedback.
-
@tirejas You might like to look at this example. You need a directory import hardware_setup
from gui.core.writer import Writer, CWriter
from gui.core.ugui import Screen, ssd
from gui.widgets.graph import CartesianGraph, TSequence
from gui.widgets import Label, Button, CloseButton
from primitives import RingbufQueue
import asyncio
from array import array
from math import sin
import gui.fonts.arial10 as arial10
from gui.core.colors import *
wri = CWriter(ssd, arial10, GREEN, BLACK, verbose=False)
arr = array("f", (0.0 for _ in range(50)))
rq = RingbufQueue(arr)
async def populate(): # Acquire samples
t = 0
while True:
try:
rq.put_nowait(0.9*sin(t/10))
except IndexError:
pass # Overwrite oldest
t += 1
await asyncio.sleep_ms(400)
def fwdbutton(writer, row, col, cls_screen, text, color, *args, **kwargs):
def fwd(button):
Screen.change(cls_screen, args = args, kwargs = kwargs)
Button(writer, row, col, callback = fwd, bgcolor = color,
text = text, textcolor = BLACK, height = 20, width = 60)
class TSeq(Screen):
def __init__(self):
super().__init__()
self.g = CartesianGraph(wri, 2, 2, xorigin = 10, fgcolor=GREEN,
gridcolor=LIGHTGREEN, bdcolor=False)
Label(wri, 100, 2, 'Time sequence.')
CloseButton(wri)
def after_open(self): # After graph has been drawn
self.reg_task(self.run(self.g), True) # Cancel on screen change
async def run(self, g):
await asyncio.sleep_ms(0)
tsy = TSequence(g, YELLOW, 50)
async for sample in rq:
g.show() # Redraw the empty graph
tsy.add(sample)
await asyncio.sleep_ms(0)
class BaseScreen(Screen):
def __init__(self):
super().__init__()
row = 2
col = 2
fwdbutton(wri, row, col, TSeq, 'Forward', GREEN)
CloseButton(wri)
asyncio.create_task(populate())
def test():
Screen.change(BaseScreen)
test() |
Beta Was this translation helpful? Give feedback.
-
@peterhinch - a very nice example of your ring buffer, but just a note to the unwary (like me :) ) that if using the touch library rather than the micro-gui then: |
Beta Was this translation helpful? Give feedback.
-
I'm having trouble setting up a SPI
240 x 380 V1.2 TFT display from a raspberry pi pico W with micropython V1.22.2
For this I am using the MicroPython ILI9341Display & XPT2046 Touch Screen Driver libraries from Rdagger. When running the program demo_touch.py, which I attached, the touch application does not work.
demo_touch.py_.txt
Could you help me with this problem?
Another issue would be the SD card configuration.
Could I use SPI0 together with the LCD?
Would you have any configuration example to read and write to the SD card?
Thanks you
Beta Was this translation helpful? Give feedback.
All reactions