Archive for January 2016
Arduino Scheduler: sleep x time then run for y time
Recent days I was playing with my Arduino uno to perform several tasks. One task is something like, say sleep for 10 mins and switch on a pin for 3 mins then sleep for 10 mins, and the cycle continues. I evaluated several libraries but most of them run a task based on an interval. For e.g. toggle pin 13 every 1 minute, it’s more like a delay. But what I wanted was, delay for 2 minutes then give a HIGH voltage to pin 13 for 1 minute then write LOW to pin 13 and again sleep for 10mins.
My search leads nothing, so I decided to write a quick and dirty Scheduler for me. I came up with a library after spending 3 hours yesterday night. I didn’t had much programming experience in C++, so I had to spend some time to understand how things work in C++ world. I also use the Timer library as a reference.
Let’s see the sketch that use my library.
#include "TaskScheduler.h" TaskScheduler t1; TaskScheduler t2; TaskScheduler t3; void setup() { Serial.begin(9600); pinMode(13, OUTPUT); pinMode(12, OUTPUT); t1.sleepThenToggle(4000,1000,13,HIGH); t2.every(2000,readSensor); t3.write(12,HIGH,4000); } void readSensor(){ Serial.println("Reading sensors..."); } void loop() { t1.update(); t2.update(); t3.update(); }
Here I declared three tasks, t1, t2 and t3.
Task t1 is a toggle pin task with sleep, in the sample code above, Arduino sleeps for 4000ms then switch on pin 13 for 1000ms and the cycle continues.
- sleepThenToggle(<sleep time>,<keep the pin state for x ms>,<pin number>,<starting state of the pin>);
Task t2 is a callback task, in the above case, the function readSensor will get called every 2000ms.
- every(<sleeptime>,<callback>);
Task t3 is a digitalWrite with timeout. One scenario we can use that functionality is, say the switching on/off of a pin is based on an external command, it might be coming from a Raspberry pi. In a situation if the Pi went down with some reason after issuing a switch on command then Arduino will keep the Pin on till a reset. These scenarios, we can use write, in the above code, the pin 12 will be HIGH for 4000ms, after that it will get switched off automatically.
- t3.write(<pin number>,<starting state of the pin>,<timeout period>);
Make sure to call the ‘update()’ in the loop, other wise no action will be taken.
For the curious minds visit my Gitrepo to see the code.
Happy coding…
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….