Hi, I have a project to control a 12V motor. At the moment I have a setup that generally works sometimes.
Sometimes it runs for hours sometimes minutes and sometime just a step or two. Doesn't freeze or lock up the same way too — at times you can press the button and it start again (sequence status LED is off), other times the power needs to be turned off as the button is unresponsive (sequence status LED is on). Doesn't freeze at the same step. Only consistency is that it seems to be happening during the transition from one step to another, not mid way. Tried a Nano and an Uno board and it's the same.
Hardware:
Arduino Nano or Uno (used both)
Two 5V single channel relays (wired up like a car power window circuit to change polarity of motor)
3 LED's (status led and two others connected the relay to show motor direction)
Push button switch - tried a variety of buttons (internal pull up)
12V Motor
12V power supply (10A, much more than this needs)
Buck converter for 5V
Arduino is running a trigger wire to the relays through a diode which at first I thought solved the issue, only to still have it happening. It's a bit tricky figuring this out as it is very random. Relays are powered through 5V, NOT from the arduino. Motor is powered through separate 12V. Only two standard red LED's are ever on at the same time.
Requirements: Motor needs to rotate one direction for a specified time, pause, rotate the other direction, pause and then start the sequence again. This needs to be able to continue an infinite amount of times until the button is pressed to turn off the motor. When the button is pressed during the sequence the motor needs to stop instantly. The next time the button is pressed the sequence needs to start from the beginning.
#define RELAYONE 11
#define RELAYTWO 10
#define SW1_PIN 9
#define LEDSTAT 8
const unsigned long RELAY_ON_INTERVAL = 9000;
const unsigned long PAUSE_INTERVAL = 500;
const unsigned long MOTOR_OFF_INTERVAL = 500; /* not using this */
const unsigned long SPARE_INTERVAL = 750; /* not using this */
unsigned long startMillis;
// true: RELAY signal is ON
// false: RELAY signal is OFF
bool isRELAY = false;
// Tracks the current steps
uint8_t steps = 0;
// Holds the current state
bool relay_one_state = false;
bool relay_two_state = false;
bool led_state = false;
// This is for button debouncing
bool currState = HIGH;
bool prevState = HIGH;
bool buttonState = HIGH;
unsigned long debounceStart = 0;
unsigned long debounceDuration = 50;
void setup() {
pinMode(RELAYONE, OUTPUT);
pinMode(RELAYTWO, OUTPUT);
pinMode(SW1_PIN, INPUT_PULLUP);
pinMode(LEDSTAT, OUTPUT);
Serial.begin(9600);
}
void loop() {
/*
* Here is the breakdown of the steps:
* 0: RELAYONE is on (high)
* 1: off
* 2: RELAYTWO is on (high)
* 3: off
*/
// Logic for the RELAY
// Pseudo code:
// if RELAY is ON, check the current steps
// if steps is 1 and 3
// send PAUSE_INTERVAL
// if steps is 0
// send RELAY_ON_INTERVAL
// if steps is 2
// send RELAY_ON_INTERVAL
// The duration of each signal is achieve using
// the millis() function
// For example:
// if ( ( millis() - startMillis ) >= RELAY_ON_INTERVAL ) {
// steps++;
// startMillis = millis(); // save the start time
// }
// The ( millis() - startMillis ) is basically the elapse time
// since the startMillis is recorded
// so that ( ( millis() - startMillis ) >= RELAY_ON_INTERVAL ) is
// basically for checking if the required interval is achieve.
// If it becomes true, increment the counter and record the time
// and so on
if (isRELAY) {
if ( ( steps == 1 ) ||
( steps == 3 ) ) {
Serial.println("pause");
relay_one_state = false;
relay_two_state = false;
if ( ( millis() - startMillis ) >= PAUSE_INTERVAL ) {
steps++;
startMillis = millis(); // save the start time
}
} else if ( ( steps == 0 )) {
Serial.println("step 0");
relay_one_state = true;
relay_two_state = false;
led_state = true;
if ( ( millis() - startMillis ) >= RELAY_ON_INTERVAL ) {
// signal interval is complete
// move to the next step
steps++;
startMillis = millis(); // save the start time
}
} else if ( ( steps == 2 ) ) {
Serial.println("step 2");
relay_one_state = false;
relay_two_state = true;
if ( ( millis() - startMillis ) >= RELAY_ON_INTERVAL ) {
steps++;
startMillis = millis(); // save the start time
}
} else {
relay_one_state = false;
relay_two_state = false;
if ( ( millis() - startMillis ) >= MOTOR_OFF_INTERVAL ) {
steps++;
startMillis = millis(); // save the start time
}
}
// if the steps reach steps 5, go back to steps 0
if (steps > 4) steps = 0;
}
// Update the output signal
digitalWrite(RELAYONE, relay_one_state);
digitalWrite(RELAYTWO, relay_two_state);
digitalWrite (LEDSTAT, led_state);
/*
* This is for debouncing the tactile switch
*/
currState = digitalRead(SW1_PIN);
if (currState != prevState) {
debounceStart = millis();
}
if ((millis() - debounceStart) > debounceDuration) {
if (currState != buttonState) {
buttonState = currState;
if (currState == LOW) {
if ( isRELAY ) {
// currently sending motor sequence, now turn it off
isRELAY = false;
Serial.println("off");
relay_one_state = false;
relay_two_state = false;
led_state = false;
} else {
// currently motor sequence is off, now turn it on
isRELAY = true;
startMillis = millis();
Serial.println("on");
steps = 0;
}
}
}
}
prevState = currState;
// Do other stuffs here, without blocking
}


