Motion Sensor Jingle Player – Code

The code included a custom library we built, the Alarm library. The library contains functionality that lets users build their own Jingles to be played, as well as some built-in, default jingles.

The note() method

The main part of the Alarm library is the Jingle class’s note() method, which simplifies the process of playing tones for the user. The note() function makes use of the Arduino tone() and delay() functions. The tone() function outputs a specified frequency to a specified output pin for a specified duration. Since the tone() function doesn’t wait for the note to complete before moving onto the next command, the delay() function is called so that the notes can be properly spaced.

To let users make jingles more easily, different musical notes are pre-programmed. The notes are set to the corresponding frequency that the Arduino’s tone() function will use to play the note.

One of the preset alarms


Motion Sensor Jingle Player – Big Picture

The goal of this project is to create a motion detected alarm system with a button to turn the alarm on or off and toggle between different jingles.

When the PIR motion detector is triggered, a Honeytone speaker will play a jingle, controlled by a custom C++ library. The jingle won’t play if the alarm isn’t set; the user can tell because of an LED that is lit up when the alarm is on. The pushbutton, when long pressed, turns the alarm on or off; if short pressed, it will toggle between different preset jingles.

The project uses an Arduino board because of the built-in library to output single-frequency tones. Originally, the project also used interrupts, but it conflicted with the Arduino’s library; instead, logic for all inputs and outputs is handled within the loop() method.

The project was a success: the motion detector will trigger and the speaker play the selected jingle when the alarm is on, but won’t do anything when the alarm is off.

Basic Demonstration Video

Motion Sensor Jingle Player – Schematics

Motion detector
Cardboard walls

The final design made use of a PIR Motion Sensor. The sensor is powered to 5V, grounded, and connected to digital input pin 2 on the Arduino board. The motion sensor has two potentiometers on its side, one which controlled the sensitivity and another which controlled the delay between detection signals.

The motion detector is able to detect motion from across a room, which caused some issues with staying as still as possible while trying to test and eventually led to the design of cardboard walls for the sensor. The walls act as blinders to narrow the sensor’s detection range and simplifies testing. In a general purpose design, the walls would make sure the sensor only detects motion it’s supposed to.

Full Schematic

Simon Says – Code

This snippet was some of the most driving code within the Simon Says system. The randomized pattern generation to illuminate the LED’s was critical to operational success. Patterns could have been hard coded, but at the cost of efficiency and code readability.

Following the randomized pattern generation, this display function illustrates the initial step in reading user input. This “lock and key” mechanism (LED display and user input) ensures the advancement of progress throughout the game.

Wireless Data Transmission – Schematics

The transmitter unit must be constructed in such a way that a laser diode may be powered on and off in order to send the previously mentioned high/low states. For that reason, the circuit consists of a power circuit, which utilizes an NPN Bipolar Junction Transistor as a current switch. This means that depending on the applied voltage, the Transistor will allow or prevent current from flowing to the laser diode, effectively allowing a microcontroller to turn the laser diode on and off. An accompanying program is then written to allow the laser diode to transmit the data bits of ASCII characters received via serial link from host device and the transmitting microcontroller. The user simply enters whichever ASCII characters they desire to transmit. The microcontroller interrupts on any given serial event and immediately begins transmitting the character received.

The receiver unit was constructed using a Wheatstone Bridge circuit. The Wheatstone Bridge is a resistive circuit. Therefore, resistors and resistive sensors, such as photoresistors, make up each branch of the circuit. R2 and Rx in the circuit are similar photoresistors in order to allow for automatic adjustment to dynamic ambient light conditions. The versatility and relative accuracy of the Wheatstone Bridge allow for the photoresistors, which change resistance inversely with the amount of light shined on them, to change the overall circuit resistance allowing obvious high and low states to develop. These can then be interpreted by a Microcontroller such as the Xplained Mini Board with the appropriate software.

Wireless Data Transmission – Code

Transmitter Program

#define LASER_PIN           7
#define LASER_BAUDRATE      5  // bits per second
#define SIGNAL_HOLD_PERIOD  (1.0 / LASER_BAUDRATE) * 1000.0
#define SIGNAL_START_HOLD_PERIOD  SIGNAL_HOLD_PERIOD / 2.0

unsigned long transmit_begin;
byte c;
int message[10] = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0};


int isNthBitSet (byte c, int n) {
  static unsigned char mask[] = {128, 64, 32, 16, 8, 4, 2, 1};
  return ((c & mask[n]) != 0);
}

void transmitHoldStart() {
  while (millis() - transmit_begin < SIGNAL_START_HOLD_PERIOD) {}
}

void transmitHold() {
  //transmit_begin = millis();
  while (millis() - transmit_begin < SIGNAL_HOLD_PERIOD) {}
}

void transmitByte(byte c) {

  for (int idx=0; idx<8; idx++) {
    message[idx+1] = isNthBitSet(c, idx);
  }

  transmit_begin = millis();
  digitalWrite(LASER_PIN, message[0]);
  transmitHoldStart();

  for (int idx=1; idx<10; idx++) {
    transmit_begin = millis();
    digitalWrite(LASER_PIN, message[idx]);
    transmitHold();
  }
}

void serialEvent() {
  c = Serial.read();
  //if (!isPrintable(c)) { return; }
  //Serial.write("Transmitting '");
  transmitByte( c );
  //if (isPrintable(c)) {
    Serial.write(c);
  //}
  //Serial.write("&gt;&gt;&gt; ");
}


void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(LASER_PIN, OUTPUT);
  transmit_begin = 0;
  c = '\0';
  Serial.begin(9600);
  Serial.write("\r\nReady to transmit!\r\n");
  Serial.write("\n&gt;&gt;&gt; ");

}

void loop() {
  
}

Receiver program

#define REF_PIN       24
#define SIG_PIN          23
#define LOGIC_1_CUTOFF      0
#define LASER_BAUDRATE      5
#define SIGNAL_HOLD_PERIOD  (1.0 / LASER_BAUDRATE) * 1000.0
#define START_BIT           1
#define STOP_BIT            0

int bit_val;
static unsigned char mask[] = {128, 64, 32, 16, 8, 4, 2, 1};
int buff[8] = {};
byte data = 0;
unsigned long receive_begin;
int bias = 0;
int bias_samp_size = 20;
int bias_samp_delay = 100;

void adjustSensorBias() {
  for (int i=0; i<bias_samp_size; i++) {
    bias += analogRead(SIG_PIN) - analogRead(REF_PIN);
    delay(bias_samp_delay);
  }
  bias /= bias_samp_size;
}

int sensorRead() {
  int val = analogRead(SIG_PIN) - analogRead(REF_PIN) - bias;
  Serial.write("sensorRead(): val = ");
  Serial.print(val);
  Serial.println();
  if (val < LOGIC_1_CUTOFF) { return 1; }
  return 0;
}

void poolBuffer() {
  int tmp = 0;
  for (int idx=0; idx<8; idx++) {
    tmp += buff[idx] * mask[idx];
  }
  data = (byte)tmp;
}

void receiveWait() {
  receive_begin = millis();
  while (millis() - receive_begin < SIGNAL_HOLD_PERIOD) {}
}

void laserRead() {
  receiveWait();
  for (int idx=0; idx<8; idx++) {
    buff[idx] = sensorRead();
    receiveWait();
  }
  if (sensorRead() != STOP_BIT) {
    receiveWait();
    receiveWait();
  }
}

void setup() {
  Serial.begin(9600);
  pinMode(REF_PIN, INPUT);
  pinMode(SIG_PIN, INPUT);
  pinMode(LED_BUILTIN, OUTPUT);
  adjustSensorBias();
}

void loop() {
  bit_val = sensorRead();

  //Serial.write("\r\nbit_val = ");
  //Serial.print(bit_val);
  //Serial.println();

  if (bit_val == START_BIT) {
    laserRead();
    poolBuffer();
    Serial.write("\r\ndata = ");
    Serial.write(data);
    Serial.println();
  }
}

Wireless Data Transmission – Big Picture

Wireless data transmission is achieved via optical means utilizing receiver and transmitter units. The transmitter unit consists of a laser diode and supporting power and switching circuit. The laser diode is supplied power from an Arduino. The 3.3V from the Arduino is voltage divided to near 3.0V to match with the laser diode specifications. The 3.0V is provided for the diode through a transistor, which also functions as a current switch controlled by software running on the Arduino. The circuit is used by the microcontroller to transmit binary data in the form of diode off (0) and diode on (1). The data is transmitted common asynchronous serial format (8N1). The receiver unit consists of photoresistors and an accompanying resistive circuit, arranged in a Wheatstone Bridge configuration. An Xplained Mini Board then uses both points ‘D’ and ‘B’ in the circuit to measure signal strength; one as a reference to ambient light, the other as a measure of ambient light plus signal light (i.e laser diode light). The Xplained Mini Board then decodes the bits received (8N1) and extracts the data bits, finally translating them back into ASCII characters that can be displayed via the serial terminal on the connected host device; TeraTerm in the case of this experiment

Simon Says Schematic

The Simon Says game was created using two breadboards, three LED’s of color green, blue, and red. It was wired using 300 ohm resistors and three push buttons were added to complete the circuit. Building the circuit was initially difficult as it was hard to determine a user-friendly circuit layout.  The final decision was to place the LEDs and buttons on the same row of the breadboard. Initially, the idea was to place the buttons underneath the corresponding LED, but the

Coin Sorter/Counter – Code

Main Arduino Code

#include<printing.h>                           //custom library
#include<LiquidCrystal.h>

LiquidCrystal lcd(12,13,8,9,10,11);            //sets pins for lcd
printing p();
#define SENSORPIN 2                            //dime
#define SENSORPIN2 3                           //nickel
#define SENSORPIN3 4                           //quarter

int sensorState = 0;
int lastState = 0;
int sensorState2 = 0;
int sensorState3 = 0;
int sum;                                                                             // keeps track of current money total
void setup() {      
  pinMode(SENSORPIN, INPUT);                  //initialize sensor as input 
  pinMode(SENSORPIN2, INPUT);                 //initialize sensor as input
  pinMode(SENSORPIN3, INPUT);                 //initialize sensor as input     
  digitalWrite(SENSORPIN, HIGH);              //set initial value for sensor as HIGH
  digitalWrite(SENSORPIN2, HIGH);             //set initial value for sensor as HIGH
  digitalWrite(SENSORPIN3, HIGH);             //set initial value for sensor as HIGH
  
  Serial.begin(9600);
}
 
void loop(){
  sensorState = digitalRead(SENSORPIN);        //reads sensor value
  sensorState2 = digitalRead(SENSORPIN2);      //reads sensor value
  sensorState3 = digitalRead(SENSORPIN3);      //reads sensor value
 
  if (sensorState == LOW) {                    //checks if sensor 1 beam is broken    
    delay(500);
    sum += 10;                                 //adds 10 to the current total
    displayLCD();
    p.printingDime();
 
  } 

   if (sensorState2 == LOW){                    //checks if sensor 2 beam is broken
    delay(500);
    sum += 5;                                   //adds 5 to current total
    displayLCD();
    p.printingNickel();
  }
  if(sensorState3 == LOW) {                     //checks if sensor 3 beam is broken
    delay(500);
    sum += 25;                                  //adds 25 to current total
    displayLCD();
    p.printingQuarter();
  }

  if (sensorState && !lastState) {
    Serial.println("Unbroken");
  } 
  if (!sensorState && lastState) {
    Serial.println("Broken");
  }
  lastState = sensorState;
}
void displayLCD(){                                                             //function to display total value
  lcd.clear();
  lcd.print("Total:");
  lcd.print(sum);
}

library.cpp – Our custom code library

#include "printing.h"
#inlcude "arduino.h"
#include <stdio.h>
printing::printing()
void printing::printingDime(){
	Serial.println("Break - Dime");
}
void printing::printingQuarter(){
	Serial.println("Break - Quarter");
}
void printing::printingNickel(){
	Serial.println("Break - Nickel");
}

library.h – Header file for our custom code library

#ifndef printing_h
#define printing_h

class printing
{
	public:
		printing();
		void printingDime();
		void printingQuarter();
		void printingNickel();
		
}

#endif

These are the three files we used to code the project, the first being the main Arduino file, the second being the custom library used in our main Arduino file, and lastly the header file used for the custom library. This code is responsible for detecting breaks in the IR break beams and adding to the count of the total amount in coins that has been sorted. The code for the IR breaks was mostly original with help from the Adafruit documentation/learning section specifically for the IR break beam sensors we used.

Coin Sorter/Counter – Schematic

The hardware we used for this project was an Arduino, Adafruit IR Break Beam Sensor, resistors, and a 16×2 LCD. Originally, we used IR LED lights and a simple IR sensor. This proved to be highly inaccurate and inconsistent. The Adafruit IR break beam sensor was exponentially more reliable and worked all the time. To figure out how to wire these components, we referenced the Arduino documentation. The documentation is extensive and extremely helpful for anything related to Arduino.