Re-working PWM routines

This commit is contained in:
HomeSpan 2021-09-12 09:23:29 -05:00
parent 8d45e20671
commit a5d31b1ea5
5 changed files with 113 additions and 89 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

BIN
src/.DS_Store vendored Normal file

Binary file not shown.

View File

@ -3,56 +3,75 @@
///////////////////
LedPin::LedPin(uint8_t pin, uint8_t level){
if(numChannels+ServoPin::numChannels>15){
Serial.printf("\n*** ERROR: Can't create LedPin(%d) - no open PWM channels ***\n\n",pin);
ledChannel.gpio_num=0;
return;
LedPin::LedPin(uint8_t pin, uint8_t level, uint16_t freq){
if(freq==0)
freq=DEFAULT_PWM_FREQ;
for(int nMode=0;nMode<LEDC_SPEED_MODE_MAX;nMode++){
for(int nChannel=0;nChannel<LEDC_CHANNEL_MAX;nChannel++){
for(int nTimer=0;nTimer<LEDC_TIMER_MAX;nTimer++){
if(!channelList[nChannel][nMode]){
if(!timerList[nTimer][nMode]){ // if this timer slot is free, use it
timerList[nTimer][nMode]=new ledc_timer_config_t; // create new timer instance
timerList[nTimer][nMode]->speed_mode=(ledc_mode_t)nMode;
timerList[nTimer][nMode]->timer_num=(ledc_timer_t)nTimer;
timerList[nTimer][nMode]->freq_hz=freq;
int res=20; // find the maximum possible resolution
while(getApbFrequency()/(freq*pow(2,res))<1)
res--;
timerList[nTimer][nMode]->duty_resolution=(ledc_timer_bit_t)res;
ledc_timer_config(timerList[nTimer][nMode]);
}
if(timerList[nTimer][nMode]->freq_hz==freq){ // if timer matches desired frequency (always true if newly-created above)
channelList[nChannel][nMode]=new ledc_channel_config_t; // create new channel instance
channelList[nChannel][nMode]->speed_mode=(ledc_mode_t)nMode;
channelList[nChannel][nMode]->channel=(ledc_channel_t)nChannel;
channelList[nChannel][nMode]->timer_sel=(ledc_timer_t)nTimer;
channelList[nChannel][nMode]->intr_type=LEDC_INTR_DISABLE;
channelList[nChannel][nMode]->hpoint=0;
channelList[nChannel][nMode]->gpio_num=pin;
ledTimer=timerList[nTimer][nMode];
ledChannel=channelList[nChannel][nMode];
set(level);
return;
}
}
}
}
}
enabled=true;
Serial.printf("\n*** ERROR: Can't create LedPin(%d) - no open PWM channels and/or Timers ***\n\n",pin);
if(numChannels==0){ // first instantiation of an LedPin
ledc_timer_config_t ledTimer;
ledTimer.timer_num=LEDC_TIMER_0;
ledTimer.duty_resolution=LEDC_TIMER_10_BIT;
ledTimer.freq_hz=5000;
ledTimer.speed_mode=LEDC_HIGH_SPEED_MODE; // configure both the HIGH-Speed Timer 0 and Low-Speed Timer 0
ledc_timer_config(&ledTimer);
ledTimer.speed_mode=LEDC_LOW_SPEED_MODE;
ledc_timer_config(&ledTimer);
}
ledChannel.gpio_num=pin;
if(numChannels<8){
ledChannel.speed_mode=LEDC_LOW_SPEED_MODE;
ledChannel.channel=(ledc_channel_t)(7-numChannels);
} else {
ledChannel.speed_mode=LEDC_HIGH_SPEED_MODE;
ledChannel.channel=(ledc_channel_t)(15-numChannels);
}
numChannels++;
ledChannel.intr_type=LEDC_INTR_DISABLE;
ledChannel.timer_sel=LEDC_TIMER_0;
ledChannel.hpoint=0;
ledc_channel_config(&ledChannel);
set(level);
}
///////////////////
void LedPin::set(uint8_t level){
if(!enabled)
if(!ledChannel)
return;
ledChannel.duty=level*1023;
ledChannel.duty/=100;
ledChannel.duty&=0x03FF;
ledc_channel_config(&ledChannel);
Serial.printf("pin=%d, ch=%d, mode=%d, timer=%d, freq=%d, res=%d\n",
ledChannel->gpio_num,
ledChannel->channel,
ledChannel->speed_mode,
ledChannel->timer_sel,
ledTimer->freq_hz,
ledTimer->duty_resolution
);
if(level>100)
level=100;
ledChannel->duty=level*(pow(2,ledTimer->duty_resolution)-1);
ledChannel->duty/=100;
ledc_channel_config(ledChannel);
}
@ -170,6 +189,10 @@ void ServoPin::set(double degrees){
const double ServoPin::micros2duty=65535.0/20000.0;
uint8_t LedPin::numChannels=0;
uint8_t ServoPin::numChannels=0;
uint8_t LedC::nChannels=0;
vector<ledc_timer_config_t> LedC::timers;
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

View File

@ -22,17 +22,33 @@
#include <Arduino.h>
#include <driver/ledc.h>
#include <vector>
using std::vector;
#define DEFAULT_PWM_FREQ 5000
/////////////////////////////////////
class LedPin {
boolean enabled=false;
ledc_channel_config_t ledChannel;
class LedC {
protected:
static uint8_t nChannels;
static vector<ledc_timer_config_t> timers;
static ledc_channel_config_t *channelList[LEDC_CHANNEL_MAX][LEDC_SPEED_MODE_MAX];
static ledc_timer_config_t *timerList[LEDC_TIMER_MAX][LEDC_SPEED_MODE_MAX];
};
/////////////////////////////////////
class LedPin : LedC {
ledc_channel_config_t *ledChannel=NULL;
ledc_timer_config_t *ledTimer;
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
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)
int getPin(){return(ledChannel?ledChannel->gpio_num:-1);} // 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

View File

@ -3,6 +3,7 @@
// as well as compile and test from this point. This file is ignored when the library is included in other sketches.
#include "PwmPin.h"
#include <soc/ledc_reg.h>
void setup(){
@ -13,53 +14,37 @@ void setup(){
Serial.println("Starting...");
LedPin led0(18,100,0);
LedPin led1(19,100,2000);
LedPin led2(16,10,80000);
LedPin led3(17,100,2000);
LedPin led4(23);
LedPin led5(22,0,3000);
LedPin led6(14,0,1);
LedPin led7(32,0,1850);
LedPin led8(15);
LedPin led9(33);
LedPin led10(27);
LedPin led11(12,100,23);
LedPin led12(13,100);
LedPin led13(26);
LedPin led14(25,0);
LedPin led15(4,0);
LedPin led16(5,0);
LedPin yellow(16,10);
LedPin d1(19);
LedPin d2(19);
LedPin d3(19);
LedPin d4(19);
LedPin d5(19);
LedPin d6(19);
LedPin d7(19);
LedPin d8(19);
LedPin d9(19);
LedPin d10(19);
LedPin d11(19);
LedPin d12(19);
LedPin red(17);
led16.set(20);
led0.set(5);
led2.set(100);
// ServoPin servo(18,0,500,2200,-90,90);
ServoPin s0(19);
ServoPin servo(18,45);
ServoPin s1(19);
uint32_t v=REG_READ(LEDC_HSTIMER0_CONF_REG);
Serial.printf("HS %d %d %d %d\n",(v>>25)&1,v&0x1f,(v>>13)&0x3FF,(v>>5)&0xFF);
while(1){
for(int i=0;i<100;i++){
yellow.set(i);
delay(10);
}
v=REG_READ(LEDC_LSTIMER0_CONF_REG);
Serial.printf("LS %d %d %d %d %d\n",(v>>25)&1,v&0x1f,(v>>13)&0x3FF,(v>>5)&0xFF,REG_READ(LEDC_CONF_REG));
for(int i=100;i>=0;i--){
red.set(i);
delay(10);
}
}
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);
}
}
while(1);
}
void loop(){