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!
// 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
voidsetup() {
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!
voidloop() {
updateButtonStates();
}
voidupdateButtonStates() {
// 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
voiddoDataUpdate() {
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);
}