State Not Declared in Scope - Lamination Machine Debugging

Howdy folks,

Sorry to be posting another generically labeled question likely with a very simple answer. I have tried searching around the internet for a solution, but I am not finding one.

This is my first program using finite state machine logic, and I'm a bit lost. I also got overly confident and wrote it all out without trying to compile and test as I went. I know, I know. Shame on me.

This is for a machine that laminates two pieces of 4x8 material together using two roller tables and a spray nozzle that sweeps back and forth over the moving material. It is running three NEMA 23 stepper motors that control two roller tables and one spray gantry assembly. I was able to get everything running smoothly using functions and the loop, and then suddenly the sprayer motor quit on me. I think it is somehow related to the fake TB6006 drivers I got on amazon. Replacing with gecko G203V drivers asap (a separate issue for a different section of this forum).

The code you see below is the first tab, the other tabs that have not been posted contain the functions that the state machine will call upon. I switched over to a state machine because I felt that it would be less expensive to run the code in that way. That, and the LCD commands were far too expensive to be looping over and over again to the degree that they were slowing down the speed of the steppers. I want the state machine to return to an idle state after each task is executed. Idle would reset the stepper values and display a message reading "idling" displays on the LCD screen.

When I try to compile I get this error message:

cleanSlateOS:8:31: error: 'state0' was not declared in this scope
 State* S0 = machine.addState(&state0);    // startup
                               ^~~~~~
/Users/lewisdenver/Desktop/cleanSlateOS/cleanSlateOS.ino:8:31: note: suggested alternative: 'State'
 State* S0 = machine.addState(&state0);    // startup
                               ^~~~~~
                               State
cleanSlateOS:9:31: error: 'state1' was not declared in this scope
 State* S1 = machine.addState(&state1);    // idle
                               ^~~~~~
/Users/lewisdenver/Desktop/cleanSlateOS/cleanSlateOS.ino:9:31: note: suggested alternative: 'State'
 State* S1 = machine.addState(&state1);    // idle
                               ^~~~~~
                               State
cleanSlateOS:10:31: error: 'state2' was not declared in this scope
 State* S2 = machine.addState(&state2);    // forward
                               ^~~~~~
/Users/lewisdenver/Desktop/cleanSlateOS/cleanSlateOS.ino:10:31: note: suggested alternative: 'State'
 State* S2 = machine.addState(&state2);    // forward
                               ^~~~~~
                               State
cleanSlateOS:11:31: error: 'state3' was not declared in this scope
 State* S3 = machine.addState(&state3);    // reverse
                               ^~~~~~
/Users/lewisdenver/Desktop/cleanSlateOS/cleanSlateOS.ino:11:31: note: suggested alternative: 'State'
 State* S3 = machine.addState(&state3);    // reverse
                               ^~~~~~
                               State
cleanSlateOS:12:31: error: 'state4' was not declared in this scope
 State* S4 = machine.addState(&state4);    // laminate
                               ^~~~~~
/Users/lewisdenver/Desktop/cleanSlateOS/cleanSlateOS.ino:12:31: note: suggested alternative: 'State'
 State* S4 = machine.addState(&state4);    // laminate
                               ^~~~~~
                               State
cleanSlateOS:13:31: error: 'state5' was not declared in this scope
 State* S5 = machine.addState(&state5);    // reset
                               ^~~~~~
/Users/lewisdenver/Desktop/cleanSlateOS/cleanSlateOS.ino:13:31: note: suggested alternative: 'State'
 State* S5 = machine.addState(&state5);    // reset
                               ^~~~~~
                               State
/Users/lewisdenver/Desktop/cleanSlateOS/cleanSlateOS.ino: In function 'void transitionS0S1()':
cleanSlateOS:126:7: error: 'bootUp' was not declared in this scope
   if (bootUp == true){
       ^~~~~~
/Users/lewisdenver/Desktop/cleanSlateOS/cleanSlateOS.ino:126:7: note: suggested alternative: 'loop'
   if (bootUp == true){
       ^~~~~~
       loop
/Users/lewisdenver/Desktop/cleanSlateOS/cleanSlateOS.ino: At global scope:
cleanSlateOS:199:3: error: 'machine' does not name a type
   machine.executeOnce(startUpScreen());
   ^~~~~~~
cleanSlateOS:200:1: error: expected declaration before '}' token
 }
 ^
exit status 1
'state0' was not declared in this scope

So am I missing something simple? Do I need to declare these states somewhere else? I was under the assumption that replicating the example code in the library would work without declaring ints.

#include <AccelStepper.h>
#include <LiquidCrystal.h>
#include <YA_FSM.h>
#include <StateMachine.h>

StateMachine machine = StateMachine();

State* S0 = machine.addState(&state0);    // startup
State* S1 = machine.addState(&state1);    // idle
State* S2 = machine.addState(&state2);    // forward
State* S3 = machine.addState(&state3);    // reverse
State* S4 = machine.addState(&state4);    // laminate
State* S5 = machine.addState(&state5);    // reset


///////////////   LCD SCREEN SETUP      /////////////

const int rs = 8, en = 9, d4 = 4, d5 = 5, d6 = 6, d7 = 7;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

//state machine for LCD 
YA_FSM screenMachine;

///////////////    MOTOR SETUP & VARIABLES   //////////////

AccelStepper sprayer(1, 35, 33); // 1, pulse pin, direction pin
AccelStepper table1(1, 43, 41);  // 1, pulse pin, direction pin
AccelStepper table2(1, 47, 45);  // 1, pulse pin, direction pin

int tableSpeed = 10000;     
int tableAccel = 5000;    

int spraySpeed = 10000;  
int sprayAccel = 2000;

//////////////     BUTTONS & STATUS      //////////////

//start
int startButton = 52;  
int startButtonStatus = 0;   

//manual advance
int forwardButton = 49;
int forwardButtonStatus = 0;

//manual reverse
int reverseButton = 51;
int reverseButtonStatus = 0;

//table reset
int tableResetButton = 53;
int tableResetStatus = 0;

//sprayer reset
int sprayerResetButton = 50;
int sprayerResetStatus = 0;

//////////////      MILLIS VARIABLES     //////////////

long previousMillis = 0;
long sprayHomeTime = 1000;
long tableHomeTime = 80000;

//////////////      BOOLEANS            ///////////////

bool sprayerOff = true;
bool tableOff = true;
bool tableHomeOff = true;
bool sprayHomeOff = true;

///////////////////////////////////////////////////////
////////////////////    SETUP    //////////////////////
///////////////////////////////////////////////////////

void setup() {

  //initalize LCD screen
  lcd.begin(16, 2);
  
  //initalize stepper motors
  sprayer.setAcceleration(sprayAccel);
  sprayer.setMaxSpeed(spraySpeed);
  sprayer.moveTo(1800);     //sets limits sprayer sweep distance

  table1.setMaxSpeed(tableSpeed);
  table1.setAcceleration(tableAccel);

  table2.setMaxSpeed(tableSpeed);
  table2.setAcceleration(tableAccel);

  //declare buttons as inputs
  pinMode (startButton, INPUT);
  pinMode (forwardButton, INPUT);
  pinMode (reverseButton, INPUT);
  pinMode (sprayerResetButton, INPUT);
  pinMode (tableResetButton, INPUT);


  S0->addTransition(&transitionS0S1,S1);    //startup to idle
  S1->addTransition(&transitionS1S2,S2);    //idle to fwd
  S2->addTransition(&transitionS2S1,S1);    //fwd to idle
  S1->addTransition(&transitionS1S3,S3);    //idle to reverse
  S3->addTransition(&transitionS3S1,S1);    //reverse to idle
  S1->addTransition(&transitionS1S4,S4);    //idle to laminate
  S4->addTransition(&transitionS4S1,S1);    //laminate to idle
  S1->addTransition(&transitionS1S5,S5);    //idle to reset
  S5->addTransition(&transitionS5S1,S1);    //reset to idle
  //add flipper state???
  
}

////////////////////////////////////////////////////
///////////////////      LOOP      /////////////////
////////////////////////////////////////////////////

void loop () {
  machine.run();
}

///////////////////////////////////////////////////////
/////////////         TRANSITIONS        //////////////
///////////////////////////////////////////////////////

//startup to idle
void transitionS0S1(){
  if (bootUp == true){
    return true;
  }
}

//idle to forward
void transitionS1S2(){
  forwardButtonStatus = digitalRead(forwardButton);
  if (forwardButtonStatus == HIGH) {
    return true;
  }
}

//forward to idle
void transitionS2S1(){
  reverseButtonStatus = digitalRead(reverseButton);
  if (reverseButtonStatus == HIGH) {
    return true;
  }
}


//idle to reverse
void transitionS1S3(){
  reverseButtonStatus = digitalRead(reverseButton);
  if (reverseButtonStatus == HIGH) {
    return true;
  }
}

//reverse to idle
void transitionS3S1(){
  forwardButtonStatus = digitalRead(forwardButton);
  if (forwardButtonStatus == LOW) {
    return true;
  }
}

//idle to laminate
void transitionS1S4(){
  startButtonStatus = digitalRead(startButton);
  if (startButtonStatus == HIGH) {
    return true;
  }
}

//laminate to idle
void transitionS4S1(){
  if (sprayerOff == true & tableOff == true){
    return true;
  }
}

//idle to reset
void transitionS1S5(){
  tableResetStatus = digitalRead(tableResetButton);
  if (tableResetStatus == HIGH) {
    return true;
  }
}

//reset to idle
void transitionS5S1(){
  if (tableHomeOff == true){
    return true;
  }
}

///////////////////////////////////////////////////////
////////////////        STATES        /////////////////
///////////////////////////////////////////////////////
                //startup sequence\\
void state0(){
  machine.executeOnce(startUpScreen());
}
                   //idle state\\
void state1(){
  machine.executeOnce(IdleState());
  machine.executeOnce(idleScreen());
}
                  //advance state\\
void state2(){
  table1Advance();
  table2Advance();
  machine.executeOnce(advanceScreen());
}
                  //reverse state\\
void state3(){
  table1Reverse();
  table2Reverse();
  machine.executeOnce(reverseScreen());
}
                 //lamination state\\
void state4(){
  driveTable();
  spray();
  machine.executeOnce(laminationScreen());
}
                     //resetState\\
void state5(){
  tableHome();
  machine.executeOnce(resetScreen());
}

I apologize again for the mess I have brought to this forum, and thank you in advance for any guidance you can give.

Don't get cute with backslashes ''

why @thememberformarlyknownasAWOL

See post #1

Did you notice this ?

//startup sequence\\
void state0(){
  machine.executeOnce(startUpScreen());
}

Can you see that "void state0()" is greyed-out?

Yes I did, is that because of the backslashes? @TheMemberFormerlyKnownAsAWOL

Yup.

removed backslashes, now the state related errors are gone the program seems to be angry with the

executeOnce(**arbitrary function name**());

lines. Am I using this incorrectly?
@anon73444976

I can't see your code

What I am referring to is in this section:

///////////////////////////////////////////////////////
////////////////        STATES        /////////////////
///////////////////////////////////////////////////////
                //startup sequence
void state0(){
  machine.executeOnce(startUpScreen());
}
                   //idle state
void state1(){
  machine.executeOnce(idleState());
  machine.executeOnce(idleScreen());
}
                  //advance state
void state2(){
  table1Advance();
  table2Advance();
  machine.executeOnce(advanceScreen());
}
                  //reverse state
void state3(){
  table1Reverse();
  table2Reverse();
  machine.executeOnce(reverseScreen());
}
                 //lamination state
void state4(){
  driveTable();
  spray();
  machine.executeOnce(laminationScreen());
}
                     //resetState
void state5(){
  tableHome();
  machine.executeOnce(resetScreen());
}

Error messsage :


/Users/lewisdenver/Desktop/cleanSlateOS/cleanSlateOS.ino: In function 'void state0()':
cleanSlateOS:200:38: error: expression cannot be used as a function
   machine.executeOnce(startUpScreen());
                                      ^
/Users/lewisdenver/Desktop/cleanSlateOS/cleanSlateOS.ino: In function 'void state1()':
cleanSlateOS:204:34: error: expression cannot be used as a function
   machine.executeOnce(idleState());
                                  ^
cleanSlateOS:205:35: error: expression cannot be used as a function
   machine.executeOnce(idleScreen());
                                   ^
/Users/lewisdenver/Desktop/cleanSlateOS/cleanSlateOS.ino: In function 'void state2()':
cleanSlateOS:211:38: error: expression cannot be used as a function
   machine.executeOnce(advanceScreen());
                                      ^
/Users/lewisdenver/Desktop/cleanSlateOS/cleanSlateOS.ino: In function 'void state3()':
cleanSlateOS:217:38: error: expression cannot be used as a function
   machine.executeOnce(reverseScreen());
                                      ^
/Users/lewisdenver/Desktop/cleanSlateOS/cleanSlateOS.ino: In function 'void state4()':
cleanSlateOS:223:41: error: expression cannot be used as a function
   machine.executeOnce(laminationScreen());
                                         ^
/Users/lewisdenver/Desktop/cleanSlateOS/cleanSlateOS.ino: In function 'void state5()':
cleanSlateOS:228:36: error: expression cannot be used as a function
   machine.executeOnce(resetScreen());
                                    ^
exit status 1
expression cannot be used as a function

So does machine.executeOnce need to be structured within an if statement?
@TheMemberFormerlyKnownAsAWOL

I can't see the definition of startupScreen

my bad. It is a separate set of functions on a different tab @anon73444976


long startUpTime = 2500;


void startUpScreen(){
  lcd.print("SPRAY TABLE V2.0");
  lcd.setCursor(0, 2);
  lcd.print("INITALIZING...");
  delay(2500);
  unsigned long currentBootupTime = millis();
  if (currentBootupTime - previousMillis > startUpTime){
    bootUp = true;
  }
}


void idleScreen(){
  lcd.clear();
  lcd.print("Status:");
  lcd.setCursor(0, 2);
  lcd.print("Ready to proceed");
}


void advanceScreen(){
  lcd.print("STATUS:      ");
  lcd.setCursor(0, 2);
  lcd.print("Advancing       ");
  forwardButtonStatus = digitalRead(forwardButton);
  if (forwardButtonStatus == LOW){
    idleScreen();
  }
}


void reverseScreen(){
  lcd.print("STATUS:        ");
  lcd.setCursor(0, 2);
  lcd.print("Reversing       ");
  reverseButtonStatus = digitalRead(reverseButton);
  if(reverseButtonStatus == LOW){
    idleScreen();
  }
}


void laminationScreen(){
  lcd.print("Status:");
  lcd.setCursor(0,2);
  lcd.print("Laminating       ");
  if (tableOff == true & sprayerOff == true){
    idleScreen();
  }
}


void resetScreen(){
  lcd.clear();
  lcd.print(F("Status:"));
  lcd.setCursor(0, 2);
  lcd.print(F("Table Resetting"));
  if (sprayHomeOff == true & tableHomeOff == true){
    idleScreen();
  }
}

also ignore the if statements that call on idleScreen(), I just removed them, from a previous (poorly written) version of the code.

IMHO this kind of state-machine is pretty advanced and and using functions in a complicated way. This might be useful for real professionals that have coded a lot of state-machines and know all the whistles and bells how to use pointers to functions etc.

But IMHO it is very bad suited for a beginner.

Do you have any working example-code that uses this

machine.executeOnce()

stuff?

where is this object "machine" defined?

Did you divide the project into multiple tabs?

If you really want help you have to provide each and every line of code
my estimation is learning easy to use state-machines and write it new from scratch will be less time than to fiddle around with this
best regards Stefan

You've now got a different set of error messages, so we need to see your code.

I expect that executeOnce expects a pointer to a function. Here though you called a function (and a void one at that) to pass:

void state0(){
  machine.executeOnce(startUpScreen());
}

All your xxxxScreen() functions are defined as void .... they return NOTHING. So, how can you use their return value as an argument to the executeOnce() function?

EDIT:
Ahhh.... perhaps what @wildbill said. But, there's no way for us to tell has @lewisdenver didn't provide the source code for the StateMachine class.

Yes, I have written all of this code. I'll go ahead and post everything, I was just trying to avoid bombarding everyone with heaps of code. I'm no beginner to Arduino, I just usually avoid state machines and the resulting code is janky. I want this code to work perfectly as it is being implemented into an industrial machine.

It will work with a higher reliability if you use simpler coding techniques than a state-machine-class that uses pointers to functions

EDIT a state-machine makes sense here. But a state-machine that uses a much simpler coding tecnique. A simple switch-case-break-statement will do

Hobbyist-quality processor boards running amateur-written firmware doesn't seem (to me) to be the best combination for an industrial control application.

"Simpler" is relative to the skill and experience of the coder. There's nothing inherently unreliable about OOP and / or function pointers. You just need to know what you're doing.

1 Like

#include <AccelStepper.h>
#include <LiquidCrystal.h>
#include <YA_FSM.h>
#include <StateMachine.h>

StateMachine machine = StateMachine();

State* S0 = machine.addState(&state0);    // startup
State* S1 = machine.addState(&state1);    // idle
State* S2 = machine.addState(&state2);    // forward
State* S3 = machine.addState(&state3);    // reverse
State* S4 = machine.addState(&state4);    // laminate
State* S5 = machine.addState(&state5);    // reset


///////////////   LCD SCREEN SETUP      /////////////

const int rs = 8, en = 9, d4 = 4, d5 = 5, d6 = 6, d7 = 7;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

//state machine for LCD 
YA_FSM screenMachine;

///////////////    MOTOR SETUP & VARIABLES   //////////////

AccelStepper sprayer(1, 35, 33); // 1, pulse pin, direction pin
AccelStepper table1(1, 43, 41);  // 1, pulse pin, direction pin
AccelStepper table2(1, 47, 45);  // 1, pulse pin, direction pin

int tableSpeed = 10000;     
int tableAccel = 5000;    

int spraySpeed = 10000;  
int sprayAccel = 2000;

//////////////     BUTTONS & STATUS      //////////////

//start
int startButton = 52;  // CHANGE TO startButton
int startButtonStatus = 0;   // change to startButtonStatus

//manual advance
int forwardButton = 49;
int forwardButtonStatus = 0;

//manual reverse
int reverseButton = 51;
int reverseButtonStatus = 0;

//table reset
int tableResetButton = 53;
int tableResetStatus = 0;

//sprayer reset
int sprayerResetButton = 50;
int sprayerResetStatus = 0;

//////////////      MILLIS VARIABLES     //////////////

long previousMillis = 0;
long sprayHomeTime = 1000;
long tableHomeTime = 80000;

//////////////      BOOLEANS            ///////////////

bool sprayerOff = true;
bool tableOff = true;
bool tableHomeOff = true;
bool sprayHomeOff = true;
bool bootUp = false;

///////////////////////////////////////////////////////
////////////////////    SETUP    //////////////////////
///////////////////////////////////////////////////////

void setup() {

  //initalize LCD screen
  lcd.begin(16, 2);
  
  //initalize stepper motors
  sprayer.setAcceleration(sprayAccel);
  sprayer.setMaxSpeed(spraySpeed);
  sprayer.moveTo(1800);     //sets limits sprayer sweep distance

  table1.setMaxSpeed(tableSpeed);
  table1.setAcceleration(tableAccel);

  table2.setMaxSpeed(tableSpeed);
  table2.setAcceleration(tableAccel);

  //declare buttons as inputs
  pinMode (startButton, INPUT);
  pinMode (forwardButton, INPUT);
  pinMode (reverseButton, INPUT);
  pinMode (sprayerResetButton, INPUT);
  pinMode (tableResetButton, INPUT);


  S0->addTransition(&transitionS0S1,S1);    //startup to idle
  S1->addTransition(&transitionS1S2,S2);    //idle to fwd
  S2->addTransition(&transitionS2S1,S1);    //fwd to idle
  S1->addTransition(&transitionS1S3,S3);    //idle to reverse
  S3->addTransition(&transitionS3S1,S1);    //reverse to idle
  S1->addTransition(&transitionS1S4,S4);    //idle to laminate
  S4->addTransition(&transitionS4S1,S1);    //laminate to idle
  S1->addTransition(&transitionS1S5,S5);    //idle to reset
  S5->addTransition(&transitionS5S1,S1);    //reset to idle
  //add flipper state???
  
}

////////////////////////////////////////////////////
///////////////////      LOOP      /////////////////
////////////////////////////////////////////////////

void loop () {
  machine.run();
}

///////////////////////////////////////////////////////
/////////////         TRANSITIONS        //////////////
///////////////////////////////////////////////////////

//startup to idle
void transitionS0S1(){
  if (bootUp == true){
    return true;
  }
}

//idle to forward
void transitionS1S2(){
  forwardButtonStatus = digitalRead(forwardButton);
  if (forwardButtonStatus == HIGH) {
    return true;
  }
}

//forward to idle
void transitionS2S1(){
  reverseButtonStatus = digitalRead(reverseButton);
  if (reverseButtonStatus == HIGH) {
    return true;
  }
}


//idle to reverse
void transitionS1S3(){
  reverseButtonStatus = digitalRead(reverseButton);
  if (reverseButtonStatus == HIGH) {
    return true;
  }
}

//reverse to idle
void transitionS3S1(){
  forwardButtonStatus = digitalRead(forwardButton);
  if (forwardButtonStatus == LOW) {
    return true;
  }
}

//idle to laminate
void transitionS1S4(){
  startButtonStatus = digitalRead(startButton);
  if (startButtonStatus == HIGH) {
    return true;
  }
}

//laminate to idle
void transitionS4S1(){
  if (sprayerOff == true & tableOff == true){
    return true;
  }
}

//idle to reset
void transitionS1S5(){
  tableResetStatus = digitalRead(tableResetButton);
  if (tableResetStatus == HIGH) {
    return true;
  }
}

//reset to idle
void transitionS5S1(){
  if (tableHomeOff == true){
    return true;
  }
}

///////////////////////////////////////////////////////
////////////////        STATES        /////////////////
///////////////////////////////////////////////////////
                //startup sequence
void state0(){
  machine.executeOnce(startUpScreen());
}
                   //idle state
void state1(){
  machine.executeOnce(idleState());
  machine.executeOnce(idleScreen());
}
                  //advance state
void state2(){
  table1Advance();
  table2Advance();
  machine.executeOnce(advanceScreen());
}
                  //reverse state
void state3(){
  table1Reverse();
  table2Reverse();
  machine.executeOnce(reverseScreen());
}
                 //lamination state
void state4(){
  driveTable();
  spray();
  machine.executeOnce(laminationScreen());
}
                     //resetState
void state5(){
  tableHome();
  machine.executeOnce(resetScreen());
}


//advance function, table one
void table1Advance() {
  table1.setSpeed(10000);
  table1.run();
}

//reverse function, table one
void table1Reverse() {
  table1.setSpeed(-10000);
  table1.run();
}

//advance function, table two
void table2Advance() {
  table2.setSpeed(10000);
  table2.run();
}

//reverse function, table two
void table2Reverse() {
  table2.setSpeed(-10000);
  table2.run();
}

int t2RewindDistance = -24700;
int t1RewindDistance = -25500;


void tableHome() {
  unsigned long currentTableResetTime = millis();
  table1.setMaxSpeed(tableSpeed);
  table2.setMaxSpeed(tableSpeed);
  table1.moveTo(t2RewindDistance);   //driver set to 8 microsteps // previously set to -24500
  table2.moveTo(t1RewindDistance);   //driverr set to 8 microsteps
  table1.run();
  table2.run();
  if (currentTableResetTime - previousMillis > tableHomeTime){
    tableHomeOff = true;
    previousMillis = currentTableResetTime;
  }
}

long startUpTime = 2500;


void startUpScreen(){
  lcd.print("SPRAY TABLE V2.0");
  lcd.setCursor(0, 2);
  lcd.print("INITALIZING...");
  delay(2500);
  unsigned long currentBootupTime = millis();
  if (currentBootupTime - previousMillis > startUpTime){
    bootUp = true;
  }
}


void idleScreen(){
  lcd.clear();
  lcd.print("Status:");
  lcd.setCursor(0, 2);
  lcd.print("Ready to proceed");
}


void advanceScreen(){
  lcd.print("STATUS:      ");
  lcd.setCursor(0, 2);
  lcd.print("Advancing       ");
}


void reverseScreen(){
  lcd.print("STATUS:        ");
  lcd.setCursor(0, 2);
  lcd.print("Reversing       ");
}


void laminationScreen(){
  lcd.print("Status:");
  lcd.setCursor(0,2);
  lcd.print("Laminating       ");
}


void resetScreen(){
  lcd.clear();
  lcd.print("Status:");
  lcd.setCursor(0, 2);
  lcd.print("Table Resetting");
}


long sprayTime = 43900;   // changed from 45000 to 30000 to see if table movement distance is affected, it shortened the overall movement by roughly three feet, readjusted to 43000, very close, again to 53900
long tableTime = 80000;   // change from 90000 to 80000 did not affect distance of table movement
long sprayDelay = 7000;   //delay sprayer until table has correctly positioned materials // CHANGED TO 6000 from 7000


/////////////////build out idle state ()
int idleSpeed = 0;
int idleAccel = 0;
int idleDistance = 0;


  
//function that controls sprayer in "start" state
void spray() {
  unsigned long currentSprayMillis = millis();
  if  (currentSprayMillis - previousMillis > sprayDelay) {
    sprayer.setMaxSpeed(spraySpeed);
    sprayer.setAcceleration(sprayAccel);
    if (sprayer.distanceToGo() == 0)
      sprayer.moveTo(-sprayer.currentPosition());
      sprayer.run();  
    if (currentSprayMillis - previousMillis > sprayTime) {  //deleted "+ spray delay) from end of perentheses
      sprayerOff = true;
      previousMillis = currentSprayMillis;
    }
  }
}



//function that controls table in "start" state
void driveTable() {
  unsigned long currentTableMillis = millis();

  //sprayer.setAcceleration(sprayAccel);

  table1.setMaxSpeed(tableSpeed);
  table1.setAcceleration(tableAccel);
  //table1.moveTo(33000); // works when driver is set to 4 microsteps   
  table1.moveTo(20000);   // driver set to 8 microsteps //previously set to 16500
  
  table2.setMaxSpeed(tableSpeed);
  table2.setAcceleration(tableAccel);
  //table2.moveTo(48000); // works when driver is set to 4 microsteps
  table2.moveTo(23800);   // driver set to 8 microsteps
  
  table1.run();
  table2.run();
  if (currentTableMillis - previousMillis > tableTime) {
    tableOff = true;
    previousMillis = currentTableMillis;
  }
}



void idleState() {
  sprayer.setMaxSpeed(idleSpeed);
  sprayer.setAcceleration(idleAccel);
  sprayer.moveTo(idleDistance);

  table1.setMaxSpeed(idleSpeed);
  table1.setAcceleration(idleAccel);
  table1.moveTo(idleDistance);               

  table2.setMaxSpeed(idleSpeed);
  table2.setAcceleration(idleAccel);
  table2.moveTo(idleDistance);
}

Keep in mind that some sections are still being built out. I've also left a lot of comments in there to help me remember where I have picked up and left off as I have been developing this code for several weeks now (I work in a warehouse where I am constantly being interrupted to do other completely unrelated tasks).

@StefanL38

Thank you for your assistance, I am new to state machines and this is helping me learn much faster than I would without the help of this forum.

Yes, materials are moved into position by hand.

The way I have written the code, both tables begin to advance simultaneously (so that one piece can exit table 2 while the piece that has just been loaded onto table1 is being sprayed)

The sprayer starts after a fixed waiting interval - "sprayDelay". It stops after a different interval - "sprayTime".

This is not a separate movement, table 1 and table two start and stop based on distance values that are set by "moveTo" in the accellStepper library. This is what you will see in the function "tableDrive" which uses the command "table1.moveTo(fixed distance value here)"

I have these values set so that table1 and table2 start at the same time, and when the material is no longer touching table 1, table 1 stops moving. This is determined by a fixed value from testing on the actual machine. after table 1 stops, table 2 is still advancing to the distance it was set to (a fixed value that brings the material to the end of table 2).

This may be actuated by this program (cleanSlateOS) at a later point in time but for now, it is actuated through a pneumatic mechanism controlled by workers and it is not connected to the Arduino. Maybe servos in the future? I haven't gotten that far yet. For now, I just want the functions for startup, idle, forward, reverse, laminate, and reset to execute their tasks properly.

I have not yet built the second spray table. The second spray table may be running on a second Arduino MEGA and the same code, or I might just add "table3, table4, sprayer2" to the existing program. Once again, I have not gotten that far yet.

I will post a full description for programming shortly.