raspberry pi model B surveillance camera

How to turn your Raspberry Pi into a video streaming surveillance webcam and take simultaneously time lapse snapshots?

I want to make a time lapse video of our garden a whole year around and at the same time have a video stream that shows what is going on. I did quite a bit of reading and testing and this is what I ended up with:

– live streaming via a website

– taking a snapshot every minute

– save the files in a folder as jpg

– create a folder for every single day

– create files incl. date & time in the file name

– access the files via Mac OSx / AFP

Hardware:

– Raspberry PI v2

Raspberry Pi model B

Raspberry Pi model B

– Raspicam module

Raspberry Pi Camera Module

Raspberry Pi Camera Module

– Dummy Surveillance Camera (optional)

Dummy surveilance camera

Dummy surveilance camera

– Passive POE injector & splitter (optional)

passive PoE injector & splitter

passive PoE injector & splitter

– 5V USB charger (make sure it is a good quality one, otherwise you might experience that the Raspberry hangs occasionally, like I had)

USB charger

USB charger

– class 10 SD Card, the larger it is, the more storage space you have for the images.

16 GB SD Card

16 GB SD Card

– some m3 bolts & nuts

m3 nuts and bolts

First I hacked together the hardware like this:

1) cut the micro USB cable in two and insert the DC Plug & DC Socket in between (5.5mm x 2.1mm fits the Digitus passive POE connectors)

USB cable with power connector in between

USB cable with power connector in between

PoE injector & splitter combined with the modified USB cable

PoE injector & splitter combined with the modified USB cable

I took apart the dummy camera and removed the battery holder. Leave the leads on the LED, as they will be reconnected to raspberry pi. Drill two holes in the metal plate to which the battery holder was fixed. The holes must line up with the mounting holes of the RPI. Make sure to leave enough space for the SD card which faces the fake lens. In the holes, I mounted M3 brass hex spacers to attach the RPI to the board with m3 screws.

I made connectors to the leads of the LED and attached them directly to the 3.3V and ground on the GPIO of the Raspberry. I cut a hole in the fake lens and taped the Raspi cam with double sided tape behind the hole. It is not a problem that the camera is mounted upside down, because in the software you can flip the image 180 degrees.

The result can be seen in the images below.

Raspberry Pi with camera mounted on base plate

Raspberry Pi with camera mounted on base plate

Raspberry Pi with camera mounted on base plate

Raspberry Pi with camera mounted on base plate

 

There is quite a bit of space in the dummy camera to fit everything in.

View inside the camera housing

View inside the camera housing

I made a separate short network cable that goes through housing. Just screw the housing together and the hardware is ready.

 raspi cam apart raspi cam finished

But……before you put everything inside the housing, you want to be sure that the software is properly setup.

The steps I took to get the software up and running:

Perform the Raspberry Pi basic setup

install the lastest version of Raspbian Wheezy

connect via SSH (user: pi password: raspberry)

then update all OS files and firmware

sudo apt-get update

sudo apt-get dist-upgrade

sudo rpi-update

sudo reboot

sudo raspi-config

and make the following config changes

– expand the file system

– enable the camera

– enable ssh

– set time-zone

sudo reboot

From this point onwards is where the additional software is installed:

Installing motion software

sudo apt-get install motion

cd /tmp

sudo apt-get install -y libjpeg62 libjpeg62-dev libavformat53 libavformat-dev libavcodec53 libavcodec-dev libavutil51 libavutil-dev libc6-dev zlib1g-dev libmysqlclient18 libmysqlclient-dev libpq5 libpq-dev

Download the necessary Pi Cam driver

wget https://www.dropbox.com/s/pl9sqpwwotm8eak/motion-mmal.tar.gz

or use the mirror on google drive (in case dropbox has suspended my account again):

wget https://drive.google.com/uc?export=download&id=0B92GGEMLt5yZQkZXa2JyWFRvUGM

Download the configuration file with my preset configuration

wget https://www.dropbox.com/s/smubr3qtsbs2c2n/motion.conf

or use the mirror on google drive (in case dropbox has suspended my account again):

wget https://drive.google.com/uc?export=download&id=0B92GGEMLt5yZWktxSVVVek9DTlU

Unpack and move the downloaded files

tar zxvf motion-mmal.tar.gz

sudo mv motion /usr/bin/motion

sudo mv motion.conf /etc/motion.conf

Turn on motion deamon by default

sudo nano /etc/default/motion

and make the following change

start_motion_daemon=yes

ctrl-x, Y and enter to save

create necessary folder for storing the files and set the appropriate access rights

sudo chmod 664 /etc/motion.conf

sudo chmod 755 /usr/bin/motion

sudo touch /tmp/motion.log

sudo chmod 775 /tmp/motion.log

cd /home/pi

mkdir motion

sudo su

chmod 777 motion

The montion.conf that I included in this instruction works out of the box. In case you want to modify the motion.conf you can type:

sudo nano /etc/motion.conf

the major changes that I made:

deamon on

logfile /tmp/motion.log

rotate 180 (necessary as I mounted the camera upside down)

width 1280

height 720

framerate 10

threshold 0 (effectively turns of motion detection, as I just want the stream & the snapshots every minute)

ffmpeg_video_codec msmpeg4 (necessary to stream to windows based pc’s)

snapshot_interval 60 (every minute one snapshot)

text_left CAMERA %t (CAMERA can be any name you like and will appear on the image)

The following commands create file locations: a folder per day, per camera, per capture type. File names show camera #, image number, date & time

snapshot_filename %Y%m%d/camera-%t/snapshots/camera-%t-%v-%Y%m%d%H%M%S

picture_filename %Y%m%d/camera-%t/motions/camera-%t-%v-%Y%m%d%H%M%S-%q

movie_filename %Y%m%d/camera-%t/movies/camera-%t-%v-%Y%m%d%H%M%S-movie

timelapse_filename %Y%m%d/camera-%t/timelapses/camera-%t-%Y%m%d-timelapse

stream_port 8081

stream_localhost off

ctrl-x, Y and enter to save

You have to restart motion in order to apply the changes

sudo /etc/init.d/motion restart

Adding network access

Last step is to add netatalk for easy access to the images via Mac OSx finder, Windows users should consider installing Samba or mount a NAS / network drive on the Raspberry Pi as described here.

sudo apt-get install netatalk

sudo reboot

The video stream is directly visible via the Safari browser:

http://IP-ADDRESS-OF-RASPBERRY:8081

If you want to access the snapshots via Finder, in the SHARED section of Finder you will find the RASPBERRY. Connect to your RASPBERRY using user:pi password:raspberry.  After that you can browse the folders like any other. The images are roughly 100kB each.

Enjoy!

How to get rid of Raspberry PI SSH warning: Setting locale failed

As I am using Mac OS, I get error messages when using the build-in shell of OSx (perl: warning: Setting locale failed). In order to get rid of these messages I amended .bashrc

sudo nano .bashrc

and included the following command:

export LC_ALL=C

ctrl-x, Y and enter to save

sudo reboot

That’s it!

Screen Shot 2013-12-21 at 16.09.50

Raspberry Pi master controls Arduino UNO slaves via I2C

OK, I finally have the software up and running to control my Arduino (or up to 127 of them) from a single Raspberry Pi.

My objective was to add a simple way to control the i/o ports on the Arduino both analog and digital from my Raspberry Pi. Besides controlling them, I also wanted to be able to read the values on the pins, both digital & analog. Already at an early stage I figured to use the I2C interface. It’s pretty simple and straight forward and works with a bunch of other devices.

So, what I did, is turn the Arduino UNO in a slave, waiting for the commands from the Raspberry Pi.

I implemented the following commands:

setPin(device, pin, mode)
This is the equivalent of the pinMode(pin, mode).
Usage e.g. setPin(33, “13”, “OUPUT”).
INPUT, OUTPUT and INPUT_PULLUP are supported.

writePin(device, pin, value)
This is the equivalent of digitalWrite(pin, value).
Usage e.g. writePin(33, “13”, “HIGH”)

analogWritePin(device, pin, value)
This is the equivalent of analogWrite(pin, value) and can only be used on the PWM capable pins.
Usage e.g. writePin(33, “6”, “120”)

getStatus(device)
This asks the Arduino to read all the pins and return the values in a single 30 byte string. The Arduino performs a digital read on all the digital pins and an analog read on all the analog pins. The digital pins that are PWM enabled, are not read in case the PWM is in use. Because a read event would interrupt the PWM cycle, instead a P is returned as value.
A return string could look like this: 11000000000P011023000005121023 and can be read as follows: pin 0 and 1 are HIGH, pin 2 – 10 are LOW, pin 11 is in PWM mode, pin 12 is low, pin 13 is HIGH, A0 = 1023, A1 = 0000, A2 = 0512 and A3 = 1023.

A4 and A5 can’t be used as the pins are required for the I2C communication. 

pinValue(device, pin)
this is the equivalent of both digitalRead(pin) and analogRead(pin), it returns the value that is currently read for the specific pin.

The Python code for the raspberry can be found here.

In order to make use of the Raspberry Pi Master, you need to install the slave code on the Arduino. You need Arduino_I2C_slave_v0_21. This slave version v0_21 is not fully compatible with the Arduino Master software from my previous post and only works 100% with the Raspberry Pi.

I’m just a beginning programmer, so any feedback for me to improve is really appreciated. I’ve tried to document the programs extensively in the code.

The I2C wiring is quite simple as well. You could use an I2C connection without level shifter between the 3.3v Raspberry Pi and 5v Arduino as signals are send by pulling the signal low. However, I prefer using a level shifter in order to avoid problems.

The code on the RPi to control the Arduino could look like this if you wanted to blink the LED on pin 13:

import I2C_Master_v0.2.py

setPin(33, “13”, “Output”)

while True:
writePin(33,” 13″, “High”)
    print (“Status pin 13 = ” + pinValue(33,’13’))
    writePin(33,”13″,”Low”)

After every message from the Raspberry Pi to the Arduino a 1 sec pause is included in the code in order to avoid a request overload on the Arduino, because the Arduino is much slower than the Raspberry Pi. It would get interrupted before completing the command.

Happy tinkering!

Racer993

Raspberry Pi and Arduino Uno connected via I2C.

Raspberry Pi and Arduino Uno connected via I2C.

This is the RPI code:

I2C_Master_v0_2.py (click to download from my dropbox)

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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
#// Arduino I2C Wire master version 0.2
#// Turns the Raspberry Pi into a I2C master device using I2C-tools.
#// send commands to the I2C Arduino slave for configuring pins,
#// read and write to pins via a simple instruction set.
#// the i2c-tools are required use "sudo apt-get install i2c-tools"
#// the I2C slave software must be installed on the Arduino
#// Supported instructions
#// pinMode             = setPin(device, pinnumber, INPUT/OUTPUT/INPUT_PULLUP)
#// digitalWrite        = writePin(device,pinnumber,HIGH/LOW)
#// analogWrite (=PWM)  = analogWritePin(device,pinnumber,0-255)
#// digital/analog read = getStatus(device) reads all the digital/analog pins
#// digital/analog read = pinValue gets the value for a single pin
#// A0 - analog read / digital write
#// A1 - analog read / digital write
#// A2 - analog read / digital write
#// A3 - analog read / digital write
#// A4 - IN USE as SDA
#// A5 - IN USE as SCL
#//  1 - digital read / write + RX
#//  2 - digital read / write + TX  + Interrupt
#//  3 - digital read / write + PWM + Interrupt
#//  4 - digital read / write
#//  5 - digital read / write + PWM
#//  6 - digital read / write + PWM
#//  7 - digital read / write
#//  8 - digital read / write
#//  9 - digital read / write + PWM
#// 10 - digital read / write + PWM + SPI - SS
#// 11 - digital read / write + PWM + SPI - MOSI
#// 12 - digital read / write +       SPI - MISO
#// 13 - digital read / write + LED + SPI - SCK
#// HOW TO USE
#// sending commands
#// general: all commands must be 7 bytes long + 1 ending byte
#// 1) to set the pinMode write a message with 7 characters on I2C bus to the arduino
#// first character = S for set pinMode
#// second & third character are pin ID 00 - 13 for digital pins & A0 - A3 for analog pins
#// fourth character is to set the mode I for INPUT, O for OUTPUT, P for INPUT_PULLUP
#// character 5,6,7 are not used, set to 000
#// e.g. S13O000 Sets pin 13 to an OUTPUT
#// 2) to turn the pin on or off write a message with 7 characters on I2C bus to the arduino
#// first character = W for digitalWrite
#// second & third character are pin ID 00 - 13 for digital pins & A0 - A3 for analog pins
#// fourth character is to turn off or on H for HIGH and L for LOW
#// character 5,6,7 are not used, set to 000
#// e.g. W13H000 turns pin 13 on
#// 3) to turn use PWM write a message with 7 characters on I2C bus to the arduino
#// first character = A for analogWrite
#// second & third character are pin ID 00 - 13 for digital pins & A0 - A3 for analog pins
#// forth character is not used, set to X
#// fifth - seventh character are used to write the PWM cycle (000-255)
#// e.g. A05X120 performs an analogWrite on digital pin 5 with a PWM cycle of 120
#// 4) to get a status with pin readings send Wire.requestFrom(device, #chars = 30)
#// the arduino will send back 30 chars
#// char 1-14 for each digital pin 1 = on 0 = off P = PWM
#// char 15-18 for reading of A0, 1000 is added to the A0 reading in order to guarantee a 4 digit reading, subtract 1000 to get the proper reading
#// char 19-22 for reading of A1, 1000 is added to the A0 reading in order to guarantee a 4 digit reading, subtract 1000 to get the proper reading
#// char 23-26 for reading of A2, 1000 is added to the A0 reading in order to guarantee a 4 digit reading, subtract 1000 to get the proper reading
#// char 27-30 for reading of A3, 1000 is added to the A0 reading in order to guarantee a 4 digit reading, subtract 1000 to get the proper reading
#// 5) to get the value for a single pin use pinValue(device,pin) to get the value back 1=HIGH, 0= LOW, P=PWM for digital pins and 0-1023 for analog pins
#// remark: the communication between the RPi and Arduino is very sensitive, especially for timings
#// as the RPi is much faster than the Arduino you need to included pauses between commands of atleast
#// 1 sec to be save, I found that 0.5 seconds works as well (most of the time) but in that case you
#// occasionally  need to perform a hard reset on the Arduino as it locks up.
#// Created 28 July 2013
#// This example code is in the public domain.
import smbus
import time
# RPi rev 1 = SMBus(0)
# RPi rev 2 = SMBus(1)
bus = smbus.SMBus(1)
# address of the Arduino use "i2cdetect -y 1" from the RPi prompt to detect the Arduinos (up to 127!)
device = 0x21
# initialize variables
pin      = ""  #holds the pin number 0 - 13 or A0 - A3
type     = ""  #holds the pin type: INPUT, OUTPUT, INPUT_PULLUP
mode     = ""  #holds the pinmode: HIGH, LOW, PWM
pwmValue = ""  #holds the pwmValue
pwm      = ""  #holds the pwmValue in 3 digits
val      = ""  #holds a String to be converted into ASCII
cmd      = ""  #holds the first byte of the message for the Arduino
message  = ""  #holds the second - seventh byte of the message for the Arduino
valCmd   = 88                #holds the command as ASCII value 88 = "X"
valMessage  = [88,88,88,88,88,88] #holds the Message as ASCII values
# ------------------------------------------------------------------------------------------------------------------------------------------------
# this routine sends a setPin command to the Arduino to make a pin INPUT, OUTPUT or INPUT_PULLUP
def setPin(device, pin, type):
        cmd = "S"
        message = pinString(pin)+type[0]+"000"
        sendMessage(device, cmd, message)
# ------------------------------------------------------------------------------------------------------------------------------------------------
# this routine sends a writePin command to the Arduino to turn a pin HIGH or LOW
def writePin(device, pin, mode):
        cmd = "W"
        message = pinString(pin)+mode[0]+"000"
        sendMessage(device, cmd, message)
# ------------------------------------------------------------------------------------------------------------------------------------------------
# this routine send an analogWritePin command to the Arduino to set a PWM pin to a duty cycle between 0 and 255
def analogWritePin(device, pin, pwmValue):
        cmd = "A"
        message = pinString(pin)+"X"+pwmString(pwm)
        sendMessage(device, cmd, message)
# ------------------------------------------------------------------------------------------------------------------------------------------------
# this routine converts Strings to ASCII code
def StringToBytes(val):
        retVal = []
        for c in val:
                retVal.append(ord(c))
        return retVal
# ------------------------------------------------------------------------------------------------------------------------------------------------
# this routine actually transmits the command,
# sleep is required in order to prevent a request overload on the Arduino
def sendMessage(device, cmd, message):
        cmd=cmd.upper()
        message = message.upper()
        valCmd = ord(cmd)
        valMessage  = StringToBytes(message)
        print("Message: " + cmd + message + " send to device " + str(device))       
        bus.write_i2c_block_data(device, valCmd, valMessage)
        time.sleep(1)
# ------------------------------------------------------------------------------------------------------------------------------------------------
# this routine send a request to the Arduino to provide a 30 byte status update, return all 30 bytes
def getStatus(device):
        status = ""
        for i in range (0, 30):
            status += chr(bus.read_byte(device))
            time.sleep(0.05);
        time.sleep(0.1)       
        return status
# ------------------------------------------------------------------------------------------------------------------------------------------------
# this routine send a request to the Arduino to provide a 30 byte status update, return the value of a single pin
def pinValue(device,pin):
        status = ""
        for i in range (0, 30):
            status += chr(bus.read_byte(device))
            time.sleep(0.05);
        pinvalues = {'0':status[0],
                     '1':status[1],
                     '2':status[2],
                     '3':status[3],
                     '4':status[4],
                     '5':status[5],
                     '6':status[6],
                     '7':status[7],
                     '8':status[8],
                     '9':status[9],
                     '10':status[10],
                     '11':status[11],
                     '12':status[12],
                     '13':status[13],
                     'A0':int(status[14]+status[15]+status[16]+status[17])-1000,
                     'A1':int(status[18]+status[19]+status[20]+status[21])-1000,
                     'A2':int(status[22]+status[23]+status[24]+status[25])-1000,
                     'A3':int(status[26]+status[27]+status[28]+status[29])-1000}
        time.sleep(0.1)
        return  pinvalues[pin]
# ------------------------------------------------------------------------------------------------------------------------------------------------
# this routine converts a 1 or 2 digit pin into a 2 digit equivalent
def pinString(pin):
        while len(pin) < 2:
              pin = "0"+pin;
        return pin
# ------------------------------------------------------------------------------------------------------------------------------------------------
# this routine converts a 1, 2 or 3 digit pin into a 3 digit equivalent
def pwmString(pwm):
        while len(pwm) < 3:
              pwm = "0"+pwm;
        return pwm
# ------------------------------------------------------------------------------------------------------------------------------------------------
# this is where the main program starts
while True:
   setPin(33, "13", "Output"#on Arduino with I2C ID #33 set pin 13 to OUTPUT
   writePin(33,"13", "High")   #on Arduino with I2C ID #33 set pin 13 HIGH
   print ("Status pin 13 =" + pinValue(33,'13'))
   
   writePin(33,"13","Low")     #on Arduino with I2C ID #33 set pin 13 LOW
   print("30 byte status:" + getStatus(33))

This is the Arduino Slave code:

Arduino_I2C_slave_v0_21 (click to download from my dropbox)

// Arduino I2C Wire Slave version 0.21
// by Racer993 <https://raspberrypi4dummies.wordpress.com/&gt;

// Turns the Arduino to a I2C slave device (for the Raspberry Pi)
// using the Wire library. Configure pins, read and write to pins
// via a simple instruction set.

// Supported instructions
// pinMode = setPin(device, pinnumber, INPUT/OUTPUT/INPUT_PULLUP)
// digitalWrite = writePin(device,pinnumber,HIGH/LOW)
// analogWrite = analogWritePin(device,pinnumber,0-255)
// getStatus(device)

// A0 – analog read / digital write
// A1 – analog read / digital write
// A2 – analog read / digital write
// A3 – analog read / digital write
// A4 – IN USE as SDA
// A5 – IN USE as SCL

// 1 – digital read / write + RX
// 2 – digital read / write + TX + Interrupt
// 3 – digital read / write + PWM + Interrupt
// 4 – digital read / write
// 5 – digital read / write + PWM
// 6 – digital read / write + PWM
// 7 – digital read / write
// 8 – digital read / write
// 9 – digital read / write + PWM
// 10 – digital read / write + PWM + SPI – SS
// 11 – digital read / write + PWM + SPI – MOSI
// 12 – digital read / write + SPI – MISO
// 13 – digital read / write + LED + SPI – SCK

// HOW TO USE

// sending commands

// general: all commands must be 7 bytes long + 1 ending byte

// 1) to set the pinMode write a message with 7 characters on I2C bus to the arduino
// first character = S for set pinMode
// second & third character are pin ID 00 – 13 for digital pins & A0 – A3 for analog pins
// fourth character is to set the mode I for INPUT, O for OUTPUT, P for INPUT_PULLUP
// character 5,6,7 are not used, set to 000

// 2) to turn the pin on or off write a message with 7 characters on I2C bus to the arduino
// first character = W for digitalWrite
// second & third character are pin ID 00 – 13 for digital pins & A0 – A3 for analog pins
// fourth character is to turn off or on H for HIGH and L for LOW
// character 5,6,7 are not used, set to 000

// 3) to turn use PWM write a message with 7 characters on I2C bus to the arduino
// first character = A for analogWrite
// second & third character are pin ID 00 – 13 for digital pins & A0 – A3 for analog pins
// forth character is not used, set to X
// fifth – seventh character are used to write the PWM cycle (000-255)

// 4) to get a status with pin readings send Wire.requestFrom(device, #chars = 30)
// the arduino will send back 30 chars
// char 1-14 for each digital pin 1 = on 0 = off
// char 15-18 for reading of A0, 1000 is added to the A0 reading in order to guarantee a 4 digit reading, subtract 1000 to get the proper reading
// char 19-22 for reading of A1, 1000 is added to the A0 reading in order to guarantee a 4 digit reading, subtract 1000 to get the proper reading
// char 23-26 for reading of A2, 1000 is added to the A0 reading in order to guarantee a 4 digit reading, subtract 1000 to get the proper reading
// char 27-30 for reading of A3, 1000 is added to the A0 reading in order to guarantee a 4 digit reading, subtract 1000 to get the proper reading

// Created 17 July 2013

// This example code is in the public domain.

#include <Wire.h>

void setup()
{
int arduinoI2CAddress = 33; // set the slave address for the Arduino on the I2C buss

Wire.begin(arduinoI2CAddress); // join i2c bus with specified address
Wire.onRequest(requestEvent); // register wire.request interrupt event
Wire.onReceive(receiveEvent); // register wire.write interrupt event
}

char sendStatus[31] = “000000000000000000000000000000”; // initialize the container variable
int index = 0; // initialize the index variable
char pwm[15] = “00000000000000”; // initialize the PWM flag container

void loop()
{

String pinStatus=””; // initialize pinStatus variable

for(int digitalPin = 0; digitalPin <= 13; digitalPin++) // loop through 14 digital pins 0 – 13
{
if (pwm[digitalPin] == 0) // in case PWM is off for the pin, read the pin status
{
pinStatus += String (digitalRead(digitalPin)); // read the pin status & add it to the container variable
}
else
{
pinStatus += “P”; // in case PWM is on for the pin, add P to the pin status container string
}
}

for(int analogPin = 0; analogPin <= 3; analogPin++) // loop through the 4 (unused) analog pins 0 – 3
{
pinStatus += String (1000+analogRead(analogPin)); // read the analog value from the pin, add 1000 to make it 4 digit & add it to the container variable
}

pinStatus.toCharArray(sendStatus, 31); // convert the container variable pinStatus to a char array which can be send over i2c

delay(1000); // wait for an interrupt event
}

//——————————————————————————–
// function that executes whenever a status update is requested by master
// this function is registered as an event, see setup()

void requestEvent() {
Wire.write(sendStatus[index]);
++index;
if (index >= 30) {
index = 0;
}
}

//——————————————————————————–
// function that executes whenever a message is received from master
// this function is registered as an event, see setup()

void receiveEvent(int howMany)
{
int receiveByte = 0; // set index to 0
char command[7]; // expect 7 char + 1 end byte
String mode = “”; // initialize mode variable for holding the mode
String pin = “”; // initialize pin variable for holding the pin number as a String
String awValue = “”; // intitalize the variable for holding the analogWrite value
int pinVal; // inititalize the variable for holding the pin number as integer
int awValueVal; // initialize the variable for holding the analog write value as integer (only PWM pins!)

while(Wire.available()) // loop through all incoming bytes
{
command[receiveByte] = Wire.read(); // receive byte as a character
receiveByte++; // increase index by 1
}

pin = String(command[1]) + String(command[2]); // combine byte 2 and 3 in order to get the pin number
awValue = String(command[4]) + String(command[5]) + String(command[6]); // combine byte 5, 6 and 7 in order to get the analogWrite value
awValueVal = awValue.toInt(); // convert the awValue string to a value

if (String(command[1]) != “A” ) { pinVal = pin.toInt();} // in case of not an analog pin assignment convert into digital pin number
if (String(command[1]) != “A” ) { pwm[pinVal] = 0;} // in case of not an analog pin assignment set PWM flag to 0

// incase of analog pin assignment determine analog pin to be set
if (String(command[1]) == “A” && String(command[2]) == “0”) { pinVal = A0;}
if (String(command[1]) == “A” && String(command[2]) == “1”) { pinVal = A1;}
if (String(command[1]) == “A” && String(command[2]) == “2”) { pinVal = A2;}
if (String(command[1]) == “A” && String(command[2]) == “3”) { pinVal = A3;}

// if requested set pinmode
if (String(command[0]) == “S” && String(command[3]) == “I”) { pinMode(pinVal, INPUT);}
if (String(command[0]) == “S” && String(command[3]) == “O”) { pinMode(pinVal, OUTPUT);}
if (String(command[0]) == “S” && String(command[3]) == “P”) { pinMode(pinVal, INPUT_PULLUP);}

// if requested perform digital write
if (String(command[0]) == “W” && String(command[3]) == “H”) { digitalWrite(pinVal, HIGH);}
if (String(command[0]) == “W” && String(command[3]) == “L”) { digitalWrite(pinVal, LOW);}
// if requested perform analog write
if (String(command[0]) == “A” && pinVal == 3 || pinVal == 5 || pinVal == 6 || pinVal == 9 || pinVal == 10 || pinVal == 11 )
{
analogWrite(pinVal, awValueVal);
pwm[pinVal] = 1;
}

}

I2C communication with the Arduino Uno

It has been a while since I last wrote. Too busy at work and no time to sit down and tinker… I’ve done some reading in the past couple of weeks, because I want to extend my Raspberry Pi with some additional IO ports for my garden project, especially some analog ports would be welcome.

In my garden project I want to be able to use the Raspberry Pi for the following tasks:

– operate the pool pump
– detect wether the filter is overflowing
– measure the water temperature
– open and close the garage door
– monitor the status of the garage door (open / closed)
– make time lapse photo’s of the garden
– turn the garden lights on / off
– detect day / night
– and anything else I can possibly think off

My journey starts with adding ports to the Raspberry Pi. I figured, instead of adding a ATTiny 85 I decided to buy for €9,50 a Arduino Uno copy from China, which is much more versatile than the ATTiny 85. I figured that I can make the Raspberry Pi and Arduino Uno talk via I2C.

All I need would be some code for the Arduino Uno to accept commands from the Raspberry PI via I2C. I want to be able to set all pins individually to INPUT or OUTPUT or INPUT_PULLUP. Secondly, I must be able to set the pins HIGH or LOW. Also I want to be able to use PWM on the PWM capable digital pins (pin 3, 5, 6, 9, 10, 11) and finally, I must be able to read the values from the digital and analog pins.

So, with barely any programming skills, I wrote some code that does exactly this. The Arduino Uno Slave code looks like this:

// Arduino I2C Wire Slave version 0.1
// by Racer993 <https://raspberrypi4dummies.wordpress.com/&gt;

// Turns the Arduino to a I2C slave device (for the Raspberry Pi)
// using the Wire library. Configure pins, read and write to pins
// via a simple instruction set.

// Supported instructions
// pinMode = setPin(device, pinnumber, INPUT/OUTPUT/INPUT_PULLUP)
// digitalWrite = writePin(device,pinnumber,HIGH/LOW)
// analogWrite = analogWritePin(device,pinnumber,0-255)
// getStatus(device)

// A0 – analog read / digital write
// A1 – analog read / digital write
// A2 – analog read / digital write
// A3 – analog read / digital write
// A4 – IN USE as SDA
// A5 – IN USE as SCL

// 1 – digital read / write + RX
// 2 – digital read / write + TX + Interrupt
// 3 – digital read / write + PWM + Interrupt
// 4 – digital read / write
// 5 – digital read / write + PWM
// 6 – digital read / write + PWM
// 7 – digital read / write
// 8 – digital read / write
// 9 – digital read / write + PWM
// 10 – digital read / write + PWM + SPI – SS
// 11 – digital read / write + PWM + SPI – MOSI
// 12 – digital read / write + SPI – MISO
// 13 – digital read / write + LED + SPI – SCK

// HOW TO USE

// sending commands

// general: all commands must be 7 bytes long + 1 ending byte

// 1) to set the pinMode write a message with 7 characters on I2C bus to the arduino
// first character = S for set pinMode
// second & third character are pin ID 00 – 13 for digital pins & A0 – A3 for analog pins
// fourth character is to set the mode I for INPUT, O for OUTPUT, P for INPUT_PULLUP
// character 5,6,7 are not used, set to 000

// 2) to turn the pin on or off write a message with 7 characters on I2C bus to the arduino
// first character = W for digitalWrite
// second & third character are pin ID 00 – 13 for digital pins & A0 – A3 for analog pins
// fourth character is to turn off or on H for HIGH and L for LOW
// character 5,6,7 are not used, set to 000

// 3) to turn use PWM write a message with 7 characters on I2C bus to the arduino
// first character = A for analogWrite
// second & third character are pin ID 00 – 13 for digital pins & A0 – A3 for analog pins
// forth character is not used, set to X
// fifth – seventh character are used to write the PWM cycle (000-255)

// 4) to get a status with pin readings send Wire.requestFrom(device, #chars = 30)
// the arduino will send back 30 chars
// char 1-14 for each digital pin 1 = on 0 = off
// char 15-18 for reading of A0, 1000 is added to the A0 reading in order to guarantee a 4 digit reading, subtract 1000 to get the proper reading
// char 19-22 for reading of A1, 1000 is added to the A0 reading in order to guarantee a 4 digit reading, subtract 1000 to get the proper reading
// char 23-26 for reading of A2, 1000 is added to the A0 reading in order to guarantee a 4 digit reading, subtract 1000 to get the proper reading
// char 27-30 for reading of A3, 1000 is added to the A0 reading in order to guarantee a 4 digit reading, subtract 1000 to get the proper reading

// Created 11 July 2013

// This example code is in the public domain.

#include <Wire.h>

void setup()
{
int arduinoI2CAddress = 33; // set the slave address for the Arduino on the I2C buss

Wire.begin(arduinoI2CAddress); // join i2c bus with specified address
Wire.onRequest(requestEvent); // register wire.request interrupt event
Wire.onReceive(receiveEvent); // register wire.write interrupt event
Serial.begin(9600);
}

void loop()
{
delay(1000); // wait for an interrupt event
}

//——————————————————————————–
// function that executes whenever a status update is requested by master
// this function is registered as an event, see setup()

void requestEvent()
{
String pinStatus=””;
char sendStatus[31];

for(int digitalPin = 0; digitalPin <= 13; digitalPin++)
{
pinStatus += String (digitalRead(digitalPin));
}

for(int analogPin = 0; analogPin <= 3; analogPin++)
{
pinStatus += String (1000+analogRead(analogPin));
}
pinStatus.toCharArray(sendStatus, 31);
Wire.write(sendStatus);
}

//——————————————————————————–
// function that executes whenever a message is received from master
// this function is registered as an event, see setup()

void receiveEvent(int howMany)
{
int receiveByte = 0; // set index to 0
char command[7]; // expect 7 char + 1 end byte
String mode = “”; // initialize mode variable for holding the mode
String pin = “”; // initialize pin variable for holding the pin number as a String
String awValue = “”; // intitalize the variable for holding the analogWrite value
int pinVal; // inititalize the variable for holding the pin number as integer
int awValueVal; // initialize the variable for holding the analog write value as integer (only PWM pins!)

while(Wire.available()) // loop through all incoming bytes
{
command[receiveByte] = Wire.read(); // receive byte as a character
receiveByte++; // increase index by 1
}

pin = String(command[1]) + String(command[2]); // combine byte 2 and 3 in order to get the pin number
awValue = String(command[4]) + String(command[5]) + String(command[6]); // combine byte 5, 6 and 7 in order to get the analogWrite value
awValueVal = awValue.toInt();

if (String(command[1]) != “A” ) { pinVal = pin.toInt();}

// incase of analog pin assignment determine analog pin to be set
if (String(command[1]) == “A” && String(command[2]) == “0”) { pinVal = A0;}
if (String(command[1]) == “A” && String(command[2]) == “1”) { pinVal = A1;}
if (String(command[1]) == “A” && String(command[2]) == “2”) { pinVal = A2;}
if (String(command[1]) == “A” && String(command[2]) == “3”) { pinVal = A3;}

// if requested set pinmode
if (String(command[0]) == “S” && String(command[3]) == “I”) { pinMode(pinVal, INPUT);}
if (String(command[0]) == “S” && String(command[3]) == “O”) { pinMode(pinVal, OUTPUT);}
if (String(command[0]) == “S” && String(command[3]) == “P”) { pinMode(pinVal, INPUT_PULLUP);}

// if requested perform digital write
if (String(command[0]) == “W” && String(command[3]) == “H”) { digitalWrite(pinVal, HIGH);}
if (String(command[0]) == “W” && String(command[3]) == “L”) { digitalWrite(pinVal, LOW);}

// if requested perform analog write
if (String(command[0]) == “A” && pinVal == 3 || pinVal == 5 || pinVal == 6 || pinVal == 9 || pinVal == 10 || pinVal == 11 ) { analogWrite(pinVal, awValueVal);}

Serial.println(“command recieved: ” + String(command));
Serial.println(“pwm value: ” + String(awValueVal));

}

At this moment I don’t have the Raspberry Pi code yet, but I wrote some code for an Arduino to act as master and send commands to the Arduino I2C slave.

// Arduino I2C Wire master version 0.1
// by Racer993 <https://raspberrypi4dummies.wordpress.com/&gt;

// Turns the Arduino to a I2C master device using the Wire library.
// send commands to the I2C Arduino slave for configuring pins,
// read and write to pins via a simple instruction set.

// Supported instructions
// pinMode = setPin(device, pinnumber, INPUT/OUTPUT/INPUT_PULLUP)
// digitalWrite = writePin(device,pinnumber,HIGH/LOW)
// analogWrite = analogWritePin(device,pinnumber,0-255)
// getStatus(device) = digital/analog read of the all the digital/analog pins

// A0 – analog read / digital write
// A1 – analog read / digital write
// A2 – analog read / digital write
// A3 – analog read / digital write
// A4 – IN USE as SDA
// A5 – IN USE as SCL

// 1 – digital read / write + RX
// 2 – digital read / write + TX + Interrupt
// 3 – digital read / write + PWM + Interrupt
// 4 – digital read / write
// 5 – digital read / write + PWM
// 6 – digital read / write + PWM
// 7 – digital read / write
// 8 – digital read / write
// 9 – digital read / write + PWM
// 10 – digital read / write + PWM + SPI – SS
// 11 – digital read / write + PWM + SPI – MOSI
// 12 – digital read / write + SPI – MISO
// 13 – digital read / write + LED + SPI – SCK

// HOW TO USE

// sending commands

// general: all commands must be 7 bytes long + 1 ending byte

// 1) to set the pinMode write a message with 7 characters on I2C bus to the arduino
// first character = S for set pinMode
// second & third character are pin ID 00 – 13 for digital pins & A0 – A3 for analog pins
// fourth character is to set the mode I for INPUT, O for OUTPUT, P for INPUT_PULLUP
// character 5,6,7 are not used, set to 000

// 2) to turn the pin on or off write a message with 7 characters on I2C bus to the arduino
// first character = W for digitalWrite
// second & third character are pin ID 00 – 13 for digital pins & A0 – A3 for analog pins
// fourth character is to turn off or on H for HIGH and L for LOW
// character 5,6,7 are not used, set to 000

// 3) to turn use PWM write a message with 7 characters on I2C bus to the arduino
// first character = A for analogWrite
// second & third character are pin ID 00 – 13 for digital pins & A0 – A3 for analog pins
// forth character is not used, set to X
// fifth – seventh character are used to write the PWM cycle (000-255)

// 4) to get a status with pin readings send Wire.requestFrom(device, #chars = 30)
// the arduino will send back 30 chars
// char 1-14 for each digital pin 1 = on 0 = off
// char 15-18 for reading of A0, 1000 is added to the A0 reading in order to guarantee a 4 digit reading, subtract 1000 to get the proper reading
// char 19-22 for reading of A1, 1000 is added to the A0 reading in order to guarantee a 4 digit reading, subtract 1000 to get the proper reading
// char 23-26 for reading of A2, 1000 is added to the A0 reading in order to guarantee a 4 digit reading, subtract 1000 to get the proper reading
// char 27-30 for reading of A3, 1000 is added to the A0 reading in order to guarantee a 4 digit reading, subtract 1000 to get the proper reading

// Created 11 July 2013

// This example code is in the public domain.

#include <Wire.h>

void setup()
{
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600); // start serial for output
Serial.println(“Starting communication…”);
}

String message = “”; // initialize the varaible to hold the message
byte x = 0; // initialize the variable to hold the byte count

void loop() // example code to show how the I2C communication works with the I2C slave
{

Serial.println(“Starting loop…”); // send info on serial port
delay(2500); // wait 2,5 seconds

// example of a digital write to an analog pin
Serial.println(“Turn pin A3 on…”); // communicate actions on serial port
setPin(33,”A3″,”Output”); // set analog Pin 1 on devicde 33 to OUTPUT
writePin(33,”A3″,”High”); // set analog Pin 1 on device 33 to HIGH / turn on
Serial.println(“Request Status…”); // communicate status on serial port
Serial.println(getStatus(33)); // get the status of the pins to verify action result

delay(250); // wait 0,25 seconds
Serial.println(“Turn pin A3 off…”); // communicate actions on serial port
writePin(33,”A3″,”Low”); // set analog Pin 1 on device 33 to LOW / turn off
Serial.println(“Request Status…”); // communicate status on serial port
Serial.println(getStatus(33)); // get the status of the pins to verify action result

// example of a digital write to a digital pin
delay(250); // wait 2,5 seconds
Serial.println(“Turn pin 13 on…”); // communicate actions on serial port
setPin(33,”13″,”Output”); // set digital Pin 13 on devicde 33 to OUTPUT
writePin(33,”13″,”High”); // set digital Pin 13 on device 33 to HIGH / turn on
Serial.println(“Request Status…”); // communicate status on serial port
Serial.println(getStatus(33)); // get the status of the pins to verify action result

delay(250); // wait 0,25 seconds
Serial.println(“Turn pin 13 off…”); // communicate actions on serial port
writePin(33,”13″,”Low”); // set digital Pin 13 on device 33 to LOW / turn off
Serial.println(“Request Status…”); // communicate status on serial port
Serial.println(getStatus(33)); // get the status of the pins to verify action result

// example of a analog write to a PWM pin (digital pin 3, 5, 6, 9, 10 or 11)
delay(250); // wait 2,5 seconds
Serial.println(“Set PWM on pin 3…”); // communicate actions on serial port
setPin(33,”3″,”Output”); // set analog Pin 1 on devicde 33 to OUTPUT
analogWritePin(33, “3”, “255”); // set analog Pin 1 on device 33 to HIGH / turn on
Serial.println(“Request Status…”); // communicate status on serial port
Serial.println(getStatus(33)); // get the status of the pins to verify action result

delay(250); // wait 0,25 seconds
Serial.println(“Turn pin 3 off…”); // communicate actions on serial port
writePin(33,”3″,”Low”); // set analog Pin 1 on device 33 to LOW / turn off
Serial.println(“Request Status…”); // communicate status on serial port
Serial.println(getStatus(33)); // get the status of the pins to verify action result

}

//——————————————————————————–
String getStatus(int device)
// get status of the arduino pins
{
String getStatus = “”;
Wire.requestFrom(device, 30); // request 30 bytes from slave device #33

while(Wire.available()) // slave may send less than requested

{
char c = Wire.read(); // receive a byte as character
getStatus += c;
}

return getStatus;
}

//——————————————————————————–
void setPin(int device, String pin, String type)
// prepare message to set the pin type (input/output) on the Arduino
{
Serial.println(“Setting pin ” + pin + ” to type ” + type + ” on device ” + device);
message = “S”+pinString(pin)+type[0]+”000”;
sendMessage(device, message);
}

//——————————————————————————–
void writePin(int device, String pin, String mode)
// prepare message to set the pin mode (high/low) on the Arduino
{
Serial.println(“Setting pin ” + pin + ” to mode ” + mode + ” on device ” + device);
message = “W”+pinString(pin)+mode[0]+”000”;
sendMessage(device, message);
}

//——————————————————————————–
void analogWritePin(int device, String pin, String pwmValue)
// prepare message to set the pin mode (high/low) on the Arduino
{
Serial.println(“Setting pin ” + pin + ” to PWM value ” + pwmValue + ” on device ” + device);
message = “A”+pinString(pin)+”X”+pwmString(pwmValue);
sendMessage(device, message);
}

//——————————————————————————–
void sendMessage(int device, String message)
// send the message to the Arduino, a 7 Byte message
// byte 1 is operation (set or write)
// bytes 2 and 3 are pin identifier
// byte 4 is parameter value (input / output or high / low)
// bytes 5,6 and 7 are the PWM value
{
message.toUpperCase(); // convert String to uppercase
char sendMessage[8]; // create char array to hold 4 characters + terminating 0
message.toCharArray(sendMessage, 8); // cast String to char array
Wire.beginTransmission(device);
Wire.write(sendMessage);
Wire.endTransmission();
// delay(500);
}

//——————————————————————————–
String pinString(String pin)
// resize pin descriptor to two bytes if necessary
{
while(pin.length() < 2)
{
pin = “0” + pin;
}
return pin;
}

//——————————————————————————–
String pwmString(String pwm)
// resize pin descriptor to two bytes if necessary
{
while(pwm.length() < 3)
{
pwm = “0” + pwm;
}
return pwm;
}

Connecting the Arduino Uno’s for I2C communication is quite simple:

Arduino Uno I2C communication

Arduino Uno I2C communication

The nice thing about the code is that it supports up to 127 Arduino’s to be controlled by a single master🙂

In my next post I will try to have some code ready to show how the I2C communication between the 3.3v Raspberry Pi and the 5.0v Arduino Uno can be realized.

The Arduino Uno code can also be downloaded directly from my public dropbox.

Arduino Uno I2C connection

Arduino Uno I2C connection

The Pi Cam

Last weekend my Pi Cam arrived, on sunday I started some experiments, took some pictures and shot some video, but somehow I managed to screw up the installation after installing netcat and mplayer to bring up a Iive video stream from the Raspberry PI to my PC.

I’ll need to do some more experimenting before I can post a new image that provides streaming video from the raspberry to a windows pc.

Also I’ve started a Pyton programming course at codecademy.com. I want to combine an Arduino with my Raspberry to add some functions, like temperature reading. Communications should go via I2C. The whole setup should take a timelapse pictures of our garden, measure the water temperature, operate the water pump, stream music and switching the lights on and off, and I can probaly think of some more really not necessary things😉

Fortunately Dropbox has enabled access to my public dropbox again🙂

Happy downloading!

Bad news from Dropbox

20130521-235320.jpg

Just received a message from dropbox. They have shutdown my public Dropbox due to excessive traffic😦

However, I’m really glad that you like the SD card images for your Raspberry Pi🙂

I’m afraid that the excessive traffic might be persistent after the ban gets lifted. The plug and play SD card images that turn your Raspberry Pi into an Airprint Server, AirPi, Thin Client, Quake 3 game console, etc seem to be quite popular among the Raspberry Pi users. Maybe you can help me host the images at new locations. Just post the links to alternative download locations in the comments.

Thx!

How to play Quake 3 on your Raspberry Pi

Today, I figured, it would be nice to do some old school fragging🙂 It is time to get my Raspberry Pi to run Quake 3. There are quite a few tutorials, but it took me a couple of tries to find a combination that worked for me. 

For you, the quick way to get Quake 3 running on your Raspberry Pi is to download the Quake 3 SD card image for a 4GB SD Card from my public dropbox. You will find it under Images\Quake3\Quake3_4GB_autostart.zip In my previous posts I have explained how to mount an image on the SD Card by using Win32DiskImager. The image auto-starts Quake 3 on boot. In case you don’t want that, just use the following command after logging in:

sudo update-rc.d -f  quake3 remove 

Which removes Quake 3 from the start-up sequence. You can start the game by navigating to the directory where the game is located and start the game from there:

cd /home/pi/quake3/build/release-linux-arm
sudo ./ioquake3.arm

In case you insist in making your own image, this is how I got it to work:

Before you start, you need a 4GB SD Card with Raspbian Wheezy installed. Run sudo update and sudo upgrade. Start sudo raspi-config and expand the root partition to fill the SD card. Memory split should be configured with 64MB video memory. Reboot.

Step 1:

Log in to your Pi and then type at the command prompt:

sudo apt-get install git gcc build-essential libsdl1.2-dev

These tools are needed to install the Quake 3 source code!
Step 2:

Obtain the source code with this command:

git clone https://github.com/raspberrypi/quake3.git

Change to the Quake3 directory:

cd quake3
Step 3:

Edit the script that does the compilation:

nano build.sh
The first line (8) you are looking for starts with ARM_LIBS, change it so it says this:

ARM_LIBS=/opt/vc/lib
You also need to change the line (16) that starts with INCLUDES, change it to this:

INCLUDES=”-I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads”
The final line (19) to change starts CROSS_COMPILE:

# CROSS_COMPILE=bcm2708-
Save the file by pressing Ctrl-X followed by Y and finally return.
Step 4:

Now you can begin the compilation process by typing:

./build.sh

the process takes approximately 60 minutes!
Step 5:

Once that has finished you need to download the pak files. This lets the game function!

Type:

cd
cd quake3/build/release-linux-arm
wget https://dl.dropboxusercontent.com/u/36774536/Images/Quake3/Q3DemoPaks.zip
unzip Q3DemoPaks.zip

The directory tree should look like this (using the default Pi user):

home
– pi
– – quake3
– – – build
– – – – release-linux-arm
– – – – – baseq3

and in the directory ‘baseq3’ there should be your PAK files.
Step 6:

Running the game: In order for you to run the game you have to be in the right directory, to get there type these commands:

cd
cd quake3/build/release-linux-arm
Start your game with this command:

sudo ./ioquake3.arm

In case you want Quake 3 to boot at start up follow the additional steps below:

Step 1:

sudo nano /etc/init.d/quake3

make the content of the file look like this:

#! /bin/sh
# /etc/init.d/quake3

### BEGIN INIT INFO
# Provides:          quake3
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Simple script to start quake3 at boot
# Description:       A simple script from https://raspberrypi4dummies.wordpress.com
### END INIT INFO

# If you want a command to always run, put it here
cd /home/pi/quake3/build/release-linux-arm
sudo ./ioquake3.arm

# Carry out specific functions when asked to by the system

exit 0

Save the file by pressing Ctrl-X followed by Y and finally return.

The last two commands complete the job of starting Quake 3 on boot:

sudo chmod 755 /etc/init.d/quake3
sudo update-rc.d quake3 defaults

HAPPY FRAGGING!

foto 4