Close

Motor test program

A project log for Basic HF Short loop antenna and some design notes

A portable loop antenna that works well on 40 through 10 meters. This basic design is advanced in my other projects.

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