Posts by Lorenzo Farnararo

[Raspberry Pi – Arduino ]Lamp Switch[/caption]
A month ago we planned to manage our Arduino irrigator (aka Irrigatorino) through the NRF24l01+ wireless module. Our little project has been subjected to a little change, since we decided to make our life easier (buahahah…) and remote control a light over a browser (yes, mobile too). Surprisingly, a lot of people liked the little demo I’ve made with some raw code and asked for a tutorial, so here we are:

Ladies and (more probably) Gentleman, I’m glad to present you the lamp driven by a browser switch!

Hardware:

To test the wiring we suggest you to use the ping/pong test you can find in the RF24 libraries (both, of the raspberry and the arduino).

Raspberry Pi

The connection between the Raspberry Pi and the NRF24l01+ module was a little bit tricky, so you have to double ( or triple) check the wiring before giving up. Here is the wiring scheme, the Raspberry Pi is a revision 2, and the module is the + (plus) version.

Raspberry Pi (rev2) – NRF24l01+ Diagram

Arduino

The setup is easy and similar to a mix of our tutorials about Irrigatorino and NRF24l01+ Tests.
Just keep in mind that you are playing with dangerous voltage, so if you get struck, it’s only your fault. I would suggest, anyway, to check if everything (especially the relay board) is working with a multimeter, before connecting to a real lamp.

Arduino Nano – NRF24l01+ – Lamp Diagram

NOTE ON PACKET LOSS:

If you are encountering problems while receiving or transmitting, like packet loss, consider adding a capacitor of 10 μF between the pin 1 and 2 of the NRF24l01+, with ground capacitor side on pin 1. You should do this on both the modules, on raspberry and arduino.

Capacitor on NRF24l01+

Software

Our plan to communicate between all this stuff is to use a Node.js application to run a binary ‘sudo ./remote -m 81‘ and ‘sudo ./remote -m 80‘ sending a message to the Arduino with the text 81 and 80 . The message is composed by pin identifier (8) and action to perform (0|1|2). After the action has been read, all the other numbers identify the pin which the action refers to.

When the arduino receive it, it then sends back an acknowledgment packet to the raspberry with the same message (yeah, like a parrot), except for action 2, which will not perform any action, but will reply with actual state of the pin. In the meantime, if the message the arduino receive is 1 it will close a relay (turning on a light, like a good parrot), 0 will open it (I doubt a parrot could be so clever).

Sketching

The sketch for the Arduino Nano is nothing more than a Getting Started demo of the RF24 library. We just modified it to switch the relay on in case it receive a message with 1 as text, or open it otherwise. Of course you’ll need the RF24 library to make it work.

Arduino sketch

C

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

/*

This program is free software; you can redistribute it and/or

modify it under the terms of the GNU General Public License

version 2 as published by the Free Software Foundation.

*/

/*

Hack.lenotta.com

Modified code of Getting Started RF24 Library

It will switch a relay on if receive a message with text 1,

turn it off otherwise.

Edo

*/

#include <SPI.h>

#include "nRF24L01.h"

#include "RF24.h"

#include "printf.h"

intrelay=8;

//

// Hardware conf

//

// Set up nRF24L01 radio on SPI bus plus pins 9 & 10

RF24 radio(9,10);

//

// Topology

//

// Radio pipe addresses for the 2 nodes to communicate.

constuint64_t pipes[2]={0xF0F0F0F0E1LL,0xF0F0F0F0D2LL};

char*convertNumberIntoArray(unsignedshortnumber,unsignedshortlength){

char*arr=(char*)malloc(length*sizeof(char)),*curr=arr;

do{

*curr++=number%10;

number/=10;

}while(number!=0);

returnarr;

}

unsignedshortgetId(char*rawMessage,unsignedshortlength){

unsignedshorti=0;

unsignedshortid=0;

for(i=1;i<length;i++){

id+=rawMessage[i]*pow(10,i-1);

}

returnid;

}

unsignedshortgetMessage(char*rawMessage){

unsignedshortmessage=rawMessage[0];

return(unsignedshort)message;

}

unsignedshortgetLength(unsignedintrudeMessage){

unsignedshortlength=(unsignedshort)(log10((float)rudeMessage))+1;

returnlength;

}

voidsetup(void)

{

//

// Print preamble

//

Serial.begin(57600);

pinMode(relay,OUTPUT);

digitalWrite(relay,HIGH);

printf_begin();

printf("\nRemote Switch Arduino\n\r");

//

// Setup and configure rf radio

//

radio.begin();

// radio.setAutoAck(1); // Ensure autoACK is enabled

radio.setRetries(15,15);

radio.openWritingPipe(pipes[1]);

radio.openReadingPipe(1,pipes[0]);

radio.startListening();

radio.printDetails();

}

intgetState(unsignedshortpin){

booleanstate=digitalRead(pin);

returnstate==true?0:1;

}

voiddoAction(unsignedshortid,unsignedshortaction){

if(action==0){

digitalWrite(id,HIGH);

}else{

digitalWrite(id,LOW);

}

}

voidsendCallback(unsignedshortcallback){

// First, stop listening so we can talk

radio.stopListening();

// Send the final one back.

radio.write(&callback,sizeof(unsignedshort));

printf("Sent response.\n\r");

// Now, resume listening so we catch the next packets.

radio.startListening();

}

voidperformAction(unsignedshortrawMessage){

unsignedshortaction,id,length,callback;

char*castedMessage;

length=getLength(rawMessage);

castedMessage=convertNumberIntoArray(rawMessage,length);

action=getMessage(castedMessage);

id=getId(castedMessage,length);

if(action==0||action==1){

callback=action;

doAction(id,action);

}elseif(action==2){

callback=getState(id);

}

sendCallback(callback);

}

voidloop(void)

{

// if there is data ready

if(radio.available())

{

// Dump the payloads until we've gotten everything

unsignedshortmessage;

booldone;

// char * new;

unsignedshortrawMessage;

done=false;

while(radio.available())

{

// Fetch the payload, and see if this was the last one.

radio.read(&rawMessage,sizeof(unsignedlong));

// Spew it

printf("Got message %d...",rawMessage);

performAction(rawMessage);

delay(10);

}

}

}

Enabling Raspberry Pi GPIO and Installing Node.js

First we enable the Raspy GPIO:

Shell

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

sudo apt-getinstall python-dev

#make sure to COMMENT the lines with spi-bcm2708 and i2c-bcm2708 modules

#Pretty similar except for the python-dev package taken from the repos.

#source: Adafruit.com

sudo apt-getupdate

sudo apt-getinstall python-dev

sudo apt-getinstall python-rpi.gpio

#add this two modules: i2c-bcm2708 i2c-dev

sudo nano/etc/modules

sudo apt-getinstall python-smbus

sudo apt-getinstall i2c-tools

# do COMMENT the lines with spi and i2c modules

sudo nano/etc/modprobe.d/raspi-blacklist.conf

Let’s install node.js.
If you don’t need the latest version you can install it from the repos:

install nodejs

Shell

1

sudo apt-getinstall nodejs

Otherwise you can follow this instructions (under Ubuntu, Mint… section) to compile the latest version.

The Lamp Switch Application

For Raspberry Pi 2 users: some of our readers pointed out that this library is a bit outdated for the Raspberry 2 and it’s encountering some problems. Until we have time to update the article, please refer to this post on the Raspberry Official Forum to solve the “Preparing interface” stuck problem (kudos to Andrei).

What we need now is to write an application that will send a message to the arduino using the NRF24l01+ and the Raspi. So the first thing to do is download the RF24 library ported for Raspberry Pi. I would suggest to use git.

Install RF24 Raspberry library

Shell

1

2

3

4

5

6

7

8

9

10

11

#install git

sudo apt-getinstall git

#move to home

cd~

#clone the RF24 repos from edoardoo's github fork

git clonehttps://github.com/edoardoo/RF24RaspberryCommunicator.git

#retrieve the RF24 libs

cd~/RF24RaspberryCommunicator/

git submodule init

git submodule update

Now let’s install the library:

installing libraries

Shell

1

2

3

#install the library

cd~/RF24RaspberryCommunicator/RF24

sudo makeinstall

At this point, with the RF24 library installed, you can use the compiled remote application or compile it yourself with make command:

Shell

1

2

3

4

5

6

7

8

9

10

11

12

13

14

cd~/RF24RaspberryCommunicator

#optional: compile the remote application:

makeclean&&make

# Use remote command to send message to arduino (use sudo!)

# Message should be in this format: [id pin number][action to do]

# We've set relay at pin 8 and actions are:

# 0: turn off

# 1: turn on

# 2: get the actual state

#this message will turn the light on:

sudo./remote-m81

If everything went well you should be able to turn on (and off) the relay at this point using the sudo./remote -m 81 application, hearing the famous ‘click’ from the relay board.

The Node.js Lamp Application

At this point the only thing left is to build a little node.js server and bind a click on a client browser to an exec function on the raspberry server.

public (folder) => contains remoteClient.js, the javascript code loaded on the client and bootstrap folder for styling

remote.js => the actual node app

To run the application you need to:

Run the node application

Shell

1

2

3

4

5

6

7

8

9

10

11

12

#install the dependencies

cd~/RF24RaspberryCommunicator/LightSwitchInNode/RemoteRaspberry

#but first clean the npm cache

sudo npm cache clean

npm install

#nom nom nom installing stuff

#run the application

cd../

sudo node lightSwitch.js

Authors note (31/3/2014)

We love the way you support each other in the comments! It’s really a satisfaction for us.
We can’t be always here to answer your questions or doubts, and all your contributions are a really great value you add to this website.
Thank you all!

Update (10/5/2014)

We’ve refined a bit the code, making it more clean and definitely more readable. All you have to do now to add new buttons, is to create a new button in the node app views giving it a data-command tag. The value of that tag will be automagically passed to the old switch -f binary (now called remote -m). Of course you still need to tell arduino how to interpret the message. No more c++ recompiling. Plus, we’ve made the web interface give you a visual feedback when the raspberry receive the ack package from arduino.

Update (27/8/2014)

Looks like the Rf24 library author has changed the folder’s name. I’ve tried to fix the article with the new names. Didn’t have time to check it yet. Let me know if everything is ok. Edo.

Update (2/12/2014)

I’ve cleaned and updated the code to the latest RF24 libraries from TMRh20. I’ve managed to submit a bug (issue #46)of the RF24 lib to the TMRh20 github account, and apply the workaround he proposed. Unfortunately it looks like the modules needs time between communications, it’s a known bug that right now we don’t have time to fix. If you would like to fork the RF24RaspberryCommunicator project, magically fix it and make a pull request, we would love it. Right now, since we do it for free, we don’t have time to fix it. Hope you like it. Edo.

What we’ve used

Wiring

Wiring Diagram

Sketching

I wanted to make arduino water my plants on alternate days, so we had to add a little function‘dayOfYear’ which will tell us (guess what?) the day of the year it is. Example: February 1st is the 32nd day of the year, and our function will return ’32’.

Maybe there was a better solution, or it was already implemented, but this way was faster for our purpose.

If the day number it’s even and the time correspond to what I’ve set, it will close the relay (and the valve will open).

We’ve used the RTClib (with the little edit I mentioned about ‘dayOfYear’) to control and read the RTC.

The Sketch

C

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

//

//Sketch for a little (stupid) plants irrigator

//Baldarn and Edo

//http://hack.lenotta.com

//

#include <Wire.h>

#include "RTClib.h"

RTC_DS1307 RTC;

intrelay=8;

voidsetup(){

//Initialize the serial port, wire library and RTC module

Serial.begin(9600);

Wire.begin();

RTC.begin();

pinMode(relay,OUTPUT);

digitalWrite(relay,HIGH);

//IF YOU USE RTC FOR THE FIRST TIME: If we remove the comment from the following line, we will set up the module time and date with the computer one

//RTC.adjust(DateTime(__DATE__, __TIME__));

}

voidloop(){

DateTime now=RTC.now();

//We print the day

Serial.print(now.day(),DEC);

Serial.print('/');

//We print the month

Serial.print(now.month(),DEC);

Serial.print('/');

//We print the year

Serial.print(now.year(),DEC);

Serial.print(' ');

//We print the hour

Serial.print(now.hour(),DEC);

Serial.print(':');

//We print the minutes

Serial.print(now.minute(),DEC);

Serial.print(':');

//We print the seconds

Serial.print(now.second(),DEC);

Serial.println();

//We check the time and sent through the serial port every 3s

if(now.dayOfYear()%2==0){

if(now.hour()==20){

if(now.minute()==54){

digitalWrite(relay,LOW);

}

else{

digitalWrite(relay,HIGH);

}

}

}

//Serial.println(digitalRead(relay));

//Serial.println();

delay(3000);

}

The Function We Added

We have modified the class DateTime in RTClib.h as follow:

C

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

//

//Baldarn and Edo

//http://hack.lenotta.com

//

classDateTime{

public:

DateTime(uint32_tt=0);

DateTime(uint16_t year,uint8_t month,uint8_t day,

uint8_t hour=0,uint8_t min=0,uint8_t sec=0);

DateTime(constchar*date,constchar*time);

uint16_t year()const{return2000+yOff;}

uint8_t month()const{returnm;}

uint8_t day()const{returnd;}

uint8_t hour()const{returnhh;}

uint8_t minute()const{returnmm;}

uint8_t second()const{returnss;}

uint8_t dayOfWeek()const;

//This is the function to calculate which day of the year it is:

uint8_t dayOfYear()const;

// 32-bit times as seconds since 1/1/2000

longsecondstime()const;

// 32-bit times as seconds since 1/1/1970

uint32_t unixtime(void)const;

protected:

uint8_t yOff,m,d,hh,mm,ss;

};

and added the following function to RTClib.cpp:

C

1

2

3

4

5

6

7

8

9

10

11

12

13

//

//Baldarn and Edo

//http://hack.lenotta.com

//

uint8_t DateTime::dayOfYear()const{

uint16_t days=d;

for(uint8_ti=1;i<m;++i)

days+=pgm_read_byte(daysInMonth+i-1);

if(m>2&&yOff%4==0)

++days;

returndays;

}

Possible Developments

As you’ve seen this is a really stupid implementation, but it was on our purpose to make it stupid and not including any sort of display.
In fact, the main project is a little bit bigger than just a programmable Garduino (as someone calls it).

What we have in mind is to make the Garduino just an interpreter for our garden architect “Mr Rasp Gardner”, a raspberry pi which will communicate with the arduino using the NRF24l01+ module we tested here. As you can imagine, this drive us to an intelligent gardener, a nice web interface, statistics and much (much) more.

One of the first thing to implement, apart wireless communication, could be a simple hygrometer which will tell us if the plants have actually been watered. Maybe next week.

By continuing to use the site, or scrolling, you agree to the use of cookies. more information

The cookie settings on this website are set to "allow cookies" to give you the best browsing experience possible. If you continue to use this website without changing your cookie settings or you click "Accept" below then you are consenting to this.