Raspberry Pi and mbed communication using the USB virtual com port
In some cases, it might be useful to use mbed with a Raspberry Pi. Mbed could do some real-time I/O tasks that might run too slow on the Pi under Linux or perhaps some extra I/O features on mbed are needed. The mbed could be plugged into the Pi's USB port for both power and communication using the USB virtual com port. A demo program will be provided for each device showing how to communicate between the two devices. If a lot of commands are needed, the mbed serial RPC library could be used.
On a Pi Zero W, the mbed board's USB virtual com port shows up in Linux as "/dev/ttyACM0". Using standard Linux file system I/O API calls it is possible to communicate with mbed just like a serial port by opening this device (when mbed is attached to one of it's USB ports) and using file write and read commands. Screen or minicom using this device name could also be used to type Linux commands to send to mbed without any code to check the hardware setup, but they must be installed first using apt-get in most Pi Linux distributions. It is possible that the device name might change if several other USB devices are plugged in (especially if they also have USB virtual com ports). One way to check for this is to type "ls /dev/ttyACM*" in the Pi console window to list any similar devices. If it does have a slightly different device name it will need to be changed in the open call in the demo code. The mbed device name will not show up unless it is plugged in.
mbed side demo code
To demo this communication setup, a short test program is needed for mbed. The code below reads in characters from the USB virtual com port and echoes them back using interrupts. Led1 on mbed toggles indicating interrupt character receive activity. To show that commands from the Pi can control the mbed, whenever the receive character is a '1' led2 turns on, and when a '0' is received led2 turns off. The mbed led pin assignments are for the LPC1768, if another mbed board is used change the led pins names.
#include "mbed.h" //Pi mbed USB Slave function // connect mbed to Pi USB RawSerial pi(USBTX, USBRX); DigitalOut led1(LED1); DigitalOut led2(LED2); DigitalOut led3(LED3); DigitalOut led4(LED4); void dev_recv() { char temp = 0; led1 = !led1; while(pi.readable()) { temp = pi.getc(); pi.putc(temp); if (temp=='1') led2 = 1; if (temp=='0') led2 = 0; } } int main() { pi.baud(9600); pi.attach(&dev_recv, Serial::RxIrq); while(1) { sleep(); } }
Pi side demo code
The code for the Pi will open the USB virtual com port checking for errors, then write out a header message, read it back and display it in a terminal window. It then sends the led off/on commands (i.e., a '1' and then '0') to mbed ten times with a one second delay using sleep(). Finally, it closes the port and exits. There are a lot of options to setup the serial port in Linux on the Pi!
#include <stdio.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <termios.h> int main(int argc, char ** argv) { int fd; char buf[256]; int n; // Open the Port. We want read/write, no "controlling tty" status, // and open it no matter what state DCD is in fd = open("/dev/ttyACM0", O_RDWR | O_NOCTTY | O_NDELAY); //open mbed's USB virtual com port if (fd == -1) { perror("open_port: Unable to open /dev/ttyACM0 - "); return(-1); } // Turn off blocking for reads, use (fd, F_SETFL, FNDELAY) if you want that fcntl(fd, F_SETFL, 0); //Linux Raw serial setup options struct termios options; tcgetattr(fd,&options); //Get current serial settings in structure cfsetspeed(&options, B9600); //Change a only few options.c_cflag &= ~CSTOPB; options.c_cflag |= CLOCAL; options.c_cflag |= CREAD; cfmakeraw(&options); tcsetattr(fd,TCSANOW,&options); //Set serial to new settings sleep(1); // Write to the port n = write(fd,"Hello mbed\r",11); if (n < 0) { perror("Write failed - "); return -1; } // Read the characters from the port if they are there sleep(2); n = read(fd, buf, 11); if (n < 0) { perror("Read failed - "); return -1; } else if (n == 0) printf("No data on port\n"); else { buf[n] = 0; printf("%i bytes read back: %s\n\r", n, buf); } sleep(1); //Send command to blink mbed led 10 times at one second rate //mbed code turns on led2 with a '1' and off with a '0' //mbed echoes back each character buf[1] = '\r'; // end of line buf[2] = 0; // end of string for(int i=0;i<10;i++) { write(fd,"1",1); //led on sleep(1); //one second delay read(fd,buf,1); //read echo character printf("%s\n\r",buf); //print in terminal window write(fd,"0",1); //led off sleep(1); read(fd,buf,1); printf("%s\n\r",buf); } // Don't forget to clean up and close the port tcdrain(fd); close(fd); return 0; }
Running the Demo
Download the earlier code to mbed, and then plug it into the Pi's USB connector. Then run the code above on the Pi. The leds will blink on the mbed, and a new terminal window on the Pi will show the printf's output while the program is running. It outputs error messages, if there is a open or read error return. Errors will occur if the mbed is not plugged in and running the test code, or an open error might indicate the device name needs to be changed.
Pi terminal output window sending data to and receiving data from mbed using the USB virtual com pot. '1's and '0's from the Pi toggle an led on the mbed board.
BeagleBone Boards
Mbed can also be plugged into a BeagleBone Board's USB connector for the same purpose. The device name is the same (i.e., dev/ttyACM0), so the same two demo programs work. It was tested on a BeagleBone Black Wireless board. If mbed has any external I/O devices drawing power, a powered USB hub may be needed.
Please log in to post comments.