How it started
The desire to start a project in home automation started about 5 years ago, at the point I bought my first home.
Having installed spot lighting in the floor, I wanted to have them switch on during dark hours when we were using the room. This then extended to the kitchen with under cupboard lighting. However I used a simple timer to do the automation.
I wanted something that could make decisions based on it’s environment. Inputs such as sound, light, temperature could be used to understand the environment of each room. With such information the rooms lighting and heating could be controlled in an intelligent way. This is of course much more that my simple timer could deliver.
I have spent many hours since then looking at alternative options that already exist. Although many options are available, what I concluded was to have something more intelligent, would cost a lot of money and in many cases the performance was questionable. I refer partly to the x10 automation, which uses your existing mains wiring to communicate. In this case you need good quality wiring with little interference. Since I live in a very old house, the performance wouldn’t be great without my mains wiring being re-fitted.
Since what I wanted to do was collect information and make choices based on them, using an Arduino seemed like an interesting project…
The objective
I wanted to build a low-cost solution that would be able to :
- switch an appliance on and off.
- make decisions based on it’s environment
- send environmental data back to a computer to be harvested
- be wireless
- extend the module range using with a mesh network
The solution must be wireless, since I have an obsessive dislike of wires being visible.
The sensors would be used to make choices based on more than just the time of day. For example if it is very dark and no movement is detected within the room, turn the lights off. However if there is movement turn the lights on. Another case could be if people are in the house and it is very cold, then turn the heating on.
Although this is a convenient luxury, such automation can actually reduce the amount of energy you consume within the house. By turning off lighting and heating at non-essential times, less energy is consumed.
I opted to use an Arduino as a starting point. Using an ATmega 328 AVR on a breadboard, I could experiment various wireless technologies and see if what I wanted to do was realistic.
To begin with I was considering using an Xbee wireless module for communication, however this would increase the cost too much. What I settled on was a nRF24L01, which can be found on eBay for as little as $1.50 each. Arduino has a very good library for this and were very easy to implement.
Creating a mesh network with the nRF24L01 was actually quite simple, it has no more hardware requirements, it’s all in the code. By repeating the received message, the data is passed on to the next module in range. Of course if they’re all in range then this feature won’t be used much.
Prototyping with a breadboard
With a breadboard, I started recreating the basic Arduino circuit. This step is simplified thanks to a very detailed how to on Arduino.cc.
After assembling the basic Arduino circuit, I started to build upon it by adding the different sensors and relays.
You can see here a relay attached to support the appliance switching. Once I understood values the Arduino would receive from each sensor, I was becoming more confident that this project would actually work.
Whilst measuring light using a LDR (Light depended Resistor), the AVR would measure values from 0 (Very Dark) to 100 (Direct sunlight). At about a reading of 28, it was time to turn the light on. However I learnt that this value isn’t the same in each room as it may be more comfortable at a different value. So the target solution must have a variable limit before triggering the light to turn on…
This step was so crucial before starting to design the PCB. Prior to this experiment I didn’t know what the solution would look like or even if it was practical.
Building the module
I decided that the Arduino platform would meet my requirements and having tested the wireless transceiver in every room of the house, I had something that would work. Now the challenge was to design something that was both small and practical.
To start with I wanted to make a DC powered unit first. The thought of having to manage AC mains was too much at this stage. So I have used a trusted L7805 voltage regulator that will offer a steady 5v for the AVR. The first board would simply mirror what I created on the breadboard. The idea was to take small steps and perfect it as I go along (I’m not perfect and don’t normally get things right first time…).
Using Eagle CAD I designed the circuit schematic, which actually took longer than I expected. This wasn’t because it was complex, but because I couldn’t find a library for the nRF24L01 wireless module. Instead of creating a custom library, I just added a socket to the schematic. After all, it was going to be connected to the board with a socket.
After the components had been placed and the first PCB design was finished, I produced the board using a technique called Isolation milling. This is a rapid process, which unlike the standard etching process has no harmful waste at the end. It requires a CNC Router. The CNC only removes the copper between tracks to isolate them from each other.
When finished, it continues to drill the holes and mill the board. What you are left with is a finished board that can be soldered. This automated process is ideal for rapid prototyping as in my case from start-to-finish you can have a board ready in about an hour.
Here is a video of the most recent board being produced, from design through to completion -
I have gone though several version of board using this process.
To start with I just recreated the breadboard version, but soon after created a version with 6 analogue I/O pins and an SPI port. The SPI port made things so much easier. Without it, I had to remove the ATmega 328 and flash it using an Arduino Uno I had spare.
Now flashing the board became much easier by simply connecting a TinyISP AVR Programmer to the SPI port, the board could be flashed as if it were a real Arduino development board, directly from the IDE. Once I had a stable software build, I started using AVR Dude with a Hex file of the program.
The latest version uses a nRF24L01+ wireless module, which has a further range so the modules can work at longer distances.
Due to the pins being in a different order, much of the board layout needed changing. This board also adds 2 more I/O pins which are digital.
What about the code?
Whilst browsing the Arduino.cc tutorials, I found a great page on the nRF24L01. This made what follows a lot easier. It provided a library called MIRF. It needed to be copied to the Arduino IDE library folder and then could be used.
To communicate to the module I used the example sketch called “ping_client”. With minimal changes it suits what I needed. I modified it to enable you to send data to another Arduino using the nRF24L01 via a serial port. So using the serial monitor I could type a string of data that would be sent to the module.
Using an Arduino Uno connected to my PC and a nRF24L01, I could communicate with the module. As I could use the serial port, I wrote a .NET application to send a receive commands.
The remote PC transceiver source code :
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
| #include <SPI.h> #include <Mirf.h> #include <nRF24L01.h> #include <MirfHardwareSpiDriver.h> char data[16]; char rec[16]; int i, a, f; unsigned long startTime = 0; unsigned int timeoutValue = 5000; void setup(){ Serial.begin(9600); Serial.println( "Enter 16 characters" ); Serial.println(); Mirf.spi = &MirfHardwareSpi; Mirf.init(); Mirf.setRADDR((byte *) "clie1" ); Mirf.payload = 16; Mirf.config(); Serial.println( "Beginning ... " ); } void loop(){ if (a == 0){ if (Serial.available() > 15) { a = 1; for (i = 0; i < 16; i = i + 1) { data[i] = Serial.read(); } Serial.println( " " ); Serial.print( "you sent " ); for (i = 0; i < 16; i = i + 1) { Serial.print(data[i]); } } } if (a == 1){ Mirf.setTADDR((byte *) "serv1" ); data[Mirf.payload]; Mirf.send((byte *) &data); startTime = millis(); Serial.println(); Serial.print( "Sent at " ); Serial.print(startTime); Serial.println(); while (Mirf.isSending()){ } Serial.println( " " ); delay(10); while (!Mirf.dataReady()){ // Add Timeout and re-send if (millis() - timeoutValue > startTime){ Serial.println( "TIMEOUT" ); Serial.print( "Timed out at " ); Serial.print(millis()); Serial.println(); break ; } } Serial.print( "You Got " ); Mirf.getData((byte *) &rec); for (i = 0; i < 16; i = i + 1) { Serial.print(rec[i]); } a = 0; } } |
The module has two tasks in the code below. The first task is to act upon requests from the remote PC. In this case it will turn the relay on or off.
The second task is called “Normal Operation” This is where it makes choices based on sensor inputs. This is just a sample of the code.
The module source code :
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
| #include <SPI.h> #include <Mirf.h> #include <nRF24L01.h> #include <MirfHardwareSpiDriver.h> int relay = 4; int pwrLED = 3; boolean relayState = 0; int i; String recValue; int address = 0001; char data[16]; void setup(){ pinMode(relay, OUTPUT); pinMode(pwrLED, OUTPUT); Mirf.spi = &MirfHardwareSpi; Mirf.init(); Mirf.setRADDR((byte *) "serv1" ); Mirf.payload = 16; char data[Mirf.payload]; Mirf.config(); // Serial.begin(9600); // Serial.println("Listening..."); } void loop(){ digitalWrite(pwrLED, HIGH); /* * A buffer to store the data. */ data[Mirf.payload]; if (!Mirf.isSending() && Mirf.dataReady()){ // Serial.print("Received packet - "); Mirf.getData((byte *) data); for (i = 0; i < 16; i = i + 1) { // Serial.print(data[i]); recValue = recValue + data[i]; } Serial.println( " " ); // PARSE PACKET DATA // Parse Address if (recValue.substring(0,4) == "0001" ) { // Serial.println("Data received for address 0001"); // Parse Function if (recValue.substring(4,6) == "01" ) { // Serial.println("Function = Relay"); // Parse Action if (recValue.substring(6,8) == "01" ) { // Serial.println("Action = Activate"); // Activate Relay digitalWrite(relay, HIGH); relayState = 1; // Serial.println("Relay ON!"); } else { // Serial.println("Action = Deactivate"); // Activate Relay digitalWrite(relay, LOW); relayState = 0; // Serial.println("Relay OFF!"); } } } else { // Do Nothing } // Reset recValue recValue = "" ; // SEND RETURN DATA BACK TO SERVER Mirf.setTADDR((byte *) "clie1" ); Mirf.send((byte *) data); } else { delay(2000); // NORMAL OPERATION if (relayState == 0){ // Check Light sensor & Sound... digitalWrite(relay, HIGH); relayState = 1; // Serial.println("NOP - Relay ON!"); } } } |
So, if I sent the following string via the serial port, it would activate the relay -
0001010100000000
0001010100000000
To break it down -
- 0001 is the module serial number
- 01 is the id of the relay
- 01 is the state (00 = off, 01 = on)
- 00000000 are spare values
When the module receives the about string, it will activate the relay.
The project has come further than what I have described, but it’s not stable. It does act as a mesh and also returns sensor data back to the PC. The latest builds, schematics and software will be shared to the community as open source. I am hoping to make it available at some point in February, once it is stable.
I’m also planning to make some developer kits available via GeekBoy.it. This way you can develop this further and use my project to automate your own home, or improve upon the design / code.
The version 1 module and the compiled source (full source coming in February) is available now from our GitHub page -
https://github.com/GeekBoyIT/Home-Automation
https://github.com/GeekBoyIT/Home-Automation
What are the next steps?
- Stabilise the module code
- Add a serial port
- Publish to GitHub the first public version (Make open source)
- Start developing Raspberry PI web server (Replace the PC for control & access Home Automation via web browser)
- Support control via mobile phone
This is the very early stages of this project, however from today we’ll post regular updates and videos of the working units. We want to get these to you the community and see what cool things you can do with them!
0 komentar:
Posting Komentar