We have a custom-built microcontroller card (ST32 / ARM Cortex M3) which has a camera attached. The camera captures 10-bit greyscale at 1280x1024 resolution. We need to send that image data back to a PC host over serial. That's quite a big chunk of data; at 115200 baud transfer would be 3 minutes, assuming everything goes fine. Anything I implement to ensure robustness would seem to slow that process down (eg split into blocks, checksum the blocks, ask for resend if corrupt). So was wondering how people might make a good compromise between speed and integrity.
We are currently seeing real transfer times of about 6 minutes. We had to set the UART baud rate at a weird value - 1036800 - because at 115200 there were issues (PC is running at 115200). I'm more software than hardware so any thoughts as to why that might happen would be helpful!
Start by doing some easy compression on your image.
Either run-length encoding or delta encoding will give you less data to send.
There are much better algorithms like TIFF but you may want to trade off the complexity of TIFF-ing your buffer for easier software on the embedded side.
Then you can afford something simple like Xmodem for your compressed data.
That has the useful property of being a standard protocol too.
That might lead you to using a terminal+xmodem transfer style interface to your host.
That would make debugging the interface pretty simple too.
Tim Williscroft's answer about compressing your data is a nice first step.
Now from the serial protocol side, the real transfer rate depends a lot on how you configure and implement your software both side. The baud rate is not the only thing to care about:
Are you using hardware flow control? If using hardware flow control, you will be able to significantly increase the baud rate (x10) without generating overrun errors.
From the STM32 are you using DMA, interrupts or even worth polling method to manage the data transmission? I don't know the exact STM32 reference you are using but on the STM32 I used, the UART transmission FIFO was limited to 1 byte. So you are merely obliged to use DMA if you have performance issues.
Still from the STM32 side, you can greatly improve performances taking care on the bus accesses (and possible conflicts arbitration) your application is doing.
Moreover on STM32, all clocks are configurable. Using an external high speed oscillator (if one available on board) may be a good way to improve performance over the internal RC oscillator. Also take care about internal bus clock configuration!
Now from the PC side, the performance may be impacted depending how your application bufferize & treat the received data.
The first thing to do is to look where the time is taken:
Observe your UART signal with a scope. As you said the transfer takes twice the theoretical time, you shouldn't see a continuous signal. Without hardware flow control it is the STM32 that takes time to output data. With hardware flow control, also look at the flow control signal to determinate which side causes the pauses (it may be both).
Related
I have a project in which I need to have the lowest latency possible (in the 1-100 microseconds range at best) for a communication between a computer (Windows + Linux + MacOSX) and a microcontroller (arduino or stm32 or anything).
I stress that not only it has to be fast, but with low latency (for example a fast communication to the moon will have a low latency).
For the moment the methods I have tried are serial over USB or HID packets over USB. I get results around a little less than a millisecond. My measurement method is a round trip communication, then divide by two. This is OK, but I would be much more happy to have something faster.
EDIT:
The question seems to be quite hard to answer. The best workaround I found is to synchronize clocks of the computer and microcontroler. Synchronization requires communication indeed. With the process below, dt is half a round trip, and sync is the difference between the clocks.
t = time()
write(ACK);
read(remotet)
dt = (time() - t) / 2
sync = time() - remotet - dt
Note that the imprecision of this synchronization is at most dt. The importance of the fastest communication channel stands, but I have an estimation of the precision.
Also note technicalities related to the difference of timestamp on different systems (us/ms based on epoch on Linux, ms/us since the MCU booted on Arduino).
Pay attention to the clock shift on Arduino. It is safer to synchronize often (every measure in my case).
USB Raw HID with hacked 8KHz poll rate (125us poll interval) combined with Teensy 3.2 (or above). Mouse overclockers have achieved 8KHz poll rate with low USB jitter, and Teensy 3.2 (Arduino clone) is able to do 8KHz poll rate with a slightly modified USB FTDI driver on the PC side.
Barring this, and you need even better, you're now looking at PCI-Express parallel ports, to do lower-latency signalling via digital pins directly to pins on the parallel port. They must be true parallel ports, and not through a USB layer. DOS apps on gigahertz-level PCs were tested to get sub-1us ability (1.4Ghz Pentium IV) with parallel port pin signalling, but if you write a virtual device driver, you can probably get sub-100us within Windows.
Use raised priority & critical sections out of the wazoo, preferably a non-garbage-collected language, minimum background apps, and essentially consume 100% of a CPU core on your critical loop, and you can definitely reliably achieve <100us. Not 100% of the time, but certainly in the territory of five-nines (and probably even far better than that). If you can tolerate such aberrations.
To answer the question, there are two low latency methods:
Serial or parallel port. It is possible to get latency down to the millisecond scale, although your performance may vary depending on manufacturer. One good brand is Brainboxes, although their cards can cost over $100!
Write your own driver. It should be possible to achieve latencies on the order of a few hundred micro seconds, although obviously the kernel can interrupt your process mid-way if it needs to serve something with a higher priority. This how a lot of scientific equipment actually works. (and a lot of the people telling you that a PC can't be made to work on short deadlines are wrong).
For info, I just ran some tests on a Windows 10 PC fitted with two dedicated PCIe parallel port cards.
Sending TTL (square wave) pulses out using Python code (actually using Psychopy Builder and Psychopy coder) the 2 channel osciloscope showed very consistant offsets between the two pulses of 4us to 8us.
This was when the python code was run at 'above normal' priority.
When run at normal priority it was mostly the same apart from a very occassional 30us gap, presumably when task switching took place)
In short, PCs aren't set up to handle that short of deadline. Even using a bare metal RTOS on an Intel Core series processor you end up with interrupt latency (how fast the processor can respond to interrupts) in the 2-3 µS range. (see http://www.intel.com/content/dam/www/public/us/en/documents/white-papers/industrial-solutions-real-time-performance-white-paper.pdf)
That's ignoring any sort of communication link like USB or ethernet (or other) that requires packetizing data, handshaking, buffering to avoid data loss, etc.
USB stacks are going to have latency, regardless of how fast the link is, because of buffering to avoid data loss. Same with ethernet. Really, any modern stack driver on a full blown OS isn't going to be capable of low latency because of what else is going on in the system and the need for robustness in the protocols.
If you have deadlines that are in the single digit of microseconds (or even in the millisecond range), you really need to do your real time processing on a microcontroller and have the slower control loop/visualization be handled by the host.
You have no guarantees about latency to userland without real time operating system. You're at the mercy of the kernel and it's slice time and preemption rules. Which could be higher than your maximum 100us.
In order for a workstation to respond to a hardware event you have to use interrupts and a device driver.
Your options are limited to interfaces that offer an IRQ:
Hardware serial/parallel port.
PCI
Some interface bridge on PCI.
Or. If you're into abusing IO, the soundcard.
USB is not one of them, it has a 1kHz polling rate.
Maybe Thunderbolt does, but I'm not sure about that.
Ethernet
Look for a board that has a gigabit ethernet port directly connected to the microcontroller, and connect it to the PC directly with a crossover cable.
I'm trying to understand whether its redundant for me to include some kind of CRC or checksum in my communication protocol. Does the chrome.serial and other chrome hardware communication API's in general if anyone can speak to them (e.g. chrome.hid, chrome.bluetoothLowEnergy, ...)
Serial communications is simply a way of transmitting bits and its major reason for existence is that it's one bit at a time -- and can therefore work over just a single communications link, such as a simple telephone line. There's no built-in CRC or checksum or anything.
There are many systems that live on top of serial comms that attempt to deal with the fact that communications often takes place in a noisy environment. Back in the day of modems over telephone lines, you might have to deal with the fact that someone else in the house might pick up another extension on the phone line and inject a bunch of noise into your download. Thus, protocols like XMODEM were invented, wrappering serial comms in a more robust framework. (Then, when XMODEM proved unreliable, we went to YMODEM and ZMODEM.)
Depending on what you're talking to (for example, a device like an Arduino connnected to a USB serial port over a wire that's 25 cm long) you might find that putting the work into checksumming the data isn't worth the trouble, because the likelihood of interference is so low and the consequences are trivial. On the other hand, if you're talking to a controller for a laser weapon, you might want to make sure the command you send is the command that's received.
I don't know anything about the other systems you mention, but I'm old enough to have spent a lot of time doing serial comms back in the '80s (and now doing it again for devices using chrome.serial, go figure).
I'm using Chrome's serial API to communicate with Arduino devices, and I have yet to experience random corruption in the middle of an exchange (my exchanges are short bursts, 50-500 bytes max). However, I do see garbage bytes blast out if a connection is flaky or a cable is "rudely" disconnected (like a few minutes ago when I tripped over the FTDI cable).
In my project, a mis-processed command wont break anything, and I can get by with a master-slave protocol. Because of this, I designed a pretty slim solution: The Arduino slave listens for an "attention byte" (!) followed by a command byte, after which it reads a fixed number of data bytes depending on the command. Since the Arduino discards until it hears an attention byte and a valid command, the breaking-errors usually occur when a connection is cut while a slave is "awaiting x data bytes". To account for this, the first thing the master does on connect is to blindly blast out enough AT bytes to push the Arduino through "awaiting data" even in the worst-case-scenario. Crude, yet sufficient.
I realize my solution is pretty lo-fi, so I did a bit of surfing around and I found this post to be pretty comprehensive: Simple serial point-to-point communication protocol
Also, if you need a strategy for error-correction over error-detection/re-transmission (or over my strategy, which I guess is "error-brute-forcing"), you may want to check out the link to a technique called "Hamming," near the bottom of that thread - That one looked promising!
Good luck!
-Matt
New here, so a bit about myself first:
I am a fire alarm commissioning engineer by trade, but like to mess with electronics as a hobby.
my main area of interest is integration between various systems (which is one of the reasons I like doing fire alarms, as they interface with most systems in big buildings) and have recently started getting more involved with serial comms to interface systems, rather than boring relay contacts.
In my house, I have an 8X8 audio/video matrix switcher, this connects the stereo systems in all the rooms to each other so that i can patch any rooms audio to any of the other rooms in the house.
This switcher has an RS-232 serial port on the back, which I'm hoping I can interface to either a PI or an arduino, so that I can control it via a web interface.
After a while searching, I found the protocol for it online... but things haven't gone so smoothly after that unfortunately.
Currently I'm just using a usb-232 converter and a null modem cable, along with a program called 232 analyser on my laptop...
I can read data fine, and send data to the unit... but it keeps spitting back a 'framing error' message.
I'm not sure what I'm doing wrong, please could someone advise? this is the first time I've really used serial so pointers would be cool.
One thing i did think is that the protocol specifies:
RS-232C STANDARD
START Bit 1
STOP Bit 1
DATA Bit 8
PARITY Bit EVEN
BAUD RATE 9600bps
CODE ASCII
TERMINATE
but my analyser program only lets me set the baud rate, data bits, parity, stop bit, and data format. not start bit. could that be my issue? and if so how do i get around it?
thanks so much in advance!
The format most commonly used for serial connections use one start bit, 8 data bits, no parity, and one stop bit.
I'm building an electronic device that has to be prepared for RS232 connections, and I'd like to know if it's really necessary to make room for more than 3 pins (Tx, Rx, GND) on each port.
If I don't use the rest of signals (those made for handshaking): am I going to find problems communicating with any device?
Generally, yes, that's a problem. The kind of problem that you can only avoid if you can give specific instructions to the client on how to configure the port on his end. Which is never not a problem, if that's not done properly then data transfer just won't occur and finding out why can be very awkward. You are almost guaranteed to get a support call.
A lot of standard programs pay attention to your DTR signal, DSR on their end. Data Terminal Ready indicates that your device is powered up and whatever the client receives is not produced by electrical noise. Without DSR they'll just ignore what you send. Very simple to implement, just tie it to your power supply.
Pretty common is flow control through the RTS/CTS signals. If enabled in the client program, it won't send you anything until you turn on the Request To Send signal. Again very simple to implement if you don't need flow control, just tie it logically high like DTR so the client program's configuration doesn't matter.
DCD and Ring are modem signals, pretty unlikely to matter to a generic device. Tie them logically low.
Very simple to implement, avoids lots of mishaps and support calls, do wire them.
And do consider whether you can actually live without flow control. It is very rarely a problem on the client end, modern machines can very easily keep up with the kind of data rates that are common on serial ports. That is not necessarily the case on your end, the usual limitation is the amount of RAM you can reserve for the receive buffer and the speed of the embedded processor. A modern machine can firehose you with data pretty easily. If your uart FIFO or receive interrupt handler or data processing code cannot keep up then the inevitable data loss is very hard to deal with. Not an issue if you use RTS/CTS or Xon/Xoff handshaking or if you use a master/slave protocol or are comfortable with a low enough baudrate.
What is the difference between a Relay Controller and a Microcontroller?
I'm looking into Arduino boards and am just getting into electronics, so I wanted to know the difference.
I know this is not a programming question, but I am developing in PHP and would like to know what the difference is before I start to code to make sure I'm going down the right path.
Those two devices are very different. Depending on exactly what you're trying to do, you may be able to use either, however. You'll have to tell more about your goal.
If you're switching high-current or high-voltage loads on and off, you'll need some sort of relay (or perhaps a large FET). If your current and voltage requirements are sufficiently low (5V, 40ma), you may be able to drive your load directly with the Arduino's output pins.
The Arduino is a microcontroller. That means it's an entire computer, just simplified. It has RAM, registers, an ALU, etc. Microcontrollers are generally specialized such that instead of interfacing to peripherals using some kind of bus like in a desktop computer processor, they have I/O capabilities built in, often simply in the form of outputs that can be set high (the input voltage, usually 5V) or low (0V) programmatically. The Arduino probably uses its own programming langauge, although there may be more than one language available for it (I've never used one). I doubt PHP is one of those langauges.
The relay controller is exactly what the name implies -- a simple circuit that controls some relays. Relays are electrically actuated switches. There's no intelligence in the relay controller. It can't be programmed; it must be controlled externally via USB. If you're attempting to interface with it from PHP on a desktop/server computer, this is probably your best choice. You're right that it's expensive. You could probably build your own for a fraction of the cost, especially if you're willing to use the parallel port on your computer (googling for how should give simple instructions). It's worth noting that that relay controller, and presumably most others, likely contain some kind of microcontroller with the I/O pins connected to circuitry that increases the current and/or voltage to the point where it can drive the relay, which in turn switches the load.
Hmm... only very vaguely programming related :) I think we may need another StackOverflow for electronics. Maybe SparkOverflow?