first coding/can I git a witness?!!!

High guys, long time lurker, first time poster…I am more of a nuts and bolts guy, but one of my more recent project got my onto the microprocessor bus…it incorporates 14 relays of various disciplines and voltages to control an off-grid power plat and distribution at a hunting ranch way out in the boonies. the first thing I would like to do, is to utilize the Arduino to operate the generator starting and loading/ unloading and stopping sequence. I would like to expand the code to also encompass the load-sharing/load-shedding controls, but that is a few more layers than my feeble mind can handle at its current stage of development- or atrophy, as the case may be…anyway, I was hoping you guys could look at this sketch and tell me how foobarred it is. Cheers! and thank you;)-
Si

const int start = 8; //input from start triggers
const int on = 9; //input from generator indicating it is on and up to speed
const int xfer = 10; //input from aux contact of transfer switch to indicate the system is loaded
const int run = 4; //output to close start loop of genset
const int load = 5; //output to transfer states of transfer switch
const int charge = 6; //output to close contactor for battery charginbg circuit

int buttonState = 0; //sets button state to 0
int lastButtonState = 0; //sets last button state to 0

void setup(){
pinMode(start, INPUT); //set pin 8 as input with pulldown resistor
pinMode(on, INPUT); //set pin 9 as input with pulldown resistor
pinMode(xfer, INPUT); //set pin 10 to input with pulldown resistor
pinMode(run, OUTPUT); //set pin 4 as start/run output
pinMode(load, OUTPUT); //set pin 5 as transfer output
pinMode(charge, OUTPUT); //set pin 6 as charging output

}

void loop(){
buttonState = digitalRead(start); //reads button state at startup of loop

if(buttonState != lastButtonState){ //reads if button state has changed
if(buttonState == HIGH){ //if button is set HIGH(on), fire relay 1
digitalWrite(run, HIGH);
if((buttonState == HIGH) && (digitalRead(on == HIGH))){ //if inputs are true, wait, then close relay 2
delay(5000);
digitalWrite(load, HIGH);}
if((buttonState == HIGH) && (digitalRead(on == HIGH)) && (digitalRead(xfer == HIGH))){ //if inputs are true, wait, then close relay 3
delay(3000);
digitalWrite(charge, HIGH);}
}
}
else{(digitalWrite(charge, LOW)); //if button is set LOW, open relay 3, then do the following in sequence
delay(7000); //wait 7 seconds, then open relay 2
digitalWrite(load, LOW);
delay(55L*1000); //wait 55 seconds, then open relay 1( shutting off genset)
digitalWrite(start, LOW);}
lastButtonState = buttonState; //resets button state for next cycle

}

BPR_V_2_0.ino (1.92 KB)

Howdy,

I completely understand how sometimes, the code just blurs your face off. I'm a programmer tinkerer myself. I'm not an expert, but I spy a potential issue. The const int run could screw with you, because Arduino seems to recognize it as an operator of some kind. I would change it to something else. A hint is that when you type it into the sketch, "run" turns orange. I've changed it below to show what I mean.

The else statement should probably be a else if statement. I'm guessing you only want this bit of code to run if charge=LOW, so the addition of the if tests for that.

Also, your formatting is not bad, but when it comes time to debug, could be helped if you give yourself a little more breathing room. When the code complies (I.E. upload), all the spaces are removed, so the amount of spaces you have do not affect file size. I've cleaned your code a bit to demonstrate.

Lastly, when posting code, please use code tags. It's the button with # in the compose message window. Happy Tinkering!

const int start = 8;  //input from start triggers
const int on = 9;  //input from generator indicating it is on and up to speed
const int xfer = 10;  //input from aux contact of transfer switch to indicate the system is loaded

const int powerRun = 4;  //output to close start loop of genset 
//***Changed because Arduino recognises "run" as something else

const int load = 5;  //output to transfer states of transfer switch
const int charge = 6;  //output to close contactor for battery charginbg circuit

int buttonState = 0;  //sets button state to 0
int lastButtonState = 0;  //sets last button state to 0


void setup(){
  
  pinMode(start, INPUT);  //set pin 8 as input with pulldown resistor
  pinMode(on, INPUT);  //set pin 9 as input with pulldown resistor
  pinMode(xfer, INPUT);  //set pin 10 to input with pulldown resistor
  pinMode(powerRun, OUTPUT);  //set pin 4 as start/run output
  pinMode(load, OUTPUT);  //set pin 5 as transfer output
  pinMode(charge, OUTPUT);  //set pin 6 as charging output
  
}

void loop(){
  
  buttonState = digitalRead(start);  //reads button state at startup of loop
  
  if(buttonState != lastButtonState) {//reads if button state has changed
  
    if(buttonState == HIGH){  //if button is set HIGH(on), fire relay 1
      digitalWrite(powerRun, HIGH);
      
      if((buttonState == HIGH) && (digitalRead(on == HIGH))){  //if inputs are true, wait, then close relay 2
        delay(5000);
        digitalWrite(load, HIGH);
      }
        if((buttonState == HIGH) && (digitalRead(on == HIGH)) && (digitalRead(xfer == HIGH))){  //if inputs are true, wait, then close relay 3
          delay(3000);
          digitalWrite(charge, HIGH);
        }
    }
  }
  else if(digitalWrite(charge, LOW){ //if button is set LOW, open relay 3, then do the following in sequence
    delay(7000);  //wait 7 seconds, then open relay 2
    digitalWrite(load, LOW);
    delay(55L*1000);  //wait 55 seconds, then open relay 1( shutting off genset)
    digitalWrite(start, LOW);
  }
  
  lastButtonState = buttonState;  //resets button state for next cycle
  
}

crashoverride61088: I completely understand how sometimes, the code just blurs your face off. I'm a programmer tinkerer myself. I'm not an expert, but I spy a potential issue. The const int run could screw with you, because Arduino seems to recognize it as an operator of some kind. I would change it to something else. A hint is that when you type it into the sketch, "run" turns orange. I've changed it below to show what I mean.

Not as big an issue as you might think. Some built in Arduino libraries probably use "run" as a keyword for one of their functions. It's not a C++ reserved word, so it shouldn't cause any issue being used as a variable name.

As to the code first, a style tip. Closing braces ALWAYS ALWAYS ALWAYS go on their own line. The reason is to make it easy to see what blocks end where. There are two commonly used braces style: my preferred style, with opening a closing braces on their own lines:

if( conditional )
{
  // statements
}

And this style:

if( conditional ) {
  // statements
}

Doesn't matter which one you use (people will argue about the superiority of either) but it's important to pick on and use it consistently. It helps other people and yourself understand the code better.

You also need to spell out exactly what this code is supposed to do and how it needs to react to the various inputs. Since you mention a sequence, is it supposed to wait for certain inputs to go HIGH, then act? In that case, numerous nested if statements won't do any good. And what about error conditions? If the generator doesn't start properly, or runs out of gas, what then?

Furthermore, we need more information about the physical nature of the inputs and outputs. Are on and xfer just mechanical switches? Are the outputs relay coils? Do you have the appropriate hardware to drive them? An Arduino alone can't source or sink enough current to drive a relay of contactor, so you will need a driver transistor.

There's numerous problems with the code itself, but there's a good chance it'll have to be thrown out and rewritten from scratch once we have a clearer picture of what needs to be done.

I appreciate the feedback, and I’m glad someone else has reined in on this.

Thanks guys, and happy new year! OK, I knew it was rough... the background of the system is a stand alone genset, and stand alone inverter bank and the loads connected to them via the transfer switch. the idea is there are several locations where a simple dry contact closure type of switch will be used to initiate a start/run by closing the gensets start loop via closing a relay in response to the start input to the board. I then need to operate a delay-on relay in response to an input from the genset proving that it is producing power and operate a transfer switch at the end of the delay. After receiving the input to the board from the transfer switches aux contact to prove the load is on the genset, I want to wait a few seconds before allowing a relay to close a contactor that allows cuurent to flow to the inverters for battery charging. all the inputs will be switching the arduinos IO voltage via relays suited to the inputs natural voltage range and pulldown resistors to maintain stability. upon the initial input called (start = 8) falling from HIGH to LOW, I want to open the relay that controls the charging circuit contactor- which brings the inverters back to output mode before the loads get placed back on them, then after a short delay, open the relay which controls the transfer switch- thus unloading the genset and replacing the loads to the inverter, then after a cool down period, open the contacts which operate the gensets start/run loop. faults and alarms are built into the inverters and gensets individually and will act based upon time to genFault(time allowed of no ac input from time genset trigger of inverter fires) or genset local sensors/programming). this application of the arduino isn't realizing it's capabilities and is only running as a sequencing controller for the basic functions of the power interface system. I would like to use the arduino as opposed to a smart relay for cost and performance both. There are no magic bullets for what I want to do short of a dedicated board with appropriate program and I know that it can be done. I know I have a long road to hoe, but am excited to learn all the while. as I said before, I will need to sort and write the codes for the load sharing/shedding and try to get all the bits under the controllers thumb. for now, I'd like to just get the "relay board" to a state of consistent operation. Thanks again

I can't speak for anyone else but I found your explanation very difficult to read and gave up trying to follow the detail after a couple of sentences. The lack of paragraphs makes the text very dense and impenetrable.

From what I did read it looks to me as though you are describing a system that can be in one of several states at any one time and that inputs or time passing moves to another state. Perfect for a state machine by the sound of it.

Draw a series of circles, each of which represents a state. In the circles describe what is happening whilst in that state. Join the circles (states) with lines indicating a state change and label the lines with the reason for the state change (input, time passed etc).

Once you have done that you can set about programming the system. I suggest that you use a variable to hold the current state, switch/case to determine the current state and actions being taken and use millis() for timing so that the loop() function runs continuously and the current state, inputs and time passed can be checked on each pass through loop().

I'm sorry. I am an electrician!!!doh. let me see if I can esplain mo betta...

Using relays operated by the real world inputs, I will switch arduino IO to use as inputs.

using a relay shield or similar board compatible with arduino logic, I will switch the real world outputs

the resting system will have 0 active inputs, and 0 active outputs (this state has the loads conneted to the transfer switch closed to the inverter output, and the genset OFF).

upon switch closure(start input) of any of 3 parallel start trigger actuators( inverter, remote 1, or remote 2), the arduino logic will be closed back to the board as input 1 (pin 8 ), the state will change to close relay 1 ( pin 4), to start the genset.

after receiving the input from the genset that it is indeed on and running( via a 240 volt operated relay which closes the arduino logic back to the input (pin 9 )), I want to run a short delay- (using millis would be better, once I've figured out how)-after the delay period, The board should close relay 2 (pin 5), which will actuate an off board relay to change the state of the transfer switch.

once the tranfser swings, it will close an aux contact, which will close arduino logic back to the board on (pin 10) as an input, and then run another short delay before closing relay 3 (pin 6), which will close an off board contactor to close the battery charging circuit from the genset to the inverters.

upon the input 1 (pin 8 ) going from HIGH to LOW, I want to open the output relays in reverse order of firing, and with short delays between stages of shut down: input 1 goes LOW> relay 3 (ouput 3, pin 6) goes low immediately, then times down about 5 seconds before writing relay 2 (output 2, pin 5) LOW, then time a medium delay before writing relay 1 (ouput 1, pin 4) LOW.

I will play around with the switch cases and overall program story board some more and post V2.1 later for more abuse(JK- keep it coming; it IS helping) Thank yous! simon

A much better explanation, and with paragraphs too! I'll keep my claws sharp for version 2. :D

It sounds like a finite state machine will be perfect for a sequencer like this. You can read NIck Gammon's tutorial here: http://www.gammon.com.au/forum/?id=12316

It might seem a little daunting, but we can approach it step-by-step.

THANK YOU!!! I am seeing 5 states of the "machine"... 0, or default> processor idling; looking for input 1; 0 outputs fired 1>input 1 goes from LOW to HIGH, output to close relay 1; look for input 2 2>inputs 1 && 2 are true, delay a bit; then output to close relay 2; look for input 3 3>inputs 1 && 2 && 3 are true, delay a bit; output to close relay 3; look for change in input 1 4>input 1 goes from HIGH to LOW, digitalWrite OUTPUT 3, LOW; wait a bit; digitalWrite OUTPUT 2, LOW; wait a longer bit; digitalWrite OUTPUT 1, LOW.

I guess I am not quite certain how to express the switch( var) as a combination of inputs....can I define the switch (var) as && statements? AND, would I declare those above the void setup(), or would those be defined IN the void setup()? ThanX!

I guess I am not quite certain how to express the switch( var) as a combination of inputs.

You can derive the value of the switch variable using if to combine inputs.

I think that you need more states. For instance, in your state 4 you "wait a bit". To my mind that wait is a state of its own, as are the other waits. Writing things out before starting to program is useful as you can see.

You're on a good start. Defining the exact sequence you want to do will greatly simplify coding.

As another improvement, use descriptive names for the inputs, outputs, and states. start, run, xfer, run, load, and charge are in your code, and are much easier to understand than relay 1, input 1, etc.

For the states, you'll need more than 5, as waiting to turn the relay on should be its own state. For example, you could name them like this

OFF : When start input goes HIGH, move to state ON_SEQU. RUN_SEQU : Turn run output on. When on input goes high, move to state LOAD_DELAY. LOAD_DELAY : Delay for X amount of time, then turn load output on. Move to state XFER_SEQU. XFER_SEQU : When xfer input goes high, move to state CHARGE_DELAY. CHARGE_DELAY : Delay for X amount of time, then turn charge output on. Move to state CHARGING. CHARGING : No state transitions defined yet for this state.

Then, instead of having numbers for the states, you can use an enumeration like this:

typedef enum { OFF, RUN_SEQU, LOAD_DELAY, XFER_SEQU, CHARGE_DELAY, CHARGING } state_t;

With that, you'll be able to use the state names in a switch variable, rather than the state numbers.

That's just the state description for the starting sequence. The shutoff sequence will need its own set of states. You can use my example to draw up your own for that. The basic rule is to keep each state as simple as possible, performing only one action each.

I would highly recommend simulating this on a breadboard before you hook it up to a real generator. You can use DIP switches (http://www.mouser.com/ProductDetail/CTS-Electronic-Components/209-4MS/?qs=sGAEpiMZZMv%2f%252b2JhlA6ysGbG22VYatTY686GjS5J%252bRo%3d) to stand in for the relay contacts, and LEDs to show when the various outputs are going on.

I'm having difficulty using the code tags...the data seems to corrupt on its way from here to there. I will post this as an example of what my trouble is...it should have been different- at least it is in my arduino program window...

[quote]
[color=#CC6600]const[/color] [color=#CC6600]int[/color] start = 8;
[color=#CC6600]const[/color] [color=#CC6600]int[/color] on = 9;
[color=#CC6600]const[/color] [color=#CC6600]int[/color] xfer = 10;

[color=#CC6600]const[/color] [color=#CC6600]int[/color] run = 4;
[color=#CC6600]const[/color] [color=#CC6600]int[/color] load = 5;
[color=#CC6600]const[/color] [color=#CC6600]int[/color] charge = 6;

[color=#CC6600]int[/color] buttonState = 0;
[color=#CC6600]int[/color] lastButtonState = 0;


enum { OFF, START_SEQ, LOAD_DELAY, XFER_SEQ, CHARGE_UP, END_CHARGE, UNLOAD_DELAY, COOL_OFF, SHUT_DOWN } switchState = OFF;

[color=#CC6600]void[/color] [color=#CC6600][b]setup[/b][/color](){
  [color=#CC6600]pinMode[/color](start, [color=#006699]INPUT[/color]);
  [color=#CC6600]pinMode[/color](on, [color=#006699]INPUT[/color]);
  [color=#CC6600]pinMode[/color](xfer, [color=#006699]INPUT[/color]);
  [color=#CC6600]pinMode[/color](run, [color=#006699]OUTPUT[/color]);
  [color=#CC6600]pinMode[/color](load, [color=#006699]OUTPUT[/color]);
  [color=#CC6600]pinMode[/color](charge, [color=#006699]OUTPUT[/color]);
}

[color=#CC6600]void[/color] [color=#CC6600][b]loop[/b][/color](){
  [color=#CC6600]switch[/color](switchState)
  {
    [color=#CC6600]case[/color] OFF:
    buttonState = [color=#CC6600]digitalRead[/color](start);
    [color=#CC6600]if[/color](((buttonState) != (lastButtonState)) && ((buttonState) == [color=#006699]HIGH[/color]))
    {
      [color=#CC6600]delay[/color](10000);
      switchState = START_SEQ;
    }
    [color=#CC6600]break[/color];
    [color=#CC6600]case[/color] START_SEQ:
    [color=#CC6600]digitalWrite[/color](run, [color=#006699]HIGH[/color]);
    [color=#CC6600]if[/color]([color=#CC6600]digitalRead[/color](start) == [color=#006699]HIGH[/color])
    {
    switchState = LOAD_DELAY;
    }
    [color=#CC6600]else[/color]
    {
      switchState = OFF;
    }
    [color=#CC6600]break[/color];
    [color=#CC6600]case[/color] LOAD_DELAY:
    [color=#CC6600]if[/color]([color=#CC6600]digitalRead[/color](on) == [color=#006699]HIGH[/color])
    {
    [color=#CC6600]delay[/color] (5000);
    switchState = XFER_SEQ;
    }
    [color=#CC6600]break[/color];
    [color=#CC6600]case[/color] XFER_SEQ:
    [color=#CC6600]if[/color]([color=#CC6600]digitalRead[/color](start) == [color=#006699]HIGH[/color])
    {
    [color=#CC6600]digitalWrite[/color](load, [color=#006699]HIGH[/color]);
    switchState = CHARGE_UP;
    }
    [color=#CC6600]else[/color]
    {
      switchState = OFF;
    }
    [color=#CC6600]break[/color];
    [color=#CC6600]case[/color] CHARGE_UP:
    [color=#CC6600]if[/color]([color=#CC6600]digitalRead[/color](xfer) == [color=#006699]HIGH[/color])
    {
      [color=#CC6600]digitalWrite[/color](charge, [color=#006699]HIGH[/color]);
      switchState = END_CHARGE;
    }
    [color=#CC6600]break[/color];
    [color=#CC6600]case[/color] END_CHARGE:
    [color=#CC6600]if[/color]([color=#CC6600]digitalRead[/color](start) == [color=#006699]LOW[/color])
    {
      [color=#CC6600]digitalWrite[/color](charge, [color=#006699]LOW[/color]);
      switchState = UNLOAD_DELAY;
    }
    [color=#CC6600]else[/color]
    {
      switchState = END_CHARGE;
    }
    [color=#CC6600]break[/color];
    [color=#CC6600]case[/color] UNLOAD_DELAY:
    [color=#CC6600]delay[/color](7000);
    [color=#CC6600]digitalWrite[/color](load, [color=#006699]LOW[/color]);
    switchState = COOL_OFF;
    [color=#CC6600]break[/color];
    [color=#CC6600]case[/color] COOL_OFF:
    [color=#CC6600]delay[/color](53L*1000);
    switchState = SHUT_DOWN;
    [color=#CC6600]break[/color];
    [color=#CC6600]case[/color] SHUT_DOWN:
    [color=#CC6600]digitalWrite[/color](run, [color=#006699]LOW[/color]);
    [color=#CC6600]delay[/color](60L*2000);
    switchState = OFF;
    [color=#CC6600]break[/color];
  }
}
    
    
    
    
    

[/quote]

I'll try again a bit differently...

[quote]
[color=#CC6600]const[/color] [color=#CC6600]int[/color] start = 8;
[color=#CC6600]const[/color] [color=#CC6600]int[/color] on = 9;
[color=#CC6600]const[/color] [color=#CC6600]int[/color] xfer = 10;

[color=#CC6600]const[/color] [color=#CC6600]int[/color] run = 4;
[color=#CC6600]const[/color] [color=#CC6600]int[/color] load = 5;
[color=#CC6600]const[/color] [color=#CC6600]int[/color] charge = 6;

[color=#CC6600]int[/color] buttonState = 0;
[color=#CC6600]int[/color] lastButtonState = 0;


enum { OFF, START_SEQ, LOAD_DELAY, XFER_SEQ, CHARGE_UP, END_CHARGE, UNLOAD_DELAY, COOL_OFF, SHUT_DOWN } switchState = OFF;

[color=#CC6600]void[/color] [color=#CC6600][b]setup[/b][/color](){
  [color=#CC6600]pinMode[/color](start, [color=#006699]INPUT[/color]);
  [color=#CC6600]pinMode[/color](on, [color=#006699]INPUT[/color]);
  [color=#CC6600]pinMode[/color](xfer, [color=#006699]INPUT[/color]);
  [color=#CC6600]pinMode[/color](run, [color=#006699]OUTPUT[/color]);
  [color=#CC6600]pinMode[/color](load, [color=#006699]OUTPUT[/color]);
  [color=#CC6600]pinMode[/color](charge, [color=#006699]OUTPUT[/color]);
}

[color=#CC6600]void[/color] [color=#CC6600][b]loop[/b][/color](){
  [color=#CC6600]switch[/color](switchState)
  {
    [color=#CC6600]case[/color] OFF:
    buttonState = [color=#CC6600]digitalRead[/color](start);
    [color=#CC6600]if[/color](((buttonState) != (lastButtonState)) && ((buttonState) == [color=#006699]HIGH[/color]))
    {
      [color=#CC6600]delay[/color](10000);
      switchState = START_SEQ;
    }
    [color=#CC6600]break[/color];
    [color=#CC6600]case[/color] START_SEQ:
    [color=#CC6600]digitalWrite[/color](run, [color=#006699]HIGH[/color]);
    [color=#CC6600]if[/color]([color=#CC6600]digitalRead[/color](start) == [color=#006699]HIGH[/color])
    {
    switchState = LOAD_DELAY;
    }
    [color=#CC6600]else[/color]
    {
      switchState = OFF;
    }
    [color=#CC6600]break[/color];
    [color=#CC6600]case[/color] LOAD_DELAY:
    [color=#CC6600]if[/color]([color=#CC6600]digitalRead[/color](on) == [color=#006699]HIGH[/color])
    {
    [color=#CC6600]delay[/color] (5000);
    switchState = XFER_SEQ;
    }
    [color=#CC6600]break[/color];
    [color=#CC6600]case[/color] XFER_SEQ:
    [color=#CC6600]if[/color]([color=#CC6600]digitalRead[/color](start) == [color=#006699]HIGH[/color])
    {
    [color=#CC6600]digitalWrite[/color](load, [color=#006699]HIGH[/color]);
    switchState = CHARGE_UP;
    }
    [color=#CC6600]else[/color]
    {
      switchState = OFF;
    }
    [color=#CC6600]break[/color];
    [color=#CC6600]case[/color] CHARGE_UP:
    [color=#CC6600]if[/color]([color=#CC6600]digitalRead[/color](xfer) == [color=#006699]HIGH[/color])
    {
      [color=#CC6600]digitalWrite[/color](charge, [color=#006699]HIGH[/color]);
      switchState = END_CHARGE;
    }
    [color=#CC6600]break[/color];
    [color=#CC6600]case[/color] END_CHARGE:
    [color=#CC6600]if[/color]([color=#CC6600]digitalRead[/color](start) == [color=#006699]LOW[/color])
    {
      [color=#CC6600]digitalWrite[/color](charge, [color=#006699]LOW[/color]);
      switchState = UNLOAD_DELAY;
    }
    [color=#CC6600]else[/color]
    {
      switchState = END_CHARGE;
    }
    [color=#CC6600]break[/color];
    [color=#CC6600]case[/color] UNLOAD_DELAY:
    [color=#CC6600]delay[/color](7000);
    [color=#CC6600]digitalWrite[/color](load, [color=#006699]LOW[/color]);
    switchState = COOL_OFF;
    [color=#CC6600]break[/color];
    [color=#CC6600]case[/color] COOL_OFF:
    [color=#CC6600]delay[/color](53L*1000);
    switchState = SHUT_DOWN;
    [color=#CC6600]break[/color];
    [color=#CC6600]case[/color] SHUT_DOWN:
    [color=#CC6600]digitalWrite[/color](run, [color=#006699]LOW[/color]);
    [color=#CC6600]delay[/color](60L*2000);
    switchState = OFF;
    [color=#CC6600]break[/color];
  }
}
    
    
    
    
    

[/quote]
[quote]
[color=#CC6600]const[/color] [color=#CC6600]int[/color] start = 8;
[color=#CC6600]const[/color] [color=#CC6600]int[/color] on = 9;
[color=#CC6600]const[/color] [color=#CC6600]int[/color] xfer = 10;

[color=#CC6600]const[/color] [color=#CC6600]int[/color] run = 4;
[color=#CC6600]const[/color] [color=#CC6600]int[/color] load = 5;
[color=#CC6600]const[/color] [color=#CC6600]int[/color] charge = 6;

[color=#CC6600]int[/color] buttonState = 0;
[color=#CC6600]int[/color] lastButtonState = 0;


enum { OFF, START_SEQ, LOAD_DELAY, XFER_SEQ, CHARGE_UP, END_CHARGE, UNLOAD_DELAY, COOL_OFF, SHUT_DOWN } switchState = OFF;

[color=#CC6600]void[/color] [color=#CC6600][b]setup[/b][/color](){
  [color=#CC6600]pinMode[/color](start, [color=#006699]INPUT[/color]);
  [color=#CC6600]pinMode[/color](on, [color=#006699]INPUT[/color]);
  [color=#CC6600]pinMode[/color](xfer, [color=#006699]INPUT[/color]);
  [color=#CC6600]pinMode[/color](run, [color=#006699]OUTPUT[/color]);
  [color=#CC6600]pinMode[/color](load, [color=#006699]OUTPUT[/color]);
  [color=#CC6600]pinMode[/color](charge, [color=#006699]OUTPUT[/color]);
}

[color=#CC6600]void[/color] [color=#CC6600][b]loop[/b][/color](){
  [color=#CC6600]switch[/color](switchState)
  {
    [color=#CC6600]case[/color] OFF:
    buttonState = [color=#CC6600]digitalRead[/color](start);
    [color=#CC6600]if[/color](((buttonState) != (lastButtonState)) && ((buttonState) == [color=#006699]HIGH[/color]))
    {
      [color=#CC6600]delay[/color](10000);
      switchState = START_SEQ;
    }
    [color=#CC6600]break[/color];
    [color=#CC6600]case[/color] START_SEQ:
    [color=#CC6600]digitalWrite[/color](run, [color=#006699]HIGH[/color]);
    [color=#CC6600]if[/color]([color=#CC6600]digitalRead[/color](start) == [color=#006699]HIGH[/color])
    {
    switchState = LOAD_DELAY;
    }
    [color=#CC6600]else[/color]
    {
      switchState = OFF;
    }
    [color=#CC6600]break[/color];
    [color=#CC6600]case[/color] LOAD_DELAY:
    [color=#CC6600]if[/color]([color=#CC6600]digitalRead[/color](on) == [color=#006699]HIGH[/color])
    {
    [color=#CC6600]delay[/color] (5000);
    switchState = XFER_SEQ;
    }
    [color=#CC6600]break[/color];
    [color=#CC6600]case[/color] XFER_SEQ:
    [color=#CC6600]if[/color]([color=#CC6600]digitalRead[/color](start) == [color=#006699]HIGH[/color])
    {
    [color=#CC6600]digitalWrite[/color](load, [color=#006699]HIGH[/color]);
    switchState = CHARGE_UP;
    }
    [color=#CC6600]else[/color]
    {
      switchState = OFF;
    }
    [color=#CC6600]break[/color];
    [color=#CC6600]case[/color] CHARGE_UP:
    [color=#CC6600]if[/color]([color=#CC6600]digitalRead[/color](xfer) == [color=#006699]HIGH[/color])
    {
      [color=#CC6600]digitalWrite[/color](charge, [color=#006699]HIGH[/color]);
      switchState = END_CHARGE;
    }
    [color=#CC6600]break[/color];
    [color=#CC6600]case[/color] END_CHARGE:
    [color=#CC6600]if[/color]([color=#CC6600]digitalRead[/color](start) == [color=#006699]LOW[/color])
    {
      [color=#CC6600]digitalWrite[/color](charge, [color=#006699]LOW[/color]);
      switchState = UNLOAD_DELAY;
    }
    [color=#CC6600]else[/color]
    {
      switchState = END_CHARGE;
    }
    [color=#CC6600]break[/color];
    [color=#CC6600]case[/color] UNLOAD_DELAY:
    [color=#CC6600]delay[/color](7000);
    [color=#CC6600]digitalWrite[/color](load, [color=#006699]LOW[/color]);
    switchState = COOL_OFF;
    [color=#CC6600]break[/color];
    [color=#CC6600]case[/color] COOL_OFF:
    [color=#CC6600]delay[/color](53L*1000);
    switchState = SHUT_DOWN;
    [color=#CC6600]break[/color];
    [color=#CC6600]case[/color] SHUT_DOWN:
    [color=#CC6600]digitalWrite[/color](run, [color=#006699]LOW[/color]);
    [color=#CC6600]delay[/color](60L*2000);
    switchState = OFF;
    [color=#CC6600]break[/color];
  }
}
    
    

[/quote]

what is going on here?

Copy the code [u]directly[/u] from the IDE and paste it directly into the code tags. That way no color tags will be included. I suspect that you are trying to use "Copy for Forum"

Much as I like state machines, I’m not sure one is needed here for your current requirement. It looks like you simply need a start function and a stop function triggered by the state of the input on pin 8. For a first cut, assuming happy path, you could even do this with delay.

Where things get a bit more tricky is error handling. What do you do if one of your verification inputs doesn’t appear? e.g. what should the system do if the genset doesn’t start? Here you may find that the added complexity does push you towards the state machine. It may be worth coding up the simple version first though, even if it’s just a precursor to the full monty.

const int start = 8;
const int on = 9;
const int xfer = 10;

const int run = 4;
const int load = 5;
const int charge = 6;

int buttonState = 0;
int lastButtonState = 0;


enum { OFF, START_SEQ, LOAD_DELAY, XFER_SEQ, CHARGE_UP, END_CHARGE, UNLOAD_DELAY, COOL_OFF, SHUT_DOWN } switchState = OFF;

void setup(){
  pinMode(start, INPUT);
  pinMode(on, INPUT);
  pinMode(xfer, INPUT);
  pinMode(run, OUTPUT);
  pinMode(load, OUTPUT);
  pinMode(charge, OUTPUT);
}

void loop(){
  switch(switchState)
  {
    case OFF:
    buttonState = digitalRead(start);
    if(((buttonState) != (lastButtonState)) && ((buttonState) == HIGH))
    {
      delay(10000);
      switchState = START_SEQ;
    }
    break;
    case START_SEQ:
    digitalWrite(run, HIGH);
    if(digitalRead(start) == HIGH)
    {
    switchState = LOAD_DELAY;
    }
    else
    {
      switchState = OFF;
    }
    break;
    case LOAD_DELAY:
    if(digitalRead(on) == HIGH)
    {
    delay (5000);
    switchState = XFER_SEQ;
    }
    break;
    case XFER_SEQ:
    if(digitalRead(start) == HIGH)
    {
    digitalWrite(load, HIGH);
    switchState = CHARGE_UP;
    }
    else
    {
      switchState = OFF;
    }
    break;
    case CHARGE_UP:
    if(digitalRead(xfer) == HIGH)
    {
      digitalWrite(charge, HIGH);
      switchState = END_CHARGE;
    }
    break;
    case END_CHARGE:
    if(digitalRead(start) == LOW)
    {
      digitalWrite(charge, LOW);
      switchState = UNLOAD_DELAY;
    }
    else
    {
      switchState = END_CHARGE;
    }
    break;
    case UNLOAD_DELAY:
    delay(7000);
    digitalWrite(load, LOW);
    switchState = COOL_OFF;
    break;
    case COOL_OFF:
    delay(53L*1000);
    switchState = SHUT_DOWN;
    break;
    case SHUT_DOWN:
    digitalWrite(run, LOW);
    delay(60L*2000);
    switchState = OFF;
    break;
  }
}

here it is...

wildbill:
Much as I like state machines, I’m not sure one is needed here for your current requirement. It looks like you simply need a start function and a stop function triggered by the state of the input on pin 8. For a first cut, assuming happy path, you could even do this with delay.

Where things get a bit more tricky is error handling. What do you do if one of your verification inputs doesn’t appear? e.g. what should the system do if the genset doesn’t start? Here you may find that the added complexity does push you towards the state machine. It may be worth coding up the simple version first though, even if it’s just a precursor to the full monty.

ThankYOU for input…I think the state machine should do this quite well; provided I understand how to use it- that’s a different question for later perhaps, but I think I was able to fit several safety lines into this state machine which would set the switchState to off or to move it to shutdown mode depending on the inputs AND where in the sequence it is. course, I could just completely misunderstand the whole concept, at which point, you’d be spot on. I like to keep it simple where I can-what other choice does a Simon have? XD

processedpower: ``` const int start = 8; const int on = 9; const int xfer = 10;

const int run = 4; const int load = 5; const int charge = 6;

int buttonState = 0; int lastButtonState = 0;

enum { OFF, START_SEQ, LOAD_DELAY, XFER_SEQ, CHARGE_UP, END_CHARGE, UNLOAD_DELAY, COOL_OFF, SHUT_DOWN } switchState = OFF;

void setup(){   pinMode(start, INPUT);   pinMode(on, INPUT);   pinMode(xfer, INPUT);   pinMode(run, OUTPUT);   pinMode(load, OUTPUT);   pinMode(charge, OUTPUT); }

void loop(){   switch(switchState)   {     case OFF:     buttonState = digitalRead(start);     if(((buttonState) != (lastButtonState)) && ((buttonState) == HIGH))     {       delay(10000);       switchState = START_SEQ;     }     break;     case START_SEQ:     digitalWrite(run, HIGH);     if(digitalRead(start) == HIGH)     {     switchState = LOAD_DELAY;     }     else     {       switchState = OFF;     }     break;     case LOAD_DELAY:     if(digitalRead(on) == HIGH)     {     delay (5000);     switchState = XFER_SEQ;     }     break;     case XFER_SEQ:     if(digitalRead(start) == HIGH)     {     digitalWrite(load, HIGH);     switchState = CHARGE_UP;     }     else     {       switchState = OFF;     }     break;     case CHARGE_UP:     if(digitalRead(xfer) == HIGH)     {       digitalWrite(charge, HIGH);       switchState = END_CHARGE;     }     break;     case END_CHARGE:     if(digitalRead(start) == LOW)     {       digitalWrite(charge, LOW);       switchState = UNLOAD_DELAY;     }     else     {       switchState = END_CHARGE;     }     break;     case UNLOAD_DELAY:     delay(7000);     digitalWrite(load, LOW);     switchState = COOL_OFF;     break;     case COOL_OFF:     delay(53L*1000);     switchState = SHUT_DOWN;     break;     case SHUT_DOWN:     digitalWrite(run, LOW);     delay(60L*2000);     switchState = OFF;     break;   } }





here it is...

You should consider dropping the use of delay() because that stalls the operation of the program until the delay is finished. This may not be important in this program but it could become important if/when you need to do something else during the waiting period such as reading a button/switch input for say, emergency stop, at some time. Using a state machine lends itself well to using millis() for timing as the loop() function can run and repeat freely until the wait is up or an input is detected.

I have not looked at your code in detail but the principle looks sound and the use of the enum makes it much easier to read.

newest, with comments

const int start = 8;//sets pin 8 as start 
const int on = 9;//sets pin 9 as on 
const int xfer = 10;//sets pin 10 as xfer 

const int run = 4;//sets pin 4 as run 
const int load = 5;//sets pin 5 as load 
const int charge = 6;//sets pin 6 as charge 

int buttonState = 0;//set initial buttonState to 0 value
int lastButtonState = 0;//set initial lastButtonState to 0 value


enum { OFF, START_SEQ, LOAD_DELAY, XFER_SEQ, CHARGE_UP, END_CHARGE, UNLOAD_DELAY, COOL_OFF, SHUT_DOWN } switchState = OFF;//defines the sequential states of the switch(); and sets the default state to OFF

void setup(){//do once at power-up
  pinMode(start, INPUT);//sets the start pin as an input
  pinMode(on, INPUT);//sets the on pin as an input
  pinMode(xfer, INPUT);//sets the xfer pin as an input
  pinMode(run, OUTPUT);//sets the run pin as an output
  pinMode(load, OUTPUT);// sets the load pin as an output
  pinMode(charge, OUTPUT);//sets the charge pin as an output
}

void loop(){//do repeatedly
  switch(switchState)//reads the current switchState
  {
    case OFF://do when in OFF state
    buttonState = digitalRead(start);//read buttonState to see if it's time to turn on
    if(((buttonState) != (lastButtonState)) && ((buttonState) == HIGH))//reads when buttonState becomes HIGH; do next action
    {
      delay(10000);//10 second delay for buffering after potential recycled start input
      switchState = START_SEQ;//advances switchState to next case
    }
    break;//end case
    case START_SEQ://do when in STAR_SEQ state
    digitalWrite(run, HIGH);//operate start relay to turn on genset
    if(digitalRead(start) == HIGH)//verifies that system is still in GO mode; do next action
    {
    switchState = LOAD_DELAY;//advances switchState to the LOAD_DELAY case 
    }
    else//if the system is NOT still in GO mode; reset switchState
    {
      switchState = OFF;//resets the system to the Off case
    }
    break;// end case
    case LOAD_DELAY://do when in LOAD_DELAY state
    if(digitalRead(on) == HIGH)//verifies that generator started; do next action
    {
    delay (5000);//wait for engine speed to stabilize
    switchState = XFER_SEQ;//advances switchState to the XFER_SEQ case
    }
    break;//end case
    case XFER_SEQ://do when in XFER_SEQ state
    if(digitalRead(start) == HIGH)//verifies that system is still in GO mode
    {
    digitalWrite(load, HIGH);//operate transfer relay to load the genset
    switchState = CHARGE_UP;//advance switchState to the CHARGE_UP case
    }
    else//if the system is NOT still in GO mode; reset switchState
    {
      switchState = OFF;//resets the system to the Off case
    }
    break;//end case
    case CHARGE_UP://do when in CHARGE_UP state
    if(digitalRead(xfer) == HIGH)//when the transfer switch changes states; do the next action
    {
      digitalWrite(charge, HIGH);//operate the charge relay to close the battery charging contactor
      switchState = END_CHARGE;//advances switchState to the END_CHARGE case
    break;// end case
    case END_CHARGE:// do when in END_CHARGE state
    if(digitalRead(start) == LOW)// when the start input ends; begin shut-down sequence
    {
      digitalWrite(charge, LOW);// operates the charge relay to open the battery charging contactor
      switchState = UNLOAD_DELAY;//advance switchState to the UNLOAD_DELAY case
    }
    else//if start input stays HIGH; do the following
    {
      switchState = END_CHARGE;//stay in END_CHARGE state untill start input goes LOW
    }
    break;//end case
    case UNLOAD_DELAY://do when in UNLOAD_DELAY state
    delay(7000);//wait for inverters to wake up
    digitalWrite(load, LOW);//operate load relay to open tranfer switch and unload genset
    switchState = COOL_OFF;//advances switchState to the COOL_OFF case
    break;// end case
    case COOL_OFF:// do when in COOL_OFF state
    delay(53L*1000);//engine cool-down period of 53 seconds
    switchState = SHUT_DOWN;//advance switchState to the SHUT_DOWN case
    break;//end case
    case SHUT_DOWN:// do when in SHUT_DOWN state
    digitalWrite(run, LOW);//operate run relay to open run circuit on genset
    switchState = OFF;// resets switchState to the OFF case
    break;//end case
  }//end loop
}