I'm new to the Arduino and the hardware side of things but I've been hanging out here reading the past few weeks and have been playing around a bit with my Arduino.
I've been tinkering with a few projects and have noticed a tons of devices that interface via the serial port (such as XBee, GPS, MMC card modules, GPRS modems, LCD displays).
Given how my geeky "vision" involves putting an XBee in everything I make, I'll already be short a serial port.
(What if my "boozeduino" needs a gps to get my location, a MMC card to track my BAC history, and a GPRS modem to text home and say I'll be a little late leaving the pub?)
I understand there is limited CPU power to go around, so maybe I'm expecting too much to be able to use more than two serial ports at once (one via hardware and the other software serial)?
One thought would be to open/close various serial ports on the fly as I needed them. However I'm not sure this is a pratical solution or not.
Writing via software serial is no big deal. It's a blocking operation, but you're in control so the waiting is not a problem. This works quite well for write-only devices, like a serial LCD. Software serial reads are a different animal - you're basically waiting for something to happen, instead of doing interesting work. Not cool.
My thought was to use another ATmega as an I2C or SPI peripheral. I have a board made at home to do that, just gotta work out some software. Also search the forum for the dual core arduino; it's two arduinos on the same PCB, connected by I2C.
There are dedicated UART peripherals, like the MAX3100/MAX3110 SPI UARTs, but I think the ATmega route is a bit more powerful.
There is also the possibility to multiplex the devices as you suggest, but that assumes you don't need the devices all that often and never two at the same time. That's probably the most complex solution.
So the implication is (a) without additional hardware I'm limited to two concurrent serial ports and (b) depending upon the device this won't be an issue if I switch between them (LCD's as you mention, also I MMC/SD cards would be the same; a GPS is a read situation but the data flow should be constant so I could afford to wait a known period of time).
I'll take a look at the dual core solution - that could be a fairly inexpensive solution (abeit adding a bit of size/power).
You can instantiate as many software serial ports as you want, but you can only use one at a time. If you are reading from or writing to one, you aren't doing anything else on any other port (except the hardware UART is still reading/writing if data is available).
So, if you've got a GPS on a software serial port and a serial LCD on another software serial port, you can write your code to ignore the GPS until you want some fresh data, and you can ignore the LCD until you've got new data to display.
I have no idea what you mean by SD/MMC cards, unless you've got some peripheral that interfaces with them. SD has an SPI interface mode. While that's technically serial (one bit after another on a single wire), it isn't RS232, which is the flavor of "serial" ports I have been discussing.
I think you're placing too much emphasis on concurrency. First of all, since HW serial library doesn't buffer output data, you can really only use one serial port at a time; you might get a whopping 2 bytes of overlap while the uart hardware dribbles out the last bytes from a Serial.write, but for the most part you should assume that nothing else runs while you're using the HW serial.
Secondly, the Basic Stamp allows "serout" on any pin, and as far as I know that also runs to completion (and can only be done on one pin at a time, same as software serial write on arduino), but it has still be found to be quite useful.
I guess it depends on how much you do in between calls to serial functions. If your program does MOSTLY serial IO, then you have problems. If you do "occasional" serial IO while mostly doing other stuff (including "doing nothing"), the current software serial library should be sufficient.
I guess it depends on how much you do in between calls to serial functions. If your program does MOSTLY serial IO, then you have problems. If you do "occasional" serial IO while mostly doing other stuff (including "doing nothing"), the current software serial library should be sufficient.
Agreed. That's the point I was trying to make in my second post.
I didn't realize the hardware UART (as implemented in Arduino, anyway) was blocking. Is that an Arduino implementation thing, or a hardware limitation?
Serial output is really slow (about 1ms/character at 9600bps) compared to CPU clock rates. (in general; not just on arduino.) If you generate lots of output, it'll eventually block on ANY sort of computer. The normal arduino HW serial support blocks after the 2nd output byte (the HW buffers one byte in the shift register and one in the "transmitting holding register"), which is pretty much "blocks all the time." I've contemplated splitting the input buffer (128 bytes) in half and dedicating 64 bytes to an output buffer (which would let you output a moderate sized line of text every second without blocking, for example.) But for most applications, it's probably more important to have the buffering where it is now (on input.)
Yes that's the case on most micros. However, if you use ISRs to feed or empty the buffer then there should be no blocking.
I don't know how this is implemented in the Arduino I assume that on RX there is an ISR that transfers the single byte hardware input buffer to the ram based buffer and that on TX it will block until the TX buffer is free. However if there is a ram based output buffer then an ISR can be triggered on the TX buffer empty flag to stop it blocking.
However, I do think it is fine the way it is and that the level of abstraction used is a good match to the experience level of the average user.
if you use ISRs to feed or empty the buffer then there should be no blocking.
Only if your average output rate is lower than the actual serial data rate. Otherwise, the buffer fills up faster than the ISR can drain it, till it fills up, and THEN you block...
An ATmega644 has two serial ports. You could use one for the XBee the other
for the RS232/USB.
You could also multiplex the serial port. Use one of the I/O lines to switch
the RS232 channel between ports. This would be a PITA if the ports had different
settings. You would loose buffering for the disconnected port. With more than two
ports this would be a real hassle.