Einen 9-Bit-Multidrop-Bus über ein Pi-Gateway auslesen: Kann die UART das überhaupt?
Von English mit KI übersetzt ·
Lebensmittel- und Getränkebetrieb, alte Abfüllanlage. Vier Wägeindikatoren kommunizieren über einen proprietären RS-485-Multidrop-Bus aus den 90er-Jahren: 9600 Baud, 9 Datenbits, wobei das 9. Bit ein Adressbyte markiert. Die ursprüngliche SPS, die sie abgefragt hat, fällt aus, und ich möchte einen Pi 4 mit einem RS-485-HAT einsetzen, der das Pollen übernimmt und jeden Indikator als eigenes Gerät an Hermetry meldet.Den Hermetry-Teil glaube ich zu verstehen: Der Pi ist ein Gateway und sendet v1/gw/telemetry mit den vier Indikatoren als Child-Geräten. Was ich nicht weiß, ist, wie man 9-Bit-Frames aus einer Linux-UART bekommt. pyserial unterstützt nur 5 bis 8 Datenbits. Ist das auf einem Pi überhaupt möglich, oder brauche ich andere Hardware?
Food and beverage plant, old filling line. Four weighing indicators talk on a proprietary RS-485 multidrop bus from the 90s: 9600 baud, 9 data bits, where the 9th bit marks an address byte. The original PLC that polled them is dying and I want a Pi 4 with an RS-485 HAT to take over the polling and report each indicator to Hermetry as its own device.
The Hermetry part I think I understand: the Pi is a gateway and sends v1/gw/telemetry with the four indicators as children. What I don’t know is how to get 9-bit frames out of a Linux UART. pyserial only offers 5 to 8 data bits. Is this possible on a Pi at all, or do I need different hardware?
Von English mit KI übersetzt ·
Wofür genau ist das 9. Bit? Ich habe bisher immer nur 8N1 gesehen.
What’s the 9th bit for exactly? I’ve only ever seen 8N1.
Von English mit KI übersetzt ·
Wie oft brauchst du Messwerte? Wenn es langsam sein darf, werden viele Workarounds akzeptabel.
How often do you need readings? If it’s slow, a lot of hacks become acceptable.
Von English mit KI übersetzt ·
Einmal pro Sekunde pro Anzeige reicht völlig. David, das 9. Bit sagt jedem Knoten: „Dieses Byte ist eine Adresse, wach auf und prüfe, ob sie dir gehört“. Datenbytes haben es auf 0.
Once a second per indicator is plenty. David, the 9th bit tells every node „this byte is an address, wake up and check if it’s yours“. Data bytes have it at 0.
Von English mit KI übersetzt ·
Viele STM32 beherrschen 9 Bit nativ. Ein Blue Pill als Brücke, die auf 8-Bit-Serial für den Pi umsetzt, wäre die unspektakuläre, zuverlässige Antwort.
Lots of STM32s do 9-bit natively. A Blue Pill as a bridge that translates to 8-bit serial for the Pi would be the boring, reliable answer.
Von English mit KI übersetzt ·
Ich bin neu auf der Hardware-Seite, habe aber jahrelang serielle Protokolle in Software umgesetzt, und man kann das mit Parität nachbilden. Das 9. Bit wird dort gesendet, wo das Paritätsbit stehen würde. Linux unterstützt „Stick“-Parität über das CMSPAR-Flag: Mit PARENB|CMSPAR|PARODD ist das Paritätsbit immer 1 (Mark), ohne PARODD immer 0 (Space).Also: Mark-Parität setzen, das Adressbyte schreiben, warten bis es hinaus ist (tcdrain), auf Space-Parität umschalten, die Datenbytes schreiben. In Python:
import termios, serial
CMSPAR = 0o10000000000
s = serial.Serial('/dev/ttyAMA0', 9600)
def set_bit9(on):
a = termios.tcgetattr(s.fd)
a[2] |= termios.PARENB | CMSPAR
a[2] = a[2] | termios.PARODD if on else a[2] & ~termios.PARODD
termios.tcsetattr(s.fd, termios.TCSADRAIN, a)
set_bit9(True); s.write(bytes([0x03])); s.flush()
set_bit9(False); s.write(bytes([0x10, 0x00]))
Der Empfang ist die unangenehmere Hälfte: PARMRK und INPCK aktivieren, dann kommt ein Byte mit der „falschen“ Parität mit dem Präfix 0xFF 0x00 an, das dir sein 9. Bit verrät. Bei 9600 entsteht zwischen Adress- und Datenbytes durch das Umschalten eine kleine Lücke, die meisten alten Geräte stört das nicht. Verwende den PL011-UART (disable-bt), nicht den Mini-UART, denn der Mini-UART hat keine Parität.Dann wird jeder Indikator als Kind gesendet, etwa so: {„scale-1“: {„values“: {„kg“: 12.45}}} auf v1/gw/telemetry.
I’m new to the hardware side but I did serial protocol work in software for years, and you can fake this with parity. The 9th bit is sent where the parity bit would be. Linux supports „stick“ parity through the CMSPAR flag: with PARENB|CMSPAR|PARODD the parity bit is always 1 (mark), without PARODD it’s always 0 (space).
So: set mark parity, write the address byte, wait for it to leave (tcdrain), switch to space parity, write the data bytes. In Python:
import termios, serial
CMSPAR = 0o10000000000
s = serial.Serial('/dev/ttyAMA0', 9600)
def set_bit9(on):
a = termios.tcgetattr(s.fd)
a[2] |= termios.PARENB | CMSPAR
a[2] = a[2] | termios.PARODD if on else a[2] & ~termios.PARODD
termios.tcsetattr(s.fd, termios.TCSADRAIN, a)
set_bit9(True); s.write(bytes([0x03])); s.flush()
set_bit9(False); s.write(bytes([0x10, 0x00]))
Receiving is the uglier half: turn on PARMRK and INPCK and a byte with the „wrong“ parity arrives prefixed with 0xFF 0x00, which tells you its 9th bit. At 9600 the timing between the address and the data bytes gets a small gap from switching, most old devices don’t care. Use the PL011 UART (disable-bt), not the mini UART, the mini UART has no parity.
Then each indicator goes out as a child, something like {„scale-1“: {„values“: {„kg“: 12.45}}} on v1/gw/telemetry.
Von English mit KI übersetzt ·
Kevin, es funktioniert. Adressbyte mit Mark, Daten mit Space, PARMRK auf der Empfangsseite. Die Indikatoren 1, 2 und 4 haben beim ersten Versuch geantwortet, Nummer 3 wollte eine Lücke von 2 ms nach dem Adressbyte, die ich ergänzt habe. Die Kinder erschienen in Hermetry bei der ersten v1/gw/telemetry. Jasons STM32-Idee behalte ich als Plan B, falls die Leitungsleute sich beschweren.
Kevin, it works. Address byte with mark, data with space, PARMRK on the receive side. Indicators 1, 2 and 4 answered first try, number 3 wanted a 2 ms gap after the address, which I added. The children appeared in Hermetry on the first v1/gw/telemetry. Keeping Jason’s STM32 idea as plan B if the line people complain.
- Du musst angemeldet sein, um auf dieses Thema antworten zu können.
Mitdiskutieren
Melde dich an, um Fragen zu stellen und zu beantworten, hilfreiche Beiträge mit „Gefällt mir“ zu markieren und die Antwort zu kennzeichnen, die dein Problem gelöst hat. Jeder Beitrag bringt Punkte und Stufen.

