CSC270 Team 5 project 2019

From CSclasswiki
Jump to: navigation, search

Stacy Falaleeva, Joce Kofke, and Jessie Wang

Sound-Activated Stopwatch

Finalproject.jpg
Video Demonstration

Introduction

For our project, we created a stopwatch activated by the sound of a clap. It starts, stops, and resets with each clap.

Implementation

Software

Languages

We used C on both the Arduino and the Raspberry Pi.

Libraries

Hardware

  • RaspberryPi 3
  • Arduino Mega2560 : Manual
  • LED Numeric Display, 4 Digit (BL-Q39X-42) : Manual
  • Arduino KY-037 Sensitive Microphone Sensor Module : Manual

Plan

Process

DISCLAIMER: The code in this section is messy and undocumented. It was in-process code to help us form our finalized code, and is attached here to show the process and building blocks that make up the final result. The important sections were incorporated into our final code, and are explained there.

1. Sound Sensor
We began by testing the usability of the sound sensor. We hooked it up to the Arduino and flashed an LED when a clap was registered. This also allowed us to adjust the sensitivity of the sound sensor. We ran into the problem of bouncing of the signal, which we fixed by simply adding a short delay.
2. Stopwatch
We then moved on to programming the stopwatch on the Raspberry Pi, which displayed in the terminal. Despite initial trial and error, we eventually used a finite state machine to switch between the three states of running, stopped, and reset.
3. Display
For the display, we used the Sevseg library. We confirmed that it was wired properly and would display a given number.
4. Combination
This final step resulted in our final product. There were many, many issues with this step, especially with communication between the RPi and the Arduino, and the display not working properly because the refreshing of the display only occurred when the serial connection was available, but in the end we got to the final code.

Final Code

Arduino

/* Arduino Loop
 * Joce Kofke, Stacy Falaleeva, Jessie Wang
 * May 2019
 * 
 * Displays data received from Raspberry Pi stopwatch.c
 * on a 4 digit 7 segment LED display
 * 
 */

#include <SevSeg.h> // library for digit display
SevSeg sevseg; 

int incomingByte = 0;

// setup code, runs once
void setup() {
  Serial.begin(9600); // begins communication with the RPI at a baud rate of 9600 bps

  // -- SevSeg setup START -- 
  // mostly taken from reference

  byte numDigits = 4;
  byte digitPins[] = {10, 11, 12, 13};
  byte segmentPins[] = {9, 2, 3, 5, 6, 8, 7, 4};

  bool resistorsOnSegments = true; 
  bool updateWithDelaysIn = true;
  byte hardwareConfig = COMMON_CATHODE; 
  sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments);

  // -- END --

}

// main code, runs repeatedly
void loop() {

  sevseg.refreshDisplay(); // refreshes display constantly

  if (Serial.available()){
    incomingByte = Serial.read(); // reads the byte sent from RPI
    Serial.println(incomingByte, DEC); // displays the data in the Serial Monitor
    sevseg.setNumber(incomingByte); // sends the data to the display
  }

}

RaspberryPi

/* Stopwatch
 * May 2019
 * Joce Kofke, Stacy Falaleeva, Jessie Wang
 * 
 * Runs a stopwatch on the Raspberry Pi
 * based on state determined by sound sensor
 * and sends the value to the Arduino
 * 
 * to run:
 * gcc -o stopwatch stopwatch.c -lwiringpi
 * ./stopwatch
 */

#include <wiringPi.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <wiringSerial.h>

int buttonpin = 1; // the pin of the sound sensor
int state = 0; // the current state of the stopwatch ( 0 = reset, 1 = start, 2 = stop )
int clap; // reads the sound sensor
int lastClap = 0; // stores what the previous reading of the sound sensor was
int lastSec = 0, currSec = 0; // keeps track of whether a second has passed
clock_t start, end; // monitors time elapsed through the processor
int serial_port; // the serial port for communication with the Arduino
char send[5]; // the byte sent to the Arduino
int idea; // keeps track of whether "0" has been sent to the Arduino on reset

// state 2 - stops the stopwatch
void stop(){
  return;
}

// setup - runs once
void setup(){
  wiringPiSetup();
  pinMode(buttonpin, INPUT); // sets buttonpin to receive input from sound sensor
  pullUpDnControl(buttonpin, PUD_UP);
  serial_port = serialOpen("/dev/arduino", 9600); // opens serial connection with arduino, sets baud rate to 9600bps
}

// main code - runs repeatedly
void loop(){

  clap = digitalRead(buttonpin); // reads value of sound sensor - 0 if silent, 1 if clap heard

  // if the clap has finished
  if (clap == LOW && lastClap == HIGH){
    delay(250); // debouncing
    state = (state + 1) % 3; // changes state
    if (state == 1){ // if the new state is start state
      start = clock(); // sets "start" to the current processor clock value
    }
    else if(state == 0){ // if the new state is the reset state
      printf("READY\n"); // prints READY (debugging)
    }
  }

  if (state == 1){ // if the state is currently 1
    end = clock(); // sets "end" to the current processor clock value
    currSec = ((int)(end-start))/CLOCKS_PER_SEC; // finds time elapsed and divides by the number of processor ticks 
    											 // per sec to get number of seconds elapsed

    //only sends something to Arduino when second changes
    if (lastSec != currSec){
      printf("%d\n", currSec);  // debugging
      char c = (char) currSec; // changing currSec from int to char
      printf("Sending this to Arduino: ", c, "\n"); // debugging
      serialPutchar(serial_port, c); // sends c to the arduino
      idea = 0; // resets the reset check value

    }
    lastSec = currSec; // sets the current second to the last second for next loop iteration
  }

  else if (state == 2){ // if the state is currently 2
    stop(); // stop the stopwatch
  }

  else if (state == 0){ // if the state is currently 0
    if (idea == 0){ // if the reset check value is currently zero
     int zero = 0;
     char z = (int) zero;
     serialPutchar(serial_port, z); // sends "0" to the Arduino
     idea = 1; // makes sure "0" is only sent once
    }
  }

  else{ // just in case
  }

  lastClap = clap; // sets current clap value to lastClap for next loop iteration
}

// runs when program is run
int main(int argc, char *argv[]){
  printf("hello\n"); // debugging
  setup();
  printf("there\n"); // debugging
  while(1){ // loops forever
    loop();
  }
  return 0; // will never be reached
}

Debugging code was left in for reference

Additional Code

Persistent Name for Serial Port

Step by Step

Running on Boot

In the file /etc/rc.local we added

/home/pi/stopwatch &

directly above the exit 0 at the end of the file. The ampersand forks the process, allowing the Pi to finish booting despite our code looping constantly.

Resources

Installing the Arduino IDE on the Raspberry Pi

Persistent Names for USB-Serial Devices

Running on Boot

Tutorial on sprintf

Installing wiringPi