Home

Guide no. 89

The small 6 V DFRobot electric push rod with Arduino UNO and the DRV8833 driver: two buttons, the current read by the driver to stop at the end, the rest breaks.

By Ada Intelisano · informaticait.it technical team

Download the PDF (A4, 11 pages) Free to print and share, without changes — CC BY-ND 4.0
In short
  • The actuator is a small motor that pushes a rod: swap the two wires and the rod extends or retracts. DFRobot states 6 V and 128 N of thrust; the label also says 7 mm/s.
  • DFRobot doesn't say how much current it draws or whether there are limit switches inside: that is why we use Adafruit's DRV8833, which limits the current to about 1 A per bridge.
  • The AS pin of the driver puts out 0.2 V per amp: Arduino reads it and stops the motor when the rod reaches the end or hits an obstacle.
  • The label shows a 10 %: we read it as a duty cycle, and the sketch makes the actuator rest nine times as long as it moved.
Time: an afternoonLevel: next stepsBefore: guides no. 35 and 49

A linear actuator turns the rotation of a small motor into a push in a straight line: the rod extends, stops, retracts. With one of these you can open the lid of a box, a hatch, an air vent. Here we use the 6 V DFRobot actuators, which come with four different strokes, and we control them from an Arduino UNO with two buttons, OPEN and CLOSE. The most interesting part is the one you can't see: how to stop at the end without knowing how much current the motor draws, because DFRobot doesn't publish it.

1The parts

  • a 6 V DFRobot linear actuator: FIT0803 (10 mm stroke), FIT0804 (30 mm), FIT0805 (50 mm) or FIT0806 (100 mm). The examples use the FIT0805;
  • Arduino UNO R3 with its USB cable;
  • the Adafruit DRV8833 driver (3297), with the header to solder;
  • a 4 × AA battery holder with an on/off switch (Adafruit 830) and four batteries;
  • two 6 mm pushbuttons, a breadboard, male-to-male jumper wires.
New word: linear actuatorA small DC motor that moves a rod through a screw. The direction depends on which way the current reaches the two wires: swap them, and the rod that was extending retracts.

2How it's made and how far it extends

The four models share the same body; what changes is the stroke, that is how far the rod comes out. For mounting, what counts is the distance between the centers of the two 4 mm holes, the one in the ear on the body and the one in the eye of the rod. From DFRobot's drawing: retracted it is 54.5 mm plus the stroke, extended it is one stroke more. The body is 20 mm high, the tube 16 mm. The cable is red and black and ends in a 2-pin female connector.

The actuator retracted and extended, with DFRobot's dimensions (here the 50 mm stroke)LA-T8-6-7-50/105-128-N6V 7mm/s 50mm 128N 10% IP54LA-T8-6-7-50/105-128-N6V 7mm/s 50mm 128N 10% IP542-pinconnectorred and blackretracted, hole to hole: 54.5 mm + strokebody with the motortubeeye, Ø4 holeextended, hole to hole: 54.5 mm + 2 × strokeear, Ø4 holestrokerodretractedextendedinformaticait.it
ModelStrokeHole to hole, retracted ExtendedOne stroke at 7 mm/s (calculation)
FIT080310 mm64.5 mm74.5 mm1.4 s
FIT080430 mm84.5 mm114.5 mm4.3 s
FIT080550 mm104.5 mm154.5 mm7.1 s
FIT0806100 mm154.5 mm254.5 mm14.3 s

DFRobot states 6 V and a thrust of 128 N, roughly the weight of 13 kg (our calculation). The speed, 7 mm/s, is on the FIT0803 page and on the labels of all four, without saying under what load: the times in the table are only indicative, and with a weight to push the rod may move more slowly. The label also shows IP54, a rating for protection against dust and water that applies to the actuator, not to Arduino and the driver.

What DFRobot does not say matters just as much: how much current it draws, with no load and with the rod stalled; whether there are limit switches inside that cut off the motor at the end; which way the rod moves with red on +. Then there is a “10%”, which on the FIT0803 page is called “Frequency”. We read it as a duty cycle: the actuator moves for at most one tenth of the time and rests for the remainder. That is our interpretation; DFRobot doesn't explain it.

3Why the DRV8833

An Arduino pin can't drive a motor (guide no. 49), and here you also need to reverse the direction: that takes an H-bridge. Choosing one is easy when you know the motor current. Here we don't, so we look for a driver that protects itself and protects the actuator too.

Drivers in our catalogWith this actuator
Adafruit DRV8833 (3297)Motors from 2.7 to 10.8 V. Current limit already set on the board, about 1 A per bridge; protection against overcurrent, overheating and undervoltage; the AS pin to read the current. Our choice.
TB6612FNG (Adafruit 2448, DFRobot DRI0044, SparkFun 14450)Right voltage, 1.2 A average and 3.2 A peak. Toshiba states thermal and undervoltage protection, not a current limit: it's fine when the motor current is known.
DRV8871 (Adafruit 3190)Works from 6.5 V up: at 6 V it is below the minimum.
L9110H (Adafruit 4489)Adafruit rates it for 800 mA: little margin with a current we don't know.
Adafruit DRV8833 from above: the pins we use in colorDRV8833R200BR200AVMGNDFLTBIN1BIN2SLPAIN2AIN1BSASB1B2A2A1VMGNDUNO GNDFLTBIN1BIN2SLPUNO pin 10AIN2UNO pin 9AIN1UNO pin 8BSASUNO A0BOUT1BOUT2AOUT2blackAOUT1redVMotor: battery + and − (6 V)VM: unprotected, do not use it0.2 Ω: bridge A stays below about 1 A(the same for bridge B)informaticait.it

On the Adafruit board two 0.2 Ω resistors measure the current of the two bridges. When the voltage across one of them reaches 0.2 V the chip switches that bridge off for a moment, until the next cycle of its internal PWM (TI): 0.2 V divided by 0.2 Ω is 1 A, the limit set by Adafruit. If the rod stays stuck at the end, the motor gets about 1 A at most instead of all the current it would ask for. The same point comes out on the AS pin: Arduino reads it on A0 and knows how much current is flowing.

The SLP pin is held low on the board, and as long as it stays low the driver sleeps. We control it with pin 10: awake only while the rod is moving, so at rest the chip draws a few microamps and the batteries last longer.

New word: H-bridgeFour electronic switches arranged in an H around the motor. Close two of them on a diagonal and the current flows one way; with the other two it flows the opposite way. The DRV8833 has two bridges, A and B: we use bridge A, controlled by AIN1 and AIN2.
AIN1AIN2The motor
00free: the outputs are disconnected
10turns one way (AOUT1 high, AOUT2 low)
01turns the other way
11braked: both outputs low

4The wiring

Wiring: buttons, driver, actuator and batteriesabcdefghij16111621−++−OPENCLOSESCLSDAAREFGND131211109876543210IOREFRESET3.3V5VGNDGNDVINDIGITAL (PWM ~)POWERANALOG INUNO238910GNDA0AS4 × AAON/OFF+−LA-T8-6-7-50/105-128-N6V 7mm/s 50mm 128N 10% IP54AOUT1 → redAOUT2 → blackactuatorinformaticait.it
  • Buttons straddling the center channel: OPEN in columns 2 and 4, CLOSE in columns 6 and 8. Pin 2 to OPEN, pin 3 to CLOSE; the other leg of each button goes to the − rail.
  • Driver straddling the channel, with the terminal block to the right: the header in row d (AIN1 in column 11, VM in 18), the row with AOUT and AS in row g.
  • Pin 8 → AIN1, pin 9 → AIN2, pin 10 → SLP. The driver's GND goes to the − rail, and the − rail to the UNO's GND.
  • AS (column 16, row j) → A0, with the light blue wire running underneath.
  • Actuator: two jumper wires from the driver to its connector, AOUT1 to red and AOUT2 to black.
  • Batteries in the VMotor terminal block: red to +, black to −. Keep the switch off until you have checked everything.
Warning
  • The batteries go in the VMotor terminal block, which has reverse-polarity protection. The VM pin on the header is not protected (Adafruit).
  • The actuator never takes power from Arduino's 5V: the motor current comes only from the batteries.
  • All the GNDs connected together: driver, − rail, UNO. Without this, A0 reads random numbers.

5First test: out, in and the current

Put the stroke of your model in STROKE_MM. The sketch works out the time for one stroke at 7 mm/s, adds 30 % (our margin), extends the rod, waits three seconds and retracts it. Meanwhile, every 100 ms, it writes the time and the current to the Serial Monitor (115200 baud).

New word: analogReference(INTERNAL)Normally analogRead measures from 0 to 5 V in 1024 steps, almost 5 mV per step. On the AS pin there are only a few tenths of a volt, so we switch to the UNO's internal reference, 1.1 V: each step is worth about 1 mV. Arduino warns that the first readings after the change are not accurate, and the sketch throws away five of them.
// Linear actuator test: the rod extends, stops, retracts. Every 100 ms the
// Serial Monitor shows the current read on the AS pin of the DRV8833 driver.
#include <Arduino.h>

const byte AIN1 = 8;          // the two inputs of bridge A
const byte AIN2 = 9;
const byte SLP = 10;          // HIGH = driver awake, LOW = driver asleep
const byte SENSE = A0;        // AS pin: 0.2 V for every amp through the motor

const unsigned int STROKE_MM = 50;  // the stroke of your actuator: 10, 30, 50 or 100
// time for one stroke: stroke divided by 7 mm/s (DFRobot figure), plus a 30 % margin
const unsigned long TIME_MS = STROKE_MM * 1300UL / 7;

int currentMA() {
  long sum = 0;
  for (byte i = 0; i < 20; i++) sum += analogRead(SENSE);
  float mV = sum / 20.0 * 1100.0 / 1024.0;    // average in millivolts, 1.1 V scale
  return (int)(mV * 5);                       // 1 mV across 0.2 ohm = 5 mA
}

void drive(int dir) {         // 1 = out, -1 = in, 0 = stop
  digitalWrite(AIN1, dir > 0 ? HIGH : LOW);
  digitalWrite(AIN2, dir < 0 ? HIGH : LOW);
}

void stroke(int dir) {
  Serial.println(dir > 0 ? "OUT" : "IN");
  digitalWrite(SLP, HIGH);
  delay(2);                   // the DRV8833 wakes up within 1 ms
  drive(dir);
  unsigned long start = millis();
  while (millis() - start < TIME_MS) {
    char line[32];
    snprintf(line, sizeof line, "%5lu ms  %4d mA", millis() - start, currentMA());
    Serial.println(line);
    delay(100);
  }
  drive(0);
  digitalWrite(SLP, LOW);
}

void setup() {
  pinMode(AIN1, OUTPUT);
  pinMode(AIN2, OUTPUT);
  pinMode(SLP, OUTPUT);
  Serial.begin(115200);
  analogReference(INTERNAL);                      // scale from 0 to 1.1 V, not 0 to 5 V
  for (byte i = 0; i < 5; i++) analogRead(SENSE);  // the first readings don't count
  stroke(1);
  delay(3000);
  stroke(-1);
  Serial.println("Done. To repeat, press RESET after a few minutes of rest.");
}

void loop() {
}

6Read the numbers

At start-up you see a short peak: that is the motor's inrush current. Then the current drops and stays more or less steady while the rod travels. Watch closely what happens when the rod reaches the end:

  • the current drops to zero: inside the actuator there is a limit switch that cuts off the motor;
  • the current rises and stays high: the motor pushes against the end and the driver keeps it below its limit. Better to stop before that, and that is what the sketch in step 7 does.

Write down two numbers: the current during the stroke and the current at the end. You need them for the threshold. They are estimates, because the internal reference of the UNO is not as accurate as an instrument: for a true value use the multimeter in series (guide no. 8).

✓ What you should seeThe rod extends, stops for three seconds and retracts. In the Serial Monitor, lines scroll by with the time in milliseconds and the current in milliamps.
If it doesn't work
  • It doesn't move and the current is 0: the battery holder switch is off, SLP doesn't reach pin 10, or the common GND is missing.
  • With “OUT” the rod retracts: swap the two jumper wires in the actuator connector.
  • It moves but the current stays at 0: the light blue wire is on BS instead of AS, or it doesn't reach A0.
  • Before repeating the test, let the actuator rest for a few minutes: that is the 10 % from step 2.

7The lid with two buttons

OPEN extends the rod, CLOSE retracts it. The motor stops for the first of three reasons:

  • you press any button while it is moving;
  • the current stays above THRESHOLD_MA for more than 150 ms: the rod is at the end or has hit an obstacle. In the first 300 ms this doesn't count, because at start-up the current is high anyway;
  • the maximum time runs out, calculated as in the test.

Then the actuator rests for nine times as long as it moved, and meanwhile the L LED blinks: that is the 10 % on the label read as a duty cycle (our proposal). After a 7-second stroke, about a minute of rest. The sketch also remembers where it stopped: when open it ignores OPEN, when closed it ignores CLOSE. At power-up it doesn't know and accepts both.

// The lid: OPEN and CLOSE with two buttons. The motor stops for three reasons:
// a press on a button, a current that is too high (rod at the end or against an
// obstacle) or the maximum time. After each stroke the actuator rests.
#include <Arduino.h>

const byte B_OPEN = 2;        // buttons to GND, with the internal pull-up
const byte B_CLOSE = 3;
const byte AIN1 = 8;
const byte AIN2 = 9;
const byte SLP = 10;
const byte SENSE = A0;        // AS pin of the driver: 0.2 V for every amp

const unsigned int STROKE_MM = 50;                       // the stroke of your actuator
const unsigned long MAX_TIME = STROKE_MM * 1300UL / 7;  // stroke / 7 mm/s, +30 %
const int THRESHOLD_MA = 800;        // above this current the rod is stalled
const unsigned long INRUSH_MS = 300; // at start-up the current is high: ignore it
const byte REST_X = 9;               // rest = 9 times the moving time (10 %)

struct Button {
  byte pin;
  bool pressed;               // stable state
  bool reading;               // last reading
  unsigned long changed;      // when the reading changed
};
Button openBtn = {B_OPEN, false, false, 0};
Button closeBtn = {B_CLOSE, false, false, 0};

enum State { IDLE, OPENING, CLOSING, RESTING };
State state = IDLE;
char position = '?';          // O open, C closed, M midway, ? unknown
unsigned long start;          // start of the movement or of the rest
unsigned long rest;           // how long the rest must last
unsigned long normal;         // last moment with the current below threshold
int peak;                     // highest current seen after the inrush

bool tapped(Button &b) {      // true only once, when the button is pressed
  bool now = digitalRead(b.pin) == LOW;
  if (now != b.reading) {
    b.reading = now;
    b.changed = millis();
  }
  if (millis() - b.changed > 30 && b.pressed != b.reading) {   // stable for 30 ms
    b.pressed = b.reading;
    return b.pressed;
  }
  return false;
}

int currentMA() {
  long sum = 0;
  for (byte i = 0; i < 20; i++) sum += analogRead(SENSE);
  float mV = sum / 20.0 * 1100.0 / 1024.0;
  return (int)(mV * 5);
}

void go(State s) {
  state = s;
  digitalWrite(SLP, HIGH);
  delay(2);
  digitalWrite(AIN1, s == OPENING ? HIGH : LOW);
  digitalWrite(AIN2, s == CLOSING ? HIGH : LOW);
  start = normal = millis();
  peak = 0;
  Serial.println(s == OPENING ? "Opening" : "Closing");
}

void halt(const char *reason, char where) {
  digitalWrite(AIN1, LOW);
  digitalWrite(AIN2, LOW);
  digitalWrite(SLP, LOW);
  unsigned long duration = millis() - start;
  position = where;
  rest = duration * REST_X;
  start = millis();
  state = RESTING;
  char line[72];
  snprintf(line, sizeof line, "Stopped (%s) after %lu ms, peak %d mA, rest %lu s",
           reason, duration, peak, rest / 1000);
  Serial.println(line);
}

void setup() {
  pinMode(B_OPEN, INPUT_PULLUP);
  pinMode(B_CLOSE, INPUT_PULLUP);
  pinMode(AIN1, OUTPUT);
  pinMode(AIN2, OUTPUT);
  pinMode(SLP, OUTPUT);
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(115200);
  analogReference(INTERNAL);
  for (byte i = 0; i < 5; i++) analogRead(SENSE);
  Serial.println("Ready");
}

void loop() {
  bool o = tapped(openBtn);
  bool c = tapped(closeBtn);
  unsigned long now = millis();
  if (state == OPENING || state == CLOSING) {
    char endPos = state == OPENING ? 'O' : 'C';
    unsigned long t = now - start;
    int mA = currentMA();
    if (t > INRUSH_MS && mA > peak) peak = mA;
    if (t < INRUSH_MS || mA < THRESHOLD_MA) normal = now;
    if (o || c) halt("button", 'M');
    else if (now - normal > 150) halt("high current", endPos);
    else if (t > MAX_TIME) halt("max time", endPos);
  } else if (state == RESTING) {
    digitalWrite(LED_BUILTIN, (now / 250) % 2 ? HIGH : LOW);   // the L LED blinks
    if (now - start > rest) {
      state = IDLE;
      digitalWrite(LED_BUILTIN, LOW);
      Serial.println("Ready");
    }
  } else if (o && position != 'O') {
    go(OPENING);
  } else if (c && position != 'C') {
    go(CLOSING);
  }
}

8Adjust the threshold

THRESHOLD_MA = 800 is our starting value. Mount the lid (step 9), then open it and stop it halfway with a button: the “peak” the sketch writes on that line is the highest current of the stroke, with the real load. Set the threshold halfway between that peak and the current you saw at the end in the test of step 6. If in that test the current dropped to zero at the end, the threshold only matters for obstacles: keep it a little above the peak.

✓ What you should seePress OPEN: the lid opens and stops by itself, the L LED blinks, then the monitor writes “Ready”. Press CLOSE: it closes again.
If it doesn't work
  • It stops right after starting with “high current”: the threshold is too low for your load, raise it.
  • It reaches the end and hums until “max time”: the threshold is too high, lower it but keep it above the peak of the stroke.
  • The buttons don't respond: it is resting (L LED blinking), or the lid is already open or already closed and you need the other button.

9Mounting it on the lid

The actuator must be free to pivot at both ends: one pivot in the ear, fixed to the box, and one in the eye of the rod, fixed to the lid. For the 4 mm holes, an M3 screw with a self-locking nut, snug but not clamped, works as a pivot (our proposal). This way the rod pushes only along its axis, with no sideways forces.

A flap lid: the two pivots and the opening angle60 mm104.5 mm retracted53°hingepivot on the lidfixed pivotFIT0805:104.5 mm retracted154.5 mm extendedindicative measurements,angle calculated by usinformaticait.it

In the drawing the hinge is on the left, the pivot on the lid 60 mm from it and the fixed pivot 104.5 mm lower, that is the retracted hole-to-hole distance of the FIT0805. When the rod extends by 50 mm the lid opens by about 53° (our calculation, indicative measurements). With the pivot closer to the hinge the lid opens wider, but it takes more force.

DFRobot doesn't say whether the rod holds its position when the motor is off and a weight pushes on it: try it with your lid before you rely on it.

Warning
  • The lid closes with a push that can reach 128 N: keep your fingers away from the edge. The current limit and the threshold help, but they are not a safety device.
Try it yourself
  • Connect the FLT pin of the driver to a free pin with INPUT_PULLUP and write “fault” when it goes low: TI pulls it low for overcurrent and overheating.
  • An air vent that opens above 28 °C, with the TMP36 from guide no. 40.
  • A second actuator on bridge B: BIN1, BIN2, BOUT1, BOUT2, and BS for the current.
✓ What you learned
  • the actuator changes direction if you swap the two wires: you need an H-bridge;
  • if the motor current isn't stated, choose a driver that limits it by itself;
  • the voltage across a 0.2 Ω resistor tells you how much current is flowing, and when the rod is stalled;
  • the 10 % on the label, read as a duty cycle, means moving a little and resting a lot.
Sources: DFRobot, FIT0803, FIT0804, FIT0805 and FIT0806 actuators: product pages, dimensioned drawing and photos · Texas Instruments, DRV8833 datasheet (SLVSAR1E) · Adafruit, DRV8833 DC/Stepper Motor Driver Breakout (3297): product page, Learn guide and Eagle file · Toshiba, TB6612FNG datasheet; Adafruit, product pages 3190 and 4489 · Adafruit, 4 × AA battery holder with on/off switch (830) · Arduino, analogReference() and pinMode() reference · informaticait guides no. 8, 35, 40 and 49

Useful products

Other guides

All our guides →
Loading...
Back to top