loading
Home automation project using the following components


Arduino Mega 2560 http://arduino.cc/en/Main/arduinoBoardMega2560
Integrated circuits:
Maxim DS18B20 http://datasheets.maximintegrated.com/en/ds/DS18B20.pdf
Maxim DS2413 http://datasheets.maximintegrated.com/en/ds/DS2413.pdf
Panasonic AQH3213 http://www.panasonic-electric-works.com/peweu/en/downloads/ds_61613_en_aqh.pdf
UTP cabling with RJ11 connectors (star topology with serial buses, multiple devices on each bus)


Capable of handling:
8        1-wire buses (using dynamic class instances for the library)
256    switches
256    relays
128    temperature sensors (non-parasite mode for faster bus)


* Switch-to-relay associations are freely programmable

* No high voltage and power wires at wall switches, only 12V DC over UTP cable

* Lower surge current and electromagnetic radiation since SSRs turn on and off at zero crossing

* Switches are continuously scanned by the Arduino - as a result switching of relays/lamps work immediately just like for normal lamp switches (many home automation systems are a bit slow, with recognizable delay)

* Single 3.9 k pull-up resistors on the Arduino pins (passive pull-up solution)

* PIR movement sensors, light sensors etc. could be used as switch devices as well (monostable mode with adjustable timer)

* Relays are AC (SSR) or DC (MOSFET) for LED lighting etc.

* Current limitation: SSR maximum current is 1.2A therefore load should be less than 250W (at 220V AC)

* Temperature sensors readable anytime - they are "hidden" in wall switches

* Device data and settings are stored in the EEPROM of the Arduino board - system works even after power outage

* Changes are programmed by serial commands from PC, however it works standalone as well without a PC connected

* By design complex functions which are not time critical should be handled on the PC level instead of the micro controller - e.g activation of heating based on averaged temperature values  



Command examples:

R4>1   Turn on lamp connected to Relay4
R4:1 (response)

Scan    Scan for new connected devices
New devices added(list with IDs)

T8?      Temperature measured by temperature sensor
T8:18.7

R14?   State of relay
R14:1

S9>R6   Switch9 bound to Relay6
S9>R7   Switch9 also bound to Relay7 (wall switch 9 will control lamps (or other loads) 6 and 7 from now on)

Status message example:
R2:0    Lamp connected to Relay2 has been turned off by one of the associated switches or by command

---

Code sections (simplified)

Reading temperature sensor:

#include OneWire.h 
#include EEPROM.h


OneWire *ow;;   // class value initialization

byte addr[8];   //  array to store 1-wire device address
float celsius;   
byte m
;   // temperature sensor number (each sensor address uses 4 bytes in the EEPROM)
bus byte;  //  Arduino pin to use (pin=bus+1)

void MeasureTemp()
       {
       addr[0]=40;   // hex28
       addr[1]=EEPROM.read(m*4);   // address bytes 1-4 (significant bytes) stored at these positions
       addr[2]=EEPROM.read(1
+m*4);
       addr[3]=EEPROM.read(2
+m*4);
      
addr[4]=(EEPROM.read(3+m*4))&15;
       addr[5]=0;   // bytes 5 ad 6 of the 1-wire device address are always 0
       addr[6]=0;       
       addr[7]=addrOneWire::crc8(addr,7)
;   // byte 7 (CRC) is generated from the previous 7 bytes

            
       ow=new OneWire(bus+1);  // creation of class instance
       ow->.reset();
       ow->select(addr);   // select temperature sensor
       ow->write(68);   // start conversion, with zener (bus can be used during the conversion)   
      
delete(ow); // delete of class instance 
       }

       { 800 ms delay
(with timer routine) allowing the DS18B20 calculating the 12 bit temperature value }

     void ReadTemp()
       {
       addr[0]=40;
       addr[1]=EEPROM.read(
m*4);
       addr[2]=EEPROM.read(1
+m*4);
       addr[3]=EEPROM.read(2
+m*4);
       addr[4]=(EEPROM.read(3
+m*4))&15;
       addr[5]=0;
       addr[6]=0;
       addr[7]=addrOneWire::crc8(addr,7)

             

       ow=new OneWire(bus+1);
       ow->reset();
       ow->select(addr);   
       ow->write(190);   // command to read the sensor
       datalow=ow->read();   // reading bytes 1 and 2 only, the actual temperature value
       datahigh=ow->read();    
       delete(ow);   
       unsigned int raw = (datahigh << 8) | datalow; // shifting bits up to form a 12 bit value
       celsius = int(((float)raw / 16.0)*10); 
       }
   
   Serial.println (celsius/10);   // result is in Celsius with 0.1 degree accuracy


---

Reading switch status:

byte PIOdata;
byte k;          // switch ID

void ReadPIO()
    {
    ow->reset();
    addr[0]=58;          
    addr[1]=(EEPROM.read(2048+k*8));           
    addr[2]=(EEPROM.read(2049+k*8));          
    addr[3]=(EEPROM.read(2050+k*8));
    addr[4]=(EEPROM.read(2051+k*8)&15);    // address byte is always less than 15
    addr[5]=0;
    addr[6]=0;
    addr[7]=OneWire::crc8(addr,7);
    ow->select(addr);                // select switch
    ow->write(245);                    // PIO read command  
    PIOdata=ow->read();
    if (PIOdata==30)              // switch A is closed*
      {
      ToggleLamp();               // relay state inverted and short delay added to prevent flapping
      }   
  }


* if both contacts are open the result is 15

bit 0      DS2413 pin 6 (PIO A) input level
bit 1      DS2413 pin 6 (PIO A) inverted (!) output level (controls output transistor) , 0 = transistor pulls pin to ground
bit 2      DS2413 pin 4 (PIO B) input level
bit 3      DS2413 pin 4 (PIO B) inverted output level
bit 4-7  inverted values of bits 0-3

as a result 15 (0000 1111) means both input levels are HIGH (bits 0 and 2) due to the 22 kohm pullup resistors and both output transistors are open (bits 1 and 3) they allow the output to "float"

when switch A is closed pin 6 is shorted to ground resulting bit 0 to change to LOW:
input value will change from 15 (0000 1111) to 30( 0001 1110)

when switch B is closed (while switch A is released) the input is 75 (0100 1011)

---

Inverting Relay state:

void ToggleLamp()
  {
  addr[0]=58;          
  addr[1]=(EEPROM.read(1020+m*4));           
  addr[2]=(EEPROM.read(1021+m*4));          
  addr[3]=(EEPROM.read(1022+m*4));
  addr[4]=(EEPROM.read(1023+m*4)&15);
  addr[5]=0;
  addr[6]=0;
  addr[7]=OneWire::crc8(addr,7);
   
  ow->reset();
  ow->select(addr);       // select relay,
  ow->write(245);          // PIO read command
  PIOdata=dv.read();
 
  if (PIOdata==15)         // Transistors are open (=relay is open)
    {
    ow->reset();
    ow->select(addr);   
    ow->write(90);              // PIO write command
    ow->write(254);            // turn on transistor A*
    ow->write(1);                 // inverted byte must be written as well for verification (!)
    Serial.print("R");
    Serial.print (m);
    Serial.println (":1");
    }
  
  if (PIOdata==120)      // relay is closed
    {
    ow->reset();
    ow->select(addr);    
    ow->write(90);              // PIO write command
    ow->write(255);            // turn off transistor A*
    ow->write(0);                 // inverted byte must be written as well for verification (!)     
    Serial.print("R");
    Serial.print (m);
    Serial.println (":0");
    }
  }

*  The SSR's internal LED is driven by transistor A (PIO A output) of the 1-wire switch, pin 6. When bit 0 is set to 0 (111111 10) the transistor pulls the output level to GND - activating the LED and the SSR. By setting bit 0 to 1 (111111 11) the SSR is deactivated.
Output B is not in use in my circuit, however of course it could activated similarly with bit 1 (111111 01). The remaing six bits must be high all the time.

Since both switches and relay use DS2413 chips they are differentiated when a new device is added. A routine activates transistor A for a short period. In case the remote device is a relay logical LOW will be detected on the PIO B input since the two pins are connected.

In progress:

*Test of PIR sensors and addition of adjustable delay function in the software

*Developing pressure sensor

*Modifying the OneWire library to allow parallel operation on all buses (currently all 1-wire commands are sequential)

*Testing 1-wire Overdrive mode

*Web based remote management (PHP+UDP)
<p>Woowww, I'm very interested of this 1 wire arduino project !!!</p><p>Hope you can update it soon !!!</p>
<p>Hi! I'm very surprise to find this brilliant idea here!</p><p>Did you implement this project and can you share the experience?</p><p>Thank you</p>
<p>Hi, nice project! Onewire is very easy to implement and use, but <br>should'nt be used for long distances as it is one high impedance wire. <br>Did you use this with long distances? Do the one-wire bus pass near AC line cables? Did you experience problems? Thank you!</p>
<p>Hi Thx !<br><br>Maxim gives 200 meters when using normal phone cables. With the UTP cables I used it should be even more. Accordingly I experienced no problems related to distances.<br>Yes the 1-wire cables run in the same tubes as the 220 and 380 V power cables, no issues experienced with interference.<br>The only problem I found is a damaged SSR due to a failing 100W incandescent bulb. To prevent this a surge protection element is added.<br><br>I will update this project with further details in a few months. </p>
How do I get the OneWire.h? Thank you

About This Instructable

22,961views

36favorites

License:

More by Zsolt.K:Home automation project based on 1-wire devices 
Add instructable to: