Seite 1 von 1

Raspberry Pico Datenübertragung UART/RS485

Verfasst: Donnerstag 27. April 2023, 19:53
von f91w
Hallo an Alle!

Ich lese schon eine Weile hier mit und nun habe ich eine Frage. Wie in der Überschrift steht will ich mittels Pico Messwerte von
DS18B20 Fühlern weiterleiten. Dazu habe ich mir für den Pico RS485 Module gekauft: https://eckstein-shop.de/WaveShare-2-Ch ... T-To-RS485
Bisher habe ich mit Raspberry Pi und Arduino/Nano in C und Python ein wenig gebastelt. Für die UART-Geschichte habe ich die Beispiele von
Waveshare als Basis genommen und erweitert. Es klappt erstmal, aber vielleicht kann hier jemand ein paar Tips geben worauf ich
achten sollte oder was man besser machen kann. Es sind 2 Picos mit jeweils einem RS485-Modul.
Firmware ist "MicroPython v1.19.1 on 2022-06-18; Raspberry Pi Pico with RP2040"
Ich stelle meine Skripte mal hier ein.

RS485_send.py

Code: Alles auswählen

from machine import UART, Pin
import time

uart1 = UART(1, baudrate=115200, tx=Pin(4), rx=Pin(5))

#uart0 = UART(0, baudrate=115200, tx=Pin(0), rx=Pin(1))
a=0
#txData = b'RS485 send test...\r\n'
#uart1.write(txData)
print('RS485 send test...')
time.sleep(0.1)
while True:
    a=a+1
    if a > 4:
        a = 1
    time.sleep(0.5) 
    print ('request...')#shell output
    uart1.write("{}\r".format(a))
    time.sleep(0.1)
    rxData = bytes()
    while uart1.any() > 0:
        rxData += uart1.read(1)
    print('Sensor {}:'.format(a),rxData.decode('utf-8'))
 
RS485_receive.py

Code: Alles auswählen

from machine import UART, Pin
import time

sensorlist = [10, 20, 30, 40] #Sensorsimulation
#uart1 = UART(1, baudrate=115200, tx=Pin(4), rx=Pin(5))

uart1 = UART(0, baudrate=115200, tx=Pin(0), rx=Pin(1))
flag = 1
#txData = 'RS485 receive test...\r\n'
#uart1.write(txData)
print('RS485 receive test')
time.sleep(0.1)

def sensorsend(rxData):
    zahl = int(float(rxData))
    return(sensorlist[zahl - 1])
    
while True:
    rxData = bytes()
    while uart1.any() > 0:
        rxData = uart1.read()
        sensorwert = sensorsend(rxData)
        if(flag == 1):
            time.sleep(0.05)
            flag=0
        #uart1.write("{}".format(rxData.decode('utf-8')))
        uart1.write('{}'.format(sensorwert))    
        #print(rxData.decode('utf-8'))
        if(uart1.any()==0):
            uart1.write("\r")
            flag=1
mfg

f91w

Re: Raspberry Pico Datenübertragung UART/RS485

Verfasst: Freitag 28. April 2023, 00:50
von __deets__
Dieses while uart.any()-Muster ist ein Problem, das solltest du dir abgewöhnen. Im ersten Skript führt das klar zu einem Fehlverhalten, wenn aus irgendwelchen Gründen eine Antwort verspätet kommt. Sowas modelliert man andersherum - blockieren bis Daten da sind, oder ggf. explizite Timeouts nach denen eine ausgebliebene Antwort zu einem Fehlerzustand führt.

Re: Raspberry Pico Datenübertragung UART/RS485

Verfasst: Samstag 29. April 2023, 01:10
von f91w
Danke für die Antwort.
Ich habe leider keine Ahnung von UART und wenig von Python.
Daher stehe ich ein wenig im Wald. Das Problem mit "any" ist jetzt klar, aber
ich weiss nicht wie man es umgeht. Muss ich mich mal mit beschäftigen...

mfg

f91w

Re: Raspberry Pico Datenübertragung UART/RS485

Verfasst: Samstag 29. April 2023, 15:46
von __deets__
Du musst gar nichts umgehen. Sondern einfach blockierend einlesen. Solange kein timeout angegeben ist, kehrt read auch nicht frühzeitig zurück.

Re: Raspberry Pico Datenübertragung UART/RS485

Verfasst: Samstag 29. April 2023, 22:46
von f91w
Hallo,

ich habe jetzt die "while uart1.any()" Zeile rausgenommen und ein paar Kleinigkeiten geändert.
Wird wohl ne Weile dauern bis ich mich in die Materie eingearbeitet habe.

mfg

f91w

Re: Raspberry Pico Datenübertragung UART/RS485

Verfasst: Montag 22. Mai 2023, 09:53
von Sirius3
Beim Sende-Skript: ob das UART-1 oder UART-0 ist, sollte nicht im Variablennamen stehen.
Statt einer while-Schleife und händischem Zählen sollte das eine for-Schleife innerhalb der while-Schleife sein.
Wenn Du ein Zeilenbasiertes Protokoll hast, solltest Du auch exakt eine Zeile lesen.
Statt format benutzt man heutzutage f-Strings.

Code: Alles auswählen

from machine import UART, Pin
import time

def main():
    uart = UART(1, baudrate=115200, tx=Pin(4), rx=Pin(5))
    print('RS485 send test...')
    time.sleep(0.1)
    while True:
        for sensor_nummer in range(1, 5):
            time.sleep(0.5) 
            print ('request...')
            uart.write(f"{sensor_nummer}\r\n".encode('utf-8'))
            time.sleep(0.1)
            sensor_value = uart.readline().decode('utf-8').strip()
            print(f"Sensor {sensor_nummer}: {sensor_value}")

if __name__ == "__main__":
    main()
Für's receive-Skript gilt das selbe, hier ist der Variablenname sogar falsch, da URT-0 an uart1 gebunden wird. Variablen sollten dann initialisiert werden, wenn sie gebraucht werden, nicht irgendwo am Anfang des Programms.

Da Du Ganzzahlen sendest, warum benutzt Du `float`?
`return` und `if` sind keine Funktionen, die Klammern also eher verwirrend. Das Initialisieren von rxData mit bytes ist überflüssig, da der Wert sowieso gleich wieder überschrieben wird.

Warum sendest Du den Zeilenumbruch nur manchmal?

Code: Alles auswählen

from machine import UART, Pin
import time

SENSORS = [10, 20, 30, 40] #Sensorsimulation

def sensorsend(sensor_number):
    return SENSORS[int(sensor_number) - 1]

def main():
    uart = UART(0, baudrate=115200, tx=Pin(0), rx=Pin(1))
    print('RS485 receive test')
    time.sleep(0.1)
    while True:
        sensor_number = uart.readline()
        sensor_value = sensorsend(sensor_number)
        time.sleep(0.05)
        uart.write(f"{sensor_value}\r\n".encode('utf-8'))


if __name__ == "__main__":
    main()

Re: Raspberry Pico Datenübertragung UART/RS485

Verfasst: Donnerstag 6. Juli 2023, 20:43
von f91w
Zunächst mal Vielen Dank für alle Antworten.
Ich hatte das Projekt aus Zeitmangel ein wenig vernachlässigt.
Der Code ist wie er ist weil ich es nicht besser weiss und basiert auf dem Demo-Code
des Herstellers der Hardware.
Ich werde mal wieder dran arbeiten und mich dann melden.

mfg

f91w

Re: Raspberry Pico Datenübertragung UART/RS485

Verfasst: Donnerstag 13. Juli 2023, 02:52
von f91w
Ich habe mal ein wenig mit den beiden Skripten herumgespielt. Es hat nicht sofort geklappt, ich musste
etwas basteln.
Senden:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#  pico_uart_sende.py
#  
#  
#  
# Pico/Micropython Sendeskript

from machine import UART, Pin
import time

def main():
    uart = UART(1, baudrate=115200, tx=Pin(4), rx=Pin(5))
    print('RS485 send test...')
    time.sleep(0.1)
    while True:
        for sensor_nummer in range(1, 5):
            time.sleep(5) 
            print ('request...')
            uart.write(f"{sensor_nummer}\r\n".encode('utf-8'))
            time.sleep(0.1)
            rxData = uart.readline()
            if rxData is not None:    ###ohne Abfrage Fehler in der naechsten Zeile
                print(f'Sensor {sensor_nummer}: {rxData.decode('utf-8')}')
                #sensor_value = uart.readline().decode('utf-8').strip()
                #print(f"Sensor {sensor_nummer}: {sensor_value}")
            else:
                print("no data..")   

if __name__ == "__main__":
    main()

Empfangen:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#  pico_uart_empfang.py
#  
#  
#Pico/Micropython Empfangsskript aus Python Forum

from machine import UART, Pin
import time

SENSORS = [10, 20, 30, 40] #Sensorsimulation

def sensorsend(sensor_number):
    return SENSORS[int(sensor_number) - 1]

def main():
    uart = UART(0, baudrate=115200, tx=Pin(0), rx=Pin(1))
    print('RS485 receive test')
    time.sleep(0.1)
    while True:
        sensor_number = uart.read()   ###readline() wirft Fehler in sensorsend()
        #print(sensor_number)
        if sensor_number is not None:  ###Wenn "sensor_number==None" dann Fehler in sensorsend()
            sensor_value = sensorsend(sensor_number)
            time.sleep(0.05)
            uart.write(f"{sensor_value}\r\n".encode('utf-8'))
            print("data sent...", sensor_value)
        else:
        #    print("No requests received!")
            time.sleep(0.05)

if __name__ == "__main__":
    main()

In dieser Form laufen die beiden Skripte. Sonst gab es z.B Fehler wenn das Sendeskript keine Antwort bekam.
"SENSORS[int(sensor_number) - 1]" löst einen Fehler aus wenn "sensor_number" "None" ist.


mfg

f91w

Re: Raspberry Pico Datenübertragung UART/RS485

Verfasst: Donnerstag 13. Juli 2023, 08:08
von Sirius3
`readline` ist trotzdem die richtige Methode, denn so liest Du ja im Zweifel nicht die komplette Zahl, sondern nur das, was zufällig gerade im Buffer ist. Wenn dann ein None zurückkommt, dann gab es einen Timeout, und wie man damit umgehen muß, das hast Du ja jetzt eingebaut.

Re: Raspberry Pico Datenübertragung UART/RS485

Verfasst: Donnerstag 13. Juli 2023, 22:33
von f91w
Habe ich schon korrigiert, Danke.

mfg

f91w