Welcome, Guest
Username: Password: Remember me

TOPIC: Theremin with Arduino DUE and pedalSHIELD

Theremin with Arduino DUE and pedalSHIELD 4 years 5 months ago #307

  • Ray
  • Ray's Avatar
  • NOW ONLINE
  • Moderator
  • Posts: 695
  • Thank you received: 146
  • Karma: 41
I have coded a simple Theremin using pedalSHIELD and an IR detector: the Sharp GP2y0a21yk.

IMG_5984.jpg


IMG_5980.jpg



The GP2y0a21yk can detect objects in a range of 0 - 80cm.

The code is very simple; it is based in the simple sinewave generator with some small modifications to modulate the frequency of the signal following the distance detected by the IR distance detector.

Hardware: The Sharp GP2y0a21yk needs +5V, GND and the output to be connected to an ADC (using pin A11 or Arduino DUE). The wires are directly connected to the PCB pins for simplicity as you can see in the Image below:

IMG_5981.jpg



This is the code:
// Licensed under a Creative Commons Attribution 3.0 Unported License.
// Based on rcarduino.blogspot.com previous work.
// www.electrosmash.com/pedalshield
 
// sinewave.ino program creates a sinusoidal waveform adjustable in amplitude and frequency.
// potentiometer 0 controls the frequency.
// potentiometer 2 controls the amplitude.
 
// VERSION HISTORY:
// 5.1.2014 - j0uni : This version uses bitwise AND to get the "rolling" pointer to sinewave table.
 
int in_ADC0, in_ADC1;  //variables for 2 ADCs values (ADC0, ADC1)
int POT0, POT1, POT2, THEREMIN, out_DAC0, out_DAC1; //variables for 3 pots (ADC8, ADC9, ADC10)
const int LED = 3;
const int FOOTSWITCH = 7; 
const int TOGGLE = 2; 
int accumulator, sample;
 
// Create a table to hold pre computed sinewave, the table has a resolution of 600 samples
#define no_samples 4096 // must be two's complement!     
uint16_t nSineTable[no_samples]; // storing 12 bit samples in 16 bit variable.
 
void createSineTable()
{
  for(uint32_t nIndex=0; nIndex<no_samples; nIndex++)
  {
    // normalised to 12 bit range 0-4095
    nSineTable[nIndex] = (uint16_t)  (((1+sin(((2.0*PI)/no_samples)*nIndex))*4095.0)/2);
  }
}
 
void setup()
{
  createSineTable();
 
  //turn on the timer clock in the power management controller
  pmc_set_writeprotect(false);
  pmc_enable_periph_clk(ID_TC4);
 
  //we want wavesel 01 with RC 
  TC_Configure(TC1,1, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK2);
  TC_SetRC(TC1, 1, 238); // sets <> 44.1 Khz interrupt rate
  TC_Start(TC1, 1);
 
  //enable timer interrupts on the timer
  TC1->TC_CHANNEL[1].TC_IER=TC_IER_CPCS;
  TC1->TC_CHANNEL[1].TC_IDR=~TC_IER_CPCS;
 
  //Enable the interrupt in the nested vector interrupt controller 
  //TC4_IRQn where 4 is the timer number * timer channels (3) + the channel number 
  //(=(1*3)+1) for timer1 channel1 
  NVIC_EnableIRQ(TC4_IRQn);
 
  //ADC Configuration
  ADC->ADC_MR |= 0x80;   // DAC in free running mode.
  ADC->ADC_CR=2;         // Starts ADC conversion.
  ADC->ADC_CHER=0x3CC0;  // Enable ADC channels 0,1,8,9 and 10  
 
  //DAC Configuration
  analogWrite(DAC0,0);  // Enables DAC0
  analogWrite(DAC1,0);  // Enables DAC1
}
 
float pot = 0;
 
void loop()
{
  //Read the ADCs.
  while((ADC->ADC_ISR & 0x1CC0)!=0x1CC0); // wait for ADC 0, 1, 8, 9, 10 conversion complete.
  in_ADC0=ADC->ADC_CDR[7];            // read data from ADC0
  in_ADC1=ADC->ADC_CDR[6];            // read data from ADC1  
 
  POT0=ADC->ADC_CDR[10];                  // read data from ADC8          
  POT1=ADC->ADC_CDR[11];                  // read data from ADC9   
  POT2=ADC->ADC_CDR[12];                  // read data from ADC10  
 
  THEREMIN=ADC->ADC_CDR[13];                  // read data from ADC10  
}
 
//Interrupt at 44.1KHz rate (every 22.6us)
void TC4_Handler()
{
  //Clear status allowing the interrupt to be fired again.
  TC_GetStatus(TC1, 1);
 
  //update the accumulator, from 0 to 511
  accumulator=THEREMIN>>3;
  sample=sample+accumulator;
 
  // Generate the DAC output
  // AND with TWO'S COMPLEMENT value to get the bits we really want to use
  out_DAC0 = nSineTable[sample & (no_samples-1)];
  out_DAC1 = 4095 - nSineTable[sample & (no_samples-1)];
 
  //Add volume feature
  out_DAC0=map(out_DAC0,0,4095,0,POT2);
  out_DAC1=map(out_DAC1,0,4095,0,POT2);
 
  //Write the DACs.
  dacc_set_channel_selection(DACC_INTERFACE, 0);       //select DAC channel 0
  dacc_write_conversion_data(DACC_INTERFACE, out_DAC0);//write on DAC
  dacc_set_channel_selection(DACC_INTERFACE, 1);       //select DAC channel 1
  dacc_write_conversion_data(DACC_INTERFACE, out_DAC1);//write on DAC 
}

I have uploaded a basic demo to youtube:


There is plenty of improvements to this code:
  • Use more complex signals, not just a sinewave, giving a better synthesized tone.
  • Use this idea to modulate other pedals like tremolo, distortion...
Last Edit: 2 years 4 months ago by ES_Team.
The administrator has disabled public write access.
Time to create page: 0.239 seconds
Powered by Kunena Forum
Joomla SEF URLs by Artio