Arduino Entry system using 12VAC doorbell trafo

All about Arduino, Jeenode and other Clones (hardware & Software)

Moderator: Mdamen

luria
Starting Member
Starting Member
Posts: 36
Joined: Tue Mar 16, 2010 11:51 am

Re: Arduino Entry system using 12VAC doorbell trafo

Post by luria »

Weekend update:
All electronics are done, everything hooked up with utp network-cable and working nicely (pics to follow).
Started the big coding job. Got buttons, LCD and RFID working. Next is to log data to the domotiga server (have to set up some arbitrary devices there) and storing some important data (RFID tags, resistorladder offset) in eeprom.

Code: Select all

#include <LCD3Wire.h> 
#include <Tone.h>
#include <NewSoftSerial.h>
#include <EEPROM.h>

#define OCTAVE_OFFSET 0
#define LCD_LINES 2  // VFD
#define LCD2_LINES 2  // LCD
#define DOUT_PIN  9  // Dout pin vfd+lcd
#define CLK_PIN   8  // Clock pin vfd+lcd
#define STR_PIN   7  // Strobe pin vfd
#define STR2_PIN   6  // Strobe pin lcd
#define MAX_NO_CARDS 102 //Amount of RFID tags eeprom can hold
#define BELL A0 // ding-dong pin
#define BIGBELL A1 //Add a ding pin

//RFID global vars
int  c = 0; 
char code[11]; //RFID tag is 10 chars and then terminate
int offset = 0;
byte tag[5];            // tag serial numbers are 5 bytes long

// Resistor ladder inputs
byte channelAInput = 4;  //Resladder on pin 4
byte channelBInput = 5; //Resladder on pin 5
int correctIn = 15;  //Correct the indoor resladder readings for temp etc.
int correctOut = 0; //Correct the outdoor resladder readings for temp etc.

// Got milk?
boolean doorOuter = false;
boolean doorInner = false;
boolean doorBasement = false;
boolean buttonKids = false;
boolean buttonAdult = false;
boolean buttonMenu1= false;
boolean buttonMenu2 = false;

// Lets create the RFID class
NewSoftSerial mySerial(2, 53);

// ...and create some classes for the LCDs
LCD3Wire lcd1 = LCD3Wire(LCD_LINES, DOUT_PIN, STR_PIN, CLK_PIN); 
LCD3Wire lcd2 = LCD3Wire(LCD2_LINES, DOUT_PIN, STR2_PIN, CLK_PIN);

//Play some music or at least be prepared
Tone tone1;
int notes[] = { 0,
NOTE_C4, NOTE_CS4, NOTE_D4, NOTE_DS4, NOTE_E4, NOTE_F4, NOTE_FS4, NOTE_G4, NOTE_GS4, NOTE_A4, NOTE_AS4, NOTE_B4,
NOTE_C5, NOTE_CS5, NOTE_D5, NOTE_DS5, NOTE_E5, NOTE_F5, NOTE_FS5, NOTE_G5, NOTE_GS5, NOTE_A5, NOTE_AS5, NOTE_B5,
NOTE_C6, NOTE_CS6, NOTE_D6, NOTE_DS6, NOTE_E6, NOTE_F6, NOTE_FS6, NOTE_G6, NOTE_GS6, NOTE_A6, NOTE_AS6, NOTE_B6,
NOTE_C7, NOTE_CS7, NOTE_D7, NOTE_DS7, NOTE_E7, NOTE_F7, NOTE_FS7, NOTE_G7, NOTE_GS7, NOTE_A7, NOTE_AS7, NOTE_B7
};
char *song = "smb:d=4,o=5,b=100:16e6,16e6,32p,8e6,16c6,8e6,8g6,8p,8g,8p,8c6,16p,8g,16p,8e,16p,8a,8b,16a#,8a,16g.,16e6,16g6,8a6,16f6,8g6,8e6,16c6,16d6,8b,16p,8c6,16p,8g,16p,8e,16p,8a,8b,16a#,8a,16g.,16e6,16g6,8a6,16f6,8g6,8e6,16c6,16d6,8b,8p,16g6,16f#6,16f6,16d#6,16p,16e6,16p,16g#,16a,16c6,16p,16a,16c6,16d6,8p,16g6,16f#6,16f6,16d#6,16p,16e6,16p,16c7,16p,16c7,16c7,p,16g6,16f#6,16f6,16d#6,16p,16e6,16p,16g#,16a,16c6,16p,16a,16c6,16d6,8p,16d#6,8p,16d6,8p,16c6";


void setup()  
{
  //Init LCDs
  lcd1.init();
  lcd2.init();
  lcd1.clear();
  lcd2.clear();
  lcd1.printIn("Starting...");
  lcd2.printIn("Starting...");
  
  // set the data rate for serial debugging port and the NewSoftSerial port
  Serial.begin(9600);
  mySerial.begin(9600);
  
    //Set up music & bell pins
  tone1.begin(5);//Playback on Pin 5
  pinMode(BELL, OUTPUT);
  pinMode(BIGBELL, OUTPUT);
}

void loop()
{
 //Read resistor ladder inputs
 byte frontStatus = checkSensor(channelAInput, correctOut);
 byte insideStatus = checkSensor(channelBInput, correctIn); 

//Lets check front door
 if ((frontStatus & (1<<0)) && (doorOuter == false) ) {
   doorOuter=true;
   lcd1.clear();
   lcd1.printIn("Door closed"); 
 } else if ( (!(frontStatus & (1<<0))) && (doorOuter == true)) {
   doorOuter=false;
   lcd1.clear();
   lcd1.printIn("Door open");
 };
 
//Lets check if someone is at the door
 if ( frontStatus & (1<<1)) {
   buttonAdult=true;
   lcd2.printIn("Adults bell");
   pinMode(A0, OUTPUT);
   digitalWrite(A0, HIGH);
   digitalWrite(A1, HIGH);
   delay (20);
   digitalWrite(A0, LOW);
   digitalWrite(A1, LOW);
   delay (4500);
  } else {
   buttonAdult=false;
   lcd2.clear();
  };
 
 //Any kids at the door?
 if ( frontStatus & (1<<3)) {
   buttonKids=true;
   lcd2.printIn("Kids bell");
   play_rtttl(song);  //  Play Mariotune
  } else {
    lcd2.clear();
    buttonKids=false;
  };
 
 // For debugging on serial
 Serial.println("");
 
 //Check for rfid tags
 rfid();
 
 //No stress, lets take a break
 delay (300);
}
 
void rfid()
{
  
  if (mySerial.available() > 0)
  {
   c = mySerial.read();
    if ( c == 2 || c == 4 )
    {
      code[offset] = 0;
      if ( c == 4 )
      {
        lcd1.printIn("LCD 1 - Tag code is ");
        lcd1.printIn(code);
    //    lcd2.cursorTo(1,0);
        lcd2.printIn("LCD -2 Tag code is ");
      //  lcd2.cursorTo(2,0);
        lcd2.printIn(code);
        delay (1000);
        lcd1.clear();
        lcd2.clear();
      }
      offset = 0;
    }
    else
    {
      code[offset++] = c;
    }
  }
}

boolean checkSensor( byte sensorInput, int correction )
{

  byte state;
  int sensorReading = analogRead(sensorInput) + correction ;
  if( sensorReading > 1010   ) {
    state = B01111 ; 
  } else if ( sensorReading > 509 )  {
    state = B01110 ;
    } else if ( sensorReading >= 320 ) {
    state = B01101; 
  } else if ( sensorReading >= 246 ) {
    state = B01100;
  } else if ( sensorReading >= 212 ) {
    state =  B01011;
  } else if ( sensorReading >= 176 ) {
    state =  B01010;
  } else if ( sensorReading >= 148 ) {
    state =  B01001;
  } else if ( sensorReading >= 131 ) {
    state = B01000;
  } else if ( sensorReading >= 115 ) {
    state =  B00111;
  } else if ( sensorReading >= 105  ) {
    state = B00110;
   } else if ( sensorReading >= 95  ) {
    state =  B00101;
  } else if ( sensorReading >= 87   ) {
    state = B00100;
   } else if ( sensorReading >= 83   ) {
    state = B00011;  
  } else if ( sensorReading >= 78   ) {
    state = B00010;
   } else if ( sensorReading >= 73   ) {
    state = B00001;
   } else {
    state = B00000; 
     }
  Serial.print(sensorInput, DEC);
  Serial.print(": ");
  Serial.print(sensorReading, DEC);
  Serial.print(" (");
  Serial.print(state, BIN);
  Serial.print(") ");
  // Pass the current state back to the calling function
  return state;
}

#define isdigit(n) (n >= '0' && n <= '9')
void play_rtttl(char *p)
{
  // Absolutely no error checking in here

  byte default_dur = 4;
  byte default_oct = 6;
  int bpm = 63;
  int num;
  long wholenote;
  long duration;
  byte note;
  byte scale;

  // format: d=N,o=N,b=NNN:
  // find the start (skip name, etc)

  while(*p != ':') p++;    // ignore name
  p++;                     // skip ':'
  // get default duration
  if(*p == 'd')
  {
    p++; p++;              // skip "d="
    num = 0;
    while(isdigit(*p))
    {
      num = (num * 10) + (*p++ - '0');
    }
    if(num > 0) default_dur = num;
    p++;                   // skip comma
  }
   // get default octave
  if(*p == 'o')
  {
    p++; p++;              // skip "o="
    num = *p++ - '0';
    if(num >= 3 && num <=7) default_oct = num;
    p++;                   // skip comma
  }

   // get BPM
  if(*p == 'b')
  {
    p++; p++;              // skip "b="
    num = 0;
    while(isdigit(*p))
    {
      num = (num * 10) + (*p++ - '0');
    }
    bpm = num;
    p++;                   // skip colon
  }

   // BPM usually expresses the number of quarter notes per minute
  wholenote = (60 * 1000L / bpm) * 4;  // this is the time for whole note (in milliseconds)

   // now begin note loop
  while(*p)
  {
    // first, get note duration, if available
    num = 0;
    while(isdigit(*p))
    {
      num = (num * 10) + (*p++ - '0');
    }
    
    if(num) duration = wholenote / num;
    else duration = wholenote / default_dur;  // we will need to check if we are a dotted note after

    // now get the note
    note = 0;

    switch(*p)
    {
      case 'c':
        note = 1;
        break;
      case 'd':
        note = 3;
        break;
      case 'e':
        note = 5;
        break;
      case 'f':
        note = 6;
        break;
      case 'g':
        note = 8;
        break;
      case 'a':
        note = 10;
        break;
      case 'b':
        note = 12;
        break;
      case 'p':
      default:
        note = 0;
    }
    p++;

    // now, get optional '#' sharp
    if(*p == '#')
    {
      note++;
      p++;
    }

    // now, get optional '.' dotted note
    if(*p == '.')
    {
      duration += duration/2;
      p++;
    }
  
    // now, get scale
    if(isdigit(*p))
    {
      scale = *p - '0';
      p++;
    }
    else
    {
      scale = default_oct;
    }

    scale += OCTAVE_OFFSET;

    if(*p == ',')
      p++;       // skip comma for next note (or we may be at the end)

    // now play the note

    if(note)
    {
      tone1.play(notes[(scale - 4) * 12 + note]);
      delay(duration);
      tone1.stop();
    }
    else
    {
      delay(duration);
    }
  }
}
luria
Starting Member
Starting Member
Posts: 36
Joined: Tue Mar 16, 2010 11:51 am

Re: Arduino Entry system using 12VAC doorbell trafo

Post by luria »

It is ready for mounting. Top of the pic shows the arduino and ethernet shield. On top is the homemade shield with the doorbell IC and connectors.
To the top left is the indoor lcd, speaker and connections for buttons/reedswitches. I will try to find a enclosure for this tomorrow.
Bottom left shows the outdoor unit. This is sealed in an aluminium housing.

To the right is the powermodule, rfid reader and anteanna. Antenna cables are stylishly wrapped in tinfoile ( I did'nt have any coax cable). The blue and white cables are for connection to the doorbell trafo cables. I can run all of this by connecting a 9v battery to them.
ready.jpg
ready.jpg (190.42 KiB) Viewed 4586 times

The code is more or less done. I have added time, date and ntp time updates from the internet. All left is to put the status of doors, doorbells, rfid-entries and timestamps to the server, this will be done in xml-rpc, i think.
casing.jpg
casing.jpg (143.98 KiB) Viewed 4586 times
luria
Starting Member
Starting Member
Posts: 36
Joined: Tue Mar 16, 2010 11:51 am

Re: Arduino Entry system using 12VAC doorbell trafo

Post by luria »

How easy it is!
I was trying a rather complex tcp connection to the server, parsing and sending/receiving chunks of data. This would have delayed the execution by 600ms in order to establish connection, sending/receiving data and closing connection.

But why use tcp?

I already had included the UdpBitwise library in order to read the time from a ntp timeserver. Whipping up a short chunk of code, I had the Arduino sending a udp packet every second, quite effortlessly. All I need is two bytes for each resistorladder. Oh... It's so neat. A perl script on the server listens for packets and (in the future changes values in the sql-base accordingly.

This is the unfinished, but working code

Code: Select all

void sendPackets() {
  int i=0;
  byte targetIp[] = { 192, 168, 0, 32};
  int targetPort = 313131;
  UdpBytewise.beginPacket(targetIp,targetPort);
  UdpBytewise.print("Front");  //not needed, just for debug
  UdpBytewise.print(frontStatus, BIN);
  UdpBytewise.print("Inside"); //not needed, just for debug
  UdpBytewise.print(insideStatus, BIN);
  UdpBytewise.print(i++);
  UdpBytewise.endPacket();
 
 }

Code: Select all

#!/usr/bin/perl -w
# UDP listener
use strict;
use IO::Socket;
my($msglen,$sock, $newmsg, $MAXLEN, $PORTNO);
my($lasttimestamp,$timestamp,$errcount,$timeouts);


$MAXLEN = 1024;
$PORTNO = 313131;
$sock = IO::Socket::INET->new(LocalPort => $PORTNO, Proto => 'udp',
        LocalAddr => '192.168.0.32',
        Broadcast => 1)
    or die "socket: $@";
print "Awaiting UDP messages on port $PORTNO\n";
$lasttimestamp = 0;
while ($sock->recv($newmsg, $MAXLEN)) {
    $msglen = length($newmsg);
    print "Lenght $msglen $newmsg\n";
    }

die "recv: $!";

Next is to get the outside temp from the domotiga server to the arduino and display this alongside time and date on the two LCD's. Reading udp-packets is a breeze with this library, and all i need is a simple float value. thank you, Bjørn @ stanford Uni !
luria
Starting Member
Starting Member
Posts: 36
Joined: Tue Mar 16, 2010 11:51 am

Re: Arduino Entry system using 12VAC doorbell trafo

Post by luria »

The semi-finished installation: The setup has been working since december. The outside is done, all i have left is to sand & paint the inside wooden box when I put up the flush woodwork around the door.

Youtube video : http://www.youtube.com/watch?v=e7Udrjz-Y-g
Outside
Outside
IMG_2973.jpg (107.86 KiB) Viewed 4550 times
Inside: &quot;X&quot; shows that front door is closed, &quot;O&quot; that it is open.
Inside: "X" shows that front door is closed, "O" that it is open.
IMG_2971.jpg (85.04 KiB) Viewed 4550 times
A short list of the functions:
  • Doorbells: Mario theme for the kids, regular for us and tenants
    Displays: Currently displays outside temperature (and outside falling/rising) read from Domotiga datbase, date time from ntp-server, day of week.
    Outside display also shows which button goes to whom: A perl script on server sends this menu to the outside display. Both displays can be used form the server
    Logs: All buttonpresses and door opening/closing is sent as an udp-packet to server.
    RFID: Reads rfid tags, here I need to get the antenna monted against the inside of the panels, range now is too short. Also stores, deletes and reads rfid-tags to/from the eeprom memory through udp-packets sent/received by the server.
Display inside
Display inside
IMG_2972.jpg (89.77 KiB) Viewed 4550 times
Outside display (obscured by direct sunlight)
Outside display (obscured by direct sunlight)
IMG_2976.jpg (102.84 KiB) Viewed 4550 times
Arduino code

Code: Select all

#include <LCD3Wire.h> 
#include <Tone.h>
#include <NewSoftSerial.h>
#include <EEPROM.h>
#include <SPI.h>        
#include <Ethernet.h>
#include <UdpBytewise.h>
#include <Time.h> 

#define OCTAVE_OFFSET 0
#define LCD_LINES 2  // VFD
//#define LCD2_LINES 2  // LCD
#define DOUT_PIN  9  // Dout pin vfd+lcd
#define CLK_PIN   8  // Clock pin vfd+lcd
#define STR_PIN   7  // Strobe pin vfd
//#define STR2_PIN   6  // Strobe pin2 - now serial lcd
#define MAX_NO_CARDS 102 //Amount of RFID tags eeprom can hold
#define START_BYTE 0x02   //decimal 10 or LINE-FEED
#define STOP_BYTE 0x04     //decimal 13 or CARRIAGE-RETURN
#define CODE_LEN 10
#define BELL A0 // ding-dong pin
#define BIGBELL A1 //Add a ding pin
#define dt_SHORT_DAY_STRINGS //Display clock
#define dt_SHORT_MONTH_STRINGS //Display clock

// Network setup

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192,168,0,38 };
byte mask[] = { 255, 255, 255, 0 };
byte gw[] = { 192, 168, 0, 1 };
byte server[] = { 192, 168, 0, 32  }; 

 //Clock
byte SNTP_server_IP[] = { 130,149,17,21};    // ntps1-0.cs.tu-berlin.de
time_t prevDisplay = 0; // when the digital clock was displayed
const long timeZoneOffset = 3600L;
char* dag[]={"So","Ma", "Ti", "On", "To", "Fr", "Lo"};

//udp receive
unsigned int localPort = 323232; // local port to listen on
#define MAX_SIZE 32 // maximum packet size
byte packetBuffer[MAX_SIZE]; //buffer to hold incoming packet
int packetSize; // holds received packet size
byte remoteIp[4]; // holds recieved packet's originating IP
unsigned int remotePort; // holds received packet's originating port

//Display data from udp
int temp = 0;
int oldTemp = 0;
char Temp[4]="";
char newMsg[16]="";
char oldMsg[16]="";
//For LcdPrintDec
char decBuffer[] = {0,0,0,0,0,0,0};

// menu
 int menudelaycount = 0;		    
 int programnumber=0;

//RFID global vars
int  c = 0; 
char code[11]; //RFID tag is 10 chars and then terminate
byte readCard[6];
byte storedCard[6]; 
int offset = 0;
// Resistor ladder inputs
byte channelAInput = A5;  //Resladder on pin 4
byte channelBInput = A4; //Resladder on pin 5
int channelAvalue;
int channelBvalue;
int total=0; 
// Got milk?
boolean doorOuter = false;
boolean doorInner = false;
boolean doorBasement = false;
boolean buttonKids = false;
boolean buttonAdult = false;
byte frontStatus = 0;
byte insideStatus = 0;

// Lets create the RFID class
NewSoftSerial mySerial(4, 2);
NewSoftSerial lcd2(56, 6);
// ...and create some classes for the LCDs
LCD3Wire lcd1 = LCD3Wire(LCD_LINES, DOUT_PIN, STR_PIN, CLK_PIN); 
//LCD3Wire lcd2 = LCD3Wire(LCD2_LINES, DOUT_PIN, STR2_PIN, CLK_PIN);

//Play some music or at least be prepared
Tone tone1;
int notes[] = { 0,
NOTE_C4, NOTE_CS4, NOTE_D4, NOTE_DS4, NOTE_E4, NOTE_F4, NOTE_FS4, NOTE_G4, NOTE_GS4, NOTE_A4, NOTE_AS4, NOTE_B4,
NOTE_C5, NOTE_CS5, NOTE_D5, NOTE_DS5, NOTE_E5, NOTE_F5, NOTE_FS5, NOTE_G5, NOTE_GS5, NOTE_A5, NOTE_AS5, NOTE_B5,
NOTE_C6, NOTE_CS6, NOTE_D6, NOTE_DS6, NOTE_E6, NOTE_F6, NOTE_FS6, NOTE_G6, NOTE_GS6, NOTE_A6, NOTE_AS6, NOTE_B6,
NOTE_C7, NOTE_CS7, NOTE_D7, NOTE_DS7, NOTE_E7, NOTE_F7, NOTE_FS7, NOTE_G7, NOTE_GS7, NOTE_A7, NOTE_AS7, NOTE_B7
};
char *song = "smb:d=4,o=5,b=100:16e6,16e6,32p,8e6,16c6,8e6,8g6,8p,8g,8p,8c6,16p,8g,16p,8e,16p,8a,8b,16a#,8a,16g.,16e6,16g6,8a6,16f6,8g6,8e6,16c6,16d6,8b,16p,8c6,16p,8g,16p,8e,16p,8a,8b,16a#,8a,16g.,16e6,16g6,8a6,16f6,8g6,8e6,16c6,16d6,8b,8p,16g6,16f#6,16f6,16d#6,16p,16e6,16p,16g#,16a,16c6,16p,16a,16c6,16d6,8p,16g6,16f#6,16f6,16d#6,16p,16e6,16p,16c7,16p,16c7,16c7,p,16g6,16f#6,16f6,16d#6,16p,16e6,16p,16g#,16a,16c6,16p,16a,16c6,16d6,8p,16d#6,8p,16d6,8p,16c6";


void setup()  
{
  //Init network
   Ethernet.begin(mac,ip,gw,mask);
   //Init LCDs
  lcd1.init();
  lcd2.begin(9600);
  //lcd2.init();
  lcdCursorOff();
  lcdClear();
  lcd1.commandWrite(0b00001100);  //Turn off cursor
  //lcd2.commandWrite(0x20);
 // lcd2.commandWrite(0x03);  //Turn off cursor
  
   //lcd2.commandWrite(0xF2+'a');
 //  lcd2.commandWrite(0b0000000100);  //Turn off cursor
  //init time  - first
  //Init clock
 setSyncProvider(getNtpTime);
  while(timeStatus()== timeNotSet)   
     ; // wait until the time is set by the sync provider
     UdpBytewise.begin(localPort);
  //Init buttons 
  lcd1.printIn("Starting...");
   for (int i=0; i <= 9; i++){
   total=total + analogRead(channelAInput);; 
   delay(100);
   } 
    channelAvalue = total / 10;
  total =0;
  for (int i=0; i <= 9; i++){
    total=total + analogRead(channelBInput);; 
    delay(100);
   } 
  channelBvalue = total / 10;

 // Lets us know were ready
  lcd1.clear();  

  // set the data rate for serial debugging port and the NewSoftSerial port
  Serial.begin(9600);
  mySerial.begin(9600);
  
  //Set up music & bell pins
  tone1.begin(5);//Playback on Pin 5
  pinMode(BELL, OUTPUT);
  pinMode(BIGBELL, OUTPUT);
  writeOnceTag(0, 0x08,0x4B,0xA6,0x28,0xA7);

}

void digitalClockDisplay( LCD3Wire &lcd, int pos ){
  lcd.cursorTo(2, pos);
  lcdSetPosition(2, pos);
  lcd.printIn(dag[weekday()-1]);
  lcd2.print(dag[weekday()-1]);
  lcd.print(' ');
  lcd2.print(' ');
  lcd.printIn(itoa(day(),decBuffer, 10));
  lcd2.print(itoa(day(),decBuffer, 10));
  lcd.cursorTo(2,(pos-6));
   lcdSetPosition(2,(pos-6));
  // clock display of current time
   if (hour() < 10) {
  lcd.print('0');
  lcd2.print('0');
   }
  lcd.printIn(itoa(hour(),decBuffer, 10));
  lcd2.print(itoa(hour(),decBuffer, 10));
  lcd.print(':');
  lcd2.print(':');
  if (minute() < 10) {
  lcd2.print('0');
  lcd.print('0');
  }
  lcd.printIn(itoa(minute(),decBuffer, 10));
  lcd2.print(itoa(minute(),decBuffer, 10));
 // printDigits(lcd, minute());

}

void loop()
{
   //Read resistor ladder inputs
    frontStatus = checkSensor(channelAInput, channelAvalue);
    insideStatus = checkSensor(channelBInput, channelBvalue);
    update_status();
   
   // For debugging on serial
   Serial.println("");
 
  //Clock display update & udp packet send
    if( now() != prevDisplay) //update the display only if the time has changed
      {
      prevDisplay = now();
      digitalClockDisplay(lcd1, 11);  
      //digitalClockDisplay(lcd2, 27);  
      sendPackets();
      if(packetSize =UdpBytewise.available()) 
      receivePackets();
      }

    
  //Check for rfid tags
    if (mySerial.available() > 0)
      rfid();
}

void sendPackets() {
  int i=0;
  byte targetIp[] = { 192, 168, 0, 32};
  int targetPort = 313131;
  UdpBytewise.beginPacket(targetIp,targetPort);
  UdpBytewise.print("F");
  UdpBytewise.print(frontStatus, HEX);
  UdpBytewise.print("I");
  UdpBytewise.print(insideStatus, HEX);
  UdpBytewise.print(i++);
  UdpBytewise.endPacket();
  }

void receivePackets() { 
   int i;
   int test;
   boolean update=false;
   Serial.print("testing ");
   Serial.print("Received packet of size ");
   Serial.println(packetSize);
   if (packetSize == 4) {  UdpBytewise.begin(localPort);}   
      //Check message
   if (packetSize > 4 ) {  
   for (int i=0; i <= packetSize-1; i++)
     { 
       newMsg[i]=UdpBytewise.read(),BYTE; 
       if (newMsg[i] != oldMsg[i]) {
       update=true;
       oldMsg[i]=newMsg[i];
       }
     }
   }
  //  Display RFID LCD 
  if (update == true) {
      switch (newMsg[0]) {
	case '1':
          lcd1.cursorTo(1, ((16-packetSize)/2));
          for (int i=1; i <= packetSize-1; i++){
          lcd1.print(newMsg[i]);
          }
	  break;
	case '2':
	  lcdSetPosition(1, ((13-packetSize)/2)+3);
          for (int i=1; i <= packetSize-1; i++){
          lcd2.print(newMsg[i]);
          }
	  break;

        case 'L':
          getID(false);
          test=lookupTag(readCard[0],readCard[1],readCard[2],readCard[3],readCard[4]);
          if (test != 200){
          Serial.println(" ");  
          Serial.print("Hurra");
          Serial.print(" Test found at: ");
          Serial.print(test);
          Serial.println(" ");
        }
          break;
          
         case 'D':
          getID(false);
          test=lookupTag(readCard[0],readCard[1],readCard[2],readCard[3],readCard[4]);
          if (test != 200){
          Serial.println(" ");  
          Serial.print("Hurra");
          Serial.print(" Test deleted at: ");
          Serial.print(test);
          Serial.println(" ");
          deleteTag(test);
        }
          break;
          
         case 'I':
          getID(false);
          test=lookupTag(readCard[0],readCard[1],readCard[2],readCard[3],readCard[4]);
          if (test != 200){
          Serial.println(" ");  
          Serial.print("Whops");
          Serial.print(" Card already in eeprom: ");
          Serial.print(test);
          Serial.println(" ");
        } else {
          test=findEmptyTag();
          if (test != 200){
          writeTag(test, readCard[0],readCard[1],readCard[2],readCard[3],readCard[4]);   
          Serial.println("Nytt kort lagret");  
          } else {
            Serial.println("Database full!"); 
          }
        }
          break;
          
          case 'X':
          if (newMsg[1] == 'A' && newMsg[2] == 'L' && newMsg[3] == 'L' && newMsg[4] == 'C' ) {
           eraseEEPROM();
           Serial.println("Database Erased!"); 
          }
          break;
          
	default:
	  lcd2.print("No match");
          delay (5000);
	  }

  }
 
     
  // Check temperature    
  if (packetSize == 3) {
  for (int i=0; i <= packetSize-1; i++){ Temp[i]=UdpBytewise.read(),BYTE; }
  temp=atoi(Temp);
    if (oldTemp != temp) {
      lcd1.cursorTo(2,0);
      lcdSetposition(2,0);
      lcd1.printIn(Temp);
      lcd2.print(Temp);
      if (oldTemp < temp) { 
        lcd1.print(B00011000) ;
        lcd2.print(B00011000) ;
        } else {
        lcd1.print(B00011001); 
        lcd2.print(B00011001); 
       }
       oldTemp = temp; 
    }
  }
  
   //wait a bit
   delay(10);  
}
  
void update_status()
{
  //Lets check front door
 if ((frontStatus & (1<<0)) && (doorOuter == false) ) {
   doorOuter=true;
   //lcd1.clear();
   lcdSetPosition(1, 0);
   lcd2.print("X"); 
 } else if ( (!(frontStatus & (1<<0))) && (doorOuter == true)) {
   doorOuter=false;
   //lcd1.clear();
   lcdSetPosition(1, 0);
   lcd2.print("O");
 };
   //Lets check basement door
 if ((insideStatus & (1<<0)) && (doorBasement == false) ) {
   doorBasement=true;
   lcdSetPosition(1, 1);
   lcd2.print("X"); 
 } else if ( (!(insideStatus & (1<<0))) && (doorBasement == true)) {
   doorBasement=false;
   lcdSetPosition(1, 1);
   lcd2.print("O");
 };
   //Lets check Inner door
 if ((insideStatus & (1<<0)) && (doorInner == false) ) {
   doorInner=true;
   //lcd1.clear();
  // lcdSetPosition(1, 5);
  // lcd2.print("X"); 
 } else if ( (!(insideStatus & (1<<0))) && (doorInner == true)) {
   doorInner=false;
   //lcdSetPosition(1, 5);
   //lcd2.print("O");
 };
//Lets check if someone is at the door
 if ( frontStatus & (1<<3)) {
   buttonAdult=true;
   lcd1.cursorTo(1, 3);
   lcd1.printIn("Karin & Lasse");
   pinMode(A0, OUTPUT);
   digitalWrite(A0, HIGH);
   digitalWrite(A1, HIGH);
   delay (20);
   digitalWrite(A0, LOW);
   digitalWrite(A1, LOW);
   delay (4000);
   lcd1.cursorTo(1, 3);
   lcd1.printIn("             ");
  } else {
   buttonAdult=false;

  };
 
 //Any kids at the door?
 if ( frontStatus & (1<<2)) {
   buttonKids=true;
   lcd1.cursorTo(1, 4);
   lcd1.printIn("Erik & Ole");
  play_rtttl(song);  //  Play Mariotune
   lcd1.cursorTo(1, 4);
   lcd1.printIn("           ");
} else {
    buttonKids=false;
  };
  
  // Access menu?
 if (insideStatus & (1<<3)) {
    lcd2.print("Meny");
    delay (1000);
    Menu();
   }
}

void Menu(){	
  
  lcdClear(); 
  lcdSetPosition(1,2);
  lcd2.print("Program Menu");
  lcdSetPosition(2,3);	  
  switch (programnumber) {
  case 1:
    lcd2.print("Update clock");   
    break;
  case 2:
    lcd2.print("Reset doorbells");
    break;
  case 3:
    lcd2.print("Add RFID tag");
    break;
  case 4:
    lcd2.print("Delete RFID tag");
    break;
  default:
    lcd2.print("Return");
    
  }
 while((insideStatus & (1<<3))){
  insideStatus = checkSensor(channelBInput, channelBvalue); 
 }//while button is high do nothing: {} (helps with debounce after button has been pressed)
 delay(5);
while(!(insideStatus & (1<<3))){
  insideStatus = checkSensor(channelBInput, channelBvalue);
} //wait until button has been pressed (taken high).
   menudelaycount = 0; //clear menu delay
   while(menudelaycount <500){ //do this code within the 500 limit (over 500ms because of other stuff that is done and takes time)
   delay(1);
   menudelaycount++;
   while(!(insideStatus & (1<<3))){
   insideStatus = checkSensor(channelBInput, channelBvalue);  //if the button goes low (button released) within this loop then it advances one menu option
   programnumber++; //increase the menu option
   if(programnumber > 4){
     programnumber = 1;
   }
   Menu(); //then run menu code from start: the change in program number makes it change the option it is on.
   }
 }
  switch (programnumber) {
	case 1:
	  lcd2.print("clock");
          delay (5000);
	  break;
	case 2:
	  lcd2.print("buttons");
          delay (5000);
	  break;
	case 3:
	  lcd2.print("RFID inn");
          delay (5000);
	  break;
         case 4:
         lcd2.print("RFID del");
          delay (5000);
          break;

	default:
	  lcd2.print("uuun");
          delay (5000);
	}
}

/*-------- NTP code ----------*/

unsigned long getNtpTime()
{

  sendNTPpacket(SNTP_server_IP);
  delay(1000);
  
  if ( UdpBytewise.available() ) { 
    for(int i=0; i < 40; i++)
       UdpBytewise.read(); // ignore every field except the time
       const unsigned long seventy_years = 2208988800UL - 3600UL;  
                 
    return getUlong() -  seventy_years;      
  }
  return 0; // return 0 if unable to get the time
}

unsigned long sendNTPpacket(byte *address)
{
  UdpBytewise.begin(123);
  UdpBytewise.beginPacket(address, 123);
  UdpBytewise.write(B11100011);   // LI, Version, Mode
  UdpBytewise.write(0);    // Stratum
  UdpBytewise.write(6);  // Polling Interval
  UdpBytewise.write(0xEC); // Peer Clock Precision
  write_n(0, 8);    // Root Delay & Root Dispersion
  UdpBytewise.write(49); 
  UdpBytewise.write(0x4E);
  UdpBytewise.write(49);
  UdpBytewise.write(52);
  write_n(0, 32); //Reference and time stamps  
  UdpBytewise.endPacket();   
}

unsigned long getUlong()
{
    unsigned long ulong = (unsigned long)UdpBytewise.read() << 24;
    ulong |= (unsigned long)UdpBytewise.read() << 16;
    ulong |= (unsigned long)UdpBytewise.read() << 8;
    ulong |= (unsigned long)UdpBytewise.read();
    return ulong;
}

void write_n(int what, int how_many)
{
  for( int i = 0; i < how_many; i++ )
    UdpBytewise.write(what);
}


void openDoor(){
  Serial.print ("Card found");
  sendCard('E');
  lcd1.cursorTo(1,0);
  lcd1.printIn("                ");
  lcd1.cursorTo(1,0);
  for(int i = 0; i < 15; i++ ){
  lcd1.print('>');
  delay (500);
  }
  lcd1.cursorTo(1,0);
  lcd1.printIn("                ");
  mySerial.flush();
  sendCard('E');
}
void rfid()
{ 
  byte val = 0;
   if((val = mySerial.read()) == 2) 
    { 
     if (val = mySerial.read() == 82){ 
      
      getID(true);    
    }
    }
 int test=lookupTag(readCard[0],readCard[1],readCard[2],readCard[3],readCard[4]); 
 if (test!=200) {
 openDoor();
 } else {
sendCard('F');
 lcd1.cursorTo(1,0);
 lcd1.printIn("                ");
  lcd1.cursorTo(1,0);
 lcd1.printIn("  Ukjent Kort  ");
 delay(3000);
 mySerial.flush();
 sendCard('F');
  lcd1.cursorTo(1,0);
 lcd1.printIn("                ");
}
}

void sendCard(char a)
{
  
  byte targetIp[] = { 192, 168, 0, 32};
  int targetPort = 313131;
  UdpBytewise.beginPacket(targetIp,targetPort);
  UdpBytewise.print(a);
  for(int i = 0; i < 5; i++ ){ 
  if (readCard[i] <10){ UdpBytewise.print(0); }
  UdpBytewise.print(readCard[i], HEX);
  }
  UdpBytewise.endPacket();
}

boolean checkSensor( byte sensorInput, int channelValue )
{
  byte state;
  int sensorReading = analogRead(sensorInput);
  if( sensorReading > channelValue + 940   ) {
    state = B01111 ; 
  } else if ( sensorReading > channelValue + 439 )  {
    state = B01110 ;
    } else if ( sensorReading >= channelValue + 250  ) {
    state = B01101; 
  } else if ( sensorReading >= channelValue + 176 ) {
    state = B01100;
  } else if ( sensorReading >= channelValue + 147 ) {
    state =  B01011;
  } else if ( sensorReading >= channelValue + 106 ) {
    state =  B01010;
  } else if ( sensorReading >= channelValue + 78 ) {
    state =  B01001;
  } else if ( sensorReading >= channelValue + 51 ) {
    state = B01000;
  } else if ( sensorReading >= channelValue + 45 ) {
    state =  B00111;
  } else if ( sensorReading >= channelValue + 35  ) {
    state = B00110;
   } else if ( sensorReading >= channelValue + 25  ) {
    state =  B00101;
  } else if ( sensorReading >= channelValue + 17   ) {
    state = B00100;
   } else if ( sensorReading >= channelValue + 13   ) {
    state = B00011;  
  } else if ( sensorReading >= channelValue + 8  ) {
    state = B00010;
   } else if ( sensorReading >= channelValue + 3   ) {
    state = B00001;
   } else {
    state = B00000; 
    }
Serial.print(channelValue, DEC);
  Serial.print(": ");
  Serial.print(sensorInput, DEC);
  Serial.print(": ");
  Serial.print(sensorReading, DEC);
  Serial.print(" (");
  Serial.print(state, BIN);
  Serial.print(") ");
  // Pass the current state back to the calling function
  return state;
}

#define isdigit(n) (n >= '0' && n <= '9')
void play_rtttl(char *p)
{
  // Absolutely no error checking in here

  byte default_dur = 4;
  byte default_oct = 6;
  int bpm = 63;
  int num;
  long wholenote;
  long duration;
  byte note;
  byte scale;

  // format: d=N,o=N,b=NNN:
  // find the start (skip name, etc)

  while(*p != ':') p++;    // ignore name
  p++;                     // skip ':'
  // get default duration
  if(*p == 'd')
  {
    p++; p++;              // skip "d="
    num = 0;
    while(isdigit(*p))
    {
      num = (num * 10) + (*p++ - '0');
    }
    if(num > 0) default_dur = num;
    p++;                   // skip comma
  }
   // get default octave
  if(*p == 'o')
  {
    p++; p++;              // skip "o="
    num = *p++ - '0';
    if(num >= 3 && num <=7) default_oct = num;
    p++;                   // skip comma
  }

   // get BPM
  if(*p == 'b')
  {
    p++; p++;              // skip "b="
    num = 0;
    while(isdigit(*p))
    {
      num = (num * 10) + (*p++ - '0');
    }
    bpm = num;
    p++;                   // skip colon
  }

   // BPM usually expresses the number of quarter notes per minute
  wholenote = (60 * 1000L / bpm) * 4;  // this is the time for whole note (in milliseconds)

   // now begin note loop
  while(*p)
  {
    // first, get note duration, if available
    num = 0;
    while(isdigit(*p))
    {
      num = (num * 10) + (*p++ - '0');
    }
    
    if(num) duration = wholenote / num;
    else duration = wholenote / default_dur;  // we will need to check if we are a dotted note after

    // now get the note
    note = 0;

    switch(*p)
    {
      case 'c':
        note = 1;
        break;
      case 'd':
        note = 3;
        break;
      case 'e':
        note = 5;
        break;
      case 'f':
        note = 6;
        break;
      case 'g':
        note = 8;
        break;
      case 'a':
        note = 10;
        break;
      case 'b':
        note = 12;
        break;
      case 'p':
      default:
        note = 0;
    }
    p++;

    // now, get optional '#' sharp
    if(*p == '#')
    {
      note++;
      p++;
    }

    // now, get optional '.' dotted note
    if(*p == '.')
    {
      duration += duration/2;
      p++;
    }
  
    // now, get scale
    if(isdigit(*p))
    {
      scale = *p - '0';
      p++;
    }
    else
    {
      scale = default_oct;
    }

    scale += OCTAVE_OFFSET;

    if(*p == ',')
      p++;       // skip comma for next note (or we may be at the end)

    // now play the note

    if(note)
    {
      tone1.play(notes[(scale - 4) * 12 + note]);
      delay(duration);
      tone1.stop();
    }
    else
    {
      delay(duration);
    }
  }
}
// erase the entire EEPROM memory storage:

void eraseEEPROM(){                 
  for(int i = 0; i < 512; i++){
    EEPROM.write(i, 0);   
  }
}

// writes tag number in a location:
void writeTag(int startingAddress, byte byte0, byte byte1, byte byte2, byte byte3, byte byte4){    
  EEPROM.write( startingAddress*5, byte(1));   
  EEPROM.write(startingAddress*5+1, byte0);
  EEPROM.write(startingAddress*5+2, byte1);
  EEPROM.write(startingAddress*5+3, byte2);
  EEPROM.write(startingAddress*5+4, byte3);
  EEPROM.write(startingAddress*5+5, byte4);
}

// delete tag from a specified location
void deleteTag(int startingAddress){                                    
  EEPROM.write( startingAddress*5, byte(0));   
  EEPROM.write(startingAddress*5+1, byte(0));
  EEPROM.write(startingAddress*5+2, byte(0));
  EEPROM.write(startingAddress*5+3, byte(0));
  EEPROM.write(startingAddress*5+4, byte(0));
  EEPROM.write(startingAddress*5+5, byte(0));

}
// find the first empty entry in the database:
int findEmptyTag(){                              
  for (int startingAddress = 0; startingAddress< MAX_NO_CARDS; startingAddress++){
    byte value = EEPROM.read(startingAddress*5);
    if (value == byte(0)) {
      return(startingAddress);
    } 
  }  
  return(200);
}

// print the entire database
void printTags(){                                
  for (int thisTag = 0; thisTag< MAX_NO_CARDS; thisTag++){
    printOneTag(thisTag);
  }    
}

void printOneTag(int address) {
  Serial.print(address);
  Serial.print(":");
  for (int offset = 1; offset < 5; offset++) {
    int thisByte = int(EEPROM.read(address*5+offset));
    // if the byte is less than 16, i.e. only one hex character
    // add a leading 0:
    if (thisByte < 0x10) {
      Serial.print("0"); 
    }
    // print the value:
    Serial.print(thisByte,HEX);
  }
  // add a final linefeed and carriage return:
  Serial.println();
}
//lookup tag in the database:
int lookupTag(byte byte0, byte byte1, byte byte2, byte byte3, byte byte4){   
  for (int thisCard = 0; thisCard< MAX_NO_CARDS; thisCard++){
    byte value = EEPROM.read(thisCard*5);   
    if (value != byte(0)){                    //it is a valid tag
      //see if all four bytes are the same as the ones we're looking for
      if(byte0 == EEPROM.read(thisCard*5+1) && byte1 == EEPROM.read(thisCard*5+2) 
        && byte2 == EEPROM.read(thisCard*5+3) && byte3 == EEPROM.read(thisCard*5+4) && byte4 == EEPROM.read(thisCard*5+5) ) {
        return(thisCard); 
      }
    } 
  }
  // if you don't find the tag, return 200;
  return(200);   
}

void getID(boolean rfid)
{
  byte bytesread = 0;
  byte i = 0;
  byte val = 0;
  byte tempbyte = 0;
 // 5 HEX Byte code is actually 10 ASCII Bytes. 
  while ( bytesread < 10 ) // Read 10 digit code + 2 digit checksum
  {                        
    if (rfid==true) {  // Check to make sure data is coming on the serial line
      val = mySerial.read();        // Store the current ASCII byte in val
    } else { 
    val = newMsg[bytesread+1]; 
    }  
      if((val == 0x0D)||(val == 0x0A)||(val == 0x03)||(val == 0x02)) 
      { 
      break;  
      }                         // If header or stop bytes before the 10 digit reading Stop reading                                  
      if ( (val >= '0' ) && ( val <= '9' ) )    // Do Ascii/Hex conversion
      {val = val - '0';} 
      else if ( ( val >= 'A' ) && ( val <= 'F' ) ) 
      {val = 10 + val - 'A'; }
      if ( bytesread & 1 == 1 )      // Every two ASCII charactors = 1 BYTE in HEX format
      {readCard[bytesread >> 1] = (val | (tempbyte << 4)); } 
      else                                        // If it is the first HEX charactor
      {tempbyte = val; };
      bytesread++;                                // Increment the counter to keep track
    } 
  bytesread = 0;
  mySerial.flush();
  for (int i=0; i <= 4; i++){
      Serial.print(readCard[i], HEX);
      Serial.print(":"); }
  
}
void writeOnceTag(int startingAddress, byte byte0, byte byte1, byte byte2, byte byte3, byte byte4){    
  EEPROM.write( startingAddress*5, byte(1));   
  EEPROM.write(startingAddress*5+1, byte0);
  EEPROM.write(startingAddress*5+2, byte1);
  EEPROM.write(startingAddress*5+3, byte2);
  EEPROM.write(startingAddress*5+4, byte3);
  EEPROM.write(startingAddress*5+5, byte4);
}

 void lcdSetPosition(byte y, byte x)
{
  if (y==1) {
   lcd2.print(0x0f, BYTE);
   lcd2.print(0x80 + x, BYTE);
  } else if (y==2) {
    lcd2.print(0x0f, BYTE);
   lcd2.print(0xc0 + x, BYTE);
  }
}

void lcdClear() {
  lcd2.print(0x0f,BYTE); // CLEAR SCREEN CMD
 lcd2.print(0x01,BYTE); // CLEAR SCREEN CMD
}

void lcdCursorOff () {
 lcd2.print(0x0f,BYTE); // CLEAR SCREEN CMD
 lcd2.print(0x0e,BYTE); // CLEAR SCREEN CMD 
}
void lcdCursorOn () {
 lcd2.print(0x0f,BYTE); // CLEAR SCREEN CMD
 lcd2.print(0x0f,BYTE); // CLEAR SCREEN CMD 
}

 
Perl temp code

Code: Select all

  GNU nano 2.0.9            File: sender_temp.pl

#!/usr/bin/perl -w
# UDP listener
use Math::Round;
use strict;
use IO::Socket;
use DBI;
my $host = "192.168.0.40";
my $database = "domotiga";
my $tablename = "devices";
my $user = "domouser";
my $pw = "kung-fu";
# my $dbh = DBI->connect($host, $database, $user, $pw, {PrintError=>0, RaiseErr$
my $dbh = DBI->connect("DBI:mysql:$database;host=$host", $user, $pw, { RaiseErr$

my $myquery = $dbh->prepare("SELECT value FROM $tablename WHERE name=?") or die$

my $message = IO::Socket::INET->new(Proto=>"udp",PeerPort=>323232,PeerAddr=>"19$
  or die "Can't make UDP socket: $@";

$myquery->execute('Hagen') or die $dbh->errstr;

my @row_array = $myquery->fetchrow_array;
$myquery->finish ();
my $temp = round( $row_array[0]);

if ( index($temp,"-") == -1 ) {
$temp="+".$temp;
}
if (length($temp) < 3) {
substr($temp,1,0)="0";
}

print $temp;

$message->send($temp);

$dbh->disconnect;
exit 0;


Post Reply

Return to “Raspberry, Arduino, Cubietruck and other clones Forum”