Wednesday, June 8, 2016

Arduino Recess Alarm Bell

We have to remind our employees that break time is over, else they extend their recess.  Most of them do not wear wrist watches, and we do not have a clock hung on the common area's wall, so I did not blame them if they still hung around even when break time is through.  The time keeper then was our guard, who carried a metal pipe, and who would repeatedly hit the stair's hand rails to signal the start, or end of break time.

It was obvious that sounding the alarm can be done in a better way.

Fortunately, there was an Arduino Yun, and a relay shield lying around at home (bought way back 2013, but just saw action in a wireless light switch, a motion sensed photo recorder, and a remote temperature sensor).  For the hardware, a few things are needed, the Arduino Yun microcontroller, its relay shield, the bell, and electrical wires.

The design is very simple, the relay shield is attached to the microcontroller.  The trickiest part maybe is attaching the electrical wire to one of the relays.  What I did was to split one of the supply wires, and attach one end to the relay's normally open (NO) port, and the other to the common (COM) port.  The Arduino Yun should also be powered, so the micro USB cable does the job.



The design could be improved by using a single package relay, rather than a relay shield, which renders three relays unused.

The code is quite simple as well.  Here's the code with annotations:

#include <Process.h>

#define PIN_ALARM 13 //pin 13 controls relay switching
#define PIN_DEBUG 9  //pin 9 is the LED output pin to know the sketch is working
#define DELAY_GENERIC 1000 //1 second delay
#define DURATION_ALARM 1000*3 //alarm duration
#define DELAY_ALARM 1000L*60L //delay after sounding the bell "L" is for "long" data type

Process date;

int hours, minutes, seconds;

void setup() {
  pinMode(PIN_ALARM, OUTPUT);
  pinMode(PIN_DEBUG, OUTPUT);
  
  Bridge.begin(); //the bridge is needed to retrieve the time from Linio (embedded Linux)
}

void loop() {
  
  digitalWrite(PIN_DEBUG, HIGH); //turn on the debug LED

  //request the date/time from Linio
  date.begin("date");
  date.addParameter("+%T");
  date.run();
    
  if (date.available() > 0) {
    digitalWrite(PIN_DEBUG, LOW); //turn off the debug LED

    //parse the time start
    String timeString = date.readString();
  
    date.flush();
    
    int firstColon = timeString.indexOf(":");
    int secondColon = timeString.lastIndexOf(":");
    
    String hourString = timeString.substring(0, firstColon);
    String minString = timeString.substring(firstColon + 1, secondColon);
    String secString = timeString.substring(secondColon + 1);
      
    hours = hourString.toInt();
    minutes = minString.toInt();
    seconds = secString.toInt();
    //parse the time end

    //test time for debugging
    //if ((hours == 12) && (minutes == 3)) alarm();

    //alarm times
    //notice that alarm times are individual if statements
    //I could've made it one if else block, but
    //for some reason the microprocessor hung up when the times are in
    //an if else block
    if ((hours == 6) && (minutes == 0)) alarm();
    if ((hours == 7) && (minutes == 0)) alarm();
    if ((hours == 10) && (minutes == 0)) alarm();
    if ((hours == 10) && (minutes == 15)) alarm();
    if ((hours == 10) && (minutes == 30)) alarm();
    if ((hours == 12) && (minutes == 0)) alarm();
    if ((hours == 13) && (minutes == 0)) alarm();
    if ((hours == 14) && (minutes == 0)) alarm();
    if ((hours == 15) && (minutes == 0)) alarm();
    if ((hours == 15) && (minutes == 15)) alarm();
    if ((hours == 15) && (minutes == 30)) alarm();
    if ((hours == 18) && (minutes == 0)) alarm();
    if ((hours == 19) && (minutes == 0)) alarm();
  }

  //1 sec. delay for every loop run for reliability
  //I observed that the microprocessor hung up without this delay
  //1 second inaccuracy (i.e. the bell rings at say 12:00:01 instead of 12:00:00) is ok for us
  delay(DELAY_GENERIC);
}

void alarm() {
  //close the relay...
  digitalWrite(PIN_ALARM, HIGH);
  //...for 3 seconds
  delay(DURATION_ALARM);
  //open the relay
  digitalWrite(PIN_ALARM, LOW);
  //delay for a minute (for reliability as well, like the 1 sec. delay for every loop)
  delay(DELAY_ALARM);
}

When the setup is plugged, the microcontroller syncs its system time with the router, which gets its time from the Internet.  Then the bell briefly rings as part of the Yun's initialization procedure.  After another brief period, the debug LED starts blinking.  This signifies the sketch is running.  The bell rings on the specified times, give a few seconds.

I'm an engineer, not an artists, so pardon the "case", and its mounting.  Nothing special about the bell's mounting, which is away from the microprocessor to avoid excessive vibration, and electrical interference.


So now, the guard does not have to make a very unpleasant manual alarm everytime break starts, or ends.  We have a school bell that takes care of that.

No comments:

Post a Comment