Pi geçidinde 9 bitlik çok noktalı (multidrop) veri yolu okumak: UART bunu gerçekten yapabiliyor mu?
Yapay zekâ tarafından English dilinden çevrildi ·
Gıda ve içecek tesisi, eski dolum hattı. Dört tartı göstergesi, 90’lardan kalma özel bir RS-485 çok noktalı veri yolu üzerinden haberleşiyor: 9600 baud, 9 veri biti; 9. bit bir adres baytını işaret ediyor. Bunları sorgulayan orijinal PLC arızalanıyor ve ben, sorgulamayı devralıp her göstergeyi Hermetry’ye ayrı bir cihaz olarak bildirmesi için RS-485 HAT takılı bir Pi 4 kullanmak istiyorum.Hermetry kısmını sanırım anlıyorum: Pi bir geçit (gateway) olarak çalışıyor ve dört göstergeyi alt cihaz olarak içeren v1/gw/telemetry mesajını gönderiyor. Bilmediğim şey, Linux UART’ından 9 bitlik çerçeveleri nasıl alacağım. pyserial yalnızca 5 ila 8 veri bitini destekliyor. Bu Pi’de hiç mümkün mü, yoksa farklı donanım mı gerekir?
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?
Yapay zekâ tarafından English dilinden çevrildi ·
9. bit tam olarak ne için kullanılıyor? Ben yalnızca 8N1 gördüm.
What’s the 9th bit for exactly? I’ve only ever seen 8N1.
Yapay zekâ tarafından English dilinden çevrildi ·
Ne sıklıkta okumaya ihtiyacınız var? Eğer yavaşsa, birçok geçici çözüm kabul edilebilir hale gelir.
How often do you need readings? If it’s slow, a lot of hacks become acceptable.
Yapay zekâ tarafından English dilinden çevrildi ·
Gösterge başına saniyede bir kez yeterli. David, 9. bit her düğüme “bu bayt bir adres, uyan ve bunun kendisine ait olup olmadığını kontrol et” der. Veri baytlarında bu bit 0’dır.
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.
Yapay zekâ tarafından English dilinden çevrildi ·
Birçok STM32 9 biti doğal olarak destekler. Pi için 8 bitlik seri veriye çeviren bir köprü olarak Blue Pill kullanmak, en sıradan ama en güvenilir yanıt olurdu.
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.
Yapay zekâ tarafından English dilinden çevrildi ·
Donanım tarafına yeniyim ama yıllarca yazılımda seri protokol çalıştım ve bunu parite ile taklit edebilirsiniz. 9. bit, parite bitinin olacağı yere gönderilir. Linux, CMSPAR bayrağı ile “stick” pariteyi destekler: PARENB|CMSPAR|PARODD ile parite biti her zaman 1 (mark), PARODD olmadan her zaman 0 (space) olur.Yani: mark pariteyi ayarla, adres baytını yaz, çıkana kadar bekle (tcdrain), space paritesine geç, veri baytlarını yaz. Python’da:
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]))
Alma tarafı daha zahmetli: PARMRK ve INPCK’yi açın; “yanlış” pariteli bir bayt 0xFF 0x00 önekiyle gelir ve bu, 9. bitini size söyler. 9600’de adres ve veri baytları arasındaki zamanlamada, geçişten kaynaklanan küçük bir boşluk oluşur; çoğu eski cihaz buna aldırmaz. PL011 UART’ı kullanın (disable-bt), mini UART’ı değil, çünkü mini UART’ta parite yoktur.Ardından her gösterge v1/gw/telemetry üzerinden bir alt öğe olarak gönderilir, örneğin {“scale-1”: {“values”: {“kg”: 12.45}}} gibi.
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.
Yapay zekâ tarafından English dilinden çevrildi ·
Kevin, çalışıyor. Adres baytı mark ile, veri space ile gönderiliyor, alıcı tarafta PARMRK. Göstergeler 1, 2 ve 4 ilk denemede yanıt verdi; 3 numaralı olan adresten sonra 2 ms boşluk istedi, onu ekledim. Alt cihazlar ilk v1/gw/telemetry mesajında Hermetry’de göründü. Hat ekibi şikayet ederse Jason’ın STM32 fikrini B planı olarak saklıyorum.
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.
- Bu konuyu yanıtlamak için giriş yapmış olmalısınız.
Sohbete katılın
Soru sormak ve yanıtlamak, yararlı gönderileri beğenmek ve sorununuzu çözen yanıtı işaretlemek için oturum açın. Her katkı puan ve seviye kazandırır.

