How often do you get to see water defying gravity, which is outside the constraints of time and space? Not very often except in movies, but this cool levitating water display actually makes drops of water move up and down so slow that our eyes are able to watch them clearly!
This display is actually an optical illusion, as perfectly tuned strobe lights flashes at the water streams at specific frame rates similar to that of a projector to trick the human brain into thinking the water drops are actually moving up and down.
internally lit acrylic :
this thing is crossing from analog to digital... watch it go.
here is the code:
/*
* tones and buttons and a pot
*
*/
// lib to generate frequencies on any arduino digital pin
#include <TimerOne.h>
// pins defined
//
int tonePin = 9;
int ledPin = 13;
int buttonInPin[] = {4, 5, 6};
int buttonOutPin[] = {7, 8, 9};
boolean DEBUG = false;
//
// tone vars defined
//
//globals
int tones[] = {59, 60, 61};
int toneCount = 3;
int toneDuration = 1000; //ms
int toneDutyCycle = 72;
//
// button vars
//
//globals
int buttonCount = 3;
long debounceThreshold = 50; //ms
//loop vars
int state[] = {0, 0, 0};
int reading[] = {0, 0, 0};
long lastReading[] = {0, 0, 0}; //ms
// do this once
void setup () {
if (DEBUG) Serial.begin(9600);
for (int i = 0; i<buttonCount; i++) {
pinMode(buttonInPin[i], INPUT);
pinMode(buttonOutPin[i], OUTPUT);
digitalWrite(buttonOutPin[i], HIGH);
}
pinMode(tonePin, OUTPUT);
pinMode(ledPin, OUTPUT);
Timer1.initialize(calcPeriod(tones[1])); // initialize timer1, and set a 1/2 second period
Timer1.pwm(tonePin, toneDutyCycle); // setup pwm on pin 9, 50% duty cycle
Timer1.attachInterrupt(callback); // attaches callback() as a timer overflow interrupt
return;
}
void callback()
{
digitalWrite(ledPin, digitalRead(ledPin) ^ 1);
}
// do this everytime
void loop() {
readButtons();
writeButtons();
saveReadings();
return;
}
//do this to read inputs into globals
void readButtons() {
for (int i = 0; i<buttonCount; i++) {
reading[i] = digitalRead(buttonInPin[i]);
if (reading[i] != state[i]) {
// reset the debouncing timer
lastReading[i] = millis();
}
if ((millis() - lastReading[i]) > debounceThreshold) {
state[i] = reading[i];
if (state[i]) {
setTone(tones[i % toneCount]);
if (DEBUG) Serial.print("switching to ");
if (DEBUG) Serial.println(tones[i % toneCount]);
}
}
} // end button loop
return;
}
// do this to react to latest settings
void writeButtons() {
for (int i = 0; i<buttonCount; i++) {
digitalWrite(buttonOutPin[i], state[i]);
}
return;
}
// save state for next loop
void saveReadings() {
for (int i = 0; i<buttonCount; i++) {
// save the reading. Next time through the loop,
// it'll be the lastButtonState:
state[i] = reading[i];
}
return;
}
// calculates new tone period in micro seconds
// hardcoded to use A0 for fudge factor
int calcPeriod(int freq) {
int absolute = 1000002 / freq;
int reading = analogRead(A0) - 512;
return absolute - reading;
}
void setTone(int freq) {
Timer1.pwm(tonePin, toneDutyCycle, calcPeriod(freq));
return;
}
Comments (0)
You don't have permission to comment on this page.