Pymodbus with Raspberry 4 PL011 uart4 and TTL/RS485 transreceiver - python

I'm trying to act as a master with my Pi 4 B in an rs485 Modbus communication.
I'll ask for register values.
All ok with pyModbus and a USB-RS485 (like ftdi) using its virtual com (/dev/ttyUSB0)
Now...
I summoned the uart4 with the standard procedure.
dtoverlay=uart4,ctsrts
So I'll be working with /dev/ttyAMA1, TX=GPIO8, RX=GPIO9, RTS=GPIO11, CTS=GPIO10
I bought one of those cheap TTL/RS-485.
DE and RE are connected to uart RTS (CTS enabled but not used).
TX to DI, RX to RO
I ask for 5 registers one at a time (with 3s timeout for the response each) and a final pause of 3 sec.
I connected some LEDs and slowed the baud rate to 1200 to see how LEDs act.
From the other side, I'm monitoring Modbus activity with ftdi USB-rs485 and dock light programmed to respond with a certain message (acts as a 'fake' slave)
No activity of the ftdi at all.
If I de-attach DE and leave only RE with RTS, I see the TTL TX message on the RX pin (like a looping echo).
What's wrong??

I bought one of those cheap TTL/RS-485. DE and RE together and connected to uart RTS (CTS enabled but not used).
That is not right. With Modbus only one device is allowed to use the bus at a time, so you need one of those GPOx (it can also be RTS or CTS) to go low right before the device is ready to write something on the bus and stay low until the whole frame is transmitted. After a determined amount of time elapses, the signal has to go high to free the bus and allow other devices to talk.
For the practical part, since this is a very common problem, you will find all you need to fix your problem in this Q&As. A very short summary: you need to tweak whatever library you use to add the signaling to feed the drive enable/read enable pin on your TTL converter.
If you are wondering why the USB converter works and the TTL won't, the answer is very simple: your USB converter has this signal implemented in its hardware (you can read more details on the link).
The problem is not difficult to fix, but if you are short on patience or don't have time to waste, just take the fast track and buy a decent transceiver. There are many options, this is just one (I'm not affiliated with the manufacturer nor I make any profit off it). You can also stick to those connected through USB; most of them will work (not all though).
If you decide to implement the software solution be aware that you will be asking for real-time performance on a non-real-time platform, meaning that even though the solution will probably work almost 100% of the time, it is not guaranteed to always work. If your RPi is loaded with too much work, there might be instances where the signaling will not be properly timed and some frames might not get to the other side. You are warned: if your application is mission-critical in any way, just forget about it and buy a proper transceiver.

Related

How can I push a file out to multiple Raspberry Pi Pico's at once?

I am looking for a DIY replacement for the $1500 Go-Box for mass provisioning Chromebooks. I have managed to replicate this by using a Raspberry Pi Pico as the "HID Emulation". However, I need this on a mass scale. I want to be able to do 20 Chromebooks at one time. I can do this with just 20 Raspberry Pi Picos but I need to change the script every 100-150 Chromebooks I provision (changing credentials etc.). Changing each script manually is time-consuming, so I need to be able to change all 20 scripts at once, or one "master" script that the "slave" Picos go and get on boot.
At first, I thought about an SD card they can all read from and when needed, I can take it out and change the script on there, and then when the Pico boots it can copy the new script to the root of the Pico. However, this may be an issue since I do not know if the Picos will clash with each other when trying to read the script from the same place at the same time. This is my first issue.
Then I thought about a Master and Slaves setup. One Pico acts as a Master and holds the script. The other 20 are slaves that get the script from the Master when a pin is high (to signify the Picos need reprogramming). I would only use the Master when reprogramming the script. When I turn the Master on, I would have it set a pin to high and all the other slaves would check on the boot to see if the pin is high. If the Slaves find that the pin is high, it won't run the script, but it will update it from the Master. This is where I run into the problem with this method. I need to transfer the script from Master to Slaves. I haven't got any experience in communication protocols like UART, SPI, or I2C but I understand that if I want to do multiple Slaves, then I am better off using I2C.
This is my last resort since I have been googling for days and can't find a suitable solution. Is anyone able to provide any insight on any of the following:
How to get the script from one place to twenty?
Will the SD card idea clash when all 20 Picos try to access it?
How to transfer files over I2C or similar protocol?
I appreciate any help anyone can provide. I am using MicroPython v1.16 on 2021-06-18; Raspberry Pi Pico with RP2040
The pico has a uart (2 actually) which is easy to program; there are lots of examples of serial communication with the pico, typically to a full Raspberry Pi.
You could join all the rx receiver pins on the picos to the master tx transmit pin and talk to them all in parallel, with no replies.
I don't know if it is possible to tri-state the tx pins so that they could all be connected too, but only one enabled at a time, by sending suitable commands from the master tx. The problem is that the electrical load of 20 receivers, and the excessive length of the parallel cabling might not give error free transfers.
Or you could daisy chain the serial ports so the rx of pico1 is read by the software there and repeated out on its tx, which is connected to the rx of pico2, and so on. You can start each data packet with a "node number", which each pico decrements before sending it on. If this number is 1, then the packet appplies to this node. This is a sort of auto-numbering of the picos. A number like 255 can be used for a broadcast.
If the last pico's tx is wired back to the master you can even allow any pico to send a reply, provided the software waits for a break in incoming data.
It also allow for rudimentary flow control and error checking. If the master sends only 1 byte at a time, and waits for each byte to be "echoed" back from the last pico, it can ensure everyone has seen the data. Also, each serial segment can be short so there are no electrical load problems, or signal corruption.
Look at the gpib bus which daisy chains something like this, or at the simple individually-addressible RGB leds like the WS2812B which are also daisy chained.

Directly send signals to USB using Python

How can I set HIGH or LOW to a usb port connections using Python.
This could be used in come custom usb device.
For Example,
Consider I have a LED connected to the usb port(DATA Line) .
Now through the code I want to blink it or control it.
Now this can be easily achieved by using any micro controller, Arduino, Raspberry Pi
But I want to achieve this with with a normal computer and python.
[EDIT]
Can I achieve this by making a C or C++ API and make a wrapper to use it in Python. Is yes then what will be the best way to achieve it?
NOTE :
My main objective isn't just blinking some LED. I just gave it as an example.
I want to be able to directly control the USB ports.
Quoting : https://www.cmd-ltd.com/advice-centre/usb-chargers-and-power-modules/usb-and-power-module-product-help/usb-data-transfer-guide/#:~:text=How%20is%20data%20sent%20across,amounts%20known%20as%20'packets'.
Within the standard USB 2.0 connector you can see four metal strips. The outer two strips are the positive and ground of the power supply. The two central strips are dedicated to carrying data.
With the newer USB 3.0 connector, the data transfer speed is increased by the addition of extra data-carrying strips; four extra signalling wires help USB 3.0 achieve its super speed.
I want to set the values of the Data pins.
By my saying HIGH LOW please don't misunderstand that I want to set the value to +5V and GND. But I mean to control its value directly via my code without any external driver present in the computer.
I mentioned HIGH LOW to just make the language simple and so that it is easier to understand.
Controlling components like LEDs from devices like Arduino and Raspberry Pi are done using GPIO pins. In contrast, USB is designed for data transfer and not for maintaining more constant high or low signals like GPIO. It also consumes different voltage and current levels than GPIO pins and could potentially damage components meant for GPIO.
However, you can get USB to GPIO adapters for this purpose (see here for an example discussion on these options).
In terms of Python, you can use packages such as PyUSB or the libusb Python wrapper to control/transfer data/communicate with USB devices (such as the USB to GPIO adapters). The companies providing the adapters might also have designed their own easy-to-use Python package to wrap around a lower-level driver (probably written in C). See this USB controlled LED device as an example with its own Python driver. The drivers are just software programs that take in relatively simple commands from the user for what they want a device to do. They then encapsulate the lower-level complexities required for following a protocol to communicate the user's intention to the USB device and controlling the USB port at the lowest possible software level.
You cannot achieve that for several reasons:
The USB port has its own protocol of connection. Data is transmitted in packets with starting and ending bits. The negotiation and handshake process is done in the hardware layer between microchips. This process also selects the communication speed in the bidirectional data line. You have to direct access to the pin (like GPIO) to turn LEDs ON and Off or create your own connection protocol. This cannot be done in USB.
There are also voltage and current limitations. The data line is not +5 and GND. The data line is 2.8v for D+ and 0.3v for D- and both with respect to the GND. The data is transmitted and received differentially (D+ with respect to D-) and they are not compared with the GND for 1s and 0s.
The button line is you have no direct control over USB.

Use two things over GPIO SPI connection on Raspberry Pi [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 4 years ago.
Improve this question
I have a 2.8" capacitive TFT screen from and a PN532 RFID reader from Adafruit. The problem is, they both use SPI. When I use the RFID reader, the screen goes completely white and I have to restart the Pi to get the image back. I have to use the SPI interface on the reader so that I can use the Adafruit library to use it with Python. The screen going white isn't a problem as long as it's only when the RFID reader is in use. Is there anyway to "restart" the screen after using the RFID reader? Any help is appreciated.
A SPI bus consists of 3 wires + 1 chip select signal per individually addressable slave on the SPI bus. Some devices, for example NeoPixels, many DACs, every shift register, etc. allow for daisy chaining, where a chain of devices may share a common chip select line.
However in your case you most certainly want to address devices that don't support daisy chaining. So each device requires an individual chip select line.
Let's first recapitulate, how a SPI bus works.
SPI transfers typically look like this
/CS ‾‾‾\___________________ . . . ___________/‾‾‾
CLK _____/‾‾‾\___/‾‾‾\___/‾ . . . ‾‾\____________
MOSI =====X=======X=======X= . . . ===============
MISO =========X=======X===== . . . ==X============
i.e. first the chip select (/CS) goes low, then the MOSI (master out → slave in) data lines are set to the next bit to be transferred and on the rising clock edge, and on the falling clock edge the slave reads that bit. Similarly on the falling clock edge the slave pulls the data line for the master to read on the rising endge.
However some devices require inverted clock polarity or expect different timings on MOSI/MISO. However the timings as outlined above are what works for most and which I've usually do when bitbanging.
The purpose of the /CS line is to delimit a bus transaction. A falling /CS begins a transaction, a rising one ends it. Which in essence means: If a device does not see a falling /CS it will simply ignore everything that happens on the other lines.
So the first thing to wonder with a problem like your is: "Am I addressing my SPI slaves using different /CS signals, and if so, is the timing correct?" The must have debugging tool for issues like that is an oscilloscope; preferrably one with 4 channels.
Your Raspberry-Pi has a couple of GPIO pins. Each of them technically can be used for a /CS signal. However often SPI transfers are controlled by devices and/or drivers which want to use a very specific pin for /CS. I'm not familiar with the Adafruit library, if it has such an expectancy. However if you can configure a "chip select" (CS), "slave select" (SS) or "chip enable" (CE) signal in the library, then this is where you specify, which GPIO you're using as /CS for the device in question.
If you can't configure it like that, there's always the option to use a hardwired AND gate on the /CS signal. The foolproof and robust solution is to use 74HCx series gate, however this comes with a lot of redundant wires. A slightly more elegant solution is to use a logic demultiplexer like a 74HC154 where you connect /CS to the /EN pins and using 4 GPIO lines can address to which of the 16 outputs the /CS signal gets routed.
However there's also a dead-cheap variant called wired OR. Remeber that the usual convention for /CS is to be pulled low. So what you can do is us a couple of resistors – and if you can't tristate your GPIO pins a few diodes – to force the /CS signal up for the devices you don't want to address. See https://en.wikipedia.org/wiki/Wired_logic_connection for details on that.
Update
So I've had a quick look at the library hosted here https://github.com/adafruit/Adafruit_Python_PN532 and right in the example there's this https://github.com/adafruit/Adafruit_Python_PN532/blob/feaf22f659731586adc9ded4af969bb256969ed3/examples/readmifare.py#L28
# Setup how the PN532 is connected to the Raspbery Pi/BeagleBone Black.
# It is recommended to use a software SPI connection with 4 digital GPIO pins.
# Configuration for a Raspberry Pi:
CS = 18
MOSI = 23
MISO = 24
SCLK = 25
So not only is this library in question using not tied to a dedicated SPI peripheral, you can actually freely configure which GPIO pins to use, to talk to the RFID reader.

Minimum delay to communicate through serial using Python

I have a simple Python script to communicate with a micro-controller (STM32F103C8T6) using the serial port. I'm using pySerial to write a couple of 44-bytes messages at a time.
[...]
serial = serial.Serial(serial.tools.list_ports.comports()[0].device, 115200)
packet0 = bytearray(INSERT_RELEVANT_44-BYTES)
packet1 = bytearray(INSERT_RELEVANT_44-BYTES)
serial.write(packet0)
time.sleep(0.1) # Delay between communications
serial.write(packet1)
[...]
I had to insert a delay between the communications, otherwise it wouldn't work. My reasoning is that for a baud rate of 115200 bps the messages should take 44*8/115200 = ~0,003 seconds to be sent, thus this should be the minimum ideal interval between sending the packets. The code, however, doesn't work for anything smaller than 0,1.
Why? Am I missing something? I suppose there is some delay due to the operating system and the USB, but it shouldn't account for ~0,7 seconds. How can I optimize this to use the minimum possible delay?
Rather then calculating a nominal delay based on the UART link, you could simply poll the serial driver to determine whether the Tx buffer is empty:
serial.write(packet0)
while serial.outWaiting() > 0 :
pass
serial.write(packet1)
This has the advantage of accounting automatically for any latency, software overhead and buffer limitations anywhere in the chain of application code, library, driver, USB-Serial bridge. It will not however solve any problem with the STM32 serial I/O implementation, you should probably address the root problem of why the data cannot be streamed, which is most likely down to poor implementation of the at the STM32 device end.

Simple data transmission from multiple Arduinos (client) to Raspberry pi (server) wirelessly

I'm building a project where I have multiple Arduinos, each having a temperature sensor and a [input wireless transmission method here].
This data would be received by a controller, a Raspberry pi, which would act as the server: call to Arduino, collect the data, and store it. This data would be accessible to a Mobile App, but this is out of the scope of the question.
Requirements:
Arduinos must read simple raw data (in this case, the temperature reading from the sensor) and make it accessible to the Raspberry pi, which would make calls to each Arduino board (from 1 sec to 1 min time frame).
Arduino side must have a low energy consumption, as it would be powered by a small battery;
Data transmission on Arduino end must be as cheap as possible and work in low temperatures (around -5 degrees Celsius). They would be stored be inside a freezer, so temperature and a thick-ish metal layer are obstacles to overcome.
Question: is Bluetooth a viable transmission method? Is it possible to pair multiple Arduinos to one Raspberry pi at a single time?
If Bluetooth isn't any good, what is? Correct me if I'm wrong, but Wifi is a high energy consumption solution.
OBS: if needed, the Raspberry Pi board could be swapped for an Arduino one.
Cheap, low power and tiny row data?
I suggest you to use nRF 2.4GHz transceiver module. It may look some old school way but will meet with your requirements.
It consumes 0.9 nA while deep-sleep mode and ~10mA for just transmission.
Also it is easy to program and due to its connectionless arch, you will not need to know states about the connection. Just being sure to send and received successfully, suggest you to add deviceId and succeed flag in your raw requests.
Here is vendor site :
http://www.nordicsemi.com/eng/Products/2.4GHz-RF/nRF24L01
Good luck!

Categories