| META TOPICPARENT |
name="WebHome" |
LEGO Optical Theremin
It should be pretty straightforward to use one or more light sensors with a LEGO Mindstorms controller to build a theremin.
Someone did it with an Arduino, for example.
here's the link:
http://www.instructables.com/id/Arduino-Optical-Theremin/?ALLSTEPS
here's the code:
// Optical Theramin
//pin definitions
#define PHONES 9 // headphones connected to digital pin 9
#define PHOTOCELL 0 //photocell analog in pin 0
//variable definitions
long val = 0; //stores raw value from photocell
long maxread = 0; //maximum value from calibration phase
long minread = 1000; // minimum value from calibration phase
double f = 0; // frequency of sound
double normf = 0; // normalized frequency
double logf = 0; // logarithm of normalized frequency
int ilogf = 0; // rounded logarithm
int i = 0; // loop dummy variable
double factor = 0; // scaling factor for calibration
double shift = 0; // shift for calibration
long maxfreq = 1048; // maximum desired frequency after calibration
long minfreq = 131; // minimum desired frequency after calibration
//magic numbers that make the intervals sound pleasing
double gap = 1.148698355; //ratio of consecutive notes (pentatonic)
// it's the 5th root of 2
//double gap = 1.059463094; //ratio of consecutive notes (chromatic)
// its the 12th root of 2
void setup()
{
pinMode(PHONES, OUTPUT); // sets the digital pin as output
// calibration loop to determine a rasonable range of light levels (minread to maxread)
// and map that to frequencies between minfreq and maxfreq
for (i = 0; i< 500; i++) { // calibration loop runs for 5 seconds
val = analogRead(PHOTOCELL); // read photocell
tone(PHONES, val); // play raw tone to guide calibration
if (val > maxread) { // as the values climb, store the largest
maxread = val;
}
if (val < minread) { // as the values drop, store the smallest
minread = val;
}
delay(10); // reasonable delay
}
//Now we use the calibration to calculate scale and shift parameters
factor = (double)(maxfreq - minfreq) / (double)(maxread - minread); // scale parameter
//it's like a slope
shift = factor * minread - minfreq; //shift parameter: it's like an offset
}
void loop()
{
val = analogRead(PHOTOCELL); // read photocell
f = factor * val - shift; // this linearly maps the frequency to
// a value between minfreq and maxfreq
// according to the calibration result
normf = f / (double) minfreq; // Dividing an exponential function by the min value
logf = log(normf) / log(gap); // allows us to take the log (base gap) and the result
ilogf = round(logf); // is the number of notes above the lowest, once we round it.
f = minfreq * pow(gap,ilogf); // we better "unlog" it.
tone(PHONES, f); // this produces the tone signal
}
\ No newline at end of file |