Sony Arouje

a programmer's log

Archive for the ‘Raspberry Pi’ Category

Slack App to track our expenses hosted in a Raspberry Pi

with one comment

At 4Mans Land we keep struggling to track our expenses. We normally note the expenses in Whatsapp and later move to a shared excel sheet. But this is always have difficulties, there will be lot of noises in the whatsapp with ongoing discussions. We also use slack for discussions, so I decided to integrate an expense app and evaluated some. Most of them are paid and don’t want to pay for an app at this stage. One night decided to write an app for slack and by morning finished the basic app that can store expenses in a mongodb. This whole experiment started as a fun to play with some thing new and also understand the slack api.

Wrote the server in nodejs and choose mongo db for persistence. For testing the slack integration, I used ngrok to create a local tunnel. also evaluated localtunnel.me which is a free version, but very unstable. ngrok is good but we have to pay $5 per month for license.  Started evaluating other alternatives to host my server, heroku was another alternative and used it several times earlier. At the moment we wanted to spend less for hosting and infrastructure. At last decided to host the server at my home, I have a really good stable internet connection with more than 80mbps speed and a Gigabit router. Added a port forwarding at my router,  expected to access the port immediately but to my surprise it’s not working. Done port forwarding so many times earlier and could access stuffs inside my network without any issues, my ISP was different that time. Then called up my ISP support, they informed me that without a static ip I wont be able to do port forwarding, for static IP I have to pay a very minimal fee and is life long unless I switch the provider. Paid the amount and in 2 days got my static IP and could do port forwarding successfully. Also set up dynamic dns at noip.com to give a good name to my IP. With all these settings done, changed the url in slack app and used the one I setup at noip.com. Run the nodejs server at my dev machine and fired a command from slack app, viola received the command to the server running in my laptop. The server is ready and is running in my laptop, but required a system which could run 24/7. The cheap option came to my mind was to host the nodejs server in one of the Raspberrypi lying in my table, one night I decided to setup the pi with the latest Raspbian stretch.

Setting up the Raspberry pi

Expected to finish the whole setup in less than an hour, as did this several times earlier but not that day. After installing the stretch, apt-get update started throwing hash sum error, reinstalled the os couple of times. Same error again and again. This error sent me for a wild goose chase, reading one forum after another and tried all the suggestions but nothing changed. At last came across this stackoverflow post which fixed the issue and could update the os, phew.

Next installing the nodejs, used nodejs version maintained here and issue the ubuntu command, for e.g. to install nodejs 10 issue the below command from your raspberry pi

curl sL https://deb.nodesource.com/setup_10.x | sudo -E bash – sudo aptget install y nodejs

Next task is installing Mongodb, apt-get install mongodb installed an earlier version of mongodb and is not suitable for the mongoose orm which I am using in the code, either I have to use an older version of mongoose or try to find a way to install a new version of Mongodb. I choose the later and try hunting for some clues to install some newer version of mongodb. At the end, come accross this post, which has all the details of installing mongodb in Rpi jessie, which is good enough in stretch as well, also he provided a link for stretch mongo binaries. Followed the instructions and at the end mongodb started running in my machine.

When I try to connect from Compass to rpi’s mongodb instance, it’s not getting connected. Reading through some docs and forums realized that I have to comment bind_ip in /etc/mongodb.conf, commented out that config and able to connect from compass.

Before going to bed at 2am, copied the nodejs code to rpi, did some testing and all went well. Could post expenses from slack to the service running in my pi. Went to bed with peace of mind.

What this app does?

The main focus of this app is to capture the expense, for now it uses slack command to forward text to the service. Initially created a strict pattern to record expense for e.g.

/expense spent 4000 INR on Jill to fetch a pail of water by Jack

Here spent should be first word followed by amount, after ‘on’ specify the description and after ‘by’ specified who paid the amount. The nodejs service will parse them and place them in separate fields in mongodb collection. Then to query the expense, some thing like

/expense query date today

/expense query date 05/12/2018 – 05/14/2018

So here ‘spent’ and ‘query’ is a keyword, based on this keyword different handling logics will kicks in and complete the task.

I felt the syntax is more restrictive, started analyzing options to process the sentence more naturally. I come across natural, a NLP library for nodejs. Using natural’s BayesClassifier trained the system to categorize the input text and derive the right keyword, which again calls the different logic and get the task done. After the classification training, the system can take inputs like

/expense Jack paid 4000 by Card for ‘Jill to fetch a pail of water’ on 05/16/2018

The above code will classified as spent, then added some code to extract relevant part from the text. Not pure NLP approach, any thing inside single quotes will be considered as expense. Any date in the text is considered as the payment date and so on. I am learning NLP, in future I might achieve a better translation of text.

Querying command is modified as shown below

/expense today

/expense between 05/12/2018 – 05/14/2018

Can also query and return expenses in csv format

/expense today csv  will return the expense in comma seperated format.

Slack output

image

After each expense created successfully, it returns the expense with the ID and the actual text we passed to the expense command. For e.g to create first expense passed the text like

/expense Jack paid 4000 to ‘Jill to fetch a pail of water’

Here is the output for querying todays expense, issue a command like

/expense today

image

 

In csv format (/expense today csv)

image

We can also delete an expense, only the expense you created can be deleted.

/expense delete today: delete all the expense you entered today

/expense delete 116: delete the expense with id 116

Had a great fun during this experiment and learned few things.

Happy coding…

Advertisements

Written by Sony Arouje

May 18, 2018 at 5:17 pm

RF Communication using nrf24L01 and Nodejs addon

leave a comment »

Recently I started experimenting with radio communication with low cost nrf24L01 modules. These modules are very cheap compare to XBee modules which I used earlier. With these nrf24 modules we could enable wireless communication between Arduinos and Raspberry pi very effectively and economically. For my experiment I used two nrf24 modules, one connected to an Arduino Uno and another to a Raspberry pi 1.  Here is the pin connection details

Seq NRF24L01 RPi Arduino Uno
1 GND 25 (GND) GND
2 VCC 17 (3.3v) 3.3v
3 CE 15 7
4 CSN 24 8
5 SCK 23 13
6 MOSI 19 11
7 MISO 21 12
8 IRQ

 

For testing the communication, I used the RF24Network library, which is very good and has good documentation. Also it comes with e.g for both Arduino and RPi. So I didn’t write any single code just used the e.g and able to see the communication working, initially I had some troubles and at the end every thing worked well, I can see the data coming from Arduino in RPi. 

My intention is to use these modules in RPi and write code in nodejs. Unfortunately there is no nodejs support for this library. So last night I decided to write a nodejs addon for this C/C++ library. I didn’t had any experience in writing a nodejs addon, I spend an hour understanding the Nan and creating very simple addons. Then I started writing the addon for RF24Network, this task was very hard than trying with simple hello world addons.

Node-gyp was keep on failing when it tries to compile the RFNetwork modules. In my searches I realized that node-gyp uses make utility and I need to add the C/C++ files of this library. At the end I could compile the node addon. See the binding.gyp file

{ "targets": [ { "target_name": "nrf24Node", "sources": [ "nrf24Node.cc", "RF24/RF24.cpp", "RF24/utility/RPi/spi.cpp", "RF24/utility/RPi/bcm2835.c", "RF24/utility/RPi/interrupt.cpp", "RF24Network/RF24Network.cpp", "RF24Network/Sync.cpp" ], "include_dirs": [ "<!(node -e \"require('nan')\")", "RF24Network", "RF24" ], "link_settings": { "libraries": [ "-RF24", "-RFNetwork" ] } } ] }

 

I should say, I am just a beginner in node-gyp and this binding.gyp might need some improvements. Anyway with this gyp file, the compilation succeeded.

Next is to create the addon file. Here I had to learn more about the data types of Nan and Callbacks. I started simple functions to begin with and compile again, then moved on to next. I took more time in understanding callbacks which allows the addon to call javascript callback functions. Also spend a lot of time in understanding threading and creating a module to continuous listening of incoming messages and trigger the callback function, so that nodejs can process those incoming messages. I use libuv for threading, it seems more easy to understand than Async worker modules in Nan.

That whole night I spend learning and writing and refactoring the addon, I finished the module by early morning. By that time I could write a nodejs app and could listen to incoming messages.

Here is the sample code in node js to listen and acknowledge the message back to the sender.

var rf24 = require('./build/Release/nrf24Node.node'); rf24.begin(90,00); rf24.printDetails(); rf24.write(1,"Ack"); rf24.readAsync(function(from, data){ console.log(from); console.log(data); rf24.write(from,"Ack"); }); process.on('SIGINT', exitHandler); function exitHandler() { process.exit(); rf24.close(); }

 

Here is the complete addon. The code is uploaded to github, with the steps to compile and use it your own nodejs applications.

#include <nan.h> #include <v8.h> #include <RF24.h> #include <RF24Network.h> #include <iostream> #include <ctime> #include <stdio.h> #include <time.h> #include <string> using namespace Nan; using namespace v8; RF24 radio(RPI_V2_GPIO_P1_15, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_8MHZ); RF24Network network(radio); Nan::Callback *cbPeriodic; uv_async_t* async; struct payload_t { // Structure of our payload char msg[24]; }; struct payload_pi { uint16_t fromNode; char msg[24]; }; //-------------------------------------------------------------------------- //Below functions are just replica of RF24Network functions. //No need to use these functions in you app. NAN_METHOD(BeginRadio) { radio.begin(); } NAN_METHOD(BeginNetwork){ uint16_t channel = info[0]->Uint32Value(); uint16_t thisNode = info[0]->Uint32Value(); network.begin(channel,thisNode); } NAN_METHOD(Update) { network.update(); } NAN_METHOD(Available) { v8::Local<v8::Boolean> status = Nan::New(network.available()); info.GetReturnValue().Set(status); } NAN_METHOD(Read) { payload_t payload; RF24NetworkHeader header; network.read(header,&payload,sizeof(payload)); info.GetReturnValue().Set(Nan::New(payload.msg).ToLocalChecked()); } //-------------------------------------------------------------------------------- NAN_METHOD(Begin){ if (info.Length() < 2) return Nan::ThrowTypeError("Should pass Channel and Node id"); uint16_t channel = info[0]->Uint32Value(); uint16_t thisNode = info[1]->Uint32Value(); radio.begin(); delay(5); network.begin(channel, thisNode); } NAN_METHOD(Write){ if (info.Length() < 2) return Nan::ThrowTypeError("Should pass Receiver Node Id and Message"); uint16_t otherNode = info[0]->Uint32Value(); v8::String::Utf8Value message(info[1]->ToString()); std::string msg = std::string(*message); payload_t payload; strncpy(payload.msg, msg.c_str(),24); RF24NetworkHeader header(otherNode); bool ok = network.write(header,&payload, sizeof(payload)); info.GetReturnValue().Set(ok); } void keepListen(void *arg) { while(1) { network.update(); while (network.available()) { RF24NetworkHeader header; payload_t payload; network.read(header,&payload,sizeof(payload)); payload_pi localPayload; localPayload.fromNode = header.from_node; strncpy(localPayload.msg, payload.msg, 24); async->data = (void *) &localPayload; uv_async_send(async); } delay(2000); } } void doCallback(uv_async_t *handle){ payload_pi* p = (struct payload_pi*)handle->data; v8::Handle<v8::Value> argv[2] = { Nan::New(p->fromNode), Nan::New(p->msg).ToLocalChecked() }; cbPeriodic->Call(2, argv); } NAN_METHOD(ReadAsync){ if (info.Length() <= 0) return Nan::ThrowTypeError("Should pass a callback function"); if (info.Length() > 0 && !info[0]->IsFunction()) return Nan::ThrowTypeError("Provided callback must be a function"); cbPeriodic = new Nan::Callback(info[0].As<Function>()); async = (uv_async_t*)malloc(sizeof(uv_async_t)); uv_async_init(uv_default_loop(), async, doCallback); uv_thread_t id; uv_thread_create(&id, keepListen, NULL); uv_run(uv_default_loop(), UV_RUN_DEFAULT); } NAN_METHOD(PrintDetails) { radio.printDetails(); } NAN_METHOD(Close){ uv_close((uv_handle_t*) &async, NULL); } NAN_MODULE_INIT(Init){ Nan::Set(target, New<String>("beginRadio").ToLocalChecked(), GetFunction(New<FunctionTemplate>(BeginRadio)).ToLocalChecked()); Nan::Set(target, New<String>("beginNetwork").ToLocalChecked(), GetFunction(New<FunctionTemplate>(BeginNetwork)).ToLocalChecked()); Nan::Set(target, New<String>("update").ToLocalChecked(), GetFunction(New<FunctionTemplate>(Update)).ToLocalChecked()); Nan::Set(target, New<String>("printDetails").ToLocalChecked(), GetFunction(New<FunctionTemplate>(PrintDetails)).ToLocalChecked()); Nan::Set(target, New<String>("available").ToLocalChecked(), GetFunction(New<FunctionTemplate>(Available)).ToLocalChecked()); Nan::Set(target, New<String>("read").ToLocalChecked(), GetFunction(New<FunctionTemplate>(Read)).ToLocalChecked()); Nan::Set(target, New<String>("readAsync").ToLocalChecked(), GetFunction(New<FunctionTemplate>(ReadAsync)).ToLocalChecked()); Nan::Set(target, New<String>("write").ToLocalChecked(), GetFunction(New<FunctionTemplate>(Write)).ToLocalChecked()); Nan::Set(target, New<String>("close").ToLocalChecked(), GetFunction(New<FunctionTemplate>(Close)).ToLocalChecked()); Nan::Set(target, New<String>("begin").ToLocalChecked(), GetFunction(New<FunctionTemplate>(Begin)).ToLocalChecked()); } NODE_MODULE(nrf24Node, Init)

All the credit goes to the developers of RF24 and RF24Network library, I just created an addon for the great library. Along the way I learned a lot and could finish the nodejs addon.

 

Happy coding…

Written by Sony Arouje

February 5, 2017 at 4:57 pm

Farm Automation system based on Arduino and Raspberrypi

with 3 comments

Last two weeks, in my free time, I was working on a system to automate  Green house or an open field. The system designed using Arduino Nano and Raspberry Pi. The Arduino is used to read sensors and control devices and the Raspberry pi is the brain that decides what to do when an event detected by Arduino. All the systems communicates wirelessly via XBee.

In normal scenario in a farm we have to

  • Switch on the drip irrigation pump when the soil humidity is low.
  • Switch off when the soil is wet.
  • Switch on the Main motor that connects to a water source when the reservoir level goes down.
  • Switch off the main motor when the reservoir is full.
  • If it’s a Green house then monitor the humidity and control devices to increase or decrease the humidity. Also need to control temperature.

 

Below is a very ugly drawing I could come up : ), to explain the system.

image

 

Arduino based nodes

The nodes are connected to different Sensors like Soil Humidity, Temperature, Air Humidity, etc. Also the nodes can also switch on/Off drip irrigation motor, switch on/off Reservoir’s Solenoid valves, or control any hardware needed in the field.

Raspberry pi Brain

I developed this central/brain system in Nodejs. The system is very much generic and run based on configurations. So nothing is hardcoded. The XBee connected to the pi act as the coordinator and receive periodic sensor inputs from Ardunio connected in the field. This system can issue command to control devices based on the sensor inputs.

 

Let’s go through some of the scenarios to see how the system works.

Watering the plants: From the above picture you can see, there are 5 Arduino’s in the field sensing different parameters. For now lets think that they all reads the soil humidity. Say soil humidity value range from 0 to 100, where 0 is dry and 100 is fully wet. We need to switch on the drip irrigation motor when any of the sensor value is less than 20. Once all the sensor give a humidity value greater than 90 we need to switch off the motor.

As you can see the system need to take action based on the values coming from the sensor. Depending upon the crops these values can be changed. That’s where the Central Node js system comes into play.

In the central system, we can group the Sensor nodes and configure the triggering points. Also we can configure what to do when the triggering points reach. For e.g. in the above case we can say when the soil humidity of any sensor goes below 20, then send the Motor switch on command to the node sitting next to the Reservoir motor. To switch off the motor, the system needs approval from all the sensors, that means the motor will get switched off if all the nodes reported value is greater than 90.

Failover: What happens when a sensor node dies without sending soil humidity greater than 90 value, will the motor run whole day? No, the central system can be configured for that too, while configuring we can set up a timeout period. If the central system is not receiving high water level after a configured time, it automatically sends a Switch off command to the desired Arduino node to switch off the motor.

Filling Reservoir: From the above diagram, we can see there are two reservoirs and one Main motor. The main motor need to switch on to fill the Reservoir. Each reservoir is equipped with sensors to detect the High and Low water level. Also each water input is equipped with a solenoid valve. If the reservoir is high then the solenoid valve will close the input thus protect the reservoir from overflowing. Once all the reservoir get filled the system will switch off the Main motor before closing the last solenoid, other wise the pressure increase and can damage the Main motor.

The Arduino node will send a Water low when the water go down below a desired level. Then the central system will open the Solenoid before switching on the Main motor. The valve will open only for the reservoir where the water is low, rest all the valves will be closed.

If more than one Reservoir’s water is low then those valves will be open and the main pump will work until all the reservoir’s are filled. For e.g. say Reservoir A and B’s water level is low then both the valves will be open and switch on the main pump. A get filled and B is still not full then A’s valve will get closed. Once B is full the system will send Main pump switch off command then sends the command to close B’s valve.

 

System design

All the above scenarios are based on certain rules and all these rules are configurable. The central system is not aware of any rules. Based on the fields condition we need to configure it.

 

User can also see the activities in the farm via a dashboard. I haven’t designed any Dashboard UI yet.

 

Happy farming…

Written by Sony Arouje

February 17, 2016 at 6:16 pm

Communication between Raspberry Pi and Arduino using XBee

with 17 comments

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….

Written by Sony Arouje

January 21, 2016 at 12:06 am

Raspberry Pi as a Development Server

leave a comment »

In my searches, I came across a very elaborate blog about Raspberry pi and how to utilize this small computer for development purpose. Also the post touches topic about how to configure Port forwarding to access the Pi from Internet.

Worth reading the blog: How to Turn Your Raspberry Pi Into a Development Server

 

Happy coding…

Written by Sony Arouje

October 30, 2015 at 10:55 am

Posted in Raspberry Pi

MQTT Protocol for Internet of Things (IoT)

with 8 comments

I was thinking about how to control my Aeroponic system remotely via internet. The Raspberry Pi controlling the system is connected to internet via a router. I could access RaspberryPi by Port forwarding and stuff like that but it’s complicated. Next option could be using Websockets but I felt it’s an overkill for the applications running in Pi.

Recently I received a Refcard from Dzone regarding a protocol called MQTT. I was not aware of this Protocol before. So thought of doing some experiment with it. I am not going much deeper into the protocol, Dzone refcard did a great job of explaining it well.

In a nutshell, MQTT consist of three parts.

  • Broker
  • Subscribers
  • Publishers

image

 

Publisher, publish message to a specific topic and any Subscriber subscribes for that topic receives the message. Broker is the central hub, both Publishers and Subscribers are connected to the Broker and it take care of delivering the message to all the subscribers subscribed for the topic.

Brokers

We can implement our own broker using RabitMQ or Mosca plugin for Node js or any other MQTT brokers available in the market. To experiment it, I used CloudMQTT addon in Heroku. I used Heroku just to manage every thing from one central place.

Dev Environment

I created two set off Node js application, one running in my computer as a publisher and another running in my RaspberryPi as a subscriber. Both have no direct connection instead they are connected to CoudMQTT broker. Below is a test code and nothing related to my Aeroponic system.

Publisher Code

var mqtt = require('mqtt');
var client = mqtt.createClient('<<PortNumber>>', 'm11.cloudmqtt.com', {
    username: '<<UserName>>',
    password: '<<Password>>'
});

client.on('connect', function () { // When connected
    
    // subscribe to a topic
    client.subscribe('TEMPERATURE_READING', function () {
        // when a message arrives, do something with it
        client.on('message', function (topic, message, packet) {
            console.log("Received '" + message + "' on '" + topic + "'");
        });
    });
    
    // publish a message to a topic
    client.publish('SET_TEMPERATURE', '24', function () {
        console.log("Message is published");
      });
});

 

The above code act as a Publisher as well as a Subscriber. For e.g. the above code can be a piece running in Internet and the Pi’s can Publish the Temperature readings in a periodic interval and logged in a central db. We can see the readings via a webapp or which ever the way we need. Also if required we can set a temperature to all the connected RPi’s by publishing a message to topic ‘SET_TEMPERATURE’.

Subscriber Code

var mqtt = require('mqtt'), url = require('url');
var client = mqtt.createClient('<<Portnumber>>', 'm11.cloudmqtt.com', {
    username: '<<UserName>>',
    password: '<<Password>>'
});

client.on('connect', function () { // When connected
    
    // subscribe to a topic
    client.subscribe('SET_TEMPERATURE', function () {
        // when a message arrives, do something with it
        client.on('message', function (topic, message, packet) {
            console.log("Received '" + message + "' on '" + topic + "'");
           // set the temperature. 
        });
    });
    
});

 

The code is very minimal and we could achieve an easy communication to all the connected devices. In the above scenario clients are always connected. If you want to end the connection then call ‘client.end()’.

Later I implemented a Broker using Mosca, both scenarios the system worked really well.

Written by Sony Arouje

September 3, 2015 at 5:29 pm

Posted in Raspberry Pi

Tagged with ,

RS485 Communication Protocol with Micro Controllers and Raspberry pi

with 8 comments

We are in the age of connected devices, devices could talk each other either via RF or wired. In one of my post I explained about Radio Frequency communication using Xbee. In this post lets see how devices can talk each other via wired network. One of the advantage of Wired network is, it is cost effective compare to buying an XBee modules like Xbee pro. I personally prefer Wireless communication as it’s hassle free, just place the devices where ever we need.

In my previous post I explained how to Bootload Atmega16A and program it using Arduino. Next step is to establish the communication between the Micro controllers and Raspberry pi. In this case my Raspberry Pi is acting as the central hub that talk to other controllers and collect data or issue command to do some job.

RS 485 Protocol

I better leave it to Wikipedia to give a detailed explanation of the protocol. In brief using RS485, devices can communicate Full duplex or Half duplex. I used a Half duplex communication. So it’s a protocol, how do we implement the protocol in our hardware, there is a chip Max485 from Maxim. This chip can establish a half duplex communication.

Max485 Pin configuration

Max 485 is a 8 pin chip as shown below. It’s a DIP chip and SMD have different pin layout.

image

Image from Maxim site

Pin 1 – RO: It’s the Data-In pin, devices can read data from the bus using this pin. Rx pin of the Micro controllers should connect to this pin.

RE and DE: Set this pin to Logical High to transmit any data to the bus. Set this pin to Low to receive data from the bus.

Pin 4 DI: Devices can transmit data via this pin.  This pin should be connected to the Tx pin of the device.

Pin 8 and 5 – VCC and GND: To power the chip, VCC should be 5 volt.

Pin 7 and 6 – A and B: Here we connect the data line. A should connect to the A Pin of the next Max 485 and B with B.

 

Connection Diagram

The below picture will illustrate how to connect all the devices together.

RS485_SerialCommunication_bb 

Image created using Fritzing

As per the diagram, if RPi want to transmit any data. We should set a high voltage on GPIO 18 and issue a serial write. All other devices in the network will be in listening mode and can read data using serial read, if any other device wanted to transmit data, then issue a Logical High to RE DE pin and will get promoted as a master and transmit data via serial write.

Now it’s up to you to program it and do some cool things with it.

Written by Sony Arouje

April 23, 2015 at 11:05 pm

%d bloggers like this: