0

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);}
jsotola's user avatar
jsotola
1,5532 gold badges13 silver badges22 bronze badges
asked2 days ago
Jana's user avatar
New contributor
Jana is a new contributor to this site. Take care in asking for clarification, commenting, and answering.Check out ourCode of Conduct.
3
  • 1
    As 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?Commented2 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?Commentedyesterday
  • 1
    theAdditionally section is not relevant to this question, please ask it separately after you get the three PWM channels workingCommentedyesterday

0

Know someone who can answer? Share a link to thisquestion viaemail,Twitter, orFacebook.

Your Answer

Sign up orlog in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

By clicking “Post Your Answer”, you agree to ourterms of service and acknowledge you have read ourprivacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.