Motor test program
Since the last update, I finished writing a motor test program. The documentation and examples for ESP32 Arduino PWM (called ledc, because it was intended for controlling LEDs) are unclear. Using a PWM frequency of 30 KHz and a 8 bit resolution, I can get control of the motor speed reasonably well. I found that useful speeds range from PWM of 50% to 100% duty cycle. The examples on the Internet have bugs. It was actually unclear from the documentation if a PWM value of 0 is full ON or full OFF. Since I am using a H-bridge to run the motor forwards and backwards, I discovered that a PWM of 0 is required for the LOW side of the bridge. During the first testing I was unable to get the ADC to record motor stall (high current), so I am not monitoring current at the moment.
// MotorTest - A. Mitz
// Much of the code from SparkFun Thing Power Control Shield
// Spin the motor from low to high speed, then do same in reverse.
// Pins defined by ESP32 Thing and the Power Control Shield
#define CTRL_1 25 // Output 1 (Motor -)
#define CTRL_2 18 // Output 2 (Motor +)
#define forward true
#define reverse false
unsigned long timer_count;
unsigned long timer_done;
int adcVal = 0;
boolean runMode; // 0-Forward, 1-Reverse
// Useful motor speeds based on PWM controller
// index 0 to 6. Value of 0 is OFF. Value of 6 is full speed
// approx: 0=off, 1=50%, 2=60%, 3=70%, 4=80%, 5=90%, 6=100%
const int MOTORSPEED[] = {255, 125, 100, 75, 50, 25, 0}; // useful speeds from 0 to fast
const int MAXSPEED = 6;
int speed;
// PWM settings
const int PWM_freq = 30000; // 30KHz
const int PWM_resolution = 8; // Number of bits of resolution (8 bits = 0 to 255)
// Setting for forward direction PWM
const int forward_PWM_Channel = 0; // chan 0 to 15
int forward_dutyCycle = 255; // Max for 8 bits
// Setting for reverse direction PWM
const int reverse_PWM_Channel = 1; // chan 0 to 15
int reverse_dutyCycle = 255; // Max for 8 bits
void setup() {
// Initialize UART
Serial.begin(115200);
// Initialize driver pins
pinMode(CTRL_1,OUTPUT); // Forward part of H bridge
pinMode(CTRL_2,OUTPUT); // Reverse part of H bridge
// configure PWMs
ledcSetup(forward_PWM_Channel, PWM_freq, PWM_resolution);
ledcSetup(reverse_PWM_Channel, PWM_freq, PWM_resolution);
ledcAttachPin(CTRL_1, forward_PWM_Channel);
ledcAttachPin(CTRL_2, reverse_PWM_Channel);
// Initialize timer
timer_done = millis()+4000; // 4 seconds
// Initialize motor direction
runMode = forward;
speed = MAXSPEED;
forward_dutyCycle = MOTORSPEED[MAXSPEED];
reverse_dutyCycle = MOTORSPEED[MAXSPEED];
ledcWrite(forward_PWM_Channel, MOTORSPEED[MAXSPEED] );
ledcWrite(reverse_PWM_Channel, MOTORSPEED[MAXSPEED] );
digitalWrite(CTRL_1,HIGH);
digitalWrite(CTRL_2,LOW);
delay(250); // delay (during current spike) in case ADC is used
Serial.println("Initialization done");
} // setup
void loop() {
// -- timer service -- //
timer_count = millis(); // get ms since program started
if (runMode == forward) {
/* Does not work
// Sample I-Sense 2
adcVal = analogRead(34); // hard-wired port
Serial.println(adcVal);
if(adcVal > 100) { // see if the motor is stuck
runMode = reverse; // Reverse if stuck
// Stop motor for 1 second
digitalWrite(CTRL_1,LOW);
digitalWrite(CTRL_2,LOW);
delay(1000);
timer_done = timer_count+2000; // restart timer
digitalWrite(CTRL_1,LOW);
digitalWrite(CTRL_2,HIGH);
delay(250); // delay (during current spike)
} // if adcValue
*/
if (timer_count >= timer_done) { // Next slower step?
speed--; // Slow down
Serial.print("Forward speed = "); Serial.println(speed);
if (speed == 0) { // time to reverse?
// Stop motor for 1 second
Serial.println("Range done. Stop motor");
digitalWrite(CTRL_1,LOW);
digitalWrite(CTRL_2,LOW);
delay(1000);
// reverse
Serial.println("Reversing");
runMode = reverse; // Reverse direction
speed = MAXSPEED;
ledcWrite(forward_PWM_Channel, MOTORSPEED[0] ); // Low output set to zero
ledcWrite(reverse_PWM_Channel, MOTORSPEED[speed] );
digitalWrite(CTRL_1,LOW);
digitalWrite(CTRL_2,HIGH);
delay(250); // delay to prevent current spike from giving a false positive on the ADC
Serial.print("Reverse Speed = "); Serial.println(speed);
// Initialize timer for reverse direction
timer_done = millis()+4000; // 4 seconds
}
else { // slow down
Serial.println("Slowing");
ledcWrite(forward_PWM_Channel, MOTORSPEED[speed]);
timer_done = millis()+4000; // 4 seconds
}
} // if timer_count done
} // run mode forward
else { // Reverse
/* Does not work
// Sample I-Sense 2
adcVal = analogRead(34);
Serial.println(adcVal);
if(adcVal > 100) {
runMode = forward; // reverse to Forward
// Stop motor for 1 second
digitalWrite(CTRL_1,LOW);
digitalWrite(CTRL_2,LOW);
delay(1000);
timer_done = timer_count+2000; // restart timer
digitalWrite(CTRL_1,HIGH);
digitalWrite(CTRL_2,LOW);
delay(250); // delay (during current spike)
} // if adcVal
*/
if (timer_count >= timer_done) { // Next slower step?
speed--; // Slow down
Serial.print("Reverse speed = "); Serial.println(speed);
if (speed == 0) { // time to reverse (back to forward)?
// Stop motor for 1 second
Serial.println("Range done. Stop motor");
digitalWrite(CTRL_1,LOW);
digitalWrite(CTRL_2,LOW);
delay(1000);
// reverse to forward direction
Serial.println("Reversing to forward direction");
runMode = forward;
speed = MAXSPEED;
ledcWrite(forward_PWM_Channel, MOTORSPEED[speed]);
ledcWrite(reverse_PWM_Channel, MOTORSPEED[0]); // Low output set to zero
digitalWrite(CTRL_1,HIGH);
digitalWrite(CTRL_2,LOW);
delay(250); // delay to prevent current spike from giving a false positive on the ADC
// Initialize timer for forward direction
Serial.print("Forward Speed = "); Serial.println(speed);
timer_done = millis()+4000; // 4 seconds
}
else { // slow down
Serial.println("Slowing");
ledcWrite(reverse_PWM_Channel, MOTORSPEED[speed]);
timer_done = millis()+4000; // 4 seconds
}
} // timer done
} // else reverse
} // loop
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.