/* * File: varDutyT1.ino * Purpose: Varying the duty-cycle of the PWM on output pins 9 and 10 via the analog A0 input. Update rate: 15.625kHz, resolution: 10-bits. * * Version: 1.0.0 * * By: M. Stokroos * * Date: 02-12-2019 * */ // Library to be included for fast digital I/O when observing the timing with an oscilloscope. //#include // library for high performance digital reads and writes by jrraines // see http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1267553811/0 // and http://code.google.com/p/digitalwritefast/ #define LPERIOD 500000 // the main loop period time in us. In this case 500ms. #define PIN_LED 13 // PLL locking status indicator LED #define PIN_PWMA 9 // Timer1 OCR1A 10-bit PWM #define PIN_PWMB 10 // Timer1 OCR1B 10-bit PWM #define PIN_DEBUG 4 // test output pin // global vars volatile int adcVal; unsigned long nextLoop; // ****************************************************************** // Setup // ****************************************************************** void setup(){ cli(); // disable interrupts pinMode(PIN_LED, OUTPUT); pinMode(PIN_PWMA, OUTPUT); pinMode(PIN_PWMB, OUTPUT); pinMode(PIN_DEBUG, OUTPUT); // initialize ADC for continuous sampling mode DIDR0 = 0x3F; // digital inputs disabled for ADC0D to ADC5D bitSet(ADMUX, REFS0); // Select Vcc=5V as the ADC reference voltage bitClear(ADMUX, REFS1); bitClear(ADMUX, MUX0); // selecting ADC CH# 0 bitClear(ADMUX, MUX1); bitClear(ADMUX, MUX2); bitClear(ADMUX, MUX3); bitSet(ADCSRA, ADEN); // AD-converter enabled bitSet(ADCSRA, ADATE); // auto-trigger enabled bitSet(ADCSRA, ADIE); // ADC interrupt enabled bitSet(ADCSRA, ADPS0); // ADC clock prescaler set to 128 bitSet(ADCSRA, ADPS1); bitSet(ADCSRA, ADPS2); bitClear(ADCSRB, ACME); // Analog Comparator (ADC)Multiplexer enable OFF bitClear(ADCSRB, ADTS0); // triggered by Timer/Counter1 Overflow bitSet(ADCSRB, ADTS1); bitSet(ADCSRB, ADTS2); bitSet(ADCSRA, ADSC); // start conversion /* configuring TIMER1 for PWM-mode 7 */ // prescaler = 1: bitSet(TCCR1B, CS10); bitClear(TCCR1B, CS11); bitClear(TCCR1B, CS12); // mode 7: bitSet(TCCR1A, WGM10); bitSet(TCCR1A, WGM11); bitSet(TCCR1B, WGM12); bitClear(TCCR1B, WGM13); //set output compare bitClear(TCCR1A, COM1A0); // Compare Match PWM 9 bitSet(TCCR1A, COM1A1); bitSet(TCCR1A, COM1B0); // Compare Match PWM 10 - inverted channel bitSet(TCCR1A, COM1B1); // enable TIMER1 compare interrupt bitSet(TIMSK1, TOIE1); // enable Timer1 Interrupt sei(); // global enable interrupts nextLoop = micros() + LPERIOD; // Set the loop timer variable for the next loop interval. } // ****************************************************************** // Main loop // ****************************************************************** void loop(){ // do nothing here except for flashing the LED... digitalWrite(PIN_LED, !digitalRead(PIN_LED)); while(nextLoop > micros()); // wait until the end of the time interval nextLoop += LPERIOD; // set next loop time at current time + LOOP_PERIOD } /* ****************************************************************** * ADC ISR. The ADC is triggered by Timer1. * *******************************************************************/ ISR(ADC_vect){ //digitalWriteFast(PIN_DEBUG, HIGH); //for checking the interrupt frequency // read the current ADC input channel adcVal=ADCL; // store low byte adcVal+=ADCH<<8; // store high byte // write out 10bit PWM output registers A&B (pin9 and pin10). OCR1AH = adcVal>>8; //MSB OCR1AL = adcVal; //LSB //(inverted) output: OCR1BH = OCR1AH; //MSB OCR1BL = OCR1AL; //LSB //digitalWriteFast(PIN_DEBUG, LOW); } /* ****************************************************************** * Timer1 ISR *********************************************************************/ ISR(TIMER1_OVF_vect) { //empty ISR. Only used to trigger the ADC. }