DC motor control with Arduino and relay shield- coding question
July 29, 2015 8:09 AM   Subscribe

Trying to run a DC motor with an Arduino UNO and a relay shield - need help with the code!

I'm using a relay shield (this one: http://tinyurl.com/pv23nve) on top of my Arduino Uno to run a DC motor for a specific amount of time after a button press. After that time, the motor should shut off.

This is the code I've come up with after much struggling, but it still doesn't work (just turns on the motor for the 'long offDelay' value, then turns off, after which the button just turns the motor on for as long as it's pressed):

byte relayPin = 7;

//D7 -> RELAY2

volatile long lastSwitchtime = 0;

long offDelay = 5000; //change this to increase/decrease delay

void setup(){
attachInterrupt(1, active, CHANGE);
pinMode(relayPin, OUTPUT);
lastSwitchtime = millis();

void loop(){

if ((millis() - lastSwitchtime) > offDelay) {


} else {



void active()
lastSwitchtime = millis();

any suggestions?
posted by AutoPilot83 to Technology (11 answers total) 1 user marked this as a favorite
In general, you might try asking this sort of thing over at the Arduino Stack Exchange, or just generic StackOverflow, considering this is really a programming question and your hardware seems fine.

All your logic seems sound to me -- store the last time the value of input1 changed, and if lastchangetime + runtime < current-time, turn on the output pin.

It seems like you might want to make sure you are using AttachInterrupt correctly? Right now you're triggering on any change; you might want to try RISING so the timer is only triggered when the button is pushed, rather than as long as the button is held?

In general, when dealing with physical switches, you need to worry about debouncing your inputs, but I don't think a bouncing problem would cause what you're seeing.

You might look at comparisons of longs in Arduino-flavored C -- maybe do something like (millis() - lastSwitchTime) < offDelay? That's cargo-cult-y on my part; I have no reason to believe it would work but I'd try it. I have to run to work, so I can't add more now. Apologies if I'm missing some really basic logic error, I'm writing in a hurry. Cheers and good luck!
posted by Alterscape at 8:36 AM on July 29, 2015

Oh also, try using your digital pin to switch a LED (through a transistor, yatta yatta) to make sure your problem really is timing on the MCU and not some weird hardware boojum. It doesn't sound like a weird hardware boojum, but who knows.
posted by Alterscape at 8:38 AM on July 29, 2015

Seems to me like your interrupt isn't getting triggered. As an interim thing, how about tracking the state of your switch pin (1) in the main loop, and resetting your motor based on that? Set an output pin based on that input pin state and make sure the input is getting read?

And I don't think you need to worry about debouncing your button, because the worst that happens with a few spurious bounces is that your timer gets reset to a little longer.
posted by straw at 9:09 AM on July 29, 2015

Best answer: I don't work with Arduino and I'm sure it probably has a safeguard about code like this (especially with timer interrupts) but I get really nervous when the main loop is running flat-out as fast as possible and possibly not letting other things get updated. I know the example code you're basing your work from does this.

What happens if you skip reading the millisecond timer and do something like this instead?
byte relayPin = 7;
long motor_run;

void setup() {

   attachInterrupt(1, active, CHANGE);
   pinMode(relayPin, OUTPUT);
   digitalWrite(relayPin,LOW);   // start with output OFF.
   motor_run = 0;                // start with time bucket empty

void loop() {

   if (motor_run > 0) {
     digitalWrite(relayPin,HIGH);  // turn relay ON, motor runs.
     motor_run--;                  // drain the bucket
   else {
     digitalWrite(relayPin,LOW);   // no more time left, it's off
   sleep(1);  // come back in 1 mSec

void active() { 

    motor_run = 5000;   // mSec to run the motor
The idea here is to fill a "bucket" with milliseconds to count down. If the bucket has milliseconds in it, the output is switched on. Pressing the button refills the bucket. The sleep(1) does the work of watching the clock and coming back when it's time to loop.
posted by JoeZydeco at 9:24 AM on July 29, 2015

Response by poster: Joe, this makes so much more sense. The analogy helps tremendously.
posted by AutoPilot83 at 11:47 AM on July 29, 2015

Glad to help. So, does it work? =)
posted by JoeZydeco at 1:59 PM on July 29, 2015

Response by poster: The code is working fine, I tested it with a 12v LED strip and it was great. Now that I have a .5amp DC geared motor and 120v hooked through it, my relay doesn't switch after the timer, so the motor stays spinning. Sometimes if shuts off, sometimes at random times, sometimes not at all. I can hear the relay click at every point that it should be switching. EM interference?
posted by AutoPilot83 at 2:26 PM on July 29, 2015

Good to hear! At least that's working...

Can you describe in a little more detail how that motor is wired up through the relay?
posted by JoeZydeco at 2:37 PM on July 29, 2015 [1 favorite]

Response by poster: Here's a photo of my set up: http://tinypic.com/r/2enpzs4/8
posted by AutoPilot83 at 8:04 AM on July 30, 2015

I was going to float a theory about the internal pull-up resistor that you're using for the button having too much resistance to overcome the transients, but you say the relay is clicking.

I'd put a volt meter across the relay to see if it's actually opening or not, and try a different relay. Because that seems really really strange.
posted by straw at 1:18 PM on August 1, 2015

Okay, two things: assuming that your south goes to ground on one side, try a 10k Ohm resistor from the other side to Vcc. This should be super aggressive about dealing with transient interference.

Second, shadow the relay output to an LED top see if the problem is sticking relay, or weird interference.
posted by straw at 12:34 PM on August 2, 2015

« Older Good Cincinnati area Mazda mechanics?   |   Triangle best Newer »
This thread is closed to new comments.