Hi guys.
I have some problems getting PWM working on my new ESP32..
In my test sketch below I try to use a potentiometer to control the speed of a small fan connected to the board, and I can see the potentiometer readings vary between 0-4095, but my duty cycle only switches between 0 and 255, which I can't seem to figure out why..
But the real problem is that the ESP32 doesn't output a pwm signal on the set pwm_pin. I expect the signal to be readable with a multimeter ranging from 0-3.3V on that pin, or is that incorrect?
Or maybe someone more experienced can see why the signal isn't output?
Code:
#include <Wire.h>
#define pwm_pin 21 // PWM output pin 19 for fan speed control
#define level_selector 34 // Analog pin input
int max_cycle = 255; // Setting maximum pwm value for fan_speed (should be integers)
int reading;
int map_level;
int pwm_channel = 0;
int pwm_freq = 25000;
int pwm_res = 8;
void setup() {
// Setup pwm frequency on channel 0
ledcSetup(pwm_channel, pwm_freq, pwm_res); // Channel 0, 35 kHz frequency, 8-bit resolution
ledcAttachPin(pwm_pin, pwm_channel);
Serial.begin(115200); // For ESP32
pinMode(pwm_pin, OUTPUT);
pinMode(level_selector, INPUT_PULLUP);
delay(50);
// Setting fan speed to 0
ledcWrite(pwm_channel, 0); // Set duty cycle to 0%
}
void speedcontrol(int level) {
int new_cycle = (level/4095)*max_cycle;
// Setting fan speed
ledcWrite(pwm_channel, new_cycle); // Set duty cycle
Serial.print(F(" Duty Cycle: "));
Serial.println(new_cycle);
}
void loop() {
reading = analogRead(level_selector);
map_level = map(reading, 0, 4095, 0, 9); // Range normally from 0-4095
Serial.print(F("Reading: "));
Serial.print(reading);
Serial.print(F(" Mapping: "));
Serial.print(map_level);
speedcontrol(reading);
delay(10);
}
Thank you, that solved the duty cycle part of problem. What exactly did I do wrong before though? I thought by dividing level with 4095 got me a decimal value, or percentage, that when multiplied by max_cycle would give me a decimal value between 0-255, and declaring new_cycle as an integer would remove all decimals only?
I have the exact same problem on 3 new NodeMCU ESP-32s though. I'm thinking I must have something wrong with my code? Or could I be using a pin that doesn't support pwm output? Or something else?
The pinMode statement may be a problem. The ESP32 creates the PWM pulses by a special HW, and with ledcAttach you connect this HW to the correspondig pin. I think the statement
pinMode(pwm_pin, OUTPUT);
connects the pin to the standard output ports again and disconnects it from the ledc hardware.
That solved it Thank you so much!
Just to make sure I don't do anything stupid when trying to control the speed now, can I do this or will that be a problem too?
I don't think it will be a problem. But why using floats? The duty value is an integer, and because you set the resolution to 8 Bits, it is an interger between 0 and 255. So you could map your pot reading to directly give an integer between 0 and 255 ( or even less, if you don't want it to reach 255 ).
In another program, where I also had this issue, I calculate the percentage for duty cycle using some conditions and the result is a percentage of the total. But I'll give it a go and see Thanks for all help!
This is an article that discusses the ESP32 PWM in detail:
This explains and demonstrates, how to implement PWM on a DC motor and LED using the ESP WROOM-32 module. The behavior of the PWM signal is determined by duty cycle, resolution, and frequency.