[NOTE! arduino-serial has been greatly updated. See the “Arduino-serial: updated!” post for details]
The Arduino’s USB port is actually a serial port in disguise. To your computer it appears as a ‘virtual’ serial port. This is good news if you want to write custom code on your computer to talk with the Arduino, as talking to serial ports is a well-solved problem. (Unfortunately, so well-solved that there’s many ways of solving it.)
On the Arduino forum there’s been a few requests for some example C code of how to talk to Arduino. The nice thing about standard POSIX C code is that it works on every computer (Mac/Linux/PC) and doesn’t require any extra libraries (like what Java and Python need). The bad thing about C is that it can be pretty incomprehensible.
Here is arduino-serial.c (github for full source), a command-line C program that shows how to send data to and receive data from an Arduino board. It attempts to be as simple as possible while being complete enough in the port configuration to let you send and receive arbitrary binary data, not just ASCII. It’s not a great example of C coding, but from it you should be able to glean enough tricks to write your own stuff.
Usage
laptop% ./arduino-serial Usage: arduino-serial -b <bps> -p <serialport> [OPTIONS] Options: -h, --help Print this help message -b, --baud=baudrate Baudrate (bps) of Arduino (default 9600) -p, --port=serialport Serial port Arduino is connected to -s, --send=string Send string to Arduino -S, --sendline=string Send string with newline to Arduino -r, --receive Receive string from Arduino & print it out -n --num=num Send a number as a single byte -F --flush Flush serial port buffers for fresh reading -d --delay=millis Delay for specified milliseconds -e --eolchar=char Specify EOL char for reads (default '\n') -t --timeout=millis Timeout for reads in millisecs (default 5000) -q --quiet Don't print out as much info Note: Order is important. Set '-b' baudrate before opening port'-p'. Used to make series of actions: '-d 2000 -s hello -d 100 -r' means 'wait 2secs, send 'hello', wait 100msec, get reply'
Example Use
Send the single ASCII character “6” to Arduino
laptop% ./arduino-serial -b 9600 -p /dev/tty.usbserial -s 6
This would cause the Arduino to blink 6 times if you’re using the serial_read_blink.pde sketch from Spooky Arduino.
Send the string “furby” to Arduino
laptop% ./arduino-serial -b 9600 -p /dev/cu.usbserial -s furby
Receive data from Arduino
laptop% ./arduino-serial -b 9600 -p /dev/cu.usbserial -r read: 15 Hello world!
The output is what you would expect if you were running the serial_hello_world.pde sketch from Spooky Arduino.
Send ASCII string “get” to Arduino and receive result
laptop% ./arduino-serial -b 9600 -p /dev/cu.usbserial -s get -r read: d=0
Internals
There are three interesting functions that show how to implement talking to serial ports in C:
int serialport_init(const char* serialport, int baud)
— given a serial port name and a speed, return a file descriptor to the open serial port.int serialport_write(int fd, const char* str)
— write out a string on the given a serial port file descriptorint serialport_read_until(int fd, char* buf, char until, int timeout)
— read from serial port into a buffer until a given character is received or timeout reached
You can and should write improved versions of the read and write functions that better match your application.
Update 8 Dec 2006:
Justin McBride sent in a patch because it turns out Linux’s termios.h doesn’t define B14400 & B28800. I’ve updated arduino-serial.c to include the patch, but commented out for now. No one uses those baudrates much anyway. :) If you need them, uncomment the additions out, or better yet, download Justin’s tarball that includes the changes and a Makefile to auto-detect your platform.
Update 26 Dec 2007:
Added ability to sent binary bytes with the ‘-n’ flag.
Added a delay option so you can open a port, wait a bit, then send data. This is useful when using an Arduino Diecimila which resets on serial port open.
Update 29 Apr 2013:
I apologize to everyone who has commented on this post but who hasn’t received a reply. This code has had a much longer life than I expected and it was hard to get back to it to fix some of its obvious deficiencies.
I did finally get back to it (but not the comments). I’ve rewritten arduino-serial a bit and added some new options. Hopefully this will address many of the issues people have had. You can read about the changes in the “Arduino-serial: updated!” post.
Also, arduino-serial now lives on Github at:
https://github.com/todbot/arduino-serial
Please post issues and patches there. Thanks!
hello, I have a problem with the sensor sht. My question is worth the program sht75 applied to sht15?
thanks
Can i use the –send-data to load an arduino sketch into the device without using the arduino GUI?
Just so people know, I was able to get this working under windows with just a little bit of playing around. The only real catch is you have to get the full POSIX support from somewhere. Cygwin is free and what I used, and in the end all you have to do is throw a single dll into the folder that your program is in, and it works just fine. I don’t have the source file that compiles fine as I ended up merging it with another program (very messy) but it works fine. Do NOT give up, keep trying and it should fall into place.
Hi Nick,
Oh, you’re on Windows? Low-level things like serial ports are dealt with in very different ways than Unix-based OSs like Linux & Mac OS X. Most people doing serial port stuff on Windows use either Visual Basic (or .NET) or Java with the RXTX serial library. You’d likely be better off not using any of my ‘arduino-serial’ code above, as it assumes a Unix-like environment. Do a Google search for “windows serial port library” and you’ll find lots of tips.
There are ways of getting full POSIX library support in Windows, but I think it’s complex to do if you’re not used to it.
Hello again todbot,
So I was making progress, or so I thought, because I was using windows xp installed on a Mac. This allowed me to use the termios.h etc. that was unavailable for windows. I tried to go back on my windows machine and it threw the same erorr:
termios.h: No such file or directory.
with a couple others(related). Any idea how (if?) I can somehow import this or get around it? thanks again very much
You would copy the functions in the arduino-serial source code into your C++ source file and call them from within the C++ file. But really what you should probably do, since you’re writing your own C++ code, is to Google around for “C++ serial port communication” for more native examples on how to communicate with serial ports with C++.
I am confused how to use the code at the top. Such as sending Furby or 6 to Arduino.
to send 6 it gave this (code?)
laptop% ./arduino-serial -b 9600 -p /dev/tty.usbserial -s 6
Would I want to write that into my C++ program word for word? I did this and was thrown errors, so not sure how to modify or use it. Thanks again for the help!
How would implement this in Visual Studio .NET 2005 ?
The POSIX libraries are not supported.
Hi Nick,
You can use C code from within C++, so you should be able to take any C serial port code (like the arduino-serial stuff above) and use it in your C++ program that talks to Arduino.
Hi Todbot,
I am not new to Arduino, though I have some cobwebs to sjake off as it’s been over a year since we made a self-playing LP record player together. (sampled portions of record using 2 servos and simple pulley system, VERY COOL!)
Anyways, I am a senior engineering student and for my senior design project I want to communicate data from a C++ program into Arduino and use the data to have Arduino control some hardware. Have you done anything like this? Any ideas how I could do this?
Thanks in advance!
:)
p.s. keep up the great site!!
The easiest is probably to get an Arduino. Its “language” is really C for AVR.
hi there,
i’m sorry if you cover this elsewhere, but i am just getting started in trying to program in C for the avr… do you have any recommendations on resources? just looking start with a simple blinkie code so i can figure it all out. i would really appreciate it. thank you!
Ahh great, thanks alot. Seems the minimum pause I can get mine to respond after is 1500, a bit more than the Arduino site’s recomended one second, oh well not too bad.
Thanks very much!
hmm, that’s odd because the addition of the trailing delay does work for me. I assume you can get it to blink as you would expect when using the Arduino Serial Monitor?
The other thing to try is to increase the first delay a bit, say to 2000.
Thanks for the reply, but that doesn’t help. It just takes longer between the opening and closing flash of the LED.
Any other ideas?
Hi Chris,
What you’re seeing is that when
arduino-serial
opens the port, it resets the Arduino, which causes a small flash on the pin13 LED, thenarduino-serial
sends the string (“6” in this case), and then before the Arduino can fully response,arduino-serial
exits, closing the port which causes the Arduino to reset again.The solution to this is to add another “-d” delay after you send the string, so you can watch the Arduino do its thing:
./arduino-serial -b 9600 -p /dev/tty.usbserial -d 1100 -s 6 -d 2000
The auto-reset feature of the Diecimila is great, but on Mac OS X & Linux, opening & closing the port always resets it.
Awesome! Thanks for this, will prove very useful.
I’m having trouble with it though. Using your example, I upload serial_read_blink.pde to the board and then use the command “./arduino-serial -b 9600 -p dev/tty.usbserial-A9003ZlI -d 1100 -s 6”
This is just the command you gave with an added pause as I have an Arduino Diecimila. The LED blinks as soon as I send the command, and then again at the end of the command (after 1.1 seconds I assume). There are no 6 blinks.
Any idea what the problem might be?
Thanks Andy! That really cleans up that section. I’ve patched the arduino-serial.c file so others can easily use it.
I wrote up a quick diff to clean up how nonstandard Bxxxxx macros are used — with this diff you can compile on any platform without having to edit the source, and all the baudrates supported by your platform will be supported by arduino-serial.
htttp://web.hexapodia.org/~adi/arduino/fix-arduino-serial-baudrates.diff