What is it?
This device is mainly build for the PiDome Server project, but it can also be used in other situations as long as it supports I²C as the communication bus, later in this howto more about that. It is build up of three parts which make up this device:
- a light intensity sensor
- a temperature sensor
- a device for controlling the Adafruit NeoPixel Digital RGB LED strip
In this Howto we are going to build this device.
The following parts are used in the Fritzing drawing:
- Arduino Uno (rev. 3)
- Raspberry Pi (Model B)
- TMP36 (temperature sensor)
- 10k LDR (Photocell)
- Adafruit NeoPixel Digital RGB LED Strip
- T7805CT voltage regulator (but any alternative can be used)
- L78S05CV voltage regulator (2A for powering the LED strip)
- 5 diodes (1N5408, rated for 3A)
- 3 diodes (2 for seperating the regulators and 1 for protecting flow-back to ledstrip)
- 1 1uF capacitor
- 3 1.0k resistors
- 1 1.8k resistor
- 1 red LED
- bunch of wires
- heatsink (and some small nuts and bolts) (not in drawing)
- 12V powersupply (not in drawing)
- power adaptor for the Rapberry Pi (not in drawing)
- USB cable or external power for the Arduino board (not in drawing)
Things that might can come in handy for building and problemshooting:
The Fritzing drawing
The drawing is made using the open source Fritzing software for building you own setup from a breadboard to PCB. You can download is from Fritzing.org.
If you’re looking for the Adafruit NeoPixel Digital RGB LED Strip part used in the Fritzing drawing, you can download it from our PiDome Hardware Page at BitBucket.
I have tried to keep it very basic and simple to build so everyone can build and modify it without major changes. If you make modifications or know a way to do things better or more efficient, please share that with us on our website so we can make our things even better. The parts used in this device are commonly used in electronic devices and are widely available at any good electronicsshop. We mainly get our parts from Floris.cc. This is a dutch online store for electronic parts and related stuff, good pricing and a excellent service.
I have chosen to make it all run from a 12V power supply, because that is what I am running throughout my house next to the I²C-wiring and it will be enough for most of the things I want to power. First of all the 12V comes across 5 diodes (1N5408) which I used for lowering the voltage to avoid alot of (heat)dissipation on the regulators. I chose for this type of diodes because they are rated to handle 3A, the same as the sum of the voltage-regulators. As the input voltage comes through each diode the voltage drops with 0.7V, so we end up with 12V – (5 * 0.7V) = 8.5V. The voltage regulators need to have a minimum voltage of 8V to operate, so we are good there. The voltage regulator (on the right) is an L78S05CV, which is capable of handling a load of 2Amps. I used this one for the sole purpose of powering the LED strip. The other voltage-regulator is an T7805CT rated to 1A. Then there is a 1uF capacitor on the 5V rail and ground to make it a bit more stable.
As 3A may sound alot, remember that we are also powering the LED-strip from this circuit and the current can rise pretty quickly. With the 60 LEDS on full load they are consuming around 800mA, but I like to be safe and have the oppertunity to expand my LED-strip further without the need of adjusting the circuit. In the drawing the power (12V) is connected to the terminalblock on the left. Where the positive(+) goes on the left side and the ground(-) on the right.
Of course you are free to make modifications so it’s running on a lower voltage or draws less current. For example if you want to use 5V instead of 12V then you can remove the diodes (5 in series) and the voltage regulators and connect your 5V power supply directly to the rails.
Note that the 5V needs to be as close to 5.0V as possible as this voltage is also used as an analog reference voltage by the Arduino for the calculations of the temperature and light intensity. If it varies too much you will get very strange readings from those sensors. Said that, it is also good practice to always mount a heatsink to your voltage regulators to avoid the potential magic-smoke and reducing the lifetime of the regulators.
Because the communication between the device and the PiDome Server is done through the I²C-bus there are some things you might need to adjust to make it work. One important thing is the type of wire used to connect the two toghether. I have chosen for a Cat5E cable (16 meters) in combination with two 1k pull-up resistors to the 5V rail on the device (on the Fritzing drawing the 16 meter range is represented as the yellow (SCL), black (shared ground) and blue (SDA) wires going horizontally over the breadboard).
It is more or less a little bit of tweaking and testing out what are the best resistor values for your situation. In general I would say that a value of 4.7k is a good startingpoint. The longer the wire, the lower the resistance. Take some time to figure out what is working best for you, but don’t jump to a very low resistance right away as it may damage the pins on your Arduino or Raspberry Pi, so be carefull.
Also note that a longer wire increases the capacitance and therefor you have to compensate that with a lower resistance (pull-up resistor).
One other thing I want to add is that some I²C devices use/expect 3.3V to pull up the lines. In such cases a level-shifter can come in handy, they protect the devices against higher voltages. See it as a mediator between 5V and 3.3V. John will be using one for his project and will talk about that in more detail later.
Then there is also a resistor next to the 10k LDR, which pulls it down to ground. You might need to check the datasheet of your LDR what is a good pull-down value. On the Fritzing drawing I have used an 1.8k resistor for it. When you use another value, remember to also adjust this value (hardResistance) later on in the Arduino sketch. To get the best results, measure the resistor with you meter to get the most accurate Ohm-value.
Adafruit NeoPixel Digital RGB LED strip
As this device can, with some software tweaking, handle merely every RGB ledstrip, it is designed for the NeoPixel Digital RGB LED strip from Adafruit. Connecting this strip is pretty straight forward. Just connect the power (5V) to the +5V wire and GND to the ground on the breadboard or any other point where you have your ground available. Then connect the DIN (Data Input) to digital pin 3 on the Arduino and you’re done. The Arduino sketch has the default number of LEDS in the strip (numLEDS) set to 60, but can easily be changed to match your strip eighter directly in the sketch or using the I²C command ‘0x47’.
Because the device can’t function without any software, we need to get that first. Go to the PiDome BitBucket Hardware page. Download the sketch (I2C_Temperature_and_LED_sketch_final) and the Adafruit NeoPixel library, if you haven’t already done so. Compile and upload it to your Arduino.
Communicating with the device
Using the serial-bus
If you have your Arduino hooked up to a computer you can open a COM port to read out measurements, normally you would use the ‘Monitor’ inside the Arduino IDE for this.
The device will print out ‘Ready’ when it is ready with it’s initialization. (all commands are in uppercase and without any quotes)
Type ‘T’ to get the current temperature value.
Type ‘L’ to get the current Lux value (Note: this is not the same as the returned LDR value as there are calculations being done to get the Lux standard).
Type ‘C’ to get the current color of the LED-strip (as a whole) and the transitionspeed that has been set.
Here we see the device start up. First the defaults are read from EEPROM (if available). Then it will initialize, when it’s done doing that it states ‘Ready’. Now we can read and write to it. The first number is the temperature, second the Lux and last the colors and transitionspeed.
As said before, these commands are mainly to check if everything is working. To send commands to the device you need to do that through the I2C-tool: i2cset.
Using the I²C-bus
Using the device in conjunction with the PiDome Server
At the moment of posting this Howto we have not given out a release of the server software yet, but we will shortly do so. Subscribe to our twitterfeed or visit the site regularly to stay informed of the first release. In the meantime you can use and control the device directly under Linux. The PiDome Server will natively support this device and has the drivers for it build in. It is just a matter of adding the device to your ‘Devices’-page and your basically ready to go.
Using the device directly under linux
If you want to use this device directly under Linux you may have to setup I²C first. To do this, log in to your Raspberry Pi and follow the next steps to set I²C up.
Use a text editor like Vim or Nano to edit the modules file (here we use Vim):
sudo vi /etc/modules
Then add these two lines to the end of the file:
After editing the file, it should look something like this:
Now you will need to reboot for the changes to take effect.
If you have problems with I²C, then it is well worth updating to the latest version.
To test and talk/read to I²C you need to install a little package called ‘i2c-tools’.
sudo apt-get install i2c-tools
Depending on your distribution, you may also have a file called /etc/modprobe.d/raspi-blacklist.conf
If you do not have this file then there is nothing to do, however, if you do have this file, you need to edit it and comment out the line below:
by putting a # in front of them. Open an editor on the file by typing:
sudo vi /etc/modprobe.d/raspi-blacklist.conf
then edit the file, save it and exit. As shown in the image below.
Once this is all done, you can type the following command to see all the connected devices (if you are running a 256MB Raspberry Pi Model B).
sudo i2cdetect -y 0
This shows that one I2C address is in use – 0x40.
Note that if you are using one of the newer Raspberry Pi’s (a 512MB Raspberry Pi Model B) then you will need to change the command to:
sudo i2cdetect -y 1
The Raspberry Pi designers swapped over I²C ports between board releases. Just remember: 256M ones use I²C port 0, 512M Pi’s use I²C port 1!
When your device is successfully detected we can proceed talking to it. There are a bunch of commands which can be send to the device to control your LED strip.
With ‘i2cset’ you can send commands and data over the bus to the device. All data (address, commands and values) is send in HEX. So if you want a praticular RGB-color, then translate it first to the correspondent HEX values. For example you want yellow, which is in RGB (Red:255, Green:255, Blue:0), you convert it to 0xFF(red), 0xFF(green) and 0x00(blue). So yellow will be written as:
0xFF 0xFF 0x00
In these examples we use the device-address 0x40 on the first bus (which is 0). If you use another bus, change it accordingly. Also note that you might need to use ‘sudo’. To avoid this you can also add to ‘Pi’-user to the I2C group by giving the following command:
sudo adduser pi i2c
For the ease of use I give you only the HEX commands the device listens to. If your program need to handle decimal integers than convert it first.
To set the LED-strip to yellow (as we like yellow very much), we give the command:
i2cset -y 0 0x40 0x16 0xFF 0xFF 0x00 i
As you can see no results or feedback is given. This means that the device has been responsive and accepted the command. If you get an error with code 20001, then something went wrong on the bus. Either it couldn’t be found or the bus was busy with something else.
The commands and parameters are:
|0x16||3 – colors||i2cset -y 0 0x40 0x16 0xFF 0xFF 0x00 i||Sets the entire strip to yellow|
|0x20||3 – colors||i2cset -y 0 0x40 0x20 0x00 0x00 0xFF i||Fades the entire strip to blue|
|0x24||3 – colors||i2cset -y 0 0x40 0x24 0xFF 0x00 0x00 i||Wipes from left to right in red|
|0x28||3 – colors||i2cset -y 0 0x40 0x28 0x00 0xFF 0x00 i||Wipes from right to left to in green|
|0x32||3 – colors||i2cset -y 0 0x40 0x32 0xFF 0x00 0xFF i||Set random pixels to magenta|
|0x36||4 – colors & position||i2cset -y 0 0x40 0x36 0xFF 0xFF 0xFF 0x16 i||Set 22nd pixel(position) to white|
|0x41||1 – dummy||i2cset -y 0 0x40 0x41 0x00 i||Fades the light on to last known color|
|0x43||1 – dummy||i2cset -y 0 0x40 0x43 0x00 i||Fades the light off|
Those commands are for setting the LED-strip but there are also a couple of set-commands for the device to change some system values.
|0x45||1 – speed||i2cset -y 0 0x40 0x45 0x80 i||Sets speed to half, min=0x00(faster) max=0xFF(slower) (default is 0x0F, 15)|
|0x47||1 – # of LEDS||i2cset -y 0 0x40 0x47 0x3C i||Sets number of LEDS in strip (default is 0x3C, 60 LEDS)|
|0x49||1 – dummy||i2cset -y 0 0x40 0x49 0x00 i||Stores the color/speed & LEDS in EEPROM|
Storing values in memory
There is also the posibility to store your settings (color, transitionspeed and number of LEDS in the strip) to the EEPROM of the Arduino. By default there is nothing written in EEPROM (when using a new IC or haven’t used EEPROM on the IC before). In that case the sketch will use it’s defaults for those settings, which are:
- Color : 0, 0, 0
- Transitionspeed: 15
- Number of LEDS: 60
It is handy to set your settings at least once because when you experience a power-outage to your device, it will restore your setting on the next boot and you don’t have to set it again manually. Remember that writing to EEPROM is limited, although it’s not likely you run into any problems with normal use, just letting you know. Reading from EEPROM is unlimited though.
The commands to get some information, is somewhat different. As ‘i2cget’ can’t read multiple banks after a single command, you have to use or the PiDome Server software or write some custom code to write the command and read the following number of banks. For example 0x01 is the command for getting the temperature, which is given back at the registers 0x02 to 0x05 with the most significant byte first. When reading only one register it appears to be empty as the device fills the registers only when the command is called.
|0x01||None||0x02 – 0x05||Get the temperature (4-byte float)|
|0x06||None||0x07 – 0x10||Get the Lux (4-byte float)|
|0x11||None||0x12 – 0x15||Get the color (3 bytes) and speed (1 byte)|
I hope you will have as much fun building this little thingy as we did. If you run into any problem or have any questions, leave a comment and we try to answer as soon as we can.