In this blog post I’m going to discuss how to connect a Raspberry Pi to an Arduino via USB and then communicate between them serially.
If you want to communicate between an arduino and an RPI using I2C, see this older post: Raspberry Pi/I2C with Lazarus/Free Pascal.
In my last post, I did the same thing, except communicating between a PC and an Arduino serially. For this project, the arduino is configured exactly the same and running exactly the same software as it was in my prior post.
The basic idea of the project is to communicate with an Arduino that has a switch, motion detector, and LED on it. The RPI sends commands to the arduino to read the status of the switch and motion detector and to turn the LED on and off. The RPI will first look at the switch. If it is on, then it will look at the motion detector. If motion has been detected then the RPI will tell the arduino to turn on the LED. If not, it will request the LED be turned off.
You will want to look at the prior post to see how the hardware is setup and how the software works as I literally moved the software from the PC to the Raspberry Pi, made a couple of tweaks and it runs as it did in on the PC.
The Arduino-PC post can be found here: Serial Communications between a PC and an Arduino Using Lazarus / Free Pascal.
When I wrote the software that runs on a PC, it was my hope that it would require minimal changes to migrate to a Raspberry Pi. Turns out it was VERY easy. Free Pascal’s ability to move effortlessly between platforms proves itself again. I had to tweak the serial library to remove a few constants not found on the RPI. Within my own code, I needed to remove the calls to the windows multimedia library call and handle abnormal program termination (explained later).
Getting the Hardware Connected
I was not sure exactly how I was going to access an arduino serially from the RPI. Everything I read indicated I would need to use the RPI’s serial port on its the GPIO pins. I really was hoping I could just use the RPI’s USB port.
I found the answer on Oscal Liang’s blog: http://blog.oscarliang.net/connect-raspberry-pi-and-arduino-usb-cable/
Before you connect the arduino to the RPI via the USB port do this:
Type lsusb to see what USB devices are currently present:
Now type ls /dev/tty* to see what serial ports are currently defined:
Now connect the Arduino to the RPI via the USB port. Again type lsusb to verify the arduino is now being seen by the USB drivers:
and again type ls/dev/tty* to find out what device has been added. This will be the serial port we will be accessing from the RPI’s pascal program:
As you can see by the lsusb command, the arduino is being seen by the RPI and the tty device for the serial port is named /dev/ttyACM0.
That was, to me, amazingly simple. I was expecting there to be a lot more involved in getting serial access to an USB port via Linux.
Testing the Hardware
Everything appears to be running, now let’s make sure we can really communicate. First, download, compile, and install the Arduino’s software (the link is at the end of this post).
Once that is done, the Arduino will be expecting valid packets from the RPI. We are going to send a bogus packet and verify we get a valid error response back. If we do, then the link is running. We do this by simply running minicom on the RPI and typing in a bogus packet to send to the arduino.
First, type minicom at the command prompt. If the command fails, install it by typing:
sudo apt-get install minicom
Now you will simply run minicom, telling it to connect to the serial port that you discovered in the steps above. In my case, the serial port is /dev/ttyttyACM0, so I type:
minicom -b 9600 -o -D /dev/ttyACM0
This will start minicom. Now simply type a bogus packet ‘1111’ and press the return key. You should get a response of =049:
This is the response one would expect when the arduino gets an unknown packet. (‘=’ is the checksum, ’04’ is the length of the packet, and ‘9’ is the code for unknown command.
You are now communicating between the arduino and RPI. You have also installed the software on the arduino. The last step is to get the Free Pascal code running.
Tweaking the Free Pascal Code for the Raspberry Pi
If you have not done so already, install Lazarus on the Raspberry Pi:
I do not include the synaser library in my code. You will need to download that on your own. See Serial Communications between a PC and an Arduino Using Lazarus / Free Pascal for instructions on getting the synaser library.
Unfortunately the Synaser library doesn’t compile on the RPI without a few tweaks. The synaser library has defined some baud rates that are not defined on the RPI. I don’t know why this is, but it is easy enough to fix.
In my project, I have copied the synaser library into a directory inside of my Pascal source. Since I don’t intend to use this copy of the library with anything else, I modified it directly. I wouldn’t do that for any kind of production software, but this is a simple test program so I’m not to concerned about having to support it 5 years down the road.
In the file synaser.pas you will see:
Change maxrates from 30 to 19 because you are going to delete the undefined baud rates.
Now delete the lines marked in red here:
Save synaser.pas. It will compile fine now.
Now open the Pascal project. I have already made the necessary tweaks in the Pascal code so it will compile on the RPI. These tweaks were:
The RPI does not support the windows MMSystem unit. That was commented out and the sndPlaySound call has been removed. So when motion is detected, the RPI will not play sound. This should be easily remedied, but I did not follow up on it myself.
The COM ports are named differently in unix, so initializeComm now simply accepts an entire string as the COM port and opens that. So you must enter ‘/dev/tty<whatever>’ as the COM port.
In windows, I can let the main while loop run as an infinite loop and control-C to stop the program. Windows properly closes the COM port when the program terminates. RPI’s version of Linux doesn’t do that and the COM port will be left open so you cannot run the program again.
To get around this, the RPI version of the Pascal program will exit the inifinite loop if the slide switch is off. This gives the Pascal program the chance to call commport.free which will properly close the COM port.
Compile the Pascal program. It should now run exactly as it did on the RPI as it did on the PC.
If something goes wrong and the Pascal program aborts, leaving the COM port open you can either reboot the RPI or simply run minicom as outlined above and exit out of it. That is enough to clear the COM port.
There you have it. A simple program that allows a Raspberry Pi to communicate with an Arduino via a USB serial connection.