Introduction: Home Automation Project Based on 1-wire Devices

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)

Comments

author
pcludeg (author)2017-07-31

thanks

author
diman64 (author)2015-12-19

Woowww, I'm very interested of this 1 wire arduino project !!!

Hope you can update it soon !!!

author
skmbi (author)2015-10-28

Hi! I'm very surprise to find this brilliant idea here!

Did you implement this project and can you share the experience?

Thank you

author
tecnovillage (author)2015-01-18

Hi, nice project! Onewire is very easy to implement and use, but
should'nt be used for long distances as it is one high impedance wire.
Did you use this with long distances? Do the one-wire bus pass near AC line cables? Did you experience problems? Thank you!

author
ZsoltK (author)tecnovillage2015-01-19

Hi Thx !

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.
Yes the 1-wire cables run in the same tubes as the 220 and 380 V power cables, no issues experienced with interference.
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.

I will update this project with further details in a few months.

author
tteo (author)2013-08-30

How do I get the OneWire.h? Thank you

About This Instructable

23,320views

36favorites

License:

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