diff --git a/src/extras/PwmPin.cpp b/src/extras/PwmPin.cpp index 957f3c2..e302ebb 100644 --- a/src/extras/PwmPin.cpp +++ b/src/extras/PwmPin.cpp @@ -1,97 +1,10 @@ #include "PwmPin.h" -PwmPin::PwmPin(uint8_t channel, uint8_t pin){ - this->channel=channel & 0x0F; - this->pin=pin; - - ledc_timer_config_t ledTimer; - ledTimer.timer_num=LEDC_TIMER_0; - ledTimer.speed_mode=(this->channel)<8?LEDC_HIGH_SPEED_MODE:LEDC_LOW_SPEED_MODE; - ledTimer.duty_resolution=LEDC_TIMER_10_BIT; - ledTimer.freq_hz=5000; - ledc_timer_config(&ledTimer); - - ledChannel.gpio_num=pin; - ledChannel.speed_mode=(this->channel)<8?LEDC_HIGH_SPEED_MODE:LEDC_LOW_SPEED_MODE; - ledChannel.channel=(ledc_channel_t)(this->channel&0x07); - ledChannel.intr_type=LEDC_INTR_DISABLE; - ledChannel.timer_sel=LEDC_TIMER_0; - ledChannel.duty=0; - ledChannel.hpoint=0; - ledc_channel_config(&ledChannel); - -} - -void PwmPin::set(uint8_t level){ - ledChannel.duty=level*1023; - ledChannel.duty/=100; - ledChannel.duty&=0x03FF; - ledc_channel_config(&ledChannel); - -} - -/////////////////// - -void PwmPin::HSVtoRGB(float h, float s, float v, float *r, float *g, float *b ){ - - // The algorithm below was provided on the web at https://www.cs.rit.edu/~ncs/color/t_convert.html - // h = [0,360] - // s = [0,1] - // v = [0,1] - - int i; - float f, p, q, t; - - if( s == 0 ){ - *r = *g = *b = v; - return; - } - - h /= 60; - i = floor( h ) ; - f = h - i; - p = v * ( 1 - s ); - q = v * ( 1 - s * f ); - t = v * ( 1 - s * ( 1 - f ) ); - switch( i % 6 ) { - case 0: - *r = v; - *g = t; - *b = p; - break; - case 1: - *r = q; - *g = v; - *b = p; - break; - case 2: - *r = p; - *g = v; - *b = t; - break; - case 3: - *r = p; - *g = q; - *b = v; - break; - case 4: - *r = t; - *g = p; - *b = v; - break; - case 5: - *r = v; - *g = p; - *b = q; - break; - } -} - /////////////////// LedPin::LedPin(uint8_t pin, uint8_t level){ - if(numChannels>15){ + if(numChannels+ServoPin::numChannels>15){ Serial.printf("\n*** ERROR: Can't create LedPin(%d) - no open PWM channels ***\n\n",pin); return; } @@ -127,6 +40,7 @@ LedPin::LedPin(uint8_t pin, uint8_t level){ ledChannel.hpoint=0; ledc_channel_config(&ledChannel); set(level); + //Serial.printf("Configured LED on Pin %d using Channel %d in Speed Mode %d\n",ledChannel.gpio_num,ledChannel.channel,ledChannel.speed_mode); } /////////////////// @@ -201,9 +115,14 @@ void LedPin::HSVtoRGB(float h, float s, float v, float *r, float *g, float *b ){ //////////////////////////// -ServoPin::ServoPin(uint8_t channel, uint8_t pin, double initDegrees, uint16_t minMicros, uint16_t maxMicros, double minDegrees, double maxDegrees){ - this->channel=channel & 0x07; - this->pin=pin; +ServoPin::ServoPin(uint8_t pin, double initDegrees, uint16_t minMicros, uint16_t maxMicros, double minDegrees, double maxDegrees){ + if(numChannels>7 || numChannels>(15-LedPin::numChannels)){ + Serial.printf("\n*** ERROR: Can't create ServoPin(%d) - no open PWM channels ***\n\n",pin); + return; + } + + enabled=true; + this->minMicros=minMicros; this->maxMicros=maxMicros; this->minDegrees=minDegrees; @@ -216,27 +135,129 @@ ServoPin::ServoPin(uint8_t channel, uint8_t pin, double initDegrees, uint16_t mi ledTimer.freq_hz=50; ledc_timer_config(&ledTimer); - ledChannel.gpio_num=pin; - ledChannel.speed_mode=LEDC_HIGH_SPEED_MODE; - ledChannel.channel=(ledc_channel_t)(this->channel); - ledChannel.intr_type=LEDC_INTR_DISABLE; - ledChannel.timer_sel=LEDC_TIMER_1; - ledChannel.hpoint=0; - ledChannel.duty*=micros2duty; + 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); + //Serial.printf("Configured Servo on Pin %d using Channel %d in Speed Mode %d\n",servoChannel.gpio_num,servoChannel.channel,servoChannel.speed_mode); } +/////////////////// + void ServoPin::set(double degrees){ - ledChannel.duty=(degrees-minDegrees)*microsPerDegree+minMicros; + if(!enabled) + return; - if(ledChannel.dutymaxMicros) - ledChannel.duty=maxMicros; + servoChannel.duty=(degrees-minDegrees)*microsPerDegree+minMicros; + + if(servoChannel.dutymaxMicros) + servoChannel.duty=maxMicros; - ledChannel.duty*=micros2duty; - ledc_channel_config(&ledChannel); + servoChannel.duty*=micros2duty; + ledc_channel_config(&servoChannel); } +//////////////////////////// + const double ServoPin::micros2duty=65535.0/20000.0; uint8_t LedPin::numChannels=0; +uint8_t ServoPin::numChannels=0; + +//******************************************************* +// DEPRECATED - INCLUDED FOR BACKWARDS COMPATIBILITY ONLY +//******************************************************* + +PwmPin::PwmPin(uint8_t channel, uint8_t pin){ + this->channel=channel & 0x0F; + this->pin=pin; + + ledc_timer_config_t ledTimer; + ledTimer.timer_num=LEDC_TIMER_0; + ledTimer.speed_mode=(this->channel)<8?LEDC_HIGH_SPEED_MODE:LEDC_LOW_SPEED_MODE; + ledTimer.duty_resolution=LEDC_TIMER_10_BIT; + ledTimer.freq_hz=5000; + ledc_timer_config(&ledTimer); + + ledChannel.gpio_num=pin; + ledChannel.speed_mode=(this->channel)<8?LEDC_HIGH_SPEED_MODE:LEDC_LOW_SPEED_MODE; + ledChannel.channel=(ledc_channel_t)(this->channel&0x07); + ledChannel.intr_type=LEDC_INTR_DISABLE; + ledChannel.timer_sel=LEDC_TIMER_0; + ledChannel.duty=0; + ledChannel.hpoint=0; + ledc_channel_config(&ledChannel); + +} + +/////////////////// + +void PwmPin::set(uint8_t channel, uint8_t level){ + ledChannel.duty=level*1023; + ledChannel.duty/=100; + ledChannel.duty&=0x03FF; + ledc_channel_config(&ledChannel); + +} + +/////////////////// + +void PwmPin::HSVtoRGB(float h, float s, float v, float *r, float *g, float *b ){ + + // The algorithm below was provided on the web at https://www.cs.rit.edu/~ncs/color/t_convert.html + // h = [0,360] + // s = [0,1] + // v = [0,1] + + int i; + float f, p, q, t; + + if( s == 0 ){ + *r = *g = *b = v; + return; + } + + h /= 60; + i = floor( h ) ; + f = h - i; + p = v * ( 1 - s ); + q = v * ( 1 - s * f ); + t = v * ( 1 - s * ( 1 - f ) ); + switch( i % 6 ) { + case 0: + *r = v; + *g = t; + *b = p; + break; + case 1: + *r = q; + *g = v; + *b = p; + break; + case 2: + *r = p; + *g = v; + *b = t; + break; + case 3: + *r = p; + *g = q; + *b = v; + break; + case 4: + *r = t; + *g = p; + *b = v; + break; + case 5: + *r = v; + *g = p; + *b = q; + break; + } +} diff --git a/src/extras/PwmPin.h b/src/extras/PwmPin.h index 509f048..76b79fb 100644 --- a/src/extras/PwmPin.h +++ b/src/extras/PwmPin.h @@ -1,16 +1,69 @@ -///////////////////////////////////// -// PWM Pin Control // -///////////////////////////////////// - -// A wrapper around the ESP-IDF ledc library to easily set the brightness of an LED from 0-100%. -// Can be used for any device requiring a PWM output (not just an LED). Frequency of PWM -// is hardcoded to 5000 Hz and either High-Speed Timer-0 (for channels 0-7) or Low-Speed Timer-0 -// for channels (8-15) is configured and selected automatically. +///////////////////////////////////////////////////////////////////////////////////////////////////////////// +// ----- PWM Pin Control ----- +///////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Wrappers around the ESP-IDF ledc library to control PWM-based devices: +// +// LedPin(pin) - controls a Dimmable LED on specified pin with frequency=5000 Hz +// - use set(level) to set brightness from 0-100% +// +// ServoPin(pin) - controls a Servo Motor on specified pin with frequency=50 Hz +// - use set(degrees) to set position to degrees +// +// Max number of LedPin instantiations: 16 +// Max number of ServoPin instantiatons: 8 +// Max combined limit (LedPins+ServoPins): 16 +// +// Instantiation of an LedPin or ServoPin that causes any of the maximums above to be exceeded throws +// an error message. The object will still be created, but calls to set(level) or set(degrees) are ignored. +// +///////////////////////////////////////////////////////////////////////////////////////////////////////////// #include #include +///////////////////////////////////// + +class LedPin { + boolean enabled=false; + ledc_channel_config_t ledChannel; + + public: + LedPin(uint8_t pin, uint8_t level=0); // assigns pin to be output of one of 16 PWM channels within initial level + void set(uint8_t level); // sets the PWM duty to level (0-100) + int getPin(){return ledChannel.gpio_num;} // returns the pin number + + static uint8_t numChannels; + static void HSVtoRGB(float h, float s, float v, float *r, float *g, float *b ); // converts Hue/Saturation/Brightness to R/G/B +}; + +///////////////////////////////////// + +class ServoPin { + 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; +}; + +//******************************************************* +// DEPRECATED - INCLUDED FOR BACKWARDS COMPATIBILITY ONLY +//******************************************************* + class PwmPin { uint8_t channel; uint8_t pin; @@ -18,48 +71,8 @@ class PwmPin { public: PwmPin(uint8_t channel, uint8_t pin); // assigns pin to be output of one of 16 PWM channels (0-15) - void set(uint8_t level); // sets the PWM duty to level (0-100) - void set(uint8_t channel, uint8_t level){set(level);} // sets the PWM duty to level (0-100) - deprecated, but defined for backwards compatibility + void set(uint8_t channel, uint8_t level); // sets the PWM duty to level (0-100) int getPin(){return pin;} // returns the pin number static void HSVtoRGB(float h, float s, float v, float *r, float *g, float *b ); // converts Hue/Saturation/Brightness to R/G/B - -}; - -///////////////////////////////////// - -class LedPin { - boolean enabled=false; - ledc_channel_config_t ledChannel; - static uint8_t numChannels; - - public: - LedPin(uint8_t pin, uint8_t level=0); // assigns pin to be output of one of 16 PWM channels within initial level - void set(uint8_t level); // sets the PWM duty to level (0-100) - int getPin(){return ledChannel.gpio_num;} // returns the pin number - - static void HSVtoRGB(float h, float s, float v, float *r, float *g, float *b ); // converts Hue/Saturation/Brightness to R/G/B - -}; - -///////////////////////////////////// - -class ServoPin { - uint8_t channel; // channel must be in range [0,7] (only HighSpeed Channels will be used) - uint8_t pin; - uint16_t minMicros; - uint16_t maxMicros; - double minDegrees; - double microsPerDegree; - ledc_channel_config_t ledChannel; - - static const double micros2duty; - - public: - ServoPin(uint8_t channel, uint8_t pin, double initDegrees, uint16_t minMicros, uint16_t maxMicros, double minDegrees, double maxDegrees); - ServoPin(uint8_t channel, uint8_t pin, double initDegrees=0) : ServoPin(channel,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 pin;} // returns the pin number - }; diff --git a/src/extras/extras.ino b/src/extras/extras.ino index 8ce5b29..d68f7a0 100644 --- a/src/extras/extras.ino +++ b/src/extras/extras.ino @@ -5,7 +5,7 @@ #include "PwmPin.h" //ServoPin servo(3,18,-90); -ServoPin servo(3,18,0,500,2200,-90,90); +//ServoPin servo(18,0,500,2200,-90,90); void setup(){ @@ -17,7 +17,7 @@ void setup(){ Serial.println("Starting..."); - LedPin yellow(16); + LedPin yellow(16,10); LedPin d1(19); LedPin d2(19); LedPin d3(19); @@ -30,13 +30,14 @@ void setup(){ LedPin d10(19); LedPin d11(19); LedPin d12(19); - LedPin d13(19); - LedPin d14(19); - LedPin d15(19); - LedPin d16(19); - LedPin red(17); + LedPin red(17,100); - while(1){ +// ServoPin servo(18,0,500,2200,-90,90); + ServoPin s0(19); + ServoPin servo(18,45); + ServoPin s1(19); + + while(0){ for(int i=0;i<100;i++){ yellow.set(i); delay(10); @@ -48,24 +49,21 @@ void setup(){ } } + while(1){ + double STEP=1; + + for(int i=-100*STEP;i<=100*STEP;i++){ + servo.set((double)i/STEP); + delay(10); + } + + for(int i=100*STEP;i>=-100*STEP;i--){ + servo.set((double)i/STEP); + delay(10); + } + } + } void loop(){ - - -// double STEP=1; -// -// for(int i=-100*STEP;i<=100*STEP;i++){ -// servo.set((double)i/STEP); -// delay(10); -// } -// -// for(int i=100*STEP;i>=-100*STEP;i--){ -// servo.set((double)i/STEP); -// delay(10); -// } - -// return; - - }