Quadcopter Motor Test

29 Jun.,2022

Once the quadcopter is fully assembled and you’ve been able to verify that you can communicate with

 

Brushless Motor Tester

Once the quadcopter is fully assembled and you’ve been able to verify that you can communicate with the flight controller, you’ll likely want to make sure all your soldering actually worked, and you can command the motors to move.

The following code sketch can be used to perform a simple motor test by manually commanding their PWM value through the APM flight controller. This can also be useful if you would like to calibrate the ESCs without having a RC receiver connected to the flight controller. Generally the PWM range of the motors is usually 1000-2000. However you’ll likely notice that each motor may have a slightly different minimum PWM value for which it starts to rotate. These will need to be accounted for later on when we build the full flight controller. For reference, my 4 motors’ minimum PWM values were: [1045, 1150, 1050, 1150].

Instructions for calibrating the ESCs are included (for the ESCs I used) in the comments section of the code.

Also: be sure to take off the propellers before running these tests! For obvious reasons.

 

#include <AP_Common.h>
#include <AP_Math.h>
#include <AP_Param.h>
#include <AP_Progmem.h>
#include <StorageManager.h>

#include <AP_HAL.h>
#include <AP_HAL_AVR.h>


const AP_HAL::HAL& hal = AP_HAL_BOARD_DRIVER;


/*  MotorTest_USB:

This script may be used to manually command PWM values to
specific motors individually or all four at once for testing.


For ESC calibration follow these steps:

  1. Connect USB to flight controller with battery DISCONNECTED
  2. Load this script to flight controller
  3. Select option (5) to command all motors
  4. Input the maximum PWM input (2000) and press Enter
      --Console should state [All motors] currently commanded to 2000
  5. Connect the battery to power ESCs
      --Two beep sounds should be emitted, means top range of throttle
        has been confirmed and saved
  6. Input the minimum PWM input (1000) and press Enter within 2 seconds
      --A long beep sound should be emitted, means the bottom range
        of throttle has been detected
      --Several beep tones should be emitted to present the amount
        of battery cells
  7. Self test is finished a 'melody 1 2 3' tune should be emitted
  8. Verify range is set by inputting a value within throttle range
     (such as 1300)
   
  * These steps are based on "EMAX User Instruction for SimonK Series ESC"
    different steps may be needed for ESCs from different manufacturers
    
  ** When calibrating all four ESCs at once it may be hard to hear the
    specific number of beeps as described above. I recommend just
    listening for some aural feedback where appropriate then proeeding
    to the next step.
    
*/


int pwmValue = 0;

void setup (void)
{
    
    //Set baud rate to 57600 in order to transmit over SIK Radio
    hal.uartA->begin(map_baudrate(57600));
    
    // Enable all motor channels and set frequency for commands
    for (int j=0; j<4; j++) {
      hal.rcout->enable_ch(j); 
    }
    hal.rcout->set_freq(0xFF, 490);
    
}

void loop (void)
{
    int motorSelected = 0;
    
    // reset all motor commands to zero
    pwmValue = 0;
    hal.rcout->write(0,0);
    hal.rcout->write(1,0);
    hal.rcout->write(2,0);
    hal.rcout->write(3,0);

    // main menu
    hal.console->printf_P(PSTR("\n\n"
    "Select which motor to command:\n"
    "  1) Front Right (CCW)\n"
    "  2) Back Left (CCW)\n"
    "  3) Front Left (CW)\n"
    "  4) Back Right (CW)\n"
    "  5) All motors\n"));
    
    
    // wait for user input
    while( !hal.console->available() ) {
        hal.scheduler->delay(20);
    }
    
    // read in user input
    while( hal.console->available() ) {
        uint8_t asciiInput = hal.console->read();
        
        // Individual Motor:  ASCII between 49-52 equates to keys 1-4
        if (asciiInput >= 49 && asciiInput <=52){
            motorSelected = asciiInput - 48;  //Convert from ASCII to integer
        }
        
        // All Motors
        if (asciiInput == 53){
            motorSelected = 5; // all motors
        }
    }
    
    if (motorSelected >=1 && motorSelected <=5){  //Check for valid menu selection
        motorMenu(motorSelected);
    }
            
}


void motorMenu(int motorSelected){
    
    int valueInput = 0;
    
    // Remain with the selected motor until user requests to command different motor
    while (valueInput >= 0){
        
        if (motorSelected <= 4){
            //Individual Motor Menu
            hal.console->printf_P(PSTR("\n\n"
            "Current PWM command for [Motor %d] = %d\n"
            "Enter new PWM command or enter 'x' to return to motor select menu\n"),
            motorSelected,pwmValue);
        }
        
        if (motorSelected == 5){
            //All Motors Menu
            hal.console->printf_P(PSTR("\n\n"
            "Current PWM command for [All motors] = %d\n"
            "Enter new PWM command or enter 'x' to return to motor select menu\n")
            ,pwmValue);
        }
        
        // wait for user input
        while( !hal.console->available() ) {
            hal.scheduler->delay(20);
        }
        
        int valueInput = 0;
        // read in user input
        while( hal.console->available() ) {
            uint8_t asciiInput = hal.console->read();
            
            if (asciiInput == 88 || asciiInput == 120){ //ASCII for x, X
                valueInput = -1;
                return;  // Return to motor select main menu
            }
            
            // ASCII for 0 is 48
            if (asciiInput >= 48 && asciiInput <=57){ // is a key 0-9
                valueInput = valueInput*10 + asciiInput - 48;
            }
        }
        
        // Command motor(s) to valueInput
        if (valueInput >= 0){
            pwmValue = valueInput;
            if (motorSelected <= 4){
                hal.rcout->write(motorSelected - 1, pwmValue);
            }
            if (motorSelected == 5){
                hal.rcout->write(0,pwmValue);
                hal.rcout->write(1,pwmValue);
                hal.rcout->write(2,pwmValue);
                hal.rcout->write(3,pwmValue);
            }
        }
        
    }  //end while (valueInput >= 0)
}


AP_HAL_MAIN();