I try to use three PWM pins on an Arduino Nano, each with 10kHz. I know that there are timer0, timer1 and timer3 but I wonder if I can combine them while ensuring all three PWM pins to be in sync and working at 10kHz. Additionally, I want to vary their duty cycle to have 3 cases.
Case 1:pin1 = OFF,pin2 = OFF,pin3 = OFF
Case 2:pin1 = ON,pin2 = ON,pin3 = OFF
Case 3:pin1 = ON,pin2 = OFF,pin3 = ON
The cases are changed at a frequency (f_act) of e.g. 0.25Hz
My code tried to just add a third PWM pin to the timer, which obviously does not work but illustrates my intention.
// ---------------------------------------------------------------------------// 3-Channel synchronized PWM (software using Timer1) for high freq. PWM (10kHz)// + State machine for custom actuation frequency (0.25Hz) (case1 → case2 → case3)// ---------------------------------------------------------------------------// choose desired HV output: HV = -0.0104*D^2 + 0.5791*D + 1.3643// --> D_BUCK = (0.5791 - sqrt(0.5791*0.5791 - 4 * 0.0104 * (HV - 1.3643))) / (2 * 0.0104)const uint16_t HV = 5; // [kV]const uint16_t D_HV = (0.5791 - sqrt(0.5791 * 0.5791 - 4 * 0.0104 * (HV - 1.3643))) / (2 * 0.0104);// prescaler*(1+TOP)=f_arduinoNano/f_PWM=16MHz/10kHz and TOP=resolutionconst uint16_t prescaler = 1; const uint16_t fPWM = 10000; // [Hz]const uint16_t TOP = 16000000 / fPWM / prescaler - 1; // 1599 for 10 kHz with prescaler=1volatile uint16_t dutyBUCK = 0;volatile uint16_t dutyOC1 = 0;volatile uint16_t dutyOC2 = 0;// choose PWM 3 pins:const uint8_t BUCK_pin = 5;const uint8_t OC1_pin = 6;const uint8_t OC2_pin = 7;// Case switching variablesuint8_t caseNum = 1; // start in idleunsigned long lastSwitch = 0;const unsigned long switchInterval = 2000; // [ms] 4s = 0.25 Hz --> Charge&dis- same duration --> 4s/2void setup() { pinMode(BUCK_pin, OUTPUT); pinMode(OC1_pin, OUTPUT); pinMode(OC2_pin, OUTPUT); // Timer1 configuration cli(); // disable interrupts TCCR1A = 0; TCCR1B = 0; // fast mode of Timer1: WGM13 1 WGM12 1 WGM11 1 WGM10 0 TCCR1A |= (1 << WGM11); // contains WGM10 and WGM11 TCCR1B |= (1 << WGM13) | (1 << WGM12); // contains WGM12 and WGM13 ICR1 = TOP; // set TOP (100% duty cycle) TIMSK1 |= (1 << TOIE1); // overflow interrupt TIMSK1 |= (1 << OCIE1A); // compare A TIMSK1 |= (1 << OCIE1B); // compare B TIMSK1 |= (1 << OCIE1C); // compare C TCCR1B |= (1 << CS10); // set prescaler=1 for 10 kHz sei(); // enable interrupts (TIMSK1) once I finished assigning values to them}void loop() { unsigned long now = millis(); // Switch cases every 2 seconds if (now - lastSwitch >= switchInterval) { lastSwitch = now; caseNum++; if (caseNum > 3) caseNum = 1; switch (caseNum) { // ------------------- IDLE ------------------------ case 1: // BUCK=OFF, OC1=OFF, OC2=OFF dutyBUCK = 0;//D_HV; dutyOC1 = 0; dutyOC2 = 0; break; // ------------------- CHARGING ------------------------ case 2: // BUCK=ON, OC1=ON, OC2=OFF dutyBUCK = D_HV; dutyOC1 = TOP; // 100% duty dutyOC2 = 0; break; // ------------------- DISCHARGING ------------------------ case 3: // BUCK=ON, OC1=OFF, OC2=ON dutyBUCK = 0;//D_HV; dutyOC1 = 0; dutyOC2 = TOP; break; } }}// ---------------------------------------------------------------------------// check if On time for Duty cycles are over for each MOSFET at 10kHz// ---------------------------------------------------------------------------// Timer1 overflow → start of new PWM cycleISR(TIMER1_OVF_vect) { digitalWrite(BUCK_pin, HIGH); // turn all HIGH at beginning digitalWrite(OC1_pin, HIGH); digitalWrite(OC2_pin, HIGH); OCR1A = dutyBUCK; // when to turn BUCK off OCR1B = dutyOC1; // when to turn OC1 off OCR1C = dutyOC2; // when to turn OC2 off}// Compare Match A → turn BUCK offISR(TIMER1_COMPA_vect) { if (dutyBUCK > 0) digitalWrite(BUCK_pin, LOW);}// Compare Match B → turn OC1 offISR(TIMER1_COMPB_vect) { if (dutyOC1 > 0) digitalWrite(OC1_pin, LOW);}// Compare Match C → turn OC2 offISR(TIMER1_COMPC_vect) { if (dutyOC2 > 0) digitalWrite(OC2_pin, LOW);}- 1As you found, each of the 3 timers has only 2 PWM channels each. Would some web research leading to external resources likeopenmusiclabs.com/learning/digital/synchronizing-timers/… not help you?the busybee– the busybee2025-11-27 07:01:00 +00:00Commented2 days ago
- are you saying that you are trying to vary the pulse width from 0 to 100 µs (0% to 100%) on three PWM channels ? ... what step value do you want?jsotola– jsotola2025-11-27 18:07:37 +00:00Commentedyesterday
- 1the
Additionallysection is not relevant to this question, please ask it separately after you get the three PWM channels workingjsotola– jsotola2025-11-27 18:08:55 +00:00Commentedyesterday