Go Down

### Topic: How to set Sinewave with Frequency? (Read 693 times)previous topic - next topic

#### saicheng

##### Jun 09, 2014, 04:46 amLast Edit: Jun 10, 2014, 05:09 am by saicheng Reason: 1
I use the code

Code: [Select]
`// RCArduino DDS Sinewave for Arduino Due// RCArduino DDS Sinewave by RCArduino is licensed under a Creative Commons Attribution 3.0 Unported License.// Based on a work at rcarduino.blogspot.com.// For helpful background information on Arduino Due Timer Configuration, refer to the following link// thanks to Sebastian Vik// http://arduino.cc/forum/index.php?action=post;topic=130423.15;num_replies=20// For background information on the DDS Technique see// http://interface.khm.de/index.php/lab/experiments/arduino-dds-sinewave-generator/// For audio sketches making extensive use of DDS Techniques, search the RCArduino Blog// for the tags Audio or synth// These are the clock frequencies available to the timers /2,/8,/32,/128// 84Mhz/2 = 42.000 MHz// 84Mhz/8 = 10.500 MHz// 84Mhz/32 = 2.625 MHz// 84Mhz/128 = 656.250 KHz//// 44.1Khz = CD Sample Rate// Lets aim for as close to the CD Sample Rate as we can get -//// 42Mhz/44.1Khz = 952.38// 10.5Mhz/44.1Khz = 238.09 // best fit divide by 8 = TIMER_CLOCK2 and 238 ticks per sample// 2.625Hmz/44.1Khz = 59.5// 656Khz/44.1Khz = 14.88// 84Mhz/44.1Khz = 1904 instructions per tick// the phase accumulator points to the current sample in our wavetableuint32_t ulPhaseAccumulator = 0;// the phase increment controls the rate at which we move through the wave table// higher values = higher frequenciesvolatile uint32_t ulPhaseIncrement = 0;   // 32 bit phase increment, see below// full waveform = 0 to SAMPLES_PER_CYCLE// Phase Increment for 1 Hz =(SAMPLES_PER_CYCLE_FIXEDPOINT/SAMPLE_RATE) = 1Hz// Phase Increment for frequency F = (SAMPLES_PER_CYCLE/SAMPLE_RATE)*F#define SAMPLE_RATE 5000.0#define SAMPLES_PER_CYCLE 2000#define SAMPLES_PER_CYCLE_FIXEDPOINT (SAMPLES_PER_CYCLE<<20)#define TICKS_PER_CYCLE (float)((float)SAMPLES_PER_CYCLE_FIXEDPOINT/(float)SAMPLE_RATE)// to represent 600 we need 10 bits// Our fixed point format will be 10P22 = 32 bits// We have 521K flash and 96K ram to play with// Create a table to hold the phase increments we need to generate midi note frequencies at our 44.1Khz sample rate#define MIDI_NOTES 1000uint32_t nMidiPhaseIncrement[MIDI_NOTES];// fill the note table with the phase increment values we require to generate the notevoid createNoteTable(float fSampleRate){  for(uint32_t unMidiNote = 0;unMidiNote < MIDI_NOTES;unMidiNote++)  {    // Correct calculation for frequency    Serial.print(unMidiNote);    Serial.print(" ");    float fFrequency = ((pow(2.0,(unMidiNote)/12)) * 2.0);    Serial.print(fFrequency);    Serial.print(" ");       nMidiPhaseIncrement[unMidiNote] = fFrequency*TICKS_PER_CYCLE*10;    Serial.println(nMidiPhaseIncrement[unMidiNote]);  }}// Create a table to hold pre computed sinewave, the table has a resolution of 600 samples#define WAVE_SAMPLES 2000// default int is 32 bit, in most cases its best to use uint32_t but for large arrays its better to use smaller// data types if possible, here we are storing 12 bit samples in 16 bit intsuint16_t nSineTable[WAVE_SAMPLES];// create the individual samples for our sinewave tablevoid createSineTable(){  for(uint32_t nIndex = 0;nIndex < WAVE_SAMPLES;nIndex++)  {    // normalised to 12 bit range 0-4095    nSineTable[nIndex] = (uint16_t)  (((1+sin(((2.0*PI)/WAVE_SAMPLES)*nIndex))*4095.0)/2);    Serial.println(nSineTable[nIndex]);  }}void startTimer(Tc *tc, uint32_t channel, IRQn_Type irq, uint32_t frequency) {        pmc_set_writeprotect(false);        pmc_enable_periph_clk((uint32_t)irq);        TC_Configure(tc, channel, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK2);        uint32_t rc = VARIANT_MCK/8/frequency; //128 because we selected TIMER_CLOCK4 above        TC_SetRA(tc, channel, 32/2); //50% high, 50% low        TC_SetRC(tc, channel, 16);        TC_Start(tc, channel);        tc->TC_CHANNEL[channel].TC_IER=TC_IER_CPCS;        tc->TC_CHANNEL[channel].TC_IDR=~TC_IER_CPCS;        NVIC_EnableIRQ(irq);          analogWrite(DAC0,0);}void setup(){  Serial.begin(9600);  createNoteTable(SAMPLE_RATE);  createSineTable(); startTimer(TC1, 1, TC4_IRQn, 1);   // this is a cheat - enable the DAC}void loop(){  // read analog input 0 drop the range from 0-1024 to 0-127 with a right shift 3 places,  // then look up the phaseIncrement required to generate the note in our nMidiPhaseIncrement table  uint32_t ulInput = analogRead(0);  ulPhaseIncrement = nMidiPhaseIncrement[ulInput>>3];}void TC4_Handler(){  // We need to get the status to clear it and allow the interrupt to fire again  TC_GetStatus(TC1, 1);   ulPhaseAccumulator += ulPhaseIncrement;   // 32 bit phase increment, see below  // if the phase accumulator over flows - we have been through one cycle at the current pitch,  // now we need to reset the grains ready for our next cycle  if(ulPhaseAccumulator > SAMPLES_PER_CYCLE_FIXEDPOINT)  {   // DB 02/Jan/2012 - carry the remainder of the phase accumulator   ulPhaseAccumulator -= SAMPLEAS_PER_CYCLE_FIXEDPOINT;   }  // get the current sample    uint32_t ulOutput = nSineTable[ulPhaseAccumulator>>20];   // we cheated and user analogWrite to enable the dac, but here we want to be fast so  // write directly   dacc_write_conversion_data(DACC_INTERFACE, ulOutput);}`

I didn`t know how to set Frequency?
PS.Frequency rate: 20khz~200khz

#### iyahdub

#1
##### Jul 03, 2014, 08:35 am
Above the Nyquist frequency. and starts aliasing. So, highest you can achieve should be :
Sampling_rate / 2 = Nyquist frequency
i.e. 44.100/2 =22.050 kHz
10 LET Loop=Infinite
20 GO TO 10

#### MarkT

#2
##### Jul 03, 2014, 01:14 pm
In practice ~16kHz is the upper limit, about 40% of the sampling frequency.

The variable ulPhaseIncrement is set proportional to the desired frequency,
a little maths will tell you the constant of proportionality.
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

Go Up

Please enter a valid email to subscribe