Hi Ralph,
We use StreamDevice for a similar system. We have large scintillator detector arrays, with each scintillator unit having its own compact high voltage power supply. The power supplies use RS485 and are chained together in groups of 32 units.
Then we arrange groups in blocks of 1-5, each using a single RS485 chain. So each RS485 chain has from 32 to 160 power supplies on it. We use the high density Moxas that have the RJ-45 ports.
In terms of software, each power supply has a simple streamsDevice support (set/read current, voltage & status). This is loaded into an IOC, but nothing is automatically scanning at that low level. We have high level database logic in the
IOC to process the ‘read’ records in sequence. We use the sseq record, and take advantage of its put_callback support. We chain together sseq records to deal with a single group of 32. Then chain those to even higher level records to deal with up to 160 units.
We also use small delays in the sseq records, which seems to reduce communication errors. It takes many seconds, even >1 minute, to get through all the units in one loop. Then at the end of the final sseq, it forward links to the first one again.
I don’t like having 160 devices on one bus. If it was up to me, I would have pushed for no more than 32 (since they are physically grouped like that anyway) and just used more Moxa ports. That would reduce the time taken to poll all the
devices, which would aid in debugging issues if you think you have a problem with one device. Another problem can be occasional communication errors. At the moment if we miss a response, we just move onto the next device, which means the device that had a
problem can be in COMM alarm for >1 minute. It would be good if we had some retry mechanism either built into streamDevice or in the database logic. We did have to implement a debounce on the alarm logic, so the user doesn’t see a problem unless a single device
has been in error state for a few minutes.
For the sending and receiving unique ID, that sounds like a RS485 address? It can be done in streamDevice using protocol arguments. For example, by having the address (or unique ID) embedded in the record INP/OUT link for the protocol function,
like:
field(INP, "@senstech.proto getv(021) MNA")
In the above example, MNA is the Asyn port, and ‘021’ is the RS485 address, which I handle in the protocol function using the \$1 syntax (
getv {
out "\r\$1v";
in "\$1v%X";
}
So I am sending 021 (and a ‘v’ command), and it’s echoed back with the response.
The above scheme, of chaining many sseq records, works well. Although in my case I had to increase the size of the callback queue size, since it was all in one IOC and we have 10,000+ CA links from the sseq records.
Cheers,
Matt
From: Tech-talk <tech-talk-bounces at aps.anl.gov> On Behalf Of
Ralph Lange via Tech-talk
Sent: Monday, October 26, 2020 5:20 AM
To: EPICS Tech Talk <tech-talk at aps.anl.gov>
Subject: [EXTERNAL] Experiences using RS-485 Multi-Drop with StreamDevice?
Dear all,
We have a system being developed with a large number (>100) controllers that are linked through many chains of RS-485 multi-drop lines connected to Moxa boxes for remote access.
Has anyone used StreamDevice in such a setup and could share experiences? What to avoid? What to push for?
One more interesting thing: the client is expected to send a unique id with each request that gets returned by the response, so that incoming messages from the controller can be matched to outstanding requests. Has anyone implemented such
a mechanism using StreamDevice?