Tuesday 16 December 2014

ArduinoHomeAutomationProject: The Bridge-Processing-Software

The BridgeProcessing-Software


Overview in Processing


THE CODE

This is my approach to store serial-data into a SQL Database. I will describe the RPI Setup later.
import processing.serial.*;
import de.bezier.data.sql.*;
import java.util.*; 
MySQL db;
Serial myPort;  // Create object from Serial class
int myaddr = 1;
int addr;
int numeric;
int ldr;
int heat;
int light;
int node = 1;
int nodec = 1;
long setTimer = 120000;
int commandtimer = 10000;
int nrofnodes = 2;
int timerflag = 0;
int commandflag = 0;
int x = 1;
int i = 0;
int addrset;
int tempmin;
int hummin;
int lightsw;
int heatsw;
int setflag;
String TIME;
String TIMESTAMP;
String room;
float temp;  
float hum;
long oldmillis;
long newmillis;
long oldcommandmillis;
long oldutchour;
long newutchour;
int utcflag = 0;
long utc;
char c;
String inData;
String[] list = new String[32];
String inDatapl;
String[] listpl = new String [32]; 
char utch = '@';
char sof = '#';
char dof = '/';
char plm = 'P';
char eof = '|';
char rf = '0';
char wf = '1';
char ack = '2';
char set = '3';
int flag;
void setup()
{
   size(640, 360);
   smooth();
   String portName = Serial.list()[2];
   myPort = new Serial(this, portName, 19200);
   myPort.buffer(64);
   myPort.bufferUntil(eof);
 
   String user     = "youruser";
   String pass     = "yourpass";
   String database = "ahap"; //DBName
   db = new MySQL( this, "localhost", database, user, pass );
}
void draw()
{
  newmillis = millis();
  newutchour = hour();
  //serial.Event(myPort);

  readSerial();
  if (newmillis - oldmillis > setTimer/(nrofnodes-1) || timerflag == 0 || commandflag == 1) // || commandflag == 1
  {
    commandflag = 0;
    timerflag = 1;
    writeSerial();
    oldmillis = millis();
  }
  if (millis() - oldcommandmillis > commandtimer/(nrofnodes-1))
  {
   oldcommandmillis = millis();
   writeSerialCommand();
  }
   if (newutchour != oldutchour || utcflag == 0)
  {  
    oldutchour = hour();
    utcflag = 1;
    calculateutc();
  }
  background(0);
  textSize(20);
  //int y=x+1;
  text("Addresse: " + node , 50, 30);
  text("Raum: " + room , 350, 30);
  textSize(16);
  text("Daten von: data-DB", 50, 50);
  text("Daten von: data_set-DB", 350 , 50);
  textSize(14);
  text("Temperatur: " + temp/10, 50, 80);
  text("Feuchtigkeit: " + hum/10, 50, 100);
  text("Heizung: " + heat, 50, 120);
  text("LDR: " + 0.1*ldr, 50, 140);
  text("Licht: " + light, 50, 160);
  text("letzter Kontakt: " + TIME, 50, 180);

  text("Msg OUT: " + sof + addrset + dof + myaddr + dof + wf + dof + tempmin + dof + hummin + dof + lightsw + dof + heatsw + eof, 50, 240);
  text("TIMEstamp: " + utch + hour() + dof + minute() + dof + second() + dof + day() + dof + month() + dof + year() + eof, 50, 280);
  text("Durchlauf " + i , 50, 220);
  text("Msg IN: #" + list[0] + dof + list[1] + dof + list[2] + dof + list[3] + dof + list[4] + dof + eof, 50, 260);
  text("Anzahl Nodes " + nrofnodes , 50, 300);
  text("Node " + node , 50, 320);

  text("soll Temperatur: " + tempmin, 350, 80);
  text("soll Feuchtigkeit: " + hummin, 350, 100);
  text("Heizung ein/aus: " + heatsw, 350, 120);
  text("Licht ein/aus: " + lightsw, 350, 140);
  text("eingestellt am: " + TIMESTAMP, 350, 180);
  //calculateutc();
  }

 void readSerial()
 {
   if (myPort.available() >0)
   {  delay(50);
      c = myPort.readChar();
      if ( c == sof )
      {
        inData = myPort.readStringUntil(eof);
        if(inData != null){
        list = split(inData, "/");
        print("Empfänger: ");
        println(list[0]);
        print("Sender: ");
        addr = int(list[1]);
        println(list[1]);
        print("Flag: ");
        println(list[2]);
        flag = int(list[2]);
        int listcount = list.length;
        print("Listenfelder: ");
        println(listcount);
     
        if (listcount > 8){
          //println("FLAG ACK ERKANNT");
          print("Temperatur: ");
          temp = int(list[3]);
          println(temp/10);
          print("Feuchtigkeit: ");
          hum = int(list[4]);
          println(hum/10);
          print("Heizung: ");
          heat = int(list[5]);
          println(heat);
          print("LDR: ");
          ldr = int(list[6]);
          println(0.1*ldr);
          print("Licht: ");
          light = int(list[7]);
          println(light);
          println(" ");
          sqlset();
          inData = null;
          }
                     
         if (listcount < 8){
             //println("FLAG SET ERKANNT");
             //inData = myPort.readStringUntil(eof);
             //if(inData != null){
             //list = split(inData, "/");
             print("Heizung: ");
             heat = int(list[3]);
             println(heat);
             print("Licht: ");
             light = int(list[4]);
             println(light);
             commandflag = 1;
             sqlupdate();
             inData = null;
           
             }
               
         }
        }
      }
   
 
    else {
      myPort.clear();
    }
    //delay(1);
    //myPort.clear();
 }

 void writeSerial()
 { println("write Serial");
   i= i+1;
    if (node <= nrofnodes)
   {
     node++;
   }
  if (node == nrofnodes + 1 || node == 0)
  {
     node = 2;
   }
   db.connect();
 if(db.connect() == true)
  {    
   db.query( "SELECT COUNT(*) FROM room_set" );
   db.next();
 
   nrofnodes = db.getInt(1);


   db.query( "SELECT  `TIME` FROM `data` WHERE addr=('%s') ORDER BY ID DESC LIMIT 1", node);
   db.next();
   TIME = db.getString("TIME");
 
   db.query( "SELECT  `room` FROM `room_set` WHERE addr=('%s')", node);
   db.next();
   room = db.getString("room");
 
   db.query( "SELECT  `addr`, `tempmin`, `hummin`, `lightsw`, `heatsw`, `TIME` FROM `data_set` WHERE addr=('%s') ORDER BY TIME DESC LIMIT 1", node);
   db.next();
   addrset = db.getInt("addr");
   tempmin = db.getInt("tempmin");
   hummin = db.getInt("hummin");
   lightsw = db.getInt("lightsw");
   heatsw = db.getInt("heatsw");
   TIMESTAMP = db.getString("TIME");

   myPort.write(char(sof));
   myPort.write(str(addrset));
   myPort.write(char(dof));
   myPort.write(str(myaddr));
   myPort.write(char(dof));
   myPort.write(str(rf));
   myPort.write(char(dof));
   myPort.write(str(tempmin));
   myPort.write(char(dof));
   myPort.write(str(hummin));
   myPort.write(char(dof));
   myPort.write(str(lightsw));
   myPort.write(char(dof));
   myPort.write(str(heatsw));
   myPort.write(char(eof));

  }
 db.close();
 
 }

 void writeSerialCommand()
 {
    println("write Serial Command");
  if (nodec <= nrofnodes)
   {
     nodec++;
   }
  if (nodec == nrofnodes + 1 || nodec == 0)
  {
     nodec = 2;
   }
  db.connect();
  if(db.connect() == true)
    {    
     db.query( "SELECT COUNT(*) FROM room_set" );
     db.next();
     nrofnodes = db.getInt(1);
   
     db.query( "SELECT  `addr`, `tempmin`, `hummin`, `lightsw`, `heatsw`, 'setflag', `TIME` FROM `data_set` WHERE addr=('%s') ORDER BY TIME DESC LIMIT 1", nodec);
     db.next();
     
       addrset = db.getInt("addr");
       tempmin = db.getInt("tempmin");
       hummin = db.getInt("hummin");
       lightsw = db.getInt("lightsw");
       heatsw = db.getInt("heatsw");
       //setflag = db.getInt("setflag");
       TIMESTAMP = db.getString("TIME");
     
     // if (setflag == 1){
       myPort.write(char(sof));
       myPort.write(str(addrset));
       myPort.write(char(dof));
       myPort.write(str(myaddr));
       myPort.write(char(dof));
       myPort.write(str(wf));
       myPort.write(char(dof));
       myPort.write(str(tempmin));
       myPort.write(char(dof));
       myPort.write(str(hummin));
       myPort.write(char(dof));
       myPort.write(str(lightsw));
       myPort.write(char(dof));
       myPort.write(str(heatsw));
       myPort.write(char(eof));
      // setflag = 0;
      //}
   
     db.close();
     if (x == nrofnodes)
       {
       x=1;
       }  
   }
 }  
 void sqlset()

 {
   db.connect();
   if(db.connect() == true)
  {
    db.query("INSERT INTO data (addr, temp, hum, ldr, heater, light) VALUES ('%s', '%s', '%s', '%s', '%s', '%s')",addr, temp/10, hum/10, ldr*0.1, heat, light);
    db.close();
  }
 }

void sqlupdate()

 {
   db.connect();
   if(db.connect() == true)
  {
    db.query("UPDATE data_set SET heatsw =%s, lightsw =%s, setflag = %s WHERE addr='%s' ", heat, light, setflag, addr);
    db.close();
  }
 }

 void calculateutc()
 {
   println("calculateUTC");
   delay(500);
   myPort.write(char(utch));
   myPort.write(str(hour()));
   myPort.write(char(dof));
   myPort.write(str(minute()));
   myPort.write(char(dof));
   myPort.write(str(second()));
   myPort.write(char(dof));
   myPort.write(str(day()));
   myPort.write(char(dof));
   myPort.write(str(month()));
   myPort.write(char(dof));
   myPort.write(str(year()));
   myPort.write(char(eof));
   delay(10);
   println("TimeSET");
   //myPort.clear();
 }

ArduinoHomeAutomationProject: The BridgeNode: PROTOTYPE & SKETCH (USE AT OWN RISK!!!)

The BridgeNode: PROTOTYPE & SKETCH (USE AT OWN RISK!!!)

The bridge is handling the data from the RaspberryPI SerialPort. I decided to take the USB Serial because there is no need to add a voltage divider (RPI 3,3V Logic, Arduino 5V Logic). The Incoming data is forwarded over the SoftwareSerial (RS485) while setting the DE Pin of the MAX485 high.
This is working for both directions. It is working at the moment, but i have to test it with more nodes to check for timing mismatches.

The Setup is an ArduinoNano + MAX485. 




THE CODE

#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3); // RX, TX
void setup()
{
  Serial.begin(19200);
  mySerial.begin(19200);
}
void loop()
{  mySerial.listen();
  if (mySerial.available())
    Serial.write(mySerial.read());
    //delay(1);
  if (Serial.available())
    mySerial.write(Serial.read());
    delay(2);
}

TheSUN; Arduino powered wall clock; synced by AHAP


THESun; Arduino powered wall clock

Hi folks! A few days ago i decided to release my second Instructable about building an Arduino powered wall clock made of acrylic glass. Personally I am very satisfied with the result.
I attached some fotos here. The description itself can be found on Instructables.com just follow this LINK.

Startsequence

TheSUN in action



Fritzing







Wednesday 19 November 2014

ArduinoHomeAutomationProject: The SensorNode; PART 2: PROTOTYPE THE HARDWARE

The SensorNode; PART 2: PROTOTYPE THE HARDWARE

In "The SenorNode; PART 1" we made a brief plan of our node and should be able to proceed by prototyping our hardware.

Let´s have a look at how I did it:


You will need the following parts to setup the Prototype:
  • 1x Arduino nano or Arduino UNO
  • 1x breadboard + wires
  • 1x DHT22 + 4.7k pullup resistor
  • 1x LDR + 10k resistor
  • 2x LED + 2x 220Ohm resistor
  • 2x pushbutton
  • 1x I2C LCD (I´m using a I2C 16x2 LCD) + dupont wires (male - female)
You don´t need the Max485 chip + its 120Ohm resistor yet.

All you have to do is wiring everything to get a working prototype.
If you want to, you can try to make your own sketch for the prototype.
I will present and explain you my (already working) Arduino-sketch in PART 3.
Stay tuned!

Tuesday 18 November 2014

ArduinoHomeAutomationProject: The SensorNode; PART 1: HARDWARE CONSIDERATIONS

THE SENSORNODE; PART 1: HARDWARE CONSIDERATIONS

Well, it´s time to get a little more concrete what the sensor node should do.
It should definitely measure the temperature, shouldn´t it?
In my case I also wanted to get some data about humidity and luminous intensity.
Further it should be possible to display the sensor readings and the time (if you want) to the user.

Now we defined what data we want to get from the environment, but we also want to interact with it.
My plan is to switch lights and electric radiators on and off.

The above mentioned things are enough to setup a prototype.

THE HARDWARE

We are going to use Arduino for our project, so we will prefer those sensors where an Arduino compatible library exists. We also should be aware of the sensor tolerance and its accuracy.

e.g.
  •  a Sensor with a temperature range from 0 - 50°C and an accuracy of +/- 0,5°C will not make much sense for a wheaterstation. 
  • a Sensor with a range from -40 - 90°C and an accuracy of +/- 2°C will not fit our needs.
I found those nice little DHT22 Sensors which have a temperature-range of -40 - 80°C with +/- 0,5°C and a humidity measuring range of 0 - 100% (accuracy +/-2%). You can get them for a few bucks on Aliexpress. We also need some 4.7k pull-up resistors for those sensors. There is a Arduinolibrary available on https://github.com/adafruit/DHT-sensor-library.

For measuring the luminous intensity we can take a LDR and a 10k Resistor for  the voltage divider.
We don´t need a library for that, because the sensor-reading with Arduino will be pretty much like "analogRead(PIN)" + some calculation for the interpretation of the data.

Further we will implement some switches or buttons which we are going to connect with a 10k resistor to the Arduino. These switches can be used to manually switch lights on and off.

Now let´s have a look at how we present the data to the user. Take a display which is already tested with Arduino and be aware that it has enough space to display all the data.
With a 16x2 LCD you possibly run out of space and have to switch the display modes, but you can give it a shot, it is well tested and there are library’s around.
In my opinion a good choice would be an 0,96" I2C OLED. They are small, they are cheap, and you have a really good resolution to display the data.
You can get the library’s here:
Last but not least we should consider which type of transmission we will use. For easier code implementation I recommend something that supports the Serial UART bus of Arduino. 
I´m going to test the whole thing with MAX RS485 chips to build a long range RS485 bus-network (max. about 1000m via 2wire connection). If I can get some RF transceivers like "433Mhz Wireless Serial CC1101 Module" or "RF1100-232-TTL" I´m going to test them.

Monday 17 November 2014

ArduinoHomeAutomationProject: The Concept - The cognition that something big is approaching

THE START

I started to make a concept for an Arduino based home automation a couple of month ago.
In fact the concept isn´t ready yet, there are really much things you have to mind but it´s a start.

You have to mind: What should the whole thing do? How should the user interact with it?
Trust me! KEEP IT AS SIMPLE AS POSSIBLE! It will be a hard nut to crack anyway.

THE NODE

First of all we have to be sure what the sensornodes should do.
  • measuring (temperature, humidity, light intensity, buttons, current...)
  • actuators (switch on lights, radiators, sprinklers, ...)
  • how should those "sensor - readings" be shown to the user (displays, web interface, GUI for mobile devices,...)
  • how should the user interact with the system
  • communication & protocol

Is it possible to do those things with a small microcontroller like Arduino?
The answer is: most of them. We can get the sensor data, switch things on and off, and Arduino has the possibility to use displays (LCD, OLED, ...).

THE NETWORK

When you think, "that’s more than half the battle" you’re definitely wrong!

It´s a start, a sensor-node, but we need lots of them! Let’s say at minimum a handful for a small flat.

How should they communicate to each other? Arduino has SPI, I2C and Serial UART (RS232) on-board. What am I able to do? How can I extend the range of electronic signals? Do they have enough bandwidth?

It´s on you what you’re going to pick, there is enough useful hardware on the market and you can get an ArduinoLib for most of them. I´m not a great fan of radio communication so I decided to give RS485 a shot. It´s long range (over 1000m) bus-network, which is stable, doesn´t need much electronics and communication should hopefully be as easy as Serial.read(), Serial.print().
In fact there are also radio-transceivers which will work with the UART of the µC, but I wasn´t able to test them till yet.

THE DATABASE

If you’re planning an automation system or a sensor network, you probably want to save the sensor-readings into a database. I think you should, like me, give MySQL a shot. It´s free, it´s reliable, and there is a big community behind it. The planning of the database will be its own story to tell :-P

THE WAY FROM THE SENSOR TO THE DATABASE

If you use Arduino plus an Ethernetshield you have the ability to write into a DB. It is possible, but that’s not the way I wanted to do it. I was really afraid of performance issues caused by DB queries.
So I decided to take another popular device, the Raspberry PI. The RasPI should do all the jobs I’m afraid Arduino has a lack of performance. The Raspi itself also has a huge community behind it, it’s a Linux based PC, doesn´t drain much current and it is possible to run a DB Server on it. So there is still one problem left... "How the h... can we get all the data from Arduino to the DB???".
Well, you can break your minds or follow my considerations.
We have:
  • PHP, it has the ability to read from the Serial with a library, I was not able to verify it´s reliability and I´m not a big PHP Coder.
  • PYTHON, I’m not familiar with python
  • JAVA
  • Processing, it´s a sister project to Arduino so the Environment plus the Syntax are familiar to me. (option chosen)

So all we have to do is writing a "bridge-program" which takes the data from the bus, process it and handle it to the DB.
Sounds like a plan, doesn´t it? 

THE INTERFACE TO THE USER

For me that was really one of the hardest decisions in the whole project. I wanted to get the GUI into the WEB and the only chance I´ve seen to get everything together was PHP (that´s hard, I don´t really know PHP nor have I ever written a code in PHP). So I have to learn PHP, "OH MY GOD!".
The fact, that I´m not used to it will definitely slow down the work progress.

THE CONCLUSION

If you think that were the main questions and we are ready to go, follow me on my adventure, and let´s proof you´re wrong.


Impressum

Auer Markus
Karwendelstr. 13
A - 6020 Innsbruck