#include #include // PWM modified square wave generator for current control // table of values / one period / stored in flash memory PROGMEM prog_uchar sinepos[] = { // 0 degrees 127,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, 254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, 254,254,254,254,254,254,254,254,254,254,254,254, 254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, 127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127, }; PROGMEM prog_uchar sineneg[] = { // 180 degrees 127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127, 254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, 254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, 254,254,254,254,254,254,254,254,254,254,254,254, 254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, 127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127, }; #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) int stepcheck = 0; int sinestep = 0; int testPin = 7; int t2Pin = 6; byte bb; double dfreq; // const double refclk=31372.549; // =16MHz / 510 const double refclk=31376.6; // measured // variables used inside interrupt service declared as voilatile volatile byte icnt; // var inside interrupt volatile byte icnt1; // var inside interrupt volatile byte c4ms; // counter incremented all 4ms volatile unsigned long phaccu; // phase accumulator volatile unsigned long tword_m; // dds tuning word m void setup() { // pinMode(ledPin, OUTPUT); // sets the digital pin as output Serial.begin(115200); // connect to the serial port Serial.println("DDS Test"); pinMode(6, OUTPUT); // sets the digital pin as output pinMode(7, OUTPUT); // sets the digital pin as output pinMode(11, OUTPUT); // pin 11= PWM output / frequency output pinMode(3, OUTPUT); // pin 3= PWM output / frequency output Setup_timer2(); // disable interrupts to avoid timing distortion cbi (TIMSK0,TOIE0); // disable Timer0 !!! delay() is now not available sbi (TIMSK2,TOIE2); // enable Timer2 Interrupt dfreq=50.0; // initial output frequency = 50Hz tword_m=pow(2,32)*dfreq/refclk; // calulate DDS new tuning word } void loop() { while(1) { if (c4ms > 250) { // timer / wait fou a full second c4ms=0; cbi (TIMSK2,TOIE2); // disble Timer2 Interrupt sbi (TIMSK2,TOIE2); // enable Timer2 Interrupt Serial.print(dfreq); Serial.print(" "); Serial.println(tword_m); } sbi(PORTD,6); // Test / set PORTD,7 high to observe timing with a scope cbi(PORTD,6); // Test /reset PORTD,7 high to observe timing with a scope } } // timer2 setup // set prscaler to 1, PWM mode to phase correct PWM, 16000000/510 = 31372.55 Hz clock void Setup_timer2() { // Timer2 Clock Prescaler to : 1 sbi (TCCR2B, CS20); cbi (TCCR2B, CS21); cbi (TCCR2B, CS22); // Timer2 PWM Mode set to Phase Correct PWM cbi (TCCR2A, COM2A0); // clear Compare Match sbi (TCCR2A, COM2A1); sbi (TCCR2A, COM2B1); sbi (TCCR2A, WGM20); // Mode 1 / Phase Correct PWM cbi (TCCR2A, WGM21); cbi (TCCR2B, WGM22); } // Timer2 Interrupt Service at 31372,550 KHz = 32uSec // this is the timebase REFCLOCK for the DDS generator // FOUT = (M (REFCLK)) / (2 exp 32) // runtime : 8 microseconds ( inclusive push and pop) ISR(TIMER2_OVF_vect) { sbi(PORTD,7); // Test / set PORTD,7 high to observe timing with a oscope phaccu=phaccu+tword_m; // soft DDS, phase accu with 32 bits icnt=phaccu >> 24; // use upper 8 bits for phase accu as frequency information OCR2A=pgm_read_byte_near(sinepos + icnt); // read value fron ROM positive sine table and send to PWM DAC pin 11 OCR2B=pgm_read_byte_near(sineneg + icnt); // read value fron ROM negative sine table and send to PWM DAC pin 3 //Square wave generation// sinestep = pgm_read_byte_near(sinepos + icnt); stepcheck = pgm_read_byte_near(sinepos + icnt + 1); if (sinestep == 127 && stepcheck == 254) // check for first zero cross and write 12 high and 13 low { sbi(PORTB,4); //pin 12 high cbi(PORTB,5);//pin 13 low } if (sinestep == 127 && stepcheck == 0) // check for second zero cross and write 13 high and 12 low { cbi(PORTB,4);//pin 12 low sbi(PORTB,5); //pin 13 high } cbi(PORTD,7); // reset PORTD,7 }