Created
March 6, 2015 20:49
-
-
Save jtwalters/24dbe230a91484deef2a to your computer and use it in GitHub Desktop.
A little Arduino-based project that sounds like a Theremin. Uses a distance sensor for one hand and a pushbutton for the other.
This file contains 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
// #define EVENTMANAGER_EVENT_QUEUE_SIZE 20 | |
// #define EVENTMANAGER_LISTENER_LIST_SIZE 10 | |
// #include <EventManager.h> | |
#include <Event.h> | |
#include <Timer.h> | |
#include <Wire.h> | |
#include <Adafruit_GFX.h> | |
#include <Adafruit_LEDBackpack.h> | |
#include <RunningAverage.h> | |
#include <CapacitivePin.h> | |
// C Major notes | |
word freqs[24] = {1047, 1109, 1175, 1245, 1319, 1397, 1480, 1568, 1661, 1760, 1865, 1976, 2093, 2217, 2349, 2489, 2637, 2794, 2960, 3136, 3322, 3520, 3729, 3951}; | |
float pi = 3.14159265359; | |
float vibratoRadians = -pi; | |
float vibratoValue = 0; | |
Adafruit_24bargraph bar = Adafruit_24bargraph(); | |
RunningAverage runningAverage1(5); | |
RunningAverage runningAverage2(5); | |
word average1 = 0; | |
word average2 = 0; | |
word distPin = A1; | |
word ledPin = 10; | |
word touchPin = A0; | |
word speakerPin = 9; | |
byte tickEvent = 0; | |
// EventManager eventManager(EventManager::kNotInterruptSafe); | |
Timer t; | |
bool isPressed = false; | |
byte ledState = LOW; | |
word ledBrightness = 255; | |
word distValue = 0; | |
void setup() { | |
Serial.begin(9600); | |
pinMode(ledPin, OUTPUT); | |
pinMode(distPin, INPUT); | |
bar.begin(0x70); | |
for (byte b = 0; b < 24; b++) { | |
bar.setBar(b, LED_YELLOW); | |
} | |
bar.writeDisplay(); | |
delay(500); | |
bar.setBrightness(10); | |
tickEvent = t.every(10, tick, (void*)0); | |
} | |
float getVibrato(float scale) { | |
vibratoRadians += 0.33; | |
if (vibratoRadians > pi) { | |
vibratoRadians = -pi; | |
} | |
return scale * sin(vibratoRadians); | |
} | |
void setBarPercentage(byte value) { | |
value = constrain(value, 0, 100); | |
value = map(value, 0, 100, 0, 24); | |
for (byte b = 0; b < 24; b++) { | |
bar.setBar(b, b < value ? LED_GREEN : LED_OFF); | |
} | |
bar.writeDisplay(); | |
} | |
void readButton() { | |
byte value = readCapacitivePin(touchPin); | |
// isPressed = digitalRead(buttonPin) == LOW; // Inverse (INPUT_PULLUP) | |
isPressed = value > 1; | |
Serial.println(value); | |
} | |
float updateDist() { | |
distValue = map(analogRead(distPin), 0, 1023, 0, 5500); | |
if (distValue < 500) { | |
distValue = 0; | |
} | |
else if (distValue > 3000) { | |
distValue = 3000; | |
} | |
} | |
void distToTone() { | |
// byte index; | |
word freq; | |
// Serial.println(distValue); | |
if (average2 >= 500 && isPressed) { | |
// index = map(average2, 500, 3000, 0, sizeof(freqs) / sizeof(word) - 1); | |
// tone(speakerPin, freqs[index] + getVibrato(freqs[index] / 500)); | |
freq = map(average2, 500, 3000, 220, 1047); | |
tone(speakerPin, freq + getVibrato(freq / 100)); | |
} | |
else { | |
noTone(speakerPin); | |
} | |
} | |
void updateDisplay() { | |
word value = 0; | |
if (average1 >= 500) { | |
value = map(average1, 500, 3000, 0, 100); | |
} | |
else { | |
value = 0; | |
} | |
setBarPercentage(value); | |
analogWrite(ledPin, floor(value * 2.55)); | |
} | |
void loop() { | |
// Update timer. | |
t.update(); | |
// Handle any events that are in the queue. | |
// eventManager.processEvent(); | |
} | |
void tick(void* context) { | |
updateDist(); | |
// Calculate running averages. | |
runningAverage1.addValue(distValue); | |
average1 = runningAverage1.getAverage(); | |
runningAverage2.addValue(average1); | |
average2 = runningAverage2.getAverage(); | |
distToTone(); | |
updateDisplay(); | |
readButton(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment