Last active
August 29, 2015 14:01
-
-
Save mplewis/cdf8346e62a06959ce9e to your computer and use it in GitHub Desktop.
Analog proximity sensor array scanner code. EE 4951W, Spring 2014, Group 10: Optical Guitar
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Analog proximity sensor array scanner code | |
* | |
* EE 4951W Spring 2014 | |
* Group 10: Optical Guitar | |
* Advisor: Dr. James Leger | |
* Group members: Sandra Arnold, Justin Buth, Matthew Lewis, Steffen Moeller, Anh Nguyen | |
* | |
* Target device: Teensy 2.0 | |
* Program Teensy 2.0 with this sketch using Arduino software | |
*/ | |
/* This code is licensed under The MIT License (MIT). | |
* | |
* Copyright (c) 2014 Sandra Arnold, Justin Buth, Matthew Lewis, Steffen Moeller, Anh Nguyen | |
* | |
* Permission is hereby granted, free of charge, to any person obtaining a copy | |
* of this software and associated documentation files (the "Software"), to deal | |
* in the Software without restriction, including without limitation the rights | |
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
* copies of the Software, and to permit persons to whom the Software is | |
* furnished to do so, subject to the following conditions: | |
* | |
* The above copyright notice and this permission notice shall be included in | |
* all copies or substantial portions of the Software. | |
* | |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
* THE SOFTWARE. | |
*/ | |
#define SENSOR_THRESHOLD_ON 200 | |
#define SENSOR_THRESHOLD_OFF 175 | |
#define PIN_BTN_1 8 | |
#define PIN_BTN_2 9 | |
#define PIN_LR_SW 10 | |
#define PIN_DEBOUNCE_MS 5 | |
#define SERIAL_TERMINATOR 0xFF | |
#include "Bounce.h" | |
bool string1[18] = {0}; | |
bool string2[18] = {0}; | |
bool btn1latch = false; | |
bool btn2latch = false; | |
// Debounce the strum buttons using the debounce library included with Teensy | |
// See http://www.pjrc.com/teensy/td_libs_Bounce.html for more information | |
Bounce db1 = Bounce(PIN_BTN_1, PIN_DEBOUNCE_MS); | |
Bounce db2 = Bounce(PIN_BTN_2, PIN_DEBOUNCE_MS); | |
int last_note_1 = 255; | |
int last_note_2 = 255; | |
void setup() { | |
// Set digital IO pins 2 through 7 to output mode and turn them off | |
for (int pin = 2; pin <= 7; pin++) { | |
pinMode(pin, OUTPUT); | |
digitalWrite(pin, 0); | |
} | |
// Set up pins for string 1 and 2 strum buttons and lefty-righty switch | |
pinMode(PIN_BTN_1, INPUT_PULLUP); | |
pinMode(PIN_BTN_2, INPUT_PULLUP); | |
pinMode(PIN_LR_SW, INPUT_PULLUP); | |
// Set up LED pin for visible heartbeat | |
pinMode(11, OUTPUT); | |
// Start serial output so we can print sensor values to USB | |
Serial.begin(9600); | |
} | |
/* Send a serial strum or lift command to the Raspberry Pi. | |
* | |
* bool is_strum: true if strum command, false if fret release command | |
* byte string: 0x01 for string 1, 0x02 for string 2 | |
* byte fret_index: 0 means no fret pressed, 1 is nearest the neck, 18 is | |
* nearest the body | |
* | |
* Lift commands are the same as strum commands, but with the MSB of the | |
* first byte set high. | |
* | |
* A strum command for string 2, fret 9 is as follows: {0x02, 0x09, 0xFF} | |
* A lift command for string 1, fret 15 is as follows: {0x81, 0x0F, 0xFF} | |
*/ | |
void send_command(bool is_strum, byte string, byte fret_index) { | |
if(digitalRead(PIN_LR_SW)) { | |
// 2 -> 1, 1 -> 2 | |
string = 3 - string; | |
} | |
if (!is_strum) { | |
if ((string == 1 && fret_index == last_note_1) || (string == 2 && fret_index == last_note_2)) { | |
string = string + 0x80; | |
} else { | |
return; // Don't send a note off command if the fret being lifted | |
// isn't the same as the last fret played | |
} | |
} else { | |
if (string == 1) { | |
last_note_1 = fret_index; | |
} else { | |
last_note_2 = fret_index; | |
} | |
} | |
Serial.write(string); | |
Serial.write(fret_index); | |
Serial.write(SERIAL_TERMINATOR); | |
} | |
// Read all analog sensors and record their values into the fret arrays string1 and string2 | |
void read_all_sensors() { | |
for (int out = 2; out <= 7; out++) { | |
// Show a visible heartbeat on the LED | |
if (out == 2) { | |
digitalWrite(11, HIGH); | |
} else { | |
digitalWrite(11, LOW); | |
} | |
// Turn on each digital IO pin 2-7, one at a time (active-low) | |
digitalWrite(out, 0); | |
delayMicroseconds(50); | |
// Poll each analog input 0-5 while a single digital IO is on | |
for (int in = 0; in <= 5; in++) { | |
// Read the value from input analog pin in | |
int val = analogRead(in); | |
// index represents the fret number on the physical fretboard | |
byte index; | |
if (out <= 4) { // string 1 | |
index = in * 3 + (out - 2); | |
if (string1[index] == false) { // Sensor is OFF; look for ON threshold | |
if (val >= SENSOR_THRESHOLD_ON) { | |
string1[index] = true; | |
} | |
} else { // Sensor is ON; look for OFF threshold | |
if (val <= SENSOR_THRESHOLD_OFF) { | |
string1[index] = false; | |
send_command(false, 1, index + 1); | |
} | |
} | |
} else { // string 2 | |
index = in * 3 + (out - 5); | |
if (string2[index] == false) { // Sensor is OFF; look for ON threshold | |
if (val >= SENSOR_THRESHOLD_ON) { | |
string2[index] = true; | |
} | |
} else { // Sensor is ON; look for OFF threshold | |
if (val <= SENSOR_THRESHOLD_OFF) { | |
string2[index] = false; | |
send_command(false, 2, index + 1); | |
} | |
} | |
} | |
} | |
// Turn off digital IO (active-low) | |
digitalWrite(out, 1); | |
} | |
} | |
// Handle strum buttons and send serial commands on button presses | |
void handle_strum_buttons() { | |
bool sensor_pressed; | |
if (db1.update() && db1.fallingEdge()) { // String 1 button is grounded; button pressed | |
// Latching button; don't send a new-note command constantly while the button is down | |
if (!btn1latch) { | |
btn1latch = true; | |
sensor_pressed = false; | |
// Read the frets from highest (nearest the body) to lowest (nearest the neck). | |
// High frets take priority over lower ones, just like in a stringed guitar. | |
for (int index = 17; index >= 0; index--) { | |
if (string1[index] == true) { | |
send_command(true, 1, index + 1); | |
sensor_pressed = true; | |
break; | |
} | |
} | |
if (!sensor_pressed) { | |
send_command(true, 1, 0); // if no string was pressed, the fret index is 0 | |
} | |
} | |
} else { | |
btn1latch = false; | |
} | |
if (db2.update() && db2.fallingEdge()) { | |
if (!btn2latch) { | |
btn2latch = true; | |
sensor_pressed = false; | |
for (int index = 17; index >= 0; index--) { | |
if (string2[index] == true) { | |
send_command(true, 2, index + 1); | |
sensor_pressed = true; | |
break; | |
} | |
} | |
if (!sensor_pressed) { | |
send_command(true, 2, 0); | |
} | |
} | |
} else { | |
btn2latch = false; | |
} | |
} | |
void loop() { | |
read_all_sensors(); | |
handle_strum_buttons(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment