# Motor test program

A project log for HF Short loop antennas: managing expectations

Make a portable loop antenna that works well on 40 meters, then make it autotune.

Andrew Mitz 09/10/2019 at 15:170 Comments

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;
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

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 (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

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 (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