I'm getting some strange behaviour with this, that maybe somebody could help with please?
The purpose of the code is to cycle sequentially though 11 different configurations, with each configuration (I call it a crank position) calling for 3 out of 11 PWM channels to be activated. A different 3 channels for each crank position. I don't have much experience of using timers, or coding in general.
The behavior I am trying for is that the crank position should cycle through positions every 50ms then when it gets to position 11 should go back to position 1, so a cycle time of 550ms. The problem is that I am not getting PWM on the last 3 channels (8,9,10), so not reaching Crank Pos 7.
I checked things in general before introducing the Crank feature by just pulsing each channel simultaneously and attaching to LEDs and that worked fine, so I now I'm connected to pins that can be PWM'd. I don't have a scope unfortunately.
I experimented with changing the "if (gCrankPos >= 11) gCrankPos = 0;" down from 11, and it does behave to fire less of the channels, but increasing has no effect.
Debugging is proving tricky also because the serial monitor doesn't seem to be working properly for some reason. I don't know if related or not, but it works no probs with simple sketches. Baud rates math but output looks similar to when they don't. Output sample:
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode: DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:808
load:0x40078000,len:6084
load:0x40080000,len:6696
entry 0x400802e4
The ààààààààààààààààà
Then it just repeats that last character forever.
The Code:
The purpose of the code is to cycle sequentially though 11 different configurations, with each configuration (I call it a crank position) calling for 3 out of 11 PWM channels to be activated. A different 3 channels for each crank position. I don't have much experience of using timers, or coding in general.
The behavior I am trying for is that the crank position should cycle through positions every 50ms then when it gets to position 11 should go back to position 1, so a cycle time of 550ms. The problem is that I am not getting PWM on the last 3 channels (8,9,10), so not reaching Crank Pos 7.
I checked things in general before introducing the Crank feature by just pulsing each channel simultaneously and attaching to LEDs and that worked fine, so I now I'm connected to pins that can be PWM'd. I don't have a scope unfortunately.
I experimented with changing the "if (gCrankPos >= 11) gCrankPos = 0;" down from 11, and it does behave to fire less of the channels, but increasing has no effect.
Debugging is proving tricky also because the serial monitor doesn't seem to be working properly for some reason. I don't know if related or not, but it works no probs with simple sketches. Baud rates math but output looks similar to when they don't. Output sample:
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode: DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:808
load:0x40078000,len:6084
load:0x40080000,len:6696
entry 0x400802e4
The ààààààààààààààààà
Then it just repeats that last character forever.
The Code:
C:
// test5 is for 11 channel open loop speed control with crank duration to set speed. no (or untested) termistor and current sense
// initiallise the timer conditions
hw_timer_t * timer = NULL;
hw_timer_t * timer2 = NULL;
volatile bool gGetADCflag;
volatile bool gCrankPosChangeflag;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
// PWMs are for 11 channel individual Mosfets
// setting things up for PWM out - use first channel of 16 channels (started from zero)
#define LEDC_CHANNEL_0 0
#define LEDC_CHANNEL_1 1
#define LEDC_CHANNEL_2 2
#define LEDC_CHANNEL_3 3
#define LEDC_CHANNEL_4 4
#define LEDC_CHANNEL_5 5
#define LEDC_CHANNEL_6 6
#define LEDC_CHANNEL_7 7
#define LEDC_CHANNEL_8 8
#define LEDC_CHANNEL_9 9
#define LEDC_CHANNEL_10 10
// use 13 bit precission for LEDC timer
#define LEDC_TIMER_13_BIT 13
// use 5000 Hz as a LEDC base frequency
#define LEDC_BASE_FREQ 25000 // max frequency for IBT-2 is 25kHz
// fade LED PIN (replace with LED_BUILTIN constant for built-in LED)
#define PWM1 21
#define PWM2 1
#define PWM3 3
#define PWM4 22
#define PWM5 19
#define PWM6 23
#define PWM7 18
#define PWM8 5
#define PWM9 15
#define PWM10 25
#define PWM11 33
unsigned long durationNow = 0;
unsigned long previous = 0;
int PWMVal = 120; // 0-255
int analog_value = 0; // 0-4095
int outputValue = 0; // value output to the PWM (analog out)
int rateOfChange = 0; // Capture the rate of change of the input at each time step (in theory could be a deimal but if <1 then 0 is fine)
int rateLimit = 50; // ADC increments
int oldDemand = 0;
int newDemand = 0;
int mAmp = 0;
String gcommand;
int gDuty=0;
int gCrankPos = 1; // initialisation of the crank position (1-11 variable)
// timer related functions
void ADCTimer(){
gGetADCflag = true;
}
void startADCTimer() {
timer = timerBegin(0, 80, true); // timer_id = 0; divider=80; countUp = true;
timerAttachInterrupt(timer, &ADCTimer, true); // edge = true
timerAlarmWrite(timer, 1000, true); //1 ms
timerAlarmEnable(timer);
}
void endADCTimer() {
timerEnd(timer);
timer = NULL;
}
void crankTimer(){
gCrankPosChangeflag = true;
}
void startCrankTimer() {
timer2 = timerBegin(1, 80, true); // timer_id = 1; divider=80; countUp = true;
timerAttachInterrupt(timer2, &crankTimer, true); // edge = true
timerAlarmWrite(timer2, 50000, true); //50 ms (0.5s)
timerAlarmEnable(timer2);
}
void endCrankTimer() {
timerEnd(timer2);
timer2 = NULL;
}
void incCrankPos(){
// anything in here that involves shifting around the 11 channel postions
Serial.print("Crank Pos: ");
Serial.println(gCrankPos);
if (gCrankPos >= 11) gCrankPos = 0;
gCrankPos++; //
gCrankPosChangeflag = false;
}
/*
// the function that get's Called once the Timer Interrupt flag is True
void getADC() {
// do suff in here that runs outside of the ISR but is triggered by the ISR
// the timer should be set so that it triggers 10x faster than the data tare you want to see, as it will be averaged then thrown away every 10 cycles
// Note that this simplified approach will introduce a phase shift or delay to the figures, as the average figure is being reported against the final sample timestamp. a rolling average should be used if needs to be avoided
// any variables that need to not be reset each time the function is called need to be declared as static
static unsigned int counter = 1;
static int rawInput[NOOFAVERAGES] = {0}; // array for storing the 10 values
static int aveADC = 0; // variable for storing the potentiometer value
static int sumInput = 0; // variable to hold the sum of inputs prior to averaging
static int current1 = 0; // convert ADC counts to current mA, with offset and multiplier
static int offset1 = -210; // ADC offset for 1st ACS725 sensor
rawInput[counter-1] = analogRead(ANALOG_PIN_1);
sumInput = sumInput + rawInput[counter-1];
// take the NOOFAVERAGES readings from the Array and average them
if (counter == NOOFAVERAGES){
aveADC = sumInput/NOOFAVERAGES; // add up and divide by 10
current1 = (aveADC+offset1)*1000/300; // Convert ADC to mA, 264mV/A - chaged to 300mV/A
Serial.print("ADCTimer ");
Serial.print(counter);
Serial.print(" at ");
Serial.print(millis());
Serial.print(" ms ");
Serial.print(" ADC value ");
Serial.print(aveADC);
Serial.print(" Current(mA) ");
Serial.println(current1);
sumInput = 0;
counter = 0;
}
gGetADCflag = false;
counter++;
}
*/
// Arduino like analogWrite
// value has to be between 0 and valueMax
void ledcAnalogWrite(uint8_t channel, uint32_t value, uint32_t valueMax = 255) {
// calculate duty, 8191 from 2 ^ 13 - 1
uint32_t duty = (8191 / valueMax) * min(value, valueMax);
// write duty to LEDC
ledcWrite(channel, duty);
}
void setup() {
delay(1000);
Serial.begin(115200);
delay(1000);
// SerialBT.begin("ESP32hula"); //Bluetooth device name
Serial.println("The device started, now you can pair it with bluetooth!");
// Setup timer and attach timer to a pwm pin
ledcSetup(LEDC_CHANNEL_0, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT);
ledcSetup(LEDC_CHANNEL_1, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT);
ledcSetup(LEDC_CHANNEL_2, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT);
ledcSetup(LEDC_CHANNEL_3, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT);
ledcSetup(LEDC_CHANNEL_4, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT);
ledcSetup(LEDC_CHANNEL_5, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT);
ledcSetup(LEDC_CHANNEL_6, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT);
ledcSetup(LEDC_CHANNEL_7, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT);
ledcSetup(LEDC_CHANNEL_8, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT);
ledcSetup(LEDC_CHANNEL_9, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT);
ledcSetup(LEDC_CHANNEL_10, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT);
ledcAttachPin(PWM1, LEDC_CHANNEL_0);
ledcAttachPin(PWM2, LEDC_CHANNEL_1);
ledcAttachPin(PWM3, LEDC_CHANNEL_2);
ledcAttachPin(PWM4, LEDC_CHANNEL_3);
ledcAttachPin(PWM5, LEDC_CHANNEL_4);
ledcAttachPin(PWM6, LEDC_CHANNEL_5);
ledcAttachPin(PWM7, LEDC_CHANNEL_6);
ledcAttachPin(PWM8, LEDC_CHANNEL_7);
ledcAttachPin(PWM9, LEDC_CHANNEL_8);
ledcAttachPin(PWM10, LEDC_CHANNEL_9);
ledcAttachPin(PWM11, LEDC_CHANNEL_10);
// pinMode(ANALOG_PIN_0, INPUT);
// pinMode(ANALOG_PIN_1, INPUT);
// analogSetPinAttenuation(ANALOG_PIN_1, ADC_11db); // for ESP32 max vooltages are 0db = 1.1v, 2.5db = 1.4v, 6db = 1.9v, 11db = 3.2v, representing 4095 ADC (12bit)
Serial.println("pin modes set");
startADCTimer();
startCrankTimer();
delay(1000);
Serial.println("exiting setup");
}
/*
void parseCommand (String com) {
String part1;
String part2;
// split into 2 parts. 1st part will be a letter, either an override status or a motor speed change. 2nd part will be either override on/off or motor speed 0-100.
part1 = com.substring(0,1);
part2 = com.substring(1,com.indexOf("."));
// Serial.print("part1= ");
// Serial.println(part1);
// Serial.print("part2= ");
// Serial.println(part2);
if (part1.equalsIgnoreCase("o")){
gOverrideStatus = part2.toInt(); // change the global override status to either 1 or 0;
// Serial.print("gOverride status changed to ");
// Serial.println(gOverrideStatus);
}
else if(part1.equalsIgnoreCase("v")){
if (gOverrideStatus == 1){
gDuty = part2.toInt();
// Serial.print("duty (%) changed to ");
// Serial.println(gDuty);
}
}
else{
part1="";
part2="";
gcommand="";
}
}
*/
/*
int rateLimiter(int latestValue){
durationNow = millis();
// check the input value:
int sensorValue = latestValue;
newDemand = sensorValue;
rateOfChange = (newDemand-oldDemand)/(durationNow-previous);
if (rateOfChange > rateLimit)
{
if (newDemand>oldDemand)
{
newDemand = oldDemand+rateLimit;
}
if (newDemand<=oldDemand)
{
newDemand = oldDemand-rateLimit;
}
}
else
{
newDemand = newDemand;
}
//reset for next loop
oldDemand = newDemand;
previous = durationNow;
return newDemand;
}
*/
void loop() {
// Reading ADC value (current sense input)
if (gGetADCflag == true) {
// Serial.println("ADCFlag = TRUE");
// getADC();
}
if (gCrankPosChangeflag == true) {
incCrankPos();
}
// check motor speed is within acceptable boundaries and limit
if (PWMVal <= 0){
PWMVal = 0;
}
if (PWMVal >120){
PWMVal = 120; // set to be approx 2A max (true maximum 255, but would result in peak current draw)
}
// call PWM funtions for each coil
// use switch cases depeding on crank position
switch (gCrankPos) {
case 1:
ledcAnalogWrite(LEDC_CHANNEL_0, PWMVal);
ledcAnalogWrite(LEDC_CHANNEL_1, PWMVal);
ledcAnalogWrite(LEDC_CHANNEL_2, PWMVal);
ledcAnalogWrite(LEDC_CHANNEL_3, 0);
ledcAnalogWrite(LEDC_CHANNEL_4, 0);
ledcAnalogWrite(LEDC_CHANNEL_5, 0);
ledcAnalogWrite(LEDC_CHANNEL_6, 0);
ledcAnalogWrite(LEDC_CHANNEL_7, 0);
ledcAnalogWrite(LEDC_CHANNEL_8, 0);
ledcAnalogWrite(LEDC_CHANNEL_9, 0);
ledcAnalogWrite(LEDC_CHANNEL_10, 0);
break;
case 2:
ledcAnalogWrite(LEDC_CHANNEL_0, 0);
ledcAnalogWrite(LEDC_CHANNEL_1, PWMVal);
ledcAnalogWrite(LEDC_CHANNEL_2, PWMVal);
ledcAnalogWrite(LEDC_CHANNEL_3, PWMVal);
ledcAnalogWrite(LEDC_CHANNEL_4, 0);
ledcAnalogWrite(LEDC_CHANNEL_5, 0);
ledcAnalogWrite(LEDC_CHANNEL_6, 0);
ledcAnalogWrite(LEDC_CHANNEL_7, 0);
ledcAnalogWrite(LEDC_CHANNEL_8, 0);
ledcAnalogWrite(LEDC_CHANNEL_9, 0);
ledcAnalogWrite(LEDC_CHANNEL_10, 0);
break;
case 3:
ledcAnalogWrite(LEDC_CHANNEL_0, 0);
ledcAnalogWrite(LEDC_CHANNEL_1, 0);
ledcAnalogWrite(LEDC_CHANNEL_2, PWMVal);
ledcAnalogWrite(LEDC_CHANNEL_3, PWMVal);
ledcAnalogWrite(LEDC_CHANNEL_4, PWMVal);
ledcAnalogWrite(LEDC_CHANNEL_5, 0);
ledcAnalogWrite(LEDC_CHANNEL_6, 0);
ledcAnalogWrite(LEDC_CHANNEL_7, 0);
ledcAnalogWrite(LEDC_CHANNEL_8, 0);
ledcAnalogWrite(LEDC_CHANNEL_9, 0);
ledcAnalogWrite(LEDC_CHANNEL_10, 0);
break;
case 4:
ledcAnalogWrite(LEDC_CHANNEL_0, 0);
ledcAnalogWrite(LEDC_CHANNEL_1, 0);
ledcAnalogWrite(LEDC_CHANNEL_2, 0);
ledcAnalogWrite(LEDC_CHANNEL_3, PWMVal);
ledcAnalogWrite(LEDC_CHANNEL_4, PWMVal);
ledcAnalogWrite(LEDC_CHANNEL_5, PWMVal);
ledcAnalogWrite(LEDC_CHANNEL_6, 0);
ledcAnalogWrite(LEDC_CHANNEL_7, 0);
ledcAnalogWrite(LEDC_CHANNEL_8, 0);
ledcAnalogWrite(LEDC_CHANNEL_9, 0);
ledcAnalogWrite(LEDC_CHANNEL_10, 0);
break;
case 5:
ledcAnalogWrite(LEDC_CHANNEL_0, 0);
ledcAnalogWrite(LEDC_CHANNEL_1, 0);
ledcAnalogWrite(LEDC_CHANNEL_2, 0);
ledcAnalogWrite(LEDC_CHANNEL_3, 0);
ledcAnalogWrite(LEDC_CHANNEL_4, PWMVal);
ledcAnalogWrite(LEDC_CHANNEL_5, PWMVal);
ledcAnalogWrite(LEDC_CHANNEL_6, PWMVal);
ledcAnalogWrite(LEDC_CHANNEL_7, 0);
ledcAnalogWrite(LEDC_CHANNEL_8, 0);
ledcAnalogWrite(LEDC_CHANNEL_9, 0);
ledcAnalogWrite(LEDC_CHANNEL_10, 0);
break;
case 6:
ledcAnalogWrite(LEDC_CHANNEL_0, 0);
ledcAnalogWrite(LEDC_CHANNEL_1, 0);
ledcAnalogWrite(LEDC_CHANNEL_2, 0);
ledcAnalogWrite(LEDC_CHANNEL_3, 0);
ledcAnalogWrite(LEDC_CHANNEL_4, 0);
ledcAnalogWrite(LEDC_CHANNEL_5, PWMVal);
ledcAnalogWrite(LEDC_CHANNEL_6, PWMVal);
ledcAnalogWrite(LEDC_CHANNEL_7, PWMVal);
ledcAnalogWrite(LEDC_CHANNEL_8, 0);
ledcAnalogWrite(LEDC_CHANNEL_9, 0);
ledcAnalogWrite(LEDC_CHANNEL_10, 0);
break;
case 7:
ledcAnalogWrite(LEDC_CHANNEL_0, 0);
ledcAnalogWrite(LEDC_CHANNEL_1, 0);
ledcAnalogWrite(LEDC_CHANNEL_2, 0);
ledcAnalogWrite(LEDC_CHANNEL_3, 0);
ledcAnalogWrite(LEDC_CHANNEL_4, 0);
ledcAnalogWrite(LEDC_CHANNEL_5, 0);
ledcAnalogWrite(LEDC_CHANNEL_6, PWMVal);
ledcAnalogWrite(LEDC_CHANNEL_7, PWMVal);
ledcAnalogWrite(LEDC_CHANNEL_8, PWMVal);
ledcAnalogWrite(LEDC_CHANNEL_9, 0);
ledcAnalogWrite(LEDC_CHANNEL_10, 0);
break;
case 8:
ledcAnalogWrite(LEDC_CHANNEL_0, 0);
ledcAnalogWrite(LEDC_CHANNEL_1, 0);
ledcAnalogWrite(LEDC_CHANNEL_2, 0);
ledcAnalogWrite(LEDC_CHANNEL_3, 0);
ledcAnalogWrite(LEDC_CHANNEL_4, 0);
ledcAnalogWrite(LEDC_CHANNEL_5, 0);
ledcAnalogWrite(LEDC_CHANNEL_6, 0);
ledcAnalogWrite(LEDC_CHANNEL_7, PWMVal);
ledcAnalogWrite(LEDC_CHANNEL_8, PWMVal);
ledcAnalogWrite(LEDC_CHANNEL_9, PWMVal);
ledcAnalogWrite(LEDC_CHANNEL_10, 0);
break;
case 9:
ledcAnalogWrite(LEDC_CHANNEL_0, 0);
ledcAnalogWrite(LEDC_CHANNEL_1, 0);
ledcAnalogWrite(LEDC_CHANNEL_2, 0);
ledcAnalogWrite(LEDC_CHANNEL_3, 0);
ledcAnalogWrite(LEDC_CHANNEL_4, 0);
ledcAnalogWrite(LEDC_CHANNEL_5, 0);
ledcAnalogWrite(LEDC_CHANNEL_6, 0);
ledcAnalogWrite(LEDC_CHANNEL_7, 0);
ledcAnalogWrite(LEDC_CHANNEL_8, PWMVal);
ledcAnalogWrite(LEDC_CHANNEL_9, PWMVal);
ledcAnalogWrite(LEDC_CHANNEL_10, PWMVal);
break;
case 10:
ledcAnalogWrite(LEDC_CHANNEL_0, PWMVal);
ledcAnalogWrite(LEDC_CHANNEL_1, 0);
ledcAnalogWrite(LEDC_CHANNEL_2, 0);
ledcAnalogWrite(LEDC_CHANNEL_3, 0);
ledcAnalogWrite(LEDC_CHANNEL_4, 0);
ledcAnalogWrite(LEDC_CHANNEL_5, 0);
ledcAnalogWrite(LEDC_CHANNEL_6, 0);
ledcAnalogWrite(LEDC_CHANNEL_7, 0);
ledcAnalogWrite(LEDC_CHANNEL_8, 0);
ledcAnalogWrite(LEDC_CHANNEL_9, PWMVal);
ledcAnalogWrite(LEDC_CHANNEL_10, PWMVal);
break;
case 11:
ledcAnalogWrite(LEDC_CHANNEL_0, PWMVal);
ledcAnalogWrite(LEDC_CHANNEL_1, PWMVal);
ledcAnalogWrite(LEDC_CHANNEL_2, 0);
ledcAnalogWrite(LEDC_CHANNEL_3, 0);
ledcAnalogWrite(LEDC_CHANNEL_4, 0);
ledcAnalogWrite(LEDC_CHANNEL_5, 0);
ledcAnalogWrite(LEDC_CHANNEL_6, 0);
ledcAnalogWrite(LEDC_CHANNEL_7, 0);
ledcAnalogWrite(LEDC_CHANNEL_8, 0);
ledcAnalogWrite(LEDC_CHANNEL_9, 0);
ledcAnalogWrite(LEDC_CHANNEL_10, PWMVal);
break;
default:
// if nothing else matches, do the default
ledcAnalogWrite(LEDC_CHANNEL_0, 0);
ledcAnalogWrite(LEDC_CHANNEL_1, 0);
ledcAnalogWrite(LEDC_CHANNEL_2, 0);
ledcAnalogWrite(LEDC_CHANNEL_3, 0);
ledcAnalogWrite(LEDC_CHANNEL_4, 0);
ledcAnalogWrite(LEDC_CHANNEL_5, 0);
ledcAnalogWrite(LEDC_CHANNEL_6, 0);
ledcAnalogWrite(LEDC_CHANNEL_7, 0);
ledcAnalogWrite(LEDC_CHANNEL_8, 0);
ledcAnalogWrite(LEDC_CHANNEL_9, 0);
ledcAnalogWrite(LEDC_CHANNEL_10, 0);
break;
}
}
Last edited by a moderator: