Lab3 - Laboratory For Experimental Computer Science
Lab3 - Laboratory For Experimental Computer Science
http://interface.khm.de/index.php/lab/experiments/theremin-as-a-capaci...
Laboratory for Experimental Computer Science at the Academy of Media Arts Cologne logoKHM Home / Lab / Experiments
Here we show a little Theremin module which plugs onto a Arduino Board that gives out the tune to a speaker or puts out the tune as control signal like MIDI, Servo etc. We were using this device not only as a musical instrument, various kinds of proximity sensors, pointing devices or as interface in combination with Processing, Max or Pd have been build with this technique.
How it Works
The Theremin Module itself is as little LC type Radio frequency oscillator which generates a radio wave and gives out the frequency signal to the Arduino board. An Antenna connected to the LC resonator provides the Theremin effect when a person or some conductive material is placed next to the antenna. This leads to a slight frequency deviation of the oscillator frequency which is registered by the Arduino software. The Arduino itself acts in this case as a accurate frequency meter which transforms this frequency deviation into sound or control signals. Since you will find numerous articles in the Web describing the principle of a Theremin we leave here only that brief description.
Video
1 sur 9
02/10/2012 11:18
http://interface.khm.de/index.php/lab/experiments/theremin-as-a-capaci...
The Oscillator
If you have a look at the Oscillator schematic you see the components L1 and C1 that are forming a resonator responsible for the oscillator frequency of about 4.1 Mhz. The Gates IC1A and IC1B are building an analog amplifier block which is rising the oscillator signal to be fed back to the resonator. Capacitor C3 put an amount of energy back to the input as positive feedback so that an steady oscillation occurs. The Gates D and C are conditioning the wave into a digital logic level squarewave signal for the Arduino board Care must be taken in the choice of the parts L1 and C1. C1 must be a ceramic capacitor NP0 type (zero temperature coefficient) and L1 a high Q inductor suitable for high frequency such as a Neosid 00612299 but for the first test a standard 10uH Choke will do also the job. Because the oscillator frequency tends to drift by ambient temperature changes the circuit should be capsuled in a little plastic box. The antenna length should be not longer than about one meter, good results can be obtained with a ring of 1,5mm steel wire which provides also a good mechanical stability to avoid swinging or vibration. Most of the drift or other unwanted side effects are compensated by the software. It must be noticed that also that all metal parts like usb cable, connected speaker, even the connected computer are loaded by the RF signal and tend to be hot so that they work as antenna as well.
2 sur 9
02/10/2012 11:18
http://interface.khm.de/index.php/lab/experiments/theremin-as-a-capaci...
The Software
To measure the oscillator frequency the output is connected to digitalinput 5 of the Arduino Board. This pin has an alternate function as an input of the ATMEGA internal hardware Counter1 unit. If configured by software, every time a level change is present on that pin the counter is advanced by one. That happens in our case about 4 million times a second. The hardware Timer2 unit is used as a timebase to start and stop counting in a interval of exactly 1/10 second. After that period the counter value reads about 410.000 so we yield a measurement resolution of 10Hz which is what we need to see the slight frequency deviation caused by the Theremin effect. Since the Counter1 unit is only a 16 Bit counter several overflows occur during the measurement. These overflows are counted in the timebase section to be assembled after the measurement period to a long int result. The whole timing is done in an interrupt function which is invoked by the timer2 all 2 milliseconds. If the end of a timebase period is reached a flag as a global variable is set to signal the main function the presence of a new value. Since only the frequency differences not the absolute value are of interest for us, the consecutive values are substracted from the first frequency value after startup. An autocalibration to eliminate long term frequency drift is performed after a number of measurement cylces when the deviation is smaller then a certain threshold value. The threshold value and the number of cycles to calibrate has to be customized to the application. Please refer to the ATMEL Atmega168 pdf to learn about the details of the timer and counter sections.
3 sur 9
02/10/2012 11:18
http://interface.khm.de/index.php/lab/experiments/theremin-as-a-capaci...
Source Code
/* * * * * * * Theremin Test Therremin with TTL Oscillator 4MHz Timer1 for freauency measurement Timer2 for gate time connect Oscillator on digital pin 5 connect Speaker with 1K Resistor in series on pin 8
4 sur 9
02/10/2012 11:18
http://interface.khm.de/index.php/lab/experiments/theremin-as-a-capaci...
* Academy of Media Arts Cologne */ #include <Stdio.h> #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) //! Macro that clears all Timer/Counter1 interrupt flags. #define CLEAR_ALL_TIMER1_INT_FLAGS (TIFR1 = TIFR1) int pinLed = 13; int pinFreq = 5; void setup() { pinMode(pinLed, OUTPUT); pinMode(pinFreq, INPUT); pinMode(8, OUTPUT); Serial.begin(57600); // LED connected to digital pin 13
// hardware counter setup ( refer atmega168.pdf chapter 16-bit counter1) TCCR1A=0; // reset timer/counter1 control register A TCCR1B=0; // reset timer/counter1 control register A TCNT1=0; // counter value = 0 // set timer/counter1 hardware as counter , counts events on pin T1 ( arduino pin 5) // normal mode, wgm10 .. wgm13 = 0 sbi (TCCR1B ,CS10); // External clock source on T1 pin. Clock on rising edge. sbi (TCCR1B ,CS11); sbi (TCCR1B ,CS12); // timer2 setup / is used for frequency measurement gatetime generation // timer 2 presaler set to 256 / timer 2 clock = 16Mhz / 256 = 62500 Hz cbi (TCCR2B ,CS20); sbi (TCCR2B ,CS21); sbi (TCCR2B ,CS22); //set timer2 to CTC Mode cbi (TCCR2A ,WGM20); sbi (TCCR2A ,WGM21); cbi (TCCR2B ,WGM22); OCR2A = 124; // interrupt control sbi (TIMSK2,OCIE2A); } volatile volatile volatile unsigned byte i_tics; byte f_ready ; byte mlt ; int ww; // enable Timer2 Interrupt
int cal; int cal_max; char long long long st1[32]; freq_in; freq_zero; freq_cal;
5 sur 9
02/10/2012 11:18
http://interface.khm.de/index.php/lab/experiments/theremin-as-a-capaci...
tune=tune+1; while (f_ready==0) { // wait for period length end (100ms) by interrupt PORTB=((dds+=tune) >> 15); // kind of DDS tonegenerator / connect speaker to portb.0 = ar } tune = freq_in-freq_zero; // use the tune value here for your own purposes like control of servos, midi etc. // startup if (cnt==10) { freq_zero=freq_in; freq_cal=freq_in; cal_max=0; Serial.print("** START **"); } // autocalibration if (cnt % 20 == 0) { // try autocalibrate after n cycles Serial.print("*"); if (cal_max <= 2) { freq_zero=freq_in; Serial.print(" calibration"); } freq_cal=freq_in; cal_max=0; Serial.println(""); } cal = freq_in-freq_cal; if ( cal < 0) cal*=-1; // absolute value if (cal > cal_max) cal_max=cal; digitalWrite(pinLed,1); Serial.print(cnt); Serial.print(" "); // let LED blink
if ( tune < 0) tune*=-1; // absolute value sprintf(st1, " %04d",tune); Serial.print(st1); Serial.print(" "); Serial.print(freq_in); Serial.print(" "); /* Serial.print(freq_zero); Serial.print(" "); Serial.print(cal_max); */ Serial.println(""); digitalWrite(pinLed,0); } //****************************************************************** void f_meter_start() { f_ready=0; // reset period measure flag i_tics=0; // reset interrupt counter sbi (GTCCR,PSRASY); // reset presacler counting TCNT2=0; // timer2=0 TCNT1=0; // Counter1 = 0 cbi (TIMSK0,TOIE0); // dissable Timer0 again // millis and delay sbi (TIMSK2,OCIE2A); // enable Timer2 Interrupt TCCR1B = TCCR1B | 7; // Counter Clock source = pin T1 , start counting now } //****************************************************************** // Timer2 Interrupt Service is invoked by hardware Timer2 every 2ms = 500 Hz
6 sur 9
02/10/2012 11:18
http://interface.khm.de/index.php/lab/experiments/theremin-as-a-capaci...
// 16Mhz / 256 / 125 / 500 Hz // here the gatetime generation for freq. measurement takes place: ISR(TIMER2_COMPA_vect) { if (i_tics==50) { TCCR1B = TCCR1B & ~7; cbi (TIMSK2,OCIE2A); sbi (TIMSK0,TOIE0); f_ready=1; // // // // // // multiple 2ms = gate time = 100 ms end of gate time, measurement ready Gate Off / Counter T1 stopped disable Timer2 Interrupt ensable Timer0 again // millis and delay set global flag for end count period
freq_in=0x10000 * mlt; freq_in += TCNT1; mlt=0; } i_tics++; if (TIFR1 & 1) { mlt++; sbi(TIFR1,TOV1); } }
// calculate now frequeny value // mukt #ovverflows by 65636 // add counter1 value
// // // //
count number of interrupt events if Timer/Counter 1 overflow flag count number of Counter1 overflows clear Timer/Counter 1 overflow flag
Files
theremin.zip
Links
http://www.schuelke.org http://www.freyahattenberger.de/works%20leasstsich2.html http://netzspannung.org/cat/servlet/CatServlet?cmd=netzkollektor&subCommand=showEntry&forward=& entryId=87369&version=print&print=all&lang=de http://www.khm.de/en/project/paview/2446/paitems/60/pasearch/theremin/ http://www.khm.de/en/project/paview/1376/ http://www.khm.de/~alfred/state/photos.html http://mars.imk.fraunhofer.de/imk_web-pre2000/images/mars/files/graphicon99.pdf
7 sur 9
02/10/2012 11:18
http://interface.khm.de/index.php/lab/experiments/theremin-as-a-capaci...
Forum
further questions to this topic can be discussed here: http://arduino.cc/forum/index.php/topic,65991.0.html
Contact
Martin Nawrath, [email protected]
Lab3, Academy of Media Arts Cologne, Peter-Welter-Platz 2 50676 Cologne, Imprint Lab Log Art Projects Events Awards Lab Experiments SensorAktor-Shield SensorAktor-Basics Teaching Seminars Guest Lectures
8 sur 9
02/10/2012 11:18
http://interface.khm.de/index.php/lab/experiments/theremin-as-a-capaci...
People Staff Doctoral Candidates Alumni Publications Books Articles Lectures Past Research Galleries Contact
RSS-Feed
9 sur 9
02/10/2012 11:18