Sony Arouje

a programmer's log

Archive for the ‘Arduino’ Category

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

Program ESP8266 with Arduino IDE

with 4 comments

Last couple of days I was trying to setup an ESP8266 module to program using Arduino environment. By Default ESP8266 bootloaded with AT Bootloader. Initially I connected ESP to Arduino and communicated using AT Mode via WiFiESP library.

The intention of my experiments is to add internet support in my Aeroponic controller. But AT mode deals with strings and thus increase the flash size, and when I added MQTT functionality with rest of Aeroponic sketch, I almost filled the flash size of Atmega328. So I decided to look for alternative options.

One of the beauty of ESP8266 is, it has it’s own flash memory. Also the integration with Arduino IDE. This way I can write Arduino sketch and embed it into ESP8266 instead of writing it to Atmega328.

Installing ESP8266 addon to Arduino IDE.

Sparkfun have a nice post about setting up the IDE. At the end of tutorial they choose ‘Sparkfun ESP8266 Thing’, instead I selected ‘Generic Esp8266 Module’, see the screen shot below.

 esp_arduino_ide

Hardware Connection

To write Arduino sketches to ESP we need a USB TTL module. Connect the module as below.

  • ESP8266-> USB TTL
  • GND-> GND
  • TX-> RX
  • RX-> TX
  • GPIO0-> GND

I powered the ESP module from an external source, ESPs are really power hungry, I am not sure whether the USB module can give the required current.

  • ESP8266-> External power
  • VCC-> 3.3v
  • CH_PD->3.3v

Make sure you have a  common GND, for ESP, External power and USB TTL. That means connect all GNDs together. If there is no common GND then expect the unexpected, IDE will keep throwing fatal exception.

Once the sketch is uploaded, connect GPIO0 to VCC, then switch off/on the ESP module. Now the ESP will start running the sketch.

Challenges

Keep getting wdt reset message as shown below. To test I added the blink demo with a serial write. This simple program works well until I add ‘ESP8266WiFi.h’, after this header file and uploading the sketch will start throwing the below in Serial monitor.

ets Jan 8 2013,rst cause:4, boot mode:(3,6)

wdt reset
load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
v09f0c112
~ld

I tried a lot of options to resolve this issue. First I thought the module is not receiving enough current, so I powered it with 5v. This doesn’t make any difference.

In one of ESP forums some one suggest to erase flash using ESPTool, so I setup ESPTool and issued command like

python esptool.py p com6 erase_flash

This didn’t work out either. In another forum one person suggest to write blank.bin to 0x7E000, also mentioned that some times the reset can occur because of corrupted flash. This leads me to believe that corrupted flash causing the reset. So I decided to start all over again.

As an initial step I decided to boot with default AT bootloader. Here is a great post to follow.

While trying to bootload, esptool crashes always with ‘fatal exception’. I changed my USB Serial and tried again, this time all the bootloading steps works and configured the ESP back to AT mode. Then again I tried to burn the arduino sketch via Arduino IDE and it worked really well.

So I believe the wdt reset caused by, an issue with USB Serial module or corrupted flash. Now ESP8266 is working fine without any reset.

Written by Sony Arouje

November 7, 2016 at 11:40 pm

Posted in Arduino

Tagged with

Aeroponic Controller V4

with 2 comments

After the successful completion of my Aeroponic Contoller V3. I started designing the next version of the PCB. This time I decided to package every thing in a single board. In V3, controller depends on external relay modules to on/off devices. In the new version Relays are inbuilt. One of the major change in the new version is, the system is controlled by a bare bone Arduino using Atmega328. The new board has all the features of V3 plus some new features.

The board has several debugging features which allow me to monitor the internal activity of the system via a serial monitor. The board also has the ability to communicate to an external Arduino via I2C, this feature is very essential in case of testing and bug fixing.

V4 Controller with inbuilt Relay modules

IMG_1642

 

IMG_1644

 

V3 Controller with external relay modules

The below system is currently operational at my home. As you can see the system uses 4 external relay modules.

IMG_1255 - Copy

Features of the Controller system

Controlling Water Pump: One of the crucial part of Hydroponic/Aeroponic system is the cycling of water in periodic intervals. A water pump is used to cycle the water. The controller should be able to switch on motor in a particular interval and keep it on for a configured time. Say run motor every 30 mins and keep it on for 3 mins. This settings can be configured from the mobile application.

Nutrient Feeder: In Aeroponic/Hydroponic the fertilizers (called as nutrients) are mixed into the water. In normal scenario we need to add it manually, the system uses two dosage pumps to add nutrients. We can add nutrients two way, either via the mobile app or by manually pressing a button. Through mobile app, we can specify how may ml of nutrients need to mixed to water.

Nutrient Mixer: Used a small wave maker to mix the nutrients while adding it.

Maintain Reservoir Water Level: One of the important thing to consider is, the water pump should not dry run, if it does then ready to buy a new one. In this version, used water level sensors to know the water level. The system used a solenoid valve, which is connected to a water source. When the water level goes down to a set level, system will activate the valve and start filling the reservoir. Once the water reaches a set level, system will switch off the valve.

pH Feeder: This is a new feature, it’s very similar to Nutrient feeder. Instead of adding nutrients this feeder adds pH modifier like Phosphoric acid or similar modifiers to correct the pH level of the water.

Real Time Clock: To deal with time critical logics.

WiFi Module: Allow the system to communicate with Internet, this allow me to control the system from any where in the world.

Communication with the Controller: I am reusing the Android application I wrote for V3. As of now the system talks via Bluetooth.

Written by Sony Arouje

October 6, 2016 at 2:33 am

Posted in Arduino

Tagged with ,

ISP Shield for Arduino Uno to program 3 different Atmega

leave a comment »

Couple of weeks ago I designed and etched a home made pcb to program my Atmega 40 pin family micro processors. After that I redesign the PCB layout, so that I could program all the necessary processors like Atmega 40 pin, Atmega 28 pin and Attiny 8 pin family processors in a single board. I named this board as Kevino after my son Kevin. I also wanted this board in Red because my son is crazy about Red but fab house said it’s difficult for low volumes, so went with standard Green solder mask.

I received the board yesterday and assembled all the components. Below is the final outcome.

Snapseed (6)

 

 

Features of the board

1. Program any one chip by selecting the respective chip via the red dip switch.

2. The chips can be Bootloaded and programmed via Arduino uno Or using a USBASP programmer.

3. Should be able to program and monitor serial communication using USB to TTL Adapter. I can plug the TTL adapter to the female pins in the board.

4. I can also test Blink program, an on board LED to test Blink and make sure the chip bootloaded successfully.

 

Let see how it looks when connected to Uno

Snapseed (7)

 

With this shield I can Bootload and program all the Atmega Processors I used for experimenting.

 

Happy hacking…

Written by Sony Arouje

July 3, 2016 at 1:16 pm

Home made DC – DC converter for Microprocessor

leave a comment »

One important tool when you deal with Microprocessors are, regulated power supply. To power my standalone Atmega’s and test the working I assembled a regulator in a breadboard along with Atmega. I cant relay on some thing running in a breadboard, a loose wire can create tiring troubleshooting. So I decided to build a permanent solution by creating a PCB and assembling the components.

My requirement is simple, connect a 12v adapter and I need 5v and 3.3v output. The 3.3v should provide a minimum 300mA. I have to use this power supply to power ESP8266 or any module that uses 3.3v. I am using LM2575 to provide 5v and LM1117 for 3.3v. Theoretically LM2575 can withstand upto 40v.

Below is the Schematic.

schematic

 

Here is the PCB I created and assembled at home.

Printed side

IMG_1374

Lacking some soldering skills, still learning how to solder well.

IMG_1373

 

I can give input voltage via the DC Jack or screw terminal. Three female pins at the right hand side provide 5v, GND and 3.3v. Forgot to include a LED to show the voltage status.

Written by Sony Arouje

June 30, 2016 at 11:42 pm

Digital I/O Expander for Arduino

with 3 comments

When we work with processor like Amega328 or ATTiny85 we will come to a situation like we are running short of GPIO pins. One option is to go for 40pin processors like Atmega16/32/324, etc. But there are some cons with 16/32, these chips doesn’t have PCINT (Pin change interrupt) and we cant use software serial. If we are not dealing with Software serial then we can use these MC’s without any issues. Some of the experiments I am doing, deals with Software serial, so I decided to use Atmega328. But I need more Digital I/O pins. To get more IO we can pair Atmega328 with GPIO expanders like MCP23017 or MCP23S17.

Keep in mind that MCP23017 talks via I2C and MCP23S17 talks via SPI. I prefer I2C as it uses two pins of my Arduino, SCL and SDA. SPI needs 4 pins, MISO, MOSI, SCK and RESET. Also in my system there are several other chips connected to I2C bus and thus deals with only one type of communication.

Lets see how to connect MCP23017 to Arduino

MCP23017 Pinout

 

As you can see we have 16 GPIO’s in MCP23017, 1-8 and 21 to 28.

Connection

  • 5v to pin 9
  • GND to 10.
  • Arduino SCL to pin 12
  • Arduino SDA to pin 13.
  • MCS23017 RESET pin to pin9 with a 1k Resistor.

Now we need to set the I2C address of this pin. You can connect upto 8 MCP23017 by changing connection to A0 to A2 (pin 15 to 17). For e.g. connect all three pins to GND will get an address of 0, connect A0 to VCC and A1 and A2 to GND will give an address of 1 and so on.

Here I am connecting all the pins to GND and I get an address of 0.

 

Schematic

schema

 

Here I am not detailed the connection to Atmega328. I focused on the connectivity between 328 and MCP23017. To see how to run an Atmega in standalone mode, check this post.

Edit: As Anon suggested in comments sections, I added a pullup resistor to SDA and SCL lines. I2C is open drain and without a pullup resistor the system will not work.

Arduino Sketch

I used Adafruit library to interact with MCP23017, you also can directly interact with expander by just using wire library. There is a good post explaining how to write data to MCP23017 without any library.

#include <Wire.h> #include "Adafruit_MCP23017.h" Adafruit_MCP23017 mcp; void setup() { mcp.begin(0); mcp.pinMode(1, OUTPUT); } void loop() { delay(1000); mcp.digitalWrite(0, HIGH); delay(1000); mcp.digitalWrite(0, LOW); }

 

Here port 0 is referring to pin 21.

 

Here I talks about I2C connectivity but you can also use SPI using MCP23S17.

These expanders are not limited to Atmegas we can use it with Raspberry pi’s or any other processors that supports I2C or SPI communication.

Happy hacking…

Written by Sony Arouje

June 14, 2016 at 10:41 am

Posted in Arduino

Tagged with , ,

Schematic of standalone Arduino with FTDI Programming

with one comment

I recently wrote a post explaining how to setup an Arduino in a breadboard. This post will show the schematic of the system. It’s a very simple system with minimal components. Here I used Atmega 32a. To program the chip I used an FTDI module.

 

MinimalArduino

 

To program the chip via FTDI module, we have to bootload it first. I used an Arduino Uno as the ISP, I have a home made board to bootload or program Atmega 40 pin family processors.

Once the chip is programmed it can be directly powered by a 9 or 12v DC Adapter. Here I used LM2575 switching regulator to step down the source voltage to 5v. Switching regulators are very energy efficient and produce very less heat compare to linear regulators like LM7805. I am powering the system using a 12v DC source. If there is no adapter then the module can be powered from the FTDI module by shorting the jumper.

Here I configured the processor to run at 16MHZ external clock. If we are using 8MHZ internal clock then we can avoid the crystal and the two 22pF caps.

 

Happy hacking…

Written by Sony Arouje

June 3, 2016 at 9:48 am

Posted in Arduino

Tagged with , , ,

%d bloggers like this: