Posts Tagged ‘Softserial’
Communication between Raspberry Pi and Arduino using XBee
Recently I was doing some experiments to establish a wireless communication between a Raspberry pi and Arduino. To establish wireless communication I used XBee Pro Series 2 from Digi International. The idea behind this test setup is to test, whether I can control devices like motor or read different sensors remotely.
One of the biggest advantage of using XBee is, you can find a lot of tutorials and libraries for any kind of system and programming languages. For this test app, I used Node js in RPi and C in Arduino.
Test Setup
XBee: I configured two xbee, one as Coordinator and another as Router. Both in API mode 2 (AP =2). I used XCTU to configure both the device. Only reason to choose API 2 is because the Arduino library I used only support API mode 2.
Raspberry pi: connected Coordinator XBee to one of my RPi. You can see more about the connection in one of my earlier post.
Arduino Uno: connected the Router xbee to one of my Arduino. The connection is pretty simple as below.
-
XBee Rx –> Arduino Tx
-
XBee Tx -> Arduino Rx
-
XBee 3.3v-> Arduino 3.3v
-
XBee Gnd –>Arduino Gnd
Raspberry Pi Node js code
Modules used
- xbee-api: npm install xbee-api
- serialport: npm install serialport
var util = require('util'); var SerialPort = require('serialport').SerialPort; var xbee_api = require('xbee-api'); var C = xbee_api.constants; var xbeeAPI = new xbee_api.XBeeAPI({ api_mode: 2 }); var serialport = new SerialPort("/dev/ttyAMA0", { baudrate: 9600, parser: xbeeAPI.rawParser() }); var frame_obj = { type: 0x10, id: 0x01, destination64: "0013A200407A25AB", broadcastRadius: 0x00, options: 0x00, data: "MTON" }; serialport.on("open", function () { serialport.write(xbeeAPI.buildFrame(frame_obj)); console.log('Sent to serial port.'); }); // All frames parsed by the XBee will be emitted here xbeeAPI.on("frame_object", function (frame) { console.log(">>", frame); if(frame.data!== undefined) console.log(frame.data.toString('utf8')); });
Arduino Sketch
This sketch uses a XBee library, to add the library, goto Sketch->Include Library->Manage Libraries. From the window search for XBee and install the library. I am using Arduino IDE 1.6.7.
I use SoftwareSerial to establish serial communication with XBee, Pin 2 is Arduino Rx and Pin 3 is Arduino Tx.
#include <Printers.h> #include <XBee.h> #include <SoftwareSerial.h> unsigned long previousMillis = 0; const long interval = 4000; // the interval in mS XBee xbee = XBee(); // XBee's DOUT (TX) is connected to pin 2 (Arduino's Software RX) // XBee's DIN (RX) is connected to pin 3 (Arduino's Software TX) SoftwareSerial soft(2,3);// RX, TX Rx16Response rx16 = Rx16Response(); ZBRxResponse rx = ZBRxResponse(); XBeeAddress64 addr64 = XBeeAddress64(0x0013a200,0x407a25b5); char Buffer[128]; char RecBuffer[200]; void setup() { // put your setup code here, to run once: soft.begin(9600); Serial.begin(9600); xbee.setSerial(soft); } void print8Bits(byte c){ uint8_t nibble = (c >> 4); if (nibble <= 9) Serial.write(nibble + 0x30); else Serial.write(nibble + 0x37); nibble = (uint8_t) (c & 0x0F); if (nibble <= 9) Serial.write(nibble + 0x30); else Serial.write(nibble + 0x37); } void print32Bits(uint32_t dw){ print16Bits(dw >> 16); print16Bits(dw & 0xFFFF); } void print16Bits(uint16_t w){ print8Bits(w >> 8); print8Bits(w & 0x00FF); } void loop() { // put your main code here, to run repeatedly: xbee.readPacket(); if (xbee.getResponse().isAvailable()) { if (xbee.getResponse().getApiId() == ZB_RX_RESPONSE) { xbee.getResponse().getZBRxResponse(rx); if (rx.getOption() == ZB_PACKET_ACKNOWLEDGED) { // the sender got an ACK Serial.println("got ACK"); } else { // we got it (obviously) but sender didn't get an ACK Serial.println("not got ACK"); } Serial.print("Got an rx packet from: "); XBeeAddress64 senderLongAddress = rx.getRemoteAddress64(); print32Bits(senderLongAddress.getMsb()); Serial.print(" "); print32Bits(senderLongAddress.getLsb()); Serial.println(' '); // this is the actual data you sent Serial.println("Received Data: "); for (int i = 0; i < rx.getDataLength(); i++) { print8Bits(rx.getData()[i]); Serial.print(' '); } //Received data as string to serial Serial.println(' '); Serial.println("In string format"); for (int i = 0; i < rx.getDataLength(); i++) { if (iscntrl(rx.getData()[i])) RecBuffer[i] =' '; else RecBuffer[i]=rx.getData()[i]; } Serial.println(RecBuffer); String myString = String((char *)RecBuffer); if(myString=="MTON"){ Serial.println("Switching on Motor"); } else if(myString=="MTOFF"){ Serial.println("Switching off Motor"); } } //clear the char array, other wise data remains in the //buffer and creates unwanted results. memset(&RecBuffer[0], 0, sizeof(RecBuffer)); memset(&Buffer[0], 0, sizeof(Buffer)); } //Send a packet every 4 sec. unsigned long currentMillis = millis(); if (currentMillis - previousMillis >= interval) { // save the last time you blinked the LED previousMillis = currentMillis; strcpy(Buffer,"RSLOW"); uint8_t payload[20]= "RSLOW"; // ZBTxRequest zbtx = ZBTxRequest(addr64,(uint8_t *)Buffer,sizeof(Buffer)); ZBTxRequest zbtx = ZBTxRequest(addr64,payload,sizeof(payload)); xbee.send(zbtx); } }
Burn the sketch to Arduino.
Testing
Run node js code in RPi and you start receiving the frames from Arduino.
Happy coding….