Fix ESP32 PWM range

This commit is contained in:
Theo Arends 2020-08-03 11:52:25 +02:00
parent ff37beac6a
commit 1d990ad091
7 changed files with 65 additions and 56 deletions

View File

@ -54,3 +54,6 @@ The following binary downloads have been compiled with ESP8266/Arduino library c
## Changelog ## Changelog
### Version 8.4.0.1 ### Version 8.4.0.1
- Fix ESP32 PWM range
- Add Zigbee better support for IKEA Motion Sensor

View File

@ -29,28 +29,63 @@
#include <Esp.h> #include <Esp.h>
/*********************************************************************************************\ /*********************************************************************************************\
* ESP32 analogWrite support * ESP32 analogWrite emulation support
\*********************************************************************************************/ \*********************************************************************************************/
#define PWM_SUPPORTED_CHANNELS 8 #define PWM_SUPPORTED_CHANNELS 8
#define PWM_CHANNEL_OFFSET 2 // Webcam uses channel 0, so we offset standard PWM #define PWM_CHANNEL_OFFSET 2 // Webcam uses channel 0, so we offset standard PWM
uint8_t _pwm_channel[PWM_SUPPORTED_CHANNELS] = { 99, 99, 99, 99, 99, 99, 99, 99 }; uint8_t _pwm_channel[PWM_SUPPORTED_CHANNELS] = { 99, 99, 99, 99, 99, 99, 99, 99 };
uint32_t _pwm_frequency = 977; // Default 977Hz
inline void analogWriteFreq(uint32_t freq) { uint8_t _pwm_bit_num = 10; // Default 1023
}
inline void analogWriteRange(uint32_t range) {
}
inline uint32_t _analog_pin2chan(uint32_t pin) { inline uint32_t _analog_pin2chan(uint32_t pin) {
for (uint32_t cnt = 0; cnt < PWM_SUPPORTED_CHANNELS; cnt++) { for (uint32_t channel = 0; channel < PWM_SUPPORTED_CHANNELS; channel++) {
if ((_pwm_channel[cnt] < 99) && (_pwm_channel[cnt] == pin)) { if ((_pwm_channel[channel] < 99) && (_pwm_channel[channel] == pin)) {
return cnt; return channel;
} }
} }
return 0; return 0;
} }
inline void _analogWriteFreqRange(void) {
for (uint32_t channel = 0; channel < PWM_SUPPORTED_CHANNELS; channel++) {
if (_pwm_channel[channel] < 99) {
// uint32_t duty = ledcRead(channel + PWM_CHANNEL_OFFSET);
ledcSetup(channel + PWM_CHANNEL_OFFSET, _pwm_frequency, _pwm_bit_num);
// ledcWrite(channel + PWM_CHANNEL_OFFSET, duty);
}
}
// Serial.printf("freq - range %d - %d\n",freq,range);
}
// input range is in full range, ledc needs bits
inline uint32_t _analogGetResolution(uint32_t x) {
uint32_t bits = 0;
while (x) {
bits++;
x >>= 1;
}
return bits;
}
inline void analogWriteRange(uint32_t range) {
_pwm_bit_num = _analogGetResolution(range);
_analogWriteFreqRange();
}
inline void analogWriteFreq(uint32_t freq) {
_pwm_frequency = freq;
_analogWriteFreqRange();
}
inline void analogAttach(uint32_t pin, uint32_t channel) {
_pwm_channel[channel &7] = pin;
ledcAttachPin(pin, channel + PWM_CHANNEL_OFFSET);
ledcSetup(channel + PWM_CHANNEL_OFFSET, _pwm_frequency, _pwm_bit_num);
// Serial.printf("attach %d - %d\n", channel, pin);
}
inline void analogWrite(uint8_t pin, int val) inline void analogWrite(uint8_t pin, int val)
{ {
uint32_t channel = _analog_pin2chan(pin); uint32_t channel = _analog_pin2chan(pin);
@ -58,33 +93,6 @@ inline void analogWrite(uint8_t pin, int val)
// Serial.printf("write %d - %d\n",channel,val); // Serial.printf("write %d - %d\n",channel,val);
} }
inline void analogAttach(uint32_t pin, uint32_t channel) {
_pwm_channel[channel &7] = pin;
ledcAttachPin(pin, channel + PWM_CHANNEL_OFFSET);
// Serial.printf("attach %d - %d\n",channel,pin);
}
inline uint32_t _analog_pow2(uint32_t x) {
uint32_t power = 1;
uint32_t bits = 0;
while (power < x) {
power *= 2;
bits++;
}
return bits;
}
// input range is in full range, ledc needs bits
inline void analogWriteFreqRange(uint32_t channel, uint32_t freq, uint32_t irange) {
uint32_t range = _analog_pow2(irange);
for (uint32_t cnt = 0; cnt < PWM_SUPPORTED_CHANNELS; cnt++) {
if (_pwm_channel[cnt] < 99) {
ledcSetup(cnt + PWM_CHANNEL_OFFSET, freq, range);
}
}
// Serial.printf("freq - range %d - %d\n",freq,range);
}
/*********************************************************************************************/ /*********************************************************************************************/
#define INPUT_PULLDOWN_16 INPUT_PULLUP #define INPUT_PULLDOWN_16 INPUT_PULLUP

View File

@ -2,6 +2,7 @@
### 8.4.0.1 20200730 ### 8.4.0.1 20200730
- Fix ESP32 PWM range
- Add Zigbee better support for IKEA Motion Sensor - Add Zigbee better support for IKEA Motion Sensor
### 8.4.0 20200730 ### 8.4.0 20200730

View File

@ -1236,29 +1236,31 @@ void CmndPwmfrequency(void)
{ {
if ((1 == XdrvMailbox.payload) || ((XdrvMailbox.payload >= PWM_MIN) && (XdrvMailbox.payload <= PWM_MAX))) { if ((1 == XdrvMailbox.payload) || ((XdrvMailbox.payload >= PWM_MIN) && (XdrvMailbox.payload <= PWM_MAX))) {
Settings.pwm_frequency = (1 == XdrvMailbox.payload) ? PWM_FREQ : XdrvMailbox.payload; Settings.pwm_frequency = (1 == XdrvMailbox.payload) ? PWM_FREQ : XdrvMailbox.payload;
#ifdef ESP8266
analogWriteFreq(Settings.pwm_frequency); // Default is 1000 (core_esp8266_wiring_pwm.c) analogWriteFreq(Settings.pwm_frequency); // Default is 1000 (core_esp8266_wiring_pwm.c)
#else
analogWriteFreqRange(0,Settings.pwm_frequency,Settings.pwm_range);
#endif
} }
ResponseCmndNumber(Settings.pwm_frequency); ResponseCmndNumber(Settings.pwm_frequency);
} }
void CmndPwmrange(void) void CmndPwmrange(void) {
{ // Support only 8 (=255), 9 (=511) and 10 (=1023) bits resolution
if ((1 == XdrvMailbox.payload) || ((XdrvMailbox.payload > 254) && (XdrvMailbox.payload < 1024))) { if ((1 == XdrvMailbox.payload) || ((XdrvMailbox.payload > 254) && (XdrvMailbox.payload < 1024))) {
Settings.pwm_range = (1 == XdrvMailbox.payload) ? PWM_RANGE : XdrvMailbox.payload; uint32_t pwm_range = XdrvMailbox.payload;
uint32_t pwm_resolution = 0;
while (pwm_range) {
pwm_resolution++;
pwm_range >>= 1;
}
pwm_range = (1 << pwm_resolution) - 1;
uint32_t old_pwm_range = Settings.pwm_range;
Settings.pwm_range = (1 == XdrvMailbox.payload) ? PWM_RANGE : pwm_range;
for (uint32_t i = 0; i < MAX_PWMS; i++) { for (uint32_t i = 0; i < MAX_PWMS; i++) {
if (Settings.pwm_value[i] > Settings.pwm_range) { if (Settings.pwm_value[i] > Settings.pwm_range) {
Settings.pwm_value[i] = Settings.pwm_range; Settings.pwm_value[i] = Settings.pwm_range;
} }
} }
#ifdef ESP8266 if (Settings.pwm_range != old_pwm_range) { // On ESP32 this prevents loss of duty state
analogWriteRange(Settings.pwm_range); // Default is 1023 (Arduino.h) analogWriteRange(Settings.pwm_range); // Default is 1023 (Arduino.h)
#else }
analogWriteFreqRange(0,Settings.pwm_frequency,Settings.pwm_range);
#endif
} }
ResponseCmndNumber(Settings.pwm_range); ResponseCmndNumber(Settings.pwm_range);
} }

View File

@ -1564,12 +1564,12 @@ void GpioInit(void)
// AddLogBufferSize(LOG_LEVEL_DEBUG, (uint8_t*)gpio_pin, ARRAY_SIZE(gpio_pin), sizeof(gpio_pin[0])); // AddLogBufferSize(LOG_LEVEL_DEBUG, (uint8_t*)gpio_pin, ARRAY_SIZE(gpio_pin), sizeof(gpio_pin[0]));
#ifdef ESP8266
if ((2 == Pin(GPIO_TXD)) || (H801 == my_module_type)) { Serial.set_tx(2); }
analogWriteRange(Settings.pwm_range); // Default is 1023 (Arduino.h) analogWriteRange(Settings.pwm_range); // Default is 1023 (Arduino.h)
analogWriteFreq(Settings.pwm_frequency); // Default is 1000 (core_esp8266_wiring_pwm.c) analogWriteFreq(Settings.pwm_frequency); // Default is 1000 (core_esp8266_wiring_pwm.c)
#ifdef ESP8266
if ((2 == Pin(GPIO_TXD)) || (H801 == my_module_type)) { Serial.set_tx(2); }
#ifdef USE_SPI #ifdef USE_SPI
spi_flg = (((PinUsed(GPIO_SPI_CS) && (Pin(GPIO_SPI_CS) > 14)) || (Pin(GPIO_SPI_CS) < 12)) || ((PinUsed(GPIO_SPI_DC) && (Pin(GPIO_SPI_DC) > 14)) || (Pin(GPIO_SPI_DC) < 12))); spi_flg = (((PinUsed(GPIO_SPI_CS) && (Pin(GPIO_SPI_CS) > 14)) || (Pin(GPIO_SPI_CS) < 12)) || ((PinUsed(GPIO_SPI_DC) && (Pin(GPIO_SPI_DC) > 14)) || (Pin(GPIO_SPI_DC) < 12)));
if (spi_flg) { if (spi_flg) {
@ -1584,8 +1584,6 @@ void GpioInit(void)
soft_spi_flg = (PinUsed(GPIO_SSPI_CS) && PinUsed(GPIO_SSPI_SCLK) && (PinUsed(GPIO_SSPI_MOSI) || PinUsed(GPIO_SSPI_MISO))); soft_spi_flg = (PinUsed(GPIO_SSPI_CS) && PinUsed(GPIO_SSPI_SCLK) && (PinUsed(GPIO_SSPI_MOSI) || PinUsed(GPIO_SSPI_MISO)));
#endif // USE_SPI #endif // USE_SPI
#else // ESP32 #else // ESP32
analogWriteFreqRange(0, Settings.pwm_frequency, Settings.pwm_range);
#ifdef USE_SPI #ifdef USE_SPI
if (PinUsed(GPIO_SPI_CS) || PinUsed(GPIO_SPI_DC)) { if (PinUsed(GPIO_SPI_CS) || PinUsed(GPIO_SPI_DC)) {
if ((15 == Pin(GPIO_SPI_CS)) && (!GetPin(12) && !GetPin(13) && !GetPin(14))) { // HSPI if ((15 == Pin(GPIO_SPI_CS)) && (!GetPin(12) && !GetPin(13) && !GetPin(14))) { // HSPI
@ -1690,7 +1688,6 @@ void GpioInit(void)
pinMode(Pin(GPIO_PWM1, i), OUTPUT); pinMode(Pin(GPIO_PWM1, i), OUTPUT);
#else // ESP32 #else // ESP32
analogAttach(Pin(GPIO_PWM1, i), i); analogAttach(Pin(GPIO_PWM1, i), i);
analogWriteFreqRange(i, Settings.pwm_frequency, Settings.pwm_range);
#endif #endif
if (light_type) { if (light_type) {
// force PWM GPIOs to low or high mode, see #7165 // force PWM GPIOs to low or high mode, see #7165

View File

@ -1355,7 +1355,6 @@ void LightInit(void)
pinMode(Pin(GPIO_PWM1, i), OUTPUT); pinMode(Pin(GPIO_PWM1, i), OUTPUT);
#else // ESP32 #else // ESP32
analogAttach(Pin(GPIO_PWM1, i), i); analogAttach(Pin(GPIO_PWM1, i), i);
analogWriteFreqRange(i, Settings.pwm_frequency, Settings.pwm_range);
#endif #endif
} }
} }

View File

@ -152,7 +152,6 @@ void Sm16716ModuleSelected(void)
pinMode(Pin(GPIO_PWM1, i), OUTPUT); pinMode(Pin(GPIO_PWM1, i), OUTPUT);
#else // ESP32 #else // ESP32
analogAttach(Pin(GPIO_PWM1, i), i); analogAttach(Pin(GPIO_PWM1, i), i);
analogWriteFreqRange(i, Settings.pwm_frequency, Settings.pwm_range);
#endif #endif
} }
} }