Long story short you guys got me riled up (aggravation is a wondrous motivator, eh?) and in getting the code ready to send in here and making a video explaining things step by step, I saw the flaw in my logic. It was very similar to the first problem I had with the time out with millis() (this was before I wrote in for help), and I should have seen it sooner.
This is where I am at now, with much comments removed and digitalWriteFast() not in use.
#include <ServoDecode.h>
#include <digitalWriteFast.h>
char * stateStrings[] = {"NOT_SYNCHED", "ACQUIRING", "READY", "in Failsafe"};
// Define readable non-backwards states for relays.
// This is because relays are active LOW. That means you can ground the pin and activate the relay.
const byte RELAY_ON = 0;
const byte RELAY_OFF = 1;
// Give each relay friendly name and map to Arduino Digital I/O pin number
const byte Relay_1 = 2; // wire 1 of the engine kill actuator. Pulse to allow engine to run.
const byte Relay_2 = 3; // wire 2 of the engine kill actuator. Pulse to kill engine.
const byte Relay_3 = 4; // brake controller
const byte Relay_4 = 5; // currently unused
const unsigned long idleMotorKill = 5000; // delay to kill the motor
long whatTimeIsIt = 0;
boolean timeOut = false;
void setup(){
//ServoDecode setup
ServoDecode.begin();
ServoDecode.setFailsafe(3,1234); // set channel 3 failsafe pulse width
// Relay Setup Initialize Pins so relays are inactive at reset
digitalWrite(Relay_1, RELAY_OFF);
digitalWrite(Relay_2, RELAY_OFF);
digitalWrite(Relay_3, RELAY_OFF);
digitalWrite(Relay_4, RELAY_OFF);
// THEN set pins as outputs
pinMode(Relay_1, OUTPUT);
pinMode(Relay_2, OUTPUT);
pinMode(Relay_3, OUTPUT);
pinMode(Relay_4, OUTPUT);
delay(1000); // Check that all relays are inactive at Reset
// Prevent motor from starting and engage breaks
engineKill();
brakesEngage();
} // end setup()
void loop(){
if(ServoDecode.getState()!= READY_state) { // transmitter is off or out of range
engineKill(); // kill motor
brakesEngage(); // engage brakes
whatTimeIsIt = 0; // used as a semaphore
timeOut = false; // resets this semaphore
} // end if() transmitter not ready
if(ServoDecode.getState()== READY_state) {
if(whatTimeIsIt==0){ // tests for if it's the first loop through of the ready state
whatTimeIsIt = millis(); // if it's the first loop through, make a note of the time
} // end if() testing for first loop through
if(!timeOut){
engineAllow(); // allow motor to be cranked
brakesDisengage(); //disengage brakes
} // if the transmitter has not timed out
if (millis() > (whatTimeIsIt + idleMotorKill) ){ // if 5 seconds has passed since entering the ready state, kill the motor and engage the brakes
engineKill();
brakesEngage();
timeOut = true;
} // end test for timeOut
} // end if() transmitter ready
} // end main loop()
void engineKill(){
digitalWrite(Relay_1, RELAY_OFF); // just in case it was on for some random reason; prevents frying relays and/or actuators
digitalWrite(Relay_2, RELAY_ON); // eventually pulse it, but for now just latch it
} // end engineKill
void engineAllow(){
digitalWrite(Relay_2, RELAY_OFF); // just in case it was on for some random reason; prevents frying relays and/or actuators
digitalWrite(Relay_1, RELAY_ON); // eventually pulse it, but for now just latch it
} // end instantEngineKill
void brakesEngage(){
digitalWrite(Relay_3, RELAY_ON); // engages the brakes by closing the circuit to power them
} // end brakesEngage
void brakesDisengage(){
digitalWrite(Relay_3, RELAY_OFF); // disengages the brakes by opening the circuit
} // end brakesDisengage
Notice the new boolean timeOut semaphore and additional conditional logic [ if(!timeOut){} ]within the loop; that's what I was missing. As for everyone who was asking about code, the whole thing was in the OP this whole time. Yes I was running the same code as in the OP when I shot the first video. Sorry about the lack of audio, I was at work trying to be discreet about it and it seemed self evident of what I was doing based on the code.
Video is uploading now from my phone, it'll be in my channel. You can get an idea of what I am trying to do as I do explain the process of what I want to happen. It's taking it's sweet time uploading, so I'll edit this post after the fact with a direct link to it. I tried to talk slow, but my phone has audio/video sync issues of about a fraction of a second; enough to be annoying.
Direct link to the video: