From 60cb20f13269248f3094929c8cec60ecc112079a Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sun, 12 Sep 2021 15:17:27 -0500 Subject: [PATCH] Completed update to PWM code Should now work with ESP32-S2 and C3. Allows for as many LEDs and Servos as there are channels and timers across low and high (esp32 only) modes. Allows LED to be set with floating point precession instead of just uint8. Allows specification of LED frequency for each LED (1-65535 Hz). Automatically provides maximum duty resolution for frequency chosen. --- src/extras/PwmPin.cpp | 73 ++++++++++++++++++------------------------- src/extras/PwmPin.h | 9 +----- src/extras/extras.ino | 4 +-- 3 files changed, 33 insertions(+), 53 deletions(-) diff --git a/src/extras/PwmPin.cpp b/src/extras/PwmPin.cpp index fc6daa7..034c92a 100644 --- a/src/extras/PwmPin.cpp +++ b/src/extras/PwmPin.cpp @@ -58,12 +58,12 @@ LedPin::LedPin(uint8_t pin, uint8_t level, uint16_t freq) : LedC(pin, freq){ /////////////////// -void LedPin::set(uint8_t level){ +void LedPin::set(float level){ if(!channel) return; - Serial.printf("pin=%d, ch=%d, mode=%d, timer=%d, freq=%d, res=%d\n", + Serial.printf("LED pin=%d, ch=%d, mode=%d, timer=%d, freq=%d, res=%d\n", channel->gpio_num, channel->channel, channel->speed_mode, @@ -141,68 +141,55 @@ void LedPin::HSVtoRGB(float h, float s, float v, float *r, float *g, float *b ){ //////////////////////////// ServoPin::ServoPin(uint8_t pin, double initDegrees, uint16_t minMicros, uint16_t maxMicros, double minDegrees, double maxDegrees) : LedC(pin, 50){ -// if(numChannels>7 || numChannels>(15-numChannels)){ -// Serial.printf("\n*** ERROR: Can't create ServoPin(%d) - no open PWM channels ***\n\n",pin); -// servoChannel.gpio_num=0; -// return; -// } -// -// enabled=true; if(!channel) - Serial.printf("\n*** ERROR: Can't create LedPin(%d) - no open PWM channels and/or Timers ***\n\n",pin); + Serial.printf("\n*** ERROR: Can't create ServoPin(%d) - no open PWM channels and/or Timers ***\n\n",pin); - set(initDegrees); - this->minMicros=minMicros; this->maxMicros=maxMicros; this->minDegrees=minDegrees; microsPerDegree=(double)(maxMicros-minMicros)/(maxDegrees-minDegrees); + + set(initDegrees); -// if(numChannels==0){ // first instantiation of a ServoPin -// ledc_timer_config_t ledTimer; -// ledTimer.timer_num=LEDC_TIMER_1; -// ledTimer.speed_mode=LEDC_HIGH_SPEED_MODE; -// ledTimer.duty_resolution=LEDC_TIMER_16_BIT; -// ledTimer.freq_hz=50; -// ledc_timer_config(&ledTimer); -// } -// -// servoChannel.gpio_num=pin; -// servoChannel.speed_mode=LEDC_HIGH_SPEED_MODE; -// servoChannel.channel=(ledc_channel_t)numChannels++; -// servoChannel.intr_type=LEDC_INTR_DISABLE; -// servoChannel.timer_sel=LEDC_TIMER_1; -// servoChannel.hpoint=0; -// servoChannel.duty*=micros2duty; -// set(initDegrees); } /////////////////// void ServoPin::set(double degrees){ - if(!enabled) - return; - - servoChannel.duty=(degrees-minDegrees)*microsPerDegree+minMicros; - - if(servoChannel.dutymaxMicros) - servoChannel.duty=maxMicros; - servoChannel.duty*=micros2duty; - ledc_channel_config(&servoChannel); + if(!channel) + return; + + Serial.printf("Servo pin=%d, ch=%d, mode=%d, timer=%d, freq=%d, res=%d\n", + channel->gpio_num, + channel->channel, + channel->speed_mode, + channel->timer_sel, + timer->freq_hz, + timer->duty_resolution + ); + + double usec=(degrees-minDegrees)*microsPerDegree+minMicros; + + if(usecmaxMicros) + usec=maxMicros; + + usec*=timer->freq_hz/1e6*(pow(2,timer->duty_resolution)-1); + + channel->duty=usec; + ledc_channel_config(channel); } //////////////////////////// -const double ServoPin::micros2duty=65535.0/20000.0; -//uint8_t LedPin::numChannels=0; -uint8_t ServoPin::numChannels=0; ledc_channel_config_t *LedC::channelList[LEDC_CHANNEL_MAX][LEDC_SPEED_MODE_MAX]={}; ledc_timer_config_t *LedC::timerList[LEDC_TIMER_MAX][LEDC_SPEED_MODE_MAX]={}; +//////////////////////////// + //******************************************************* // DEPRECATED - INCLUDED FOR BACKWARDS COMPATIBILITY ONLY //******************************************************* diff --git a/src/extras/PwmPin.h b/src/extras/PwmPin.h index 923a7de..28a280f 100644 --- a/src/extras/PwmPin.h +++ b/src/extras/PwmPin.h @@ -52,7 +52,7 @@ class LedPin : public LedC { public: LedPin(uint8_t pin, uint8_t level=0, uint16_t freq=DEFAULT_PWM_FREQ); // assigns pin to be output of one of 16 PWM channels initial level and frequency - void set(uint8_t level); // sets the PWM duty to level (0-100) + void set(float level); // sets the PWM duty to level (0-100) static void HSVtoRGB(float h, float s, float v, float *r, float *g, float *b ); // converts Hue/Saturation/Brightness to R/G/B }; @@ -60,23 +60,16 @@ class LedPin : public LedC { ///////////////////////////////////// class ServoPin : public LedC { - boolean enabled=false; uint16_t minMicros; uint16_t maxMicros; double minDegrees; double microsPerDegree; - ledc_channel_config_t servoChannel; - - static const double micros2duty; public: ServoPin(uint8_t pin, double initDegrees, uint16_t minMicros, uint16_t maxMicros, double minDegrees, double maxDegrees); ServoPin(uint8_t pin, double initDegrees=0) : ServoPin(pin,initDegrees,1000,2000,-90,90) {}; void set(double degrees); // sets the Servo to degrees, where degrees is bounded by [minDegrees,maxDegrees] - int getPin(){return servoChannel.gpio_num;} // returns the pin number - - static uint8_t numChannels; }; //******************************************************* diff --git a/src/extras/extras.ino b/src/extras/extras.ino index 639d8b4..e9839e0 100644 --- a/src/extras/extras.ino +++ b/src/extras/extras.ino @@ -25,16 +25,16 @@ void setup(){ LedPin led8(15); LedPin led9(33); LedPin led10(27); + ServoPin led14(25); LedPin led11(12,100,23); LedPin led12(13,100); LedPin led13(26); - LedPin led14(25,0); LedPin led15(4,0); LedPin led16(5,0); led16.set(20); led0.set(5); - led2.set(100); + led14.set(100); Serial.println(led0.getPin()); Serial.println(led14.getPin());