
bdrmachine:
Where do I select the timer number?
an ESP32 has 4 timers - you check the return from timerBegin() - if it is NULL it failed
this uses 4 timers to generate three phase square waves
// ESP32 three phase square wave variable duty cycle using timers
#define phase1 16 // signal output pins
#define phase2 18
#define phase3 17
unsigned long int period = 10000;
// timer interval in uSec
unsigned long duty_cycle = 50;
// percentage
unsigned long pulse_width = period * duty_cycle / 100; // * 50 / 100;
hw_timer_t *timerperiod = NULL; // hardware timer
hw_timer_t *timerPhase1 = NULL; // hardware timer
hw_timer_t *timerPhase2 = NULL; // hardware timer
hw_timer_t *timerPhase3 = NULL; // hardware timer
// interrupt service routine to generate HIGH levels
volatile int counter = 0; // interrupt counter
void ARDUINO_ISR_ATTR onTimer() {
static byte state = 0; // determines which phase to generate
switch (state) {
case 0:
digitalWrite(phase1, HIGH);
// set phase output HIGH
timerWrite(timerPhase1, 0);
// clear timer
timerAlarm(timerPhase1, pulse_width, false, 0); // generate one shot
break;
case 1:
digitalWrite(phase2, HIGH);
timerWrite(timerPhase2, 0);
timerAlarm(timerPhase2, pulse_width, false, 0); // generate one shot
break;
case 2:
digitalWrite(phase3, HIGH);
timerWrite(timerPhase3, 0);
timerAlarm(timerPhase3, pulse_width, false, 0); // generate one shot
break;
}
if (++state >= 3) state = 0; // reset state ?
counter++;
}
// interrupt service routines to generate LOW levels
void ARDUINO_ISR_ATTR onTimerPhase1() {
digitalWrite(phase1, LOW); // set phase output LOW
}
void ARDUINO_ISR_ATTR onTimerPhase2() {
digitalWrite(phase2, LOW);
}
void ARDUINO_ISR_ATTR onTimerPhase3() {
digitalWrite(phase3, LOW);
}
void setup() {
Serial.begin(115200);
delay(2000);
Serial.println("\n\nESP32 timer three phase square wave with duty Cycle");
pinMode(phase1, OUTPUT); // enable phase outputs
pinMode(phase2, OUTPUT);
pinMode(phase3, OUTPUT);
digitalWrite(phase3, 1);
// setup timer interrupts for 1KHz three phase
if ((timerperiod = timerBegin(10000000)) == NULL) // Set timer frequency to 10Mhz
Serial.println("ERROR! timer period initialisation failed");
else Serial.println("Timer period initialization OK");
if ((timerPhase1 = timerBegin(10000000)) == NULL) // Set timer frequency to 10Mhz
Serial.println("ERROR! timer Phase 1 initialisation failed");
else Serial.println("Timer Phase 1 initialization OK");
if ((timerPhase2 = timerBegin(10000000)) == NULL) // Set timer frequency to 10Mhz
Serial.println("ERROR! timer Phase 2 initialisation failed");
else Serial.println("Timer Phase 2 initialization OK");
if ((timerPhase3 = timerBegin(10000000)) == NULL) // Set timer frequency to 10Mhz
Serial.println("ERROR! timer Phase 3 initialisation failed");
else Serial.println("Timer Phase 3 initialization OK");
timerAttachInterrupt(timerperiod, &onTimer);
// Attach timer ISR for period timing
timerAttachInterrupt(timerPhase1, &onTimerPhase1); // attch timers ISR for pulse timing
timerAttachInterrupt(timerPhase2, &onTimerPhase2);
timerAttachInterrupt(timerPhase3, &onTimerPhase3);
// Set alarm to call onTimer function every second (value in 10 microseconds).
// Repeat the alarm (third parameter) with unlimited count = 0 (fourth parameter).
timerAlarm(timerperiod, period / 3, true, 0);
Serial.println("period increment > (* by 10) decrement < (/ by 10)");
Serial.println(" duty cycle enter 1 (for 10%) to 9 (for 90%)\n");
}
// display interrupt coun ter every seconds
void loop() {
static unsigned long int unit = 10000;
// check if updated period or duty cycle entered
while (Serial.available()) { // if characters entered read them
char ch = Serial.read();
if (!isprint(ch)) continue;
if (ch == '>') {
period += unit;
if (period / unit >= 10) unit *= 10;
}
// < decrement value by 1 unit - minimum is 1 ?
if (ch == '<' && period != 1) {
if (period == unit) unit = unit / 10;
period -= unit;
}
// * increment value by 10 ?
if (ch == '*') {
period = unit = unit * 10;
}
// / decrement value by 10 - minimum is 1
if (ch == '/' && period != 1) {
if (period == unit) unit = unit / 10;
period = unit;
}
if ((ch >= '1') && (ch <= '9')) duty_cycle = (ch - '0') * 10; // set duty cycle
// duty_cycle=50;
pulse_width = period * duty_cycle / 100;
Serial.print("period = ");
Serial.print(period);
Serial.print(" frequency = ");
Serial.print(10000000.0 / (period));
Serial.print(" dutyCycle ");
Serial.print(duty_cycle);
Serial.print(" pulse width ");
Serial.println(pulse_width);
timerAlarm(timerperiod, period / 3, true, 0);
}
// every second print interupt counter
static unsigned long timert = millis();
if (millis() - timert >= 1000) {
Serial.println(counter);
counter = 0;
timert = millis();
}
}
output

1KHz_three_phase_square_wave320×240 28 KB
probably more efficient to use the Remote Control Transceiver (RMT)
however, if generating multiple signals the the ESP32 does not support the sync manager - use an ESP32S3?