The Stressed Out College Student

This project is a representation of the state of a stressed out college student, say during midterms or finals. If you touch it, this is what happens:

Here is a picture of the internals:

It is basically an Arduino with an mp3 shield controlling the speaker, reading from an SD card, and a motor shield stacked on top of it to control the motor. The motor shield was needed in order to change the direction of rotation of the motor in order to produce the ‘shaking’ effect. And out of the motor shield is a wire sticking out and taped to the box in order to measure capacitance, which is how I’m detecting touch.

Here’s the code:

#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include <SPI.h>
#include <Adafruit_VS1053.h>
#include <SD.h>
#include "pins_arduino.h"

// These are the pins used for the music maker shield
#define SHIELD_RESET  -1      // VS1053 reset pin (unused!)
#define SHIELD_CS     7      // VS1053 chip select pin (output)
#define SHIELD_DCS    6      // VS1053 Data/command select pin (output)
#define CARDCS 4     // Card chip select pin
#define DREQ 3       // VS1053 Data request, ideally an Interrupt pin

// initialize mp3 shield
Adafruit_VS1053_FilePlayer musicPlayer = Adafruit_VS1053_FilePlayer(SHIELD_RESET, SHIELD_CS, SHIELD_DCS, DREQ, CARDCS);

// initialize motor shield
Adafruit_MotorShield AFMS = Adafruit_MotorShield(0x60);
Adafruit_DCMotor *wheels = AFMS.getMotor(2);

int delayval = 100;
const int touchPin = A1;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  AFMS.begin();
  //  wheels->setSpeed(255);
  //  wheels->run(FORWARD);
  //  wheels->run(RELEASE);
  if (! musicPlayer.begin()) { // initialise the music player
    Serial.println(F("Couldn't find VS1053, do you have the right pins defined?"));
    while (1);
  }
  Serial.println(F("VS1053 found"));
  if (!SD.begin(CARDCS)) {
    Serial.println(F("SD failed, or not present"));
    while (1);  // don't do anything more
  }
  musicPlayer.setVolume(1, 1);
  musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT);
  //  Serial.println("playing music");
  //  musicPlayer.playFullFile("track001.mp3");
  //  printDirectory(SD.open("/"), 0);
}


void loop() {
  int capacitance = readCapacitivePin(touchPin);
  Serial.println(capacitance);
  if (capacitance > 5) {
    if (!musicPlayer.playingMusic) {
      musicPlayer.startPlayingFile("scream.mp3");
    }
    wheels->run(FORWARD);
    wheels->setSpeed(255);
    delay(delayval);
    wheels->run(BACKWARD);
    wheels->setSpeed(255);
    delay(delayval);
    wheels->run(FORWARD);
    wheels->setSpeed(255);
    delay(delayval);
    wheels->run(BACKWARD);
    wheels->setSpeed(255);
    delay(delayval);
    wheels->run(FORWARD);
    wheels->setSpeed(255);
    delay(delayval);
    wheels->run(BACKWARD);
    wheels->setSpeed(255);
    delay(delayval);
  } else {
    wheels->run(RELEASE);
  }
  delay(1);
}

uint8_t readCapacitivePin(int pinToMeasure) {
  // Variables used to translate from Arduino to AVR pin naming
  volatile uint8_t* port;
  volatile uint8_t* ddr;
  volatile uint8_t* pin;
  // Here we translate the input pin number from
  //  Arduino pin number to the AVR PORT, PIN, DDR,
  //  and which bit of those registers we care about.
  byte bitmask;
  port = portOutputRegister(digitalPinToPort(pinToMeasure));
  ddr = portModeRegister(digitalPinToPort(pinToMeasure));
  bitmask = digitalPinToBitMask(pinToMeasure);
  pin = portInputRegister(digitalPinToPort(pinToMeasure));
  // Discharge the pin first by setting it low and output
  *port &= ~(bitmask);
  *ddr  |= bitmask;
  delay(1);
  uint8_t SREG_old = SREG; //back up the AVR Status Register
  // Prevent the timer IRQ from disturbing our measurement
  noInterrupts();
  // Make the pin an input with the internal pull-up on
  *ddr &= ~(bitmask);
  *port |= bitmask;

  // Now see how long the pin to get pulled up. This manual unrolling of the loop
  // decreases the number of hardware cycles between each read of the pin,
  // thus increasing sensitivity.
  uint8_t cycles = 17;
  if (*pin & bitmask) {
    cycles =  0;
  }
  else if (*pin & bitmask) {
    cycles =  1;
  }
  else if (*pin & bitmask) {
    cycles =  2;
  }
  else if (*pin & bitmask) {
    cycles =  3;
  }
  else if (*pin & bitmask) {
    cycles =  4;
  }
  else if (*pin & bitmask) {
    cycles =  5;
  }
  else if (*pin & bitmask) {
    cycles =  6;
  }
  else if (*pin & bitmask) {
    cycles =  7;
  }
  else if (*pin & bitmask) {
    cycles =  8;
  }
  else if (*pin & bitmask) {
    cycles =  9;
  }
  else if (*pin & bitmask) {
    cycles = 10;
  }
  else if (*pin & bitmask) {
    cycles = 11;
  }
  else if (*pin & bitmask) {
    cycles = 12;
  }
  else if (*pin & bitmask) {
    cycles = 13;
  }
  else if (*pin & bitmask) {
    cycles = 14;
  }
  else if (*pin & bitmask) {
    cycles = 15;
  }
  else if (*pin & bitmask) {
    cycles = 16;
  }

  // End of timing-critical section; turn interrupts back on if they were on before, or leave them off if they were off before
  SREG = SREG_old;

  // Discharge the pin again by setting it low and output
  //  It's important to leave the pins low if you want to
  //  be able to touch more than 1 sensor at a time - if
  //  the sensor is left pulled high, when you touch
  //  two sensors, your body will transfer the charge between
  //  sensors.
  *port &= ~(bitmask);
  *ddr  |= bitmask;

  return cycles;
}

 

Leave a Reply

Your email address will not be published. Required fields are marked *