DC Motors

Here we combine a basic sensor (the TEMT6000 ambient light sensor) with the DRV8871 DC Motor Driver to have control of a brushed DC motor. Take a close look at the code and try to decipher where the important lines are!

Brushed DC motors are great for rotating things. You can convert rotational movement into lateral movement through the use of linkages, cams or articulated joints. The motor in your basic kit is an example of a brushed motor.

The DC motor you have in your kit have reduction gears to slow the output shaft (and also provide more torque). It's important to note that if you want to use more powerful motors (> 5V), the higher voltage power source (either another battery pack, or a wall-wart transformer) must NEVER be connected to the VIN of the Photon (sending more than 6.5V into VIN will ABSOLUTELY DESTROY your Photon).

You can swap out the light sensor with any other analog sensor in your kit, so long as you modify the code to suitably adjust the scaling of the sensor readings in relation to the desired output speed of the motor.

Don't have buttons? Just two wires touching each other can simulate a button ‘press’, with the right code written for them. This should also give you some ideas on making your own simple ‘button’ sensors!


Libraries Used

(learn how to import them in the Build IDE):


Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
// how long (ms) between each sensor update? feel free to
// change this value from 5 to 5000; use 10 as a start
// if you are logging via Particle.publish, this must not be anything less than 1000ms!
#define INTERVAL_BETWEEN_SENSE   10

// initialise the timer
Timer dataUpdateTimer(INTERVAL_BETWEEN_LOGS, doDataUpdate);

// track direction of rotation
bool isCW = true;
bool lastCW = false;
bool lastCCW = false;


// code in this setup function runs just once, when Photon is powered up or reset
void setup() {
    Serial.begin(9600);             // Open a connection via the Serial port – useful for debugging
    delay(5000);                    // Common practice to allow board to 'settle' after connecting online

    pinMode(D0, OUTPUT);            // goes to IN1 of DRV8871 controller
    pinMode(D1, OUTPUT);            // goes to IN2 of DRV8871 controller

    // we're also connecting pushbottons to D3 and D4 as basic CW/CCW direction control
    pinMode(D3, INPUT_PULLDOWN);
    pinMode(D4, INPUT_PULLDOWN);

    dataUpdateTimer.start();        // start our dataUpdateTimer
}


// code in this loop function runs forever, until you cut power!
void loop() {
    updateButtonStates();
}


void updateButtonStates() {
    // read the states of the buttons, and write them to the DRV8871's IN1/IN2 pins
    // this is updated as quickly as possible to maintain good interface response
    bool D3State = digitalRead(D3);
    bool D4State = digitalRead(D4);

    if(D3State==HIGH && lastCW==false) {
        isCW = true;
    }
    if(D4State==HIGH && lastCCW==false) {
        isCW = false;
    }

    lastCW = D3State;
    lastCCW = D4State;

    // motor will be instructed to respond in the doDataUpdate function below
}


// doDataUpdate runs every interval as set by INTERVAL_BETWEEN_LOGS
void doDataUpdate() {
    int A0State = analogRead(A0);       // read ambient light sensor range (0-4095) from A0

    // here we want the light sensor to drive the 'speed' of the motor.
    // we want to scale the sensed range to a usable range of 0-255

    int scaled = map(A0State, 0, 4095, 0, 255);     // tweak these numbers accordingly!
    scaled = constrain(scaled, 0, 255);             // make sure scaled ranged is within 0-255

    // finally, write out the states to the pins that are connected to the DRV8871 motor driver
    // here we write not only the direction – analogWrite gives us the ability to drive the overall speed too:
    if(isCW) {
        analogWrite(D1, 0);
        analogWrite(D0, scaled);
    } else {
        analogWrite(D0, 0);
        analogWrite(D1, scaled);
    }

    // form a human-readable output for viewing via the Serial port
    String output = "raw:" + String(A0State) + ",scaled:" + String(scaled);

    // prints this out the Serial port (coolterm) for us humans
    Serial.println(output);
}