Courtney Achen
Published © GPL3+

IoT Drone - Part 1 - Motor Control

After flying a friends drone I was hooked. However, I wanted to build my own, so this is part one of my drone project - motor control.

IntermediateWork in progress16 hours5,487
IoT Drone - Part 1 - Motor Control

Things used in this project

Hardware components

Photon
Particle Photon
×1
ESC's and BLDC Motors
×1
Power Distribution Board
×1
3S Lipo Battery Pack 1300mAh
×1
Propellers
×1

Hand tools and fabrication machines

3D Printer (generic)
3D Printer (generic)

Story

Read more

Schematics

Arduino ESC Wiring

Code

HTML Control Code

HTML
<html>
  <head>
      <title>IoT Drone - Part 1 - Motor Control</title>
  </head>

  <body>
      
    <P>Set Motor Speed:<br>
    <input type="range" name="degBox" id="degBoxId" min="1000" max="2000" step="50" value="1000" list="myData" onchange="speedAdjust('alt', 'args')">
    <!-- This adds the tick marks to the range but does not in Safari -->
    <datalist id="myData">
       <option value="1000">
       <option value="1100">
       <option value="1200">
       <option value="1300">
       <option value="1400">
       <option value="1500">
       <option value="1600">
       <option value="1700">
       <option value="1800">
       <option value="1900">
       <option value="2000">
    </datalist>

    <br>
    <button type="button" onclick="speedDec('alt', 'args')">-</button>
    <button type="button" onclick="speedInc('alt', 'args')">+</button>
    <button type="button" onclick="functionIdle('idle', 'args')">Motor Idle</button>
    <button type="button" onclick="functionStop('stop', 'args')">Motor Stop</button>

    <P>Set Rotation:<br>
    <input type="range" name="rotBox" id="rotBoxId" min="-100" max="100" step="10" value="0" list="myRotData" onchange="rotAdjust('rot', 'args')">
    <!-- This adds the tick marks to the range but does not in Safari -->
    <datalist id="myRotData">
       <option value="-100">
       <option value="-75">
       <option value="-50">
       <option value="-25">
       <option value="0">
       <option value="25">
       <option value="50">
       <option value="75">
       <option value="100">
    </datalist>

    <br>
    <button type="button" onclick="rotDec('rot', 'args')">-</button>
    <button type="button" onclick="rotInc('rot', 'args')">+</button>
    <button type="button" onclick="functionCenterRot('rot', 'args')">Center</button>

    <P>Set Direction:<br>
    <input type="range" name="fwdBox" id="fwdBoxId" min="-100" max="100" step="10" value="0" list="myFwdData" onchange="fwdAdjust('fwd', 'args')">
    <!-- This adds the tick marks to the range but does not in Safari -->
    <datalist id="myFwdData">
       <option value="-100">
       <option value="-75">
       <option value="-50">
       <option value="-25">
       <option value="0">
       <option value="25">
       <option value="50">
       <option value="75">
       <option value="100">
    </datalist>

    <br>
    <button type="button" onclick="fwdDec('fwd', 'args')">-</button>
    <button type="button" onclick="fwdInc('fwd', 'args')">+</button>
    <button type="button" onclick="functionCenterFwd('fwd', 'args')">Center</button>
    
    <script src="http://cdn.jsdelivr.net/sparkjs/1.0.0/spark.min.js"></script>
    <script>
      //you can use your accesstoken, or your email/passsword to log in. Uncomment accordingly below.

	var accessToken = "YOUR_ACCESS_TOKEN";
	var deviceID = "YOUR_DEVICE_ID";

	var currentValue = 1000;
	var currentRot = 0;
	var currentFwd = 0;
  
  spark.on('login', function(response) {   
    
    console.log(response);
    
  });

  // callback to be executed by each core
  var callback = function(err, data) {
    if (err) {
      console.log('An error occurred while getting core attrs:', err);
    } else {
      console.log('Core attr retrieved successfully:', data);
    }
  };
  
  function functionIdle(functionName, functionArgument){
    currentValue = 1100;
    document.getElementById("degBoxId").value = currentValue;
    spark.callFunction(deviceID, functionName, functionArgument, callback);  
  }

  function speedAdjust(functionName, functionArgument){
    currentValue = document.getElementById('degBoxId').value;
    functionArgument = currentValue;
    spark.callFunction(deviceID, functionName, functionArgument, callback);  
  }
  
  function functionStop(functionName, functionArgument){
    currentValue = 1000;
    document.getElementById("degBoxId").value = currentValue;
    spark.callFunction(deviceID, functionName, functionArgument, callback);  
  }

  function speedInc(functionName, functionArgument){
    // The function needs to be defined  in the firmware uploaded to the
    currentValue = currentValue + 50;
    functionArgument = currentValue;
    document.getElementById("degBoxId").value = currentValue;
    spark.callFunction(deviceID, functionName, functionArgument, callback);  
  }

  function speedDec(functionName, functionArgument){
    // The function needs to be defined  in the firmware uploaded to the
    currentValue = currentValue - 50;
    functionArgument = currentValue;
    document.getElementById("degBoxId").value = currentValue;
    spark.callFunction(deviceID, functionName, functionArgument, callback);  
  }

   function rotAdjust(functionName, functionArgument){
    currentRot = document.getElementById('rotBoxId').value;
    functionArgument = currentRot;
    spark.callFunction(deviceID, functionName, functionArgument, callback);  
  }

  function rotInc(functionName, functionArgument){
    // The function needs to be defined  in the firmware uploaded to the
    currentRot = currentRot + 10;
    functionArgument = currentRot;
    document.getElementById("rotBoxId").value = currentRot;
    spark.callFunction(deviceID, functionName, functionArgument, callback);  
  }

  function rotDec(functionName, functionArgument){
    // The function needs to be defined  in the firmware uploaded to the
    currentRot = currentRot - 10;
    functionArgument = currentRot;
    document.getElementById("rotBoxId").value = currentRot;
    spark.callFunction(deviceID, functionName, functionArgument, callback);  
  }

  function functionCenterRot(functionName, functionArgument){
    currentRot = 0;
    document.getElementById("rotBoxId").value = currentRot;
    spark.callFunction(deviceID, functionName, functionArgument, callback);  
  }

  function fwdAdjust(functionName, functionArgument){
    currentFwd = document.getElementById('fwdBoxId').value;
    functionArgument = currentFwd;
    spark.callFunction(deviceID, functionName, functionArgument, callback);  
  }

  function fwdInc(functionName, functionArgument){
    // The function needs to be defined  in the firmware uploaded to the
    currentFwd = currentFwd + 10;
    functionArgument = currentFwd;
    document.getElementById("fwdBoxId").value = currentFwd;
    spark.callFunction(deviceID, functionName, functionArgument, callback);  
  }

  function fwdDec(functionName, functionArgument){
    // The function needs to be defined  in the firmware uploaded to the
    currentFwd = currentFwd - 10;
    functionArgument = currentFwd;
    document.getElementById("fwdBoxId").value = currentFwd;
    spark.callFunction(deviceID, functionName, functionArgument, callback);  
  }

  function functionCenterFwd(functionName, functionArgument){
    currentFwd = 0;
    document.getElementById("fwdBoxId").value = currentFwd;
    spark.callFunction(deviceID, functionName, functionArgument, callback);  
  }
  
  // Uncomment a line below depending on your preferred log-in method.   
  //spark.login({ username: 'email@example.com', password: 'password' });  
  spark.login({ accessToken: accessToken });
  
</script>
  </body>
</html>

Photon Code

Arduino
#define MOTOR1_PIN D0
#define MOTOR2_PIN D1
#define MOTOR3_PIN D2
#define MOTOR4_PIN D3

//Set-up Servo Controllers
Servo motor1;
Servo motor2;
Servo motor3;
Servo motor4;
  
//Define variables for each rotor speed
int alt = 1000;
int rot = 0;
int fwd = 0;

int idle = 1100;
int stop = 1000;

int spd1 = 1000;
int spd2 = 1000;
int spd3 = 1000;
int spd4 = 1000;

//Tuning Parameters
int MAX_ROT = 1; //This is a multiplier for the rotation variable
int MAX_FWD = 1; //This is a multiplier for the forward variable

void setup() {
  
  //Begin serial communication for diagnostics
  Serial.begin(9600);
  
  // Set-up Spark functions for altitude, rotation, and forward velocity
  Spark.function("alt",setAlt);  //Set altitude (throttle) 1000 to 2000 microsecond range
  Spark.function("rot",setRot);  //Set rotation
  Spark.function("fwd",setFwd);  //Set forward speed
  
  Spark.function("idle",setIdle);  //Set motors to idle speed
  Spark.function("stop",setStop);  //Turn all motors off

  //Attach pins to servo controllers
  motor1.attach(MOTOR1_PIN);
  motor2.attach(MOTOR2_PIN);
  motor3.attach(MOTOR3_PIN);
  motor4.attach(MOTOR4_PIN);
  
  //Write initial value to servos for start-up calibration of the motor controllers
  motor1.writeMicroseconds(spd1);
  motor2.writeMicroseconds(spd2);
  motor3.writeMicroseconds(spd3);
  motor4.writeMicroseconds(spd4);

  delay(2000);

}

void loop() {  
    //Set the speed of each motor, including factors for rotation and direction
    spd1 = alt + rot + fwd;
    spd2 = alt - rot + fwd;
    spd3 = alt + rot - fwd;
    spd4 = alt - rot - fwd;
    
    //Write the speed of each motor to the servos
    motor1.writeMicroseconds(spd1);
    motor2.writeMicroseconds(spd2);
    motor3.writeMicroseconds(spd3);
    motor4.writeMicroseconds(spd4);

delay(500);
}

int setAlt(String command) {

    alt = command.toInt();
    Serial.println(alt);

    return 1;
    
}

int setRot(String command) {

    rot = command.toInt();
    rot = rot * MAX_ROT;

    return 1;
    
}

int setFwd(String command) {

    fwd = command.toInt();
    fwd = fwd * MAX_FWD;

    return 1;
    
}

int setIdle(String command) {

    alt = idle;
    rot = 0;
    fwd = 0;

    return 1;
    
}

int setStop(String command) {

    alt = stop;
    rot = 0;
    fwd = 0;

    return 1;
    
}

Photon ESC Calibration Code

Arduino
This code will calibrate the Electronic Speed Controllers
#define MOTOR1_PIN D0 //Front Left Motor
#define MOTOR2_PIN D1 //Front Right Motor
#define MOTOR3_PIN D2 //Rear Left Motor
#define MOTOR4_PIN D3 //Rear Right Motor

//Set-up Servo Controllers
Servo motor1;
Servo motor2;
Servo motor3;
Servo motor4;

void setup() {
  
  //Begin serial communication for diagnostics
  Serial.begin(9600);

  //Attach pins to servo controllers
  motor1.attach(MOTOR1_PIN);
  motor2.attach(MOTOR2_PIN);
  motor3.attach(MOTOR3_PIN);
  motor4.attach(MOTOR4_PIN);
  
  //Write initial value to servos for start-up calibration of the motor controllers
  motor1.writeMicroseconds(2000);
  motor2.writeMicroseconds(2000);
  motor3.writeMicroseconds(2000);
  motor4.writeMicroseconds(2000);

  delay(5000);

  motor1.writeMicroseconds(1000);
  motor2.writeMicroseconds(1000);
  motor3.writeMicroseconds(1000);
  motor4.writeMicroseconds(1000);
}

void loop() {  
    
}

Credits

Courtney Achen

Courtney Achen

4 projects • 28 followers
Electro-Mechanical Engineer

Comments