A timer with the DS1307 RTC chip: the code

Here I am again with the timer.

As I explained in the previous post I want to turn on and/or turn off an electrical appliance at 220 V using relays.

I never had any experience in using relays, then at the moment the scheme will include a led.

Here is the schema seen previously with the addition of led connected to PIN 13 Arduino digital:

persito

 

And here is the code:

 

#include <Wire.h>
#include <String.h>
#include "RTClib.h"
  
#define BUFFER_SIZE 20
#define STATE_OFF  0
#define STATE_ON   1
  
//Giornate di programmazione
const int numeroProgrammazioni = 4;
String Monday[numeroProgrammazioni] = {
  "21:35", "20:30","20:35","20:40"};
String Tuesday[numeroProgrammazioni] = {
  "11:00", "11:35","13:10","13:50"};
String Wednesday[numeroProgrammazioni] = {
  "20:55", "19:58","20:00","20:05"};
String Thursday[numeroProgrammazioni] = {
  "10:00", "10:35","17:10","20:00"};
String Friday[numeroProgrammazioni] = {
  "10:00", "10:35","14:10","15:00"};
String Saturday[numeroProgrammazioni] = {
  "18:15", "18:20","18:22","18:25"};
String Sunday[numeroProgrammazioni] = {
  "10:00", "10:35","12:10","15:00"};
//Fine giornate di programmazione
  
RTC_DS1307 rtc;
int fsm_state;
String START_TIME;
String END_TIME;
int nSize = numeroProgrammazioni / 2;
String giornoTemp[numeroProgrammazioni];
  
void setup () {
  //Serial.println("Inizio Setup");
  fsm_state = STATE_OFF;
  Serial.begin(57600);
#ifdef AVR
  Wire.begin();
#else
  Wire1.begin(); // Shield I2C pins connect to alt I2C bus on Arduino Due
#endif
  rtc.begin();
  
  if (! rtc.isrunning()) {
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }
  
  pinMode(13,OUTPUT);        //Collegamento al LED
}
  
void loop () {
    // Ricavo il time attuale
    DateTime now = rtc.now();  
  
    int giorno = now.dayOfWeek();      //0 = Monday 1 = Tuesday 2 = Wednesday ....
    //Serial.println( giorno);
    if (giorno == 1){                  //Monday
      memcpy(giornoTemp,Monday, sizeof(Monday));
    }
    else if (giorno == 2){            //Tuesday
      memcpy(giornoTemp,Tuesday, sizeof(Tuesday));
    }
    else if (giorno == 3){            //Wednesday
      memcpy(giornoTemp,Wednesday, sizeof(Wednesday));
    }
    else if (giorno == 4){            //Thursday
      memcpy(giornoTemp,Thursday, sizeof(Thursday));
    }
    else if (giorno == 5){            //Friday
      memcpy(giornoTemp,Friday, sizeof(Friday));
    }
    else if (giorno == 6){            //Saturday
      memcpy(giornoTemp,Saturday, sizeof(Saturday));
    }
    else if (giorno == 7){            //Sunday
      memcpy(giornoTemp,Sunday, sizeof(Sunday));
    }
  
    //verifico lo stato che dovrà assumere
    int isON = 0;
    for (int i= 0; i< nSize;i++){
      START_TIME = giornoTemp[i*2];
      END_TIME = giornoTemp[(i*2)+1];
      isON = setStatus(now,START_TIME,END_TIME);
      gestisciCarico(isON);
    } //end for
  
  delay(3000);
}
  
int setStatus(DateTime timeOra, String START_TIME, String END_TIME)
{
  //recupero l'ora
  DateTime dSTART_TIME = DateTime(timeOra.year(),timeOra.month(),timeOra.day(),START_TIME.substring(0, 2).toInt(),START_TIME.substring(3, 5).toInt(),0);
  DateTime dEND_TIME = DateTime(timeOra.year(),timeOra.month(),timeOra.day(),END_TIME.substring(0, 2).toInt(),END_TIME.substring(3, 5).toInt(),0);
  long lSTART_TIME = dSTART_TIME.unixtime();
  long lEND_TIME = dEND_TIME.unixtime(); 
  
  switch(fsm_state) {
  case STATE_OFF:
    if(timeOra.unixtime() > lSTART_TIME && timeOra.unixtime() < lEND_TIME) {
      fsm_state = STATE_ON;
      //Serial.println("caso 1");
    }
    break;
  case STATE_ON:
    if(timeOra.unixtime() > lEND_TIME) {
      fsm_state = STATE_OFF;
      //Serial.println("caso 2");
    }
    break;
  }
  
  return fsm_state;
}
  
void gestisciCarico(int isON)
{
  if (isON == 1){
    digitalWrite(13,HIGH);
  }
  else
  {
    digitalWrite(13,LOW);
  }
}

Code explanation:

from line 12 to line 25: setting times of day when turn led
row 47: setting RTC with time and date code compilation
row 50: setting led connection on pin 13
In the loop:
row 55: updating RTC with current day and time
row 57: Getting current day (0= monday, 1 = thusday…).
In this way i can undestand which array I have to use to determine hour settings.
line 86: using the setStatus function to test whether or not turn on the led
row 84: function setStatus: to compare dates using the function unixtime () that converts the date to unix (long): The function returns an int (0/1) 1 turn on led and 0 turn off
line 87: gestisciCarico function: the function takes as input the value previously returned. At this point it is actually switched on led.

 
This is actually what we wanted: our led will turn on or off in the hours established by us.

The next steps, which I’ll explain soon are:

1. adding a random function (optional): If the random function is activated, I’ll add some random minutes to the hour I decided in array.

2. using relay to turb off or on a 220v bulb.

That’s all.

Happy 2016!

A timer with the DS1307 RTC chip: idea and connections

Hello again everyone, thanks to my dad’s suggestion, I’d like to use Arduino to turn on and turn off a lamp or any 220 V device at certain times of the week.

So for example:
-on Monday I want my lamp lights at 8.15 till 9.40, in the afternoon from 17.10 at 17.45.
-on Tuesday, at 9.20 a.m. 10.50 a.m.
-on Wednesdays from 10.00 a.m. to 11.00 a.m. and in the afternoon from 15.10 at 15.45
and so on, until Sunday

To do this I got the chip DS1307:it’s a very cheap RTC (real-time clock) that allows you to keep track of time and date.
It also has a buffer battery which ensures the functioning of the internal clock in the absence of external power.

It is possible to communicate with the chip via I2C Protocol, so we can use the Wire library.

The connection between arduino and the chip is very simple, as shown in the picture below:

 

Timer

 

To summarize:

 

 

Arduino Pin PIN DS1307
5 V 5 V
GND GND
Analog pin 4 SDA
Analog pin 5 SCL

 

Connections between Arduino and the chip will vary depending on the model of Arduino (Uno, leonardo, etc).
In fact the PIN SDA (data line) and SCL (clock line) differ above:

 

Board I2C/TWI pins
Uno, Ethernet A4 (SDA), A5 (SCL)
Mega2560 20 (SDA), 21 (SCL)
Leonardo 2 (SDA), 3 (SCL)
Due 20 (SDA), 21 (SCL), SDA1, SCL1

 

In the next post we will see how to handle date and time, and how you can use this information when we want to turn on a device.

Bye!!!

My first clone (CH340G chip)-Arduino

For my latest experiments (see previous post) I decided to buy my first Arduino clone.

Once written the sketch I tried to upload it: nothing, no USB communication with my MAC system.

Reading the ad and looking better the tab, I found that the chip that is responsible for the serial communication is not present in the original Arduino boards but is the CH340G chip (USB/Serial Interface).

It is therefore necessary to find the correct drivers to handle the chip.

I found this very interesting guide searching in Internet.

Summary for my future and memory for those who follow me:

  1. Download the drivers fromm here (chip manufacturer’s site) or directly from my site (CH341SER_MAC)
  2. Unzip the file
  3. Open the unzipped folder, inside there is ch34xInstall.pkg file. Run the package installation
  4. If required, perform the reboot
  5. If, like me, you have OS-X, open Terminal and run the following command:
    sudo nvram boot-args="kext-dev-mode=1"
    
  6. Reboot

At this point in the Arduino Ide, on the Tools menu, serial port, you can select the correct serial port.

I hope you can help!

 

The HC-ultrasonic sensor SR04 – ARDUINO

One of the initial ideas that I had in mind in the implementation phase of my anti theft was using an ultrasonic sensor for detecting distance.

Then I used the PIR.

Now I decided to study distance sensor and to read some documentation and datasheets.

Measuring with this sensor is made by measuring the time it takes for a sound signal to reach an object and return to the sensor.

The measure is therefore not in terms of distance but in time, in specific microseconds.

HC-sensor SR04 has 4 pin: Vcc (+ 5V), Trigger, Echo, GND.

FullSizeRender

In principle, the operation is as follows:

  1. sends a ping sound Trigger pin
  2. If an obstacle is trapped the wave is reflected back.
  3. the Echo pin receive the signal returned

The time taken allows us to determine the distance between the sensor and the barrier.

How to do it?

To convert the unit of time in space is necessary to know the speed of sound in air: helps wikipedia.

In the air, the speed of sound is to 331.45 m/s at 0° C (equal to 1193.04 km/h) and 343.8 m/s (equivalent to 1237.68 km/h) at 20° C (and generally varies according to the relationship a = + 331.45 0.62 t with t is measured in° C).

Then consider about 343 m/s, expressed in centimeters: cm/0.0343 microseconds.

As space = speed * time (s = v * t) it follows that s = 0.0343 * t.

But we must consider that time identified by the Echo pin is when it departs from the Trigger pin, arrival to the obstacle and back towards the sensor.

Then you will have to split time: 0.0343 s = s * t/2.

The formula we use will be: s = 0.01715 * t

Let now understand how will be connection with Arduino:

Arduino Pin Sensor Pin
POWER 5V VCC
7 digital Trig
Digital 8 Echo
GND GND

SensoreDistanza2 SensoreDistanza1

DistanceSensor_bb

Then the code:

int trigger_Port = 7;
int echo_Port = 8;

void Setup() {
  pinmode (trigger_Port, OUTPUT);
  pinmode (echo_Port, INPUT);
  Serial .begin method (9600);
  Serial.println ("Ultrasonic Distance Sensor:");

}

void loop() {
  output low septum on the trigger pin
  digitalwrite (trigger_Port, LOW);

  send 10 pulse micro seconds on the trigger pin
  digitalwrite (trigger_Port, HIGH);
  delayMicroseconds (10);
  set  low again on the trigger pin
  digitalWrite (trigger_Port, LOW);
  I read the pin duration Echo
  long durata = pulseIn( echo_Port, HIGH );
  calculating the duration
  long r = 0.034 * durata / 2;

  Serial.print( "durata: " );
  Serial.print( durata );
  Serial.print( " ," );
  Serial.print("distanza:" );

  After 38ms is out sensor range
  if( durata > 38000 ) Serial.println( "out of sensor range");
  else {
    Serial.print( r );
    Serial.println( "cm" );
  }

  //wait for 1.0 seconds
  delay (1000);
}

You can also use the new_ping library.

Once you’ve downloaded the library and copied the folder libraries of Arduino, you can simplify writing code:

#include <NewPing.h>

#define trigger_Port 7
#define echo_Port 8
#define max_distance 200

NewPing sonar(trigger_Port, echo_Port, max_distance); 

void setup() {
 Serial.begin(9600);
}

void loop() {
 delay(50);
 unsigned int uS = sonar.ping_cm();
 Serial.print(uS);
 Serial.println("cm");
}

With this library you can also send a ping and get back the average of readings, simply use:

nsigned int uS = sonar.ping_median(numero misurazioni);

#include <NewPing.h>

#define trigger_Port 7
#define echo_Port 8
#define max_distance 200

NewPing sonar(trigger_Port, echo_Port, max_distance); 

void setup() {
 Serial.begin(9600);
}

void loop() {
  delay(50);
  unsigned int durata = sonar.ping_median(5);
  long r = 0.034 * durata / 2;
  Serial.print(r);
  Serial.println("cm");
}

In this case I set 5 the number of measurements. Then there will be the average of 5 measurements.
What can I say … it’s definitely a library as useful as easy to use!

A simple Arduino burglar alarm: the whole code

Finally I can post the complete code with the changes to the memory management !

 


#include <String.h>
#include <RCSwitch.h>
#include <Time.h>
#include <SPI.h>
#include <Ethernet.h>
#include <EEPROM.h> 

/* Informazioni Ethernet*/

byte mac[] = {
  0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 };
int SERIAL_BAUD        = 9600;
int TRASMIT_PIN       = 9;
int RECEIVE_PIN       = 0;
int NOISE_DIGITAL_PIN =    5;
//wireless code webcam
long SEGNALE_ACCENZIONE_WEBCAM = 1394001;
long SEGNALE_SPEGNIMENTO_WEBCAM= 1394004;
int nSensori = 5;

EthernetClient client;
EthernetServer server(8081);
char smtpServer[] = "smtpcorp.com";
RCSwitch mySwitch = RCSwitch();

void setup() {
  Serial.begin(SERIAL_BAUD);
  pinMode(SERIAL_BAUD, INPUT);
  mySwitch.enableReceive(RECEIVE_PIN);  // Receiver on inerrupt 0 => that is pin #2
  mySwitch.enableTransmit(TRASMIT_PIN);  // Using Pin #10
  setupComm();
}

void loop() {
  getClientConnection();
  if (detectNoise()){
   Serial.print("Rumore");
   email("Attention, noise detected!");
   accendiCam(SEGNALE_ACCENZIONE_WEBCAM) ;
   }

  if (mySwitch.available()) {
    int value = mySwitch.getReceivedValue();
    //Serial.print(value);
    if (value == 0) {
      Serial.print("Unknown encoding");
      Serial.print("\n");
    }
    else {
      long receivedValue = mySwitch.getReceivedValue();
      int isPresente = isPresenteSensore(receivedValue);
      if (isPresente != -1)
      {
        //Trovato codice
        String messaggioRilevazione = "Attention! Sensor " +String(isPresente)+ " detected!";
        Serial.println(messaggioRilevazione);
        email(messaggioRilevazione);
        accendiCam(SEGNALE_ACCENZIONE_WEBCAM) ;
        delay(1000);
      }
    }
    //mySwitch.resetAvailable();
  }
}

bool detectNoise ()
{
  bool rit = false;
  if (digitalRead(NOISE_DIGITAL_PIN) == HIGH)
  {
    rit = true;
  }
  return rit;
} 

void accendiCam(long value)
{
  mySwitch.send(value, 24);
  mySwitch.send(value, 24);
  mySwitch.send(value, 24);
  mySwitch.send(value, 24);
  mySwitch.send(value, 24);
} 

void setupComm()
{
  Serial.println("Trying to connect");
  Serial.print("\n");
  if (!Ethernet.begin(mac)){
    Serial.println("Failed to DHCP");
    // no point in carrying on, so do nothing forevermore:
    while(true);
  }

  // print your local IP address:
  Serial.print("My IP address: ");
  for (byte thisByte = 0; thisByte < 4; thisByte++) {
    Serial.print(Ethernet.localIP()[thisByte], DEC);
    Serial.print(".");
  }
  Serial.println("fine");
}

// Call to send an email.
bool email(String text)
{
  bool success = false;
  Serial.println("Sending email...");
  Serial.print("\n");
  Serial.println("SMTP server...");
  Serial.print(smtpServer); 

  if (client.connect(smtpServer, 2525)){
    Serial.println("connected");
    delay(100);
    client.println("EHLO arduino");
    for(int i=0; i<999; ++i){
      if(client.read() > 0)
        break;
    }
    Serial.println("responded");
    Serial.print("\n"); 

    client.println("AUTH LOGIN");
    client.println("XXX");
    client.println("XXXXX");        

    // Put your "from" email address here
    client.println("MAIL FROM:<dumm@gmail.com>"); //Does not seem to matter what email stands here
    for(int i=0; i<999; ++i){
      if(client.read() > 0)
        break;
    } 

    // Put where you are sending it here
    client.println("RCPT TO:<giuseppe.scola@gmail.com>"); //Must be the reciever ID

    for(int i=0; i<999; ++i){
      if(client.read() > 0)
        break;
    } 

    client.println("DATA");
    for(int i=0; i<999; ++i){
      if(client.read() > 0)
        break;
    }
    //This is the email that is listed in the sender
    client.println("from: giuseppe.scola@gmail.com");
    client.println("to: giuseppe.scola@gmail.com");
    client.println("SUBJECT: ArduAlarm");
    client.println("");
    client.println(text);
    client.println(".");
    client.println("QUIT");
    for(int i=0; i<999; ++i){
      if(i > 998){
        Serial.println("error: No response");
      }
      if(client.read() > 0)
        break;
    }
    success = true;
    client.println();
    Serial.println("end");
    Serial.print("\n");
  }
  else {
    Serial.println("Failed");
    Serial.print("\n");
    client.println("QUIT");
  }
  client.stop();
  return success;
}

void getClientConnection(){
  //Serial.println("nuova richiesta");
  EthernetClient client = server.available();
  if (client) {
    String postString ="";
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        if(postString.length()<20){
          Serial.println(c);
          postString +=c;
        }

        if (c == '\n' && currentLineIsBlank) {
          client.println(F("HTTP/1.1 200 OK"));
          client.println(F("Content-Type: text/html"));
          client.println(F("Connection: close"));  // the connection will be closed after completion of the response
          client.println();
          client.println(F("<!DOCTYPE HTML>"));
          client.println(F("<html>"));
          client.println(F("<h1>AllarDuino</h1>"));
          client.print(F("<br>"));
          client.println(F("<a href=\"./?on\">Accendi CAM</a>"));
          client.println(F("<a href=\"./?off\">Spegni CAM</a>"));
          client.print(F("<br>"));
          client.println(F("<h2>Configurazione</h2>"));
          client.print(F("<br>"));
          char linkCompleto[50];
          for (int i=0; i<nSensori; i++)
          {
            strcpy (linkCompleto, "<a href=\"./?save");            
            sprintf(linkCompleto, "%s%d", linkCompleto, i);        
            strcat(linkCompleto, "\">Salva Sensore ");            
            sprintf(linkCompleto, "%s%d", linkCompleto, i);
            strcat(linkCompleto, "</a><br/>");
            client.println(linkCompleto);
          }
          client.println(F("<a href=\"./?elenco\">Sensors data</a></html>"));
          break;
        }

        if (c == '\n') {
          currentLineIsBlank = true;
        }
        else if (c != '\r') {
          currentLineIsBlank = false;
        }
      }
    }  //fine client.connected 

    //querystring management

    if(postString.indexOf("?on") > 0){
      Serial.println("CAM On");
      accendiCam(SEGNALE_ACCENZIONE_WEBCAM);
      client.println("<br/>");
      client.println("<p>Cam on</p>");
    }
    if(postString.indexOf("?off") > 0){
      accendiCam(SEGNALE_SPEGNIMENTO_WEBCAM);
      client.println("<br/>");
      client.println("<p>Cam off</p>");
    }
    if(postString.indexOf("?save") > 0){
      int indexSave = postString.indexOf("?save");
      Serial.println("indexOf");
      Serial.println(indexSave);
      Serial.println("=====");
      //searching sensor value
      String sSensore = postString.substring(indexSave+5 ,indexSave+6);
      Serial.println(sSensore);
      int iSensore = sSensore.toInt();
      long valore = salvaSensore(iSensore);
      client.println("<br/>");
      client.println("<p>Save completed</p>");
      client.println("<br/>");
      client.println("Sensor code " + sSensore);
      Serial.println("=====");
      client.print(valore);
    }

    if(postString.indexOf("?elenco") > 0){
      for (int i=0; i<nSensori; i++)
      {
        Serial.println("<p>Sensor " + String(i)+" : </p>");
        client.println("<p>Sensor " + String(i)+" : </p>");
        client.print(String(EEPROMReadlong(i*4)));
        Serial.println(EEPROMReadlong(i*4));
      }
    }
    delay(1);
    client.stop();
    Serial.println("client disonnected");
  }
}

long salvaSensore(int iSensore)
{
  int addressTosSave = iSensore*4;
  long valore = 0;
  Serial.println("salvaSensore");
  if (mySwitch.available()) {
    Serial.println("mySwitch.available");
    valore = mySwitch.getReceivedValue();
    Serial.println("value ");
    Serial.println(valore);
    EEPROMWritelong(addressTosSave,valore);
  }
  delay(1000);
  Serial.println(valore);
  return valore;
} 

void EEPROMWritelong(int address, long value)
{
  byte four = (value & 0xFF);
  byte three = ((value >> 8) & 0xFF);
  byte two = ((value >> 16) & 0xFF);
  byte one = ((value >> 24) & 0xFF);

  //Write the 4 bytes into the eeprom memory.
  EEPROM.write(address, four);
  EEPROM.write(address + 1, three);
  EEPROM.write(address + 2, two);
  EEPROM.write(address + 3, one);
}

long EEPROMReadlong(long address)
{
  //Read the 4 bytes from the eeprom memory.
  long four = EEPROM.read(address);
  long three = EEPROM.read(address + 1);
  long two = EEPROM.read(address + 2);
  long one = EEPROM.read(address + 3);

  //Return the recomposed long by using bitshift.
  return ((four << 0) & 0xFF) + ((three << 8) & 0xFFFF) + ((two << 16) & 0xFFFFFF) + ((one << 24) & 0xFFFFFFFF);
}

//Searching for sensor number
//If not return  -1
int isPresenteSensore(long valoreRicevuto)
{

  for(int x = 0; x < nSensori; x ++){
    long valoreRegistrato = EEPROMReadlong(x*4);
    if (valoreRegistrato == valoreRicevuto)
    {
      Serial.println("ritorno");
      return i;
    }
  }

}

Explanation:

line 19: I define how many sensors I want to manage , in this case 5
line 51: call to a new function ( isPresenteSensore ) . This function ( line 322 ) takes as input the code received from the wireless sensor and if this occurs in the EEPROM . If I find sensor code this means that alarm is detected so I send email and I turn on the camera .

Some others amendments were made right on the memory management : I deleted many Serial.print and I used the function F ( ) , see for example from lines 193 to 204 .

I consider myself to the final point about the code : I am quite satisfied , but I hope to have your ideas and suggestions for improvements and optimization.

Next week I hope to finish Eagle schema! Have a good weekend!

Giuseppe

A simple burglar alarm: managing arduino memory

It has been so long since I connect … but I swear , I was trying to put together code and study Eagle.

I must thank the Arduino forum for all the valuable aids !

The hardest part was the memory management : I’m used to program in Net and having access to a few Kb made ​​me crazy!
I decided to read better the documentation to understand how to use memory a little better.

ARDUINO MEMORY

The Arduino UNO micro controller  is ATmega328P and it as  the following types of memory :

  • Flash (program space), is where the Arduino sketch  ( program ) is stored .
  • SRAM (static random access memory)  is where the sketch creates and manages the variables when it is running .
  • EEPROM  is a type of non-volatile memory , a memory that can retain information even when not powered .

For each micro controller you have available a different amount of memory :

ATMega168 ATMega328P ATmega1280 ATmega2560
Flash
(1 Kbyte used
for bootloader)
16 KBytes 32 KBytes 128 KBytes 256 KBytes
SRAM 1024 bytes 2048 bytes 8 KBytes 8 KBytes
EEPROM 512 bytes 1024 bytes 4 KBytes 4 KBytes

 

For Arduino UNO :

Flash 32k bytes
SRAM 2k bytes
EEPROM 1k byte

Strings  types in particular uses a large amount of memory, and in my sketch I  use them a lot of time to write on the web client ( client.println ) and on the console ( Serial.print ) .

For example, the command: Serial.println ( ” Trying to connect” ) ; occupies 18 bytes of SRAM memory ( 1 char = 1 byte plus the newline character ).
I remember that SRAM has available 2048 bytes!

Since version 1.0 Arduino IDE allows use of  F ( ) function which allows to storage strings in FLASH memory and not in the SRAM.
So I  decided to storage in FLASH memory  all the strings used in client.println , solving SRAM memory  problems ( int type, float type, and strings type not grouped with F ( )  will be initialized and managed in the SRAM memory) .

If you have time read this  article .

Here comes weekend and finally ( I hope) I will have time to publish the code changes and Eagle project files.

Bye!

A simple arduino burglar alarm: save sensor codes via web interface

As mentioned last time I want to make sure that the codes sensors can be stored in the EEPROM , all from a web interface !
Here’s the code that does this thing :

#include <String.h>
#include <Time.h>
#include <SPI.h>
#include <Ethernet.h>
#include <EEPROM.h>
#include <RCSwitch.h>

byte mac[] = {
  0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 };
int SERIAL_BAUD        = 9600;
EthernetServer server(8081);
RCSwitch mySwitch = RCSwitch();
int RECEIVE_PIN       = 0;
int nSensori = 5;

void setup() {
  Serial.begin(SERIAL_BAUD);
  setupComm();
  mySwitch.enableReceive(RECEIVE_PIN);
}

void loop() {
  getClientConnection();
}

void getClientConnection(){

  EthernetClient client = server.available();
  if (client) {
    String postString ="";
    Serial.println("nuova richiesta");
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        if(postString.length()<15){
          postString +=c;
        }

        if (c == 'n' && currentLineIsBlank) {
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close");  // the connection will be closed after completion of the response
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<html>");
          client.println("<h1>Configurazione</h1>");
          client.print("<br>");

          for (int i=0; i<nSensori; i++)
          {
            String linkCompleto = "";
            linkCompleto = "<a href="./?save"+ String(i);
            linkCompleto +="">Save Sensor " + String(i);
            linkCompleto += "</a><br/>";
            client.println(linkCompleto);
            Serial.println(linkCompleto);
            //client.println("<a href="./?save1">Salva Sensore 1</a>");
          }

          client.println("<br/>");
          client.println("<a href="./?elenco">Sensors list</a>");
          client.println("</html>");
          break;
          //}
        }

        if (c == 'n') {
          // you're starting a new line
          currentLineIsBlank = true;
        }
        else if (c != 'r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }

      }
    }  //fine client.connected 

    Serial.println("-------------");
    Serial.println(postString);
    Serial.println("-------------");

    if(postString.indexOf("?save") > 0){ 

      int indexSave = postString.indexOf("?save");
      Serial.println("indexOf");
      Serial.println(indexSave);
      //cerco valore del sensore
      String sSensore = postString.substring(indexSave+5 ,indexSave+6);
      Serial.println("Sensore");
      Serial.println(sSensore);
      int iSensore = sSensore.toInt();
      long valore = salvaSensore(iSensore);
      client.println("<br/>");
      client.println("<p>Salvataggio sensore effettuato</p>");
      client.println("<br/>");
      client.println("Codice sensore " + sSensore);
      client.print(valore);
    }   

    if(postString.indexOf("?elenco") > 0){
      for (int i=0; i<nSensori; i++)
      {
        client.println("<p>Sensor" + String(i)+" : </p>");
        client.print(String(EEPROMReadlong(i*4)));
        Serial.println(EEPROMReadlong(i*4));
      }
    }

    delay(1);
    // close the connection:
    client.stop();
    Serial.println("client disonnected");
  }
}

long salvaSensore(int iSensore)
{
  int addressTosSave = iSensore*4;
  long valore = 0;
  Serial.println("salvaSensore");
  if (mySwitch.available()) {
    Serial.println("mySwitch.available");
    valore = mySwitch.getReceivedValue();
    Serial.println("valore ");
    Serial.print(valore);
    EEPROMWritelong(addressTosSave,valore);
  }
  delay(1000);
  return valore;
} 

void EEPROMWritelong(int address, long value)
{
  //Decomposition from a long to 4 bytes by using bitshift.
  //One = Most significant -> Four = Least significant byte
  byte four = (value & 0xFF);
  byte three = ((value >> 8) & 0xFF);
  byte two = ((value >> 16) & 0xFF);
  byte one = ((value >> 24) & 0xFF);

  //Write the 4 bytes into the eeprom memory.
  EEPROM.write(address, four);
  EEPROM.write(address + 1, three);
  EEPROM.write(address + 2, two);
  EEPROM.write(address + 3, one);
}

void setupComm()
{
  Serial.println("Trying to connect");
  Serial.print("n");
  if (!Ethernet.begin(mac)){
    Serial.println("Failed to DHCP");
    // no point in carrying on, so do nothing forevermore:
    while(true);
  }

  // print your local IP address:
  Serial.print("My IP address: ");
  for (byte thisByte = 0; thisByte < 4; thisByte++) {
    // print the value of each byte of the IP address:
    Serial.print(Ethernet.localIP()[thisByte], DEC);
    Serial.print(".");
  }
  Serial.println("fine");
}

long EEPROMReadlong(long address)
{
  //Read the 4 bytes from the eeprom memory.
  long four = EEPROM.read(address);
  long three = EEPROM.read(address + 1);
  long two = EEPROM.read(address + 2);
  long one = EEPROM.read(address + 3);

  //Return the recomposed long by using bitshift.
  return ((four << 0) & 0xFF) + ((three << 8) & 0xFFFF) + ((two << 16) & 0xFFFFFF) + ((one << 24) & 0xFFFFFFFF);
}

The resulting web interface is as follow : (avoid comments 🙂 )

You must write in the browser the IP address that is printed in the Arduino console and also specifying port 8081 .
In my case , for example : 192.168.1.136:8081
There are 5 links that allow you to save the data sensors : pressing the button ” Save sensor 0 ” and pressing the sensor ( opening the door for example ) is stored the data in the EEPROM .

Schermata 2014-12-17 alle 22.31.29

Once data is saved , clicking ” View data sensors .”, you can view a summary list of what is saved in the EEPROM.

Schermata 2014-12-17 alle 22.31.01

Thie evening if I’ll have time I’ll make a video where you can see better storing operations.
The code is relatively simple.
I now try to explain how this links are done and their management.

line 14: Declaring variable nSensori: the number of sensors that I want to manage
line 53-57: Links are created dynamically according to the html syntax.
Links have this format: save0 , SAVE1 , SAVE2 . .. , depending on the link you want to press .
line 62: link to view stored code sensors.
riga 86-99: I save codes sensor
In detail:
line 84: I received “save” in the querystring, I know I need to save a sensor code…which one?
line 90: now i know the sensor code number!
line 94: I call salvaSensore: function: this function use mySwitch.getReceivedValue() function to save code sensor in the EEPROM.
line 95-99: I write in the HTML page the code sensor just saved
line 102-109: I write in HTML page the saved sensor list.it’s a simple for cycle that use  EEPROMReadlong to read each sensor code.
At this point , in the next article , we will implement what we saw today in our anti-theft !

So funny!!!!

See you soon!

A simple burglar alarm: save sensor code in the EEPROM

Here I am again , with flue … good excuse for not going to the gym and have fun with Arduino.
As I said in the previous article I’d like to make code improvements : in particular I don’t want that sensor code are written in the code but I want to give to the user the possibility to store sensore value from a web interface.
Pressing a web interface button, the wireless receiver module will listen the sensor code and store somewhere.
The first problem is : where and how to store them ? I thought at EEPROM memory in Arduino.
The values ​​that I want to use are long ( as you can see from the sketch lines 26,27,28,29 the previous article ) so I cannot  just  use a single cell in EEPROM (which can contain only one byte from 0 to 255 ) .
The long data type instead is four times a byte : 4 bytes . To summarize :

boolean – It can assume only two values ​​: true or false .

char – It contains a single character . Arduino register it as a number ( but we see the text ) . When the characters are used to record a number, may contain a value between -128 and 127 .

byte – It can contain a number between 0 and 255. As a character uses only one byte of memory .

int – It contains a number between -32’768 and 32’767 . It’s the variable type most used and uses two bytes of memory . unsigned int – It has the same function as int , it just can not contain negative numbers , but numbers between 0 and 65,535 . long – It’s twice the size of an int and contains the numbers between-2’147’483’648 and 2’147’483’647. unsigned long – Unsigned long version from 0 to 4’294’967’295 . float – It can store numbers with a comma . Occupies 4 bytes of RAM . double – A double-precision floating point with maximum 1’7976931348623157×10 ^ 308 .

So what I want to do is to split my code sensor (long) in 4 bytes and then I want to store each of these four bytes in a cell in the EEPROM . In this article I found this helpful code. I just checked if the code is ok, in my case :


/*
 I write and read a long i the EEPROM
 */
#include <EEPROM.h>;
// the setup routine runs once when you press reset:
void setup() {
 // initialize serial communication at 9600 bits per second:
 Serial.begin(9600);
}
// the loop routine runs over and over again forever:
void loop() {
 delay(5000);
 long address=0;
 long sensore1= 3557625;
 long sensore2= 10521177;
 EEPROMWritelong(address, sensore1);
 Serial.println("writing 1 code");
 address+=4;
 EEPROMWritelong(address, sensore2);
 Serial.println("writing 2 code");
 /*Serial.println(EEPROMReadlong(0));
 Serial.println(EEPROMReadlong(4));*/
}
void EEPROMWritelong(int address, long value)
{
 //Decomposition from a long to 4 bytes by using bitshift.
 //One = Most significant -> Four = Least significant byte
 byte four = (value & 0xFF);
 byte three = ((value >> 8) & 0xFF);
 byte two = ((value >> 16) & 0xFF);
 byte one = ((value >> 24) & 0xFF);
 //Write the 4 bytes into the eeprom memory.
 EEPROM.write(address, four);
 EEPROM.write(address + 1, three);
 EEPROM.write(address + 2, two);
 EEPROM.write(address + 3, one);
}
long EEPROMReadlong(long address)
{
 //Read the 4 bytes from the eeprom memory.
 long four = EEPROM.read(address);
 long three = EEPROM.read(address + 1);
 long two = EEPROM.read(address + 2);
 long one = EEPROM.read(address + 3);
 //Return the recomposed long by using bitshift.
 return ((four << 0) & 0xFF) + ((three << 8) & 0xFFFF) + ((two << 16) & 0xFFFFFF) + ((one << 24) & 0xFFFFFFFF);
}

line 5: include EEPROM library line 19-22: with the EEPROMWritelong  function I write the first sensor code in the address 0 then the second sensor in the address 4. Rightly 4 bytes after the first byte . At this point I turned off Arduino and then reconnect it. Let’s check if i read the value I stored before!!! I changed the loop library to read EEPROM.

void loop() {
/*delay(5000);
long address=0;
long sensore1= 3557625;
long sensore2= 10521177;
EEPROMWritelong(address, sensore1);
Serial.println("writing 1 code");
address+=4;
EEPROMWritelong(address, sensore2);
Serial.println("writing 2 code");*/

  Serial.println("Reading Sensor 1");
Serial.println(EEPROMReadlong(0));
Serial.println("Reaging Sensor 2");
Serial.println(EEPROMReadlong(4));
delay(10000000);
}

I read this values: Schermata 2014-12-03 alle 22.25.17 It works!! Ok , at this point I know how to store the values ​​in EEPROM , in the next post I will try to build the web interface to storage sensor codes. I hope this post can be helpful! Have a good day!

A simple burglar: code explanation

As told last week I want to comment the code.

For convenience I copy it again:

/*
 Ricezione dai sensori porte
 Trasmissione verso telecamera
 rivelazione rumore
 http://code.google.com/p/rc-switch/
 Need help? http://forum.ardumote.com
 */

#include <String.h>
#include <RCSwitch.h>
#include <Time.h>
#include <SPI.h>
#include <Ethernet.h>

/* Informazioni Ethernet*/

byte mac[] = {
  0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 };
int SERIAL_BAUD        = 9600;
int TRASMIT_PIN       = 9;
int RECEIVE_PIN       = 0;
int NOISE_DIGITAL_PIN =    5;
//Sensori
long PORTA_INGRESSO_SENSORE  = 3557625;
long PORTA_CUCINA_SENSORE = 10521177;
long SEGNALE_ACCENZIONE_WEBCAM = 1394001;
long SEGNALE_SPEGNIMENTO_WEBCAM= 1394004;

EthernetClient client;
EthernetServer server(8081);
char smtpServer[] = "smtpcorp.com";
RCSwitch mySwitch = RCSwitch();

void setup() {
  Serial.begin(SERIAL_BAUD);
  pinMode(SERIAL_BAUD, INPUT);
  mySwitch.enableReceive(RECEIVE_PIN);
  mySwitch.enableTransmit(TRASMIT_PIN);
  setupComm();
}

void loop() {

  getClientConnection();
  if (detectNoise()){
    Serial.print("Rumore");
    email("Waring, noise in the house!");
    accendiCam(SEGNALE_ACCENZIONE_WEBCAM) ;
  }

  if (mySwitch.available()) {

    int value = mySwitch.getReceivedValue();

    Serial.print(value);
    if (value == 0) {
      Serial.print("Unknown encoding");
      Serial.print("n");
    }
    else {
      long receivedValue = mySwitch.getReceivedValue();
      if (receivedValue == PORTA_INGRESSO_SENSORE) {
        Serial.print("Warning! Door open!");
        Serial.print("n");
        email("Warning, Door open!");
        accendiCam(SEGNALE_ACCENZIONE_WEBCAM) ;
        delay(1000);
      }
      else if(receivedValue == PORTA_CUCINA_SENSORE) {
        Serial.print("Warning! Porta cucina aperta!");
        Serial.print("n");
        email("Attenzione, porta cucina aperta!");
        accendiCam(SEGNALE_ACCENZIONE_WEBCAM) ;
        delay(1000);
      }  

      Serial.print("Received ");
      Serial.print( receivedValue);
      Serial.print(" / ");
      Serial.print( mySwitch.getReceivedBitlength() );
      Serial.print("bit ");
      Serial.print("Protocol: ");
      Serial.println( mySwitch.getReceivedProtocol() );
    }

    mySwitch.resetAvailable();
  }

}

bool detectNoise ()
{
  bool rit = false;
  if (digitalRead(NOISE_DIGITAL_PIN) == HIGH)
  {
    rit = true;
  }
  return rit;
} 

void accendiCam(long value)
{
  mySwitch.send(value, 24);
  mySwitch.send(value, 24);
  mySwitch.send(value, 24);
  mySwitch.send(value, 24);
  mySwitch.send(value, 24);
} 

void setupComm()
{
  Serial.println("Trying to connect");
  Serial.print("n");
  if (!Ethernet.begin(mac)){
    Serial.println("Failed to DHCP");
    while(true);
  }

  Serial.print("My IP address: ");
  for (byte thisByte = 0; thisByte < 4; thisByte++) {
    Serial.print(Ethernet.localIP()[thisByte], DEC);
    Serial.print(".");
  }
  Serial.println("fine");
}

// Call to send an email.
bool email(char* text)
{
  bool success = false;
  Serial.println("Sending email...");
  Serial.print("n");
  Serial.println("SMTP server...");
  Serial.print(smtpServer); 

  if (client.connect(smtpServer, 2525)){
    Serial.println("connected");
    delay(100);
    client.println("EHLO arduino");
    for(int i=0; i<999; ++i){
      if(client.read() > 0)
        break;
    }
    Serial.println("responded");
    Serial.print("n");
    client.println("AUTH LOGIN");
    client.println("xxxxxxx");           //vedi precedente post per la spiegazione
    client.println("yyyyyy");   //vedi precedenti post per la spiegazione     

    client.println("MAIL FROM:<dumm@gmail.com>");
    for(int i=0; i<999; ++i){
      if(client.read() > 0)
        break;
    } 

    client.println("RCPT TO:<giuseppe.scola@gmail.com>"); 

    for(int i=0; i<999; ++i){
      if(client.read() > 0)
        break;
    } 

    client.println("DATA");
    for(int i=0; i<999; ++i){
      if(client.read() > 0)
        break;
    }

    client.println("from: giuseppe.scola@gmail.com");
    client.println("to: giuseppe.scola@gmail.com");
    client.println("SUBJECT: ArduAlarm");
    client.println("");
    client.println(text);
    client.println(".");
    client.println("QUIT");
    for(int i=0; i<999; ++i){
      if(i > 998){
        Serial.println("error: No response");
      }
      if(client.read() > 0)
        break;
    }
    success = true;
    client.println();
    Serial.println("end");
    Serial.print("n");
  }
  else {
    Serial.println("Failed");
    Serial.print("n");
    client.println("QUIT");
  }
  client.stop();
  return success;
}

void getClientConnection(){

  EthernetClient client = server.available();
  if (client) {
    String postString ="";
    Serial.println("nuova richiesta");
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        //postString.concat(c);
        if(postString.length()<10){
          postString +=c;
        }
        // Serial.write(c);
        if (c == 'n' && currentLineIsBlank) {
          //if(readString.indexOf("id=1") > 0){
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close");  // the connection will be closed after completion of the response
          //client.println("Refresh: 5");  // refresh the page automatically every 5 sec
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<html>");
          //client.println("<h1>Settaggi</h1><br>");
          client.println("<h1>AllarDuino</h1>");
          client.print("<br>");
          client.println("<a href="./?on">Accendi CAM</a>");
          client.println("<a href="./?off">Spegni CAM</a>");
          client.println("</html>");
          break;
          //}
        }

        if (c == 'n') {
          // you're starting a new line
          currentLineIsBlank = true;
        }
        else if (c != 'r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }

      }
    }  //fine client.connected 

    Serial.println("-------------");
    Serial.println(postString);
    Serial.println("-------------");

    if(postString.indexOf("?on") > 0){
      Serial.println("accendi CAM");
      accendiCam(SEGNALE_ACCENZIONE_WEBCAM);
      client.println("<br/>");
      client.println("<p>Cam accesa</p>");

    }
    if(postString.indexOf("?off") > 0){
      accendiCam(SEGNALE_SPEGNIMENTO_WEBCAM);
      client.println("<br/>");
      client.println("<p>Cam spenta</p>");
    } 

    delay(1);
    // close the connection:
    client.stop();
    Serial.println("client disonnected");
  }
}

The “new” code is to power on/off the webcam from a client/browser.

This new feature allows you to manage calls coming from browser to Arduino, acting as a server.
In our case Arduino will listen incoming request at 8081 port as specified at line 32  EthernetServer server(8081);

At line 116 I start the server  with setupComm function (I set MAC code in the begin function).
In the loop funcion I call getClientConnection:

  • line 201: Checking if a client is sending a new request to the Arduino server.
  • line 202: if a request is incoming…
  • line 207: if client is reacheble….
  • line 298->231: I read the data sent from the client until I reach the end line (\n) and line empty: now I know I received all the datas from the client and the server (Arduino) can send the answer. Arduino send HTTP/1.1 200 OK status, all is ok! and an html page like the image :
    paginaAllarmDuino(I know..it’s an ugly page…)
    Pressing Accendi Cam (Power on Cam) I call server with the ?on paramenter in the query string while pressing Spegni Cam (Power off Cam) I call the server with ?off paramenter.
  • line 249 and line 256: I check which of the two parameters was sent to server and I act accordingly: I turn on or off the cam.
  • I finally close the connection

Well…I hope I was clear, let me know please…
I’d like to have feedbacks and comments!

The next step is to write code more customize.
I want to save the sensor code in the EEPROM and read when I need.

I have to study Arduino memory!

Have a good day!