I will try to switch to esp-timer in the future. I found a quick solution. I am changing duty value with timer interrupt (called duty_timer
) Main loop checks all the time if duty_timer has changed or not. I know it is not the best way. But does it sound terrible? Here is code
Code: Select all
#include <Wire.h>
#include "SSD1306.h"
#define LEDC_CHANNEL_0 0
#define LEDC_TIMER_13_BIT 13
SSD1306 display(0x3C, 5,4);
unsigned int pwmpin = 16;
unsigned int freq = 900;
unsigned int duty_set_min = 0;
unsigned int duty_set_max = 100;
unsigned int duty_timer = 100;
unsigned int duty_last = 100;
unsigned int resolution = 10;
unsigned int aresolution = pow(2,resolution)-1;
unsigned int rduty=map(duty_set_max, 0, aresolution, 0, 100);
hw_timer_t * timer = NULL;
volatile uint8_t stat = 0;
void IRAM_ATTR onTimer(){
stat=1-stat;
if (stat==1)duty_timer=duty_set_max;
else if (stat==0)duty_timer=duty_set_min;
}
void setup()
{
Serial.begin(9600);
while (!Serial) {
}
Serial.println("ESP32 PWM GENERATOR V2.2");
Serial.println("Commands:");
Serial.println("'f' to change frequency");
Serial.println("'d' to change duty");
Serial.println("'r' to change resolution");
Serial.println("'p' to change pin number");
display.init();
ledcSetup(0, freq, resolution);
ledcAttachPin(pwmpin, 0);
ledcWrite(0, duty_set_max);
screen(pwmpin,freq,duty_set_max,rduty);
timer = timerBegin(1, 80, true); // timer 0, MWDT clock period = 12.5 ns * TIMGn_Tx_WDT_CLK_PRESCALE -> 12.5 ns * 80 -> 1000 ns = 1 us, countUp
timerAttachInterrupt(timer, &onTimer, true); // edge (not level) triggered
timerAlarmWrite(timer, 1000000, true); // 1000000 * 1 us = 1 s, autoreload true
timerAlarmEnable(timer); // enable
}
void loop()
{
if (duty_last==duty_timer){
}
else {
duty_last=duty_timer;
pwmsettings(pwmpin,freq,duty_last,resolution);
}
if (Serial.available()) {
char cin = Serial.read();
byte cin1;
switch (cin) {
case 'f':
Serial.println("input new frequency in Hz");
while (!Serial.available());
freq = Serial.parseInt();
pwmsettings(pwmpin,freq,duty_set_max,resolution);
Serial.print("Frequency is:");
Serial.print(freq);
Serial.println("Hz");
break;
case 'd':
Serial.print("input new duty (0-");
Serial.print(aresolution);
Serial.println(")");
while (!Serial.available());
duty_set_max = Serial.parseInt();
pwmsettings(pwmpin,freq,duty_set_max,resolution);
Serial.print("New duty is:");
Serial.println(duty_set_max);
break;
case 'r':
Serial.println("input new resolution (8-16)");
while (!Serial.available());
resolution = Serial.parseInt();
pwmsettings(pwmpin,freq,duty_set_max,resolution);
Serial.print("New resolution is:");
Serial.print(resolution);
Serial.println(" bit");
break;
case 'p':
Serial.println("input new pin number");
while (!Serial.available());
pwmpin = Serial.parseInt();
pwmsettings(pwmpin,freq,duty_set_max,resolution);
Serial.print("New pin number is:");
Serial.println(pwmpin);
break;
}
}
}
void screen(unsigned int pwmpin,unsigned int freq, unsigned int duty_set_max,unsigned int rduty)
{
display.clear();
display.setTextAlignment(TEXT_ALIGN_CENTER);
display.setFont(ArialMT_Plain_10);
display.drawString(64, 10, "PWM GENERATOR V2.2");
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.drawString(0, 24, "Freq: " + String(freq)+"Hz");
display.drawString(0, 36, "Duty:"+String(duty_set_max)+" / "+String(aresolution)+" ("+String(rduty)+"%)");
display.drawString(0, 48, "Pin:"+String(pwmpin));
display.display();
}
void pwmsettings(unsigned int pwmpin,unsigned int freq, unsigned int duty_set_max,unsigned int resolution)
{
aresolution = pow(2,resolution)-1;
rduty=map(duty_set_max, 0, aresolution, 0, 100);
ledcSetup(0, freq, resolution);
ledcAttachPin(pwmpin, 0);
ledcWrite(0, duty_set_max);
screen(pwmpin,freq,duty_set_max,rduty);
}