/* Sinussignalerzeugung mittels DDS Ausgabe von zwei Sinussignalen mit vaiabler Frequenz, Amplitude und Phase mittels PWM Auflösung der Variablen R(frequenz) : F_PWM / 2^16 = 15,625kHz / 65536 = 0,238Hz R(phase) : 360° / 256 = 1,4° = 0,025 rad R(amplitude): 1 / 256 = 0,39% */ #include #define F_PWM 15625 // Hz // Muss ein ganzzahliger Teiler von 62500 sein! #define PRESCALER 1 // Vorteiler für Timer #define SHIFT 2 // zusätzlicher Shift für PWM-Werte, damit kleinere PWM-Frequenzen erreicht werden können, ohne die DDS-Tabelle anpassen zu müssen #define TIMER_RELOAD ((F_CPU / ( PRESCALER * F_PWM) -1)) // Fast PWM #define DELAY 20 // ms, Pause für Zwischenschritte im Demo #define LOOPS 1 // Anzahl Schleifen pro Modulationsdemo // Variablen volatile uint16_t frequenz; volatile uint8_t amplitude, phase; const int8_t sinus[256] PROGMEM = { 0, 3, 6, 9, 12, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 49, 51, 54, 57, 60, 63, 65, 68, 71, 73, 76, 78, 81, 83, 85, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 107, 109, 111, 112, 113, 115, 116, 117, 118, 120, 121, 122, 122, 123, 124, 125, 125, 126, 126, 126, 127, 127, 127, 127, 127, 127, 127, 126, 126, 126, 125, 125, 124, 123, 122, 122, 121, 120, 118, 117, 116, 115, 113, 112, 111, 109, 107, 106, 104, 102, 100, 98, 96, 94, 92, 90, 88, 85, 83, 81, 78, 76, 73, 71, 68, 65, 63, 60, 57, 54, 51, 49, 46, 43, 40, 37, 34, 31, 28, 25, 22, 19, 16, 12, 9, 6, 3, 0, -3, -6, -9, -12, -16, -19, -22, -25, -28, -31, -34, -37, -40, -43, -46, -49, -51, -54, -57, -60, -63, -65, -68, -71, -73, -76, -78, -81, -83, -85, -88, -90, -92, -94, -96, -98, -100, -102, -104, -106, -107, -109, -111, -112, -113, -115, -116, -117, -118, -120, -121, -122, -122, -123, -124, -125, -125, -126, -126, -126, -127, -127, -127, -127, -127, -127, -127, -126, -126, -126, -125, -125, -124, -123, -122, -122, -121, -120, -118, -117, -116, -115, -113, -112, -111, -109, -107, -106, -104, -102, -100, -98, -96, -94, -92, -90, -88, -85, -83, -81, -78, -76, -73, -71, -68, -65, -63, -60, -57, -54, -51, -49, -46, -43, -40, -37, -34, -31, -28, -25, -22, -19, -16, -12, -9, -6, -3, }; // Setzte Frequenz in Hz void set_frequenz(uint16_t frequ_Hz) { volatile uint16_t tmp; tmp = ((uint32_t)frequ_Hz<<16)/F_PWM; ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { frequenz = tmp; } } // Setze Phase in Grad void set_phase(uint16_t phase_deg) { phase = (phase_deg << 8) / 360; } // Setze Amplitude in Prozent void set_amplitude(uint16_t amplitude_prozent) { amplitude = (amplitude_prozent <<8)/100; } void demo(void) { uint16_t i, j; // Demonstration der Parameter // Amplitudenmodulation for (i=0; i0; j--) { amplitude = j; delay(DELAY); } } amplitude = 255; // Frequenzmodulation for (i=0; i0; j--) { ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { frequenz = 256+2*j; } delay(DELAY); } } ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { frequenz = 256; } // Phasenmodulation von OCR1B for (i=0; i0; j--) { phase = j; delay(DELAY); } } phase = 0; } void setup(){ pinMode(A0,INPUT); pinMode(A1,INPUT); // Arduino UNO pinMode(9,OUTPUT); // OCR1A pinMode(10,OUTPUT); // OCR1B Serial.begin(9600); // Timer1 initialisieren // Mode 14, Fast PWM (ICR1), nichtinvertierte PWM, Prescaler 1 // OCR1A, OCR1B aktiv TCCR1A = (1<= 200 ) { last = now; tmp = analogRead(A0); frequenz_hz = map(tmp, 0, 1023, 60, 120); set_frequenz(frequenz_hz); tmp = analogRead(A1); amplitude_prozent = map(tmp, 0, 1023, 0, 100); set_amplitude(amplitude_prozent); Serial.print(F("f: ")); Serial.print(frequenz_hz); Serial.print(F(" ")); Serial.print(F("a: ")); Serial.println(amplitude_prozent); } } // Interrupt für Timer 1, Frequenz F_PWM // Nachladen der PWM ISR(TIMER1_CAPT_vect) { // Index für Sinustabelle, Festkommazahl, 8 Bit Vorkomma, 8 Bit Nachkomma static uint16_t i; i += frequenz; OCR1A = ( 128+(((int8_t)pgm_read_byte(&sinus[i>>8])*(int16_t)amplitude)>>8)) << SHIFT; OCR1B = ( 128+(((int8_t)pgm_read_byte(&sinus[((i>>8)+phase) & 0xFF])*(int16_t)amplitude)>>8)) << SHIFT; }