Your device does a certain sequence of steps in a state-machine each step is called a state
Your device can be in the "state" of driving, lowering the winch, waiting with lowered winch etc.
Some steps require
- to switch on /off something to start an action
or
- wait until an event happens where "event" can be
a switch is closed (winchbutton is closed)
or a certain interval of time has passed by wait with lowered winch for some time
For your device these states could be named
enum myStates {
StartDriving,
driveUntilStopForLowering,
StartLowering,
Lowering,
WaitAtLowPosition,
StartWindup,
CheckWinchButton,
ResumeDriving
};
enum myStates myStateVar;
These are names that fit best to my brain.
But every brain has different curled connections. So if you think some names should be different just write it in a posting and we can adapt the names
If you have any questions just post the questions. In the long run answering your questions will speed up walking up the learning curve
best regards Stefan
EDIT:
The forum-software does not allow more than 3 consecutive posts.
So I append the whole text to this posting:
So after a long walk with the family and the dog and dinner
I finished the code-version that uses a switch-case state-machine.
The code does compile.
Writing down such a code without any real testing means there is a good chance that still some bugs are inside this code-version.
Pretty normal situation for me.
I prefer testing the real thing (if I can) over thinking through every detail to the max.
And if the behaviour is not as expected taking a look at the code again.
The names of the functions constants and variables explain themself.
I kept some variables from you with your original names but only as comment. This shall simplify understanding the code.
I added some functions to have function-names that explain what the single lines of code do "functional"
from two lines of code like
digitalWrite (driveMotorpin1, HIGH);
digitalWrite (driveMotorpin2, LOW);
you have to lookup some comments or even the wiring or doing a real test to understand that these two lines do
void driveTowardsBumper() {
digitalWrite (driveMotorpin1, HIGH);
digitalWrite (driveMotorpin2, LOW);
CWdriveDirection = towardsBumper;
walk = true;
}
variable-names should reflect as much as possible what their purpose is
example
drivingStarted = currentMillis;
the name "drivingStarted" brings it to the point: it is a snapshot of time where - guess what? drivingStarted
This means reading the if-condition
if (currentMillis - drivingStarted >= driveInterval) {
in conjunction with the rest of the code
case driveUntilStopForLowering:
if (currentMillis - drivingStarted >= driveInterval) {
stopDriverMotor();
is almost story telling what is happening.
code that is written in this way is very easy to maintain. You read it and understand most of it very quick.
So here is the code. I'm very curious what bugs will occur. I haven't thought about special situations yet. This is best done after some first testing.
//Short internal battery loop follows:
long readVcc() {
long result;
// Read 1.1V reference against AVcc. Charge threshold: 2850 (3.5v) - 3000 (3.9v)
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(2); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA, ADSC));
result = ADCL;
result |= ADCH << 8;
result = 1126400L / result; // Back-calculate AVcc in mV
return result;
}
// end of internal battery setup code
int BumpButtonPin = 3; // the number of the pushbutton pin
int ChargeButtonPin = 4; // the number of the pushbutton pin
int MiniWinchPin = 12; //number of the winch pin button
int eyes = 9;
int driveMotorpin1 = 6;
int driveMotorpin2 = 7;
int winchMotorpin1 = 10;
int winchMotorpin2 = 11;
byte CWdriveDirection;
const byte towardsBumper = 0;
const byte towardsCharger = 1;
enum myStates {
StartDriving,
driveUntilStopForLowering,
StartLowering,
Lowering,
WaitAtLowPosition,
StartWindup,
CheckWinchButton,
HangOutAtTop,
ResumeDriving
};
enum myStates myStateVar;
// variables will change:
boolean walk = false; //variable to pause the walk routine
int eyebright = 0; //how bright the eyes are
int eyefade = 5;
int battVolts; // made global for wider avaliblity throughout a sketch if needed, example for a low voltage alarm, etc
// value is volts X 100, 5 vdc = 500
unsigned long currentMillis = 0;
//unsigned long previousMillisT = 0; //stores last time time interval was updated.
unsigned long drivingStarted = 0;
//unsigned long previousMillisD = 0; //stores last time drop interval was updated.
unsigned long loweringStarted = 0;
//unsigned long previousMillisW = 0; //stores last time bottom dwell interval was updated.
unsigned long waitLowStarted = 0;
//unsigned long previousMillisTW = 0; //stores last time top dwell interval was updated.
unsigned long HangOutStarted = 0;
//unsigned long intervalT = 8000; //interval for walk stop & climbdown routine init
unsigned long driveInterval = 8000;
//unsigned long intervalD = 3000; // period for climbing down
unsigned long climbDownInterval = 3000;
//unsigned long dwellD = 2000; // dwell to hang out at bottom
unsigned long dwellDownInterval = 2000;
//unsigned long dwellT = 1500; //hang out at top before proceeding
unsigned long HangOutInterval = 1500;
void stopDriverMotor() {
digitalWrite (driveMotorpin1, LOW);
digitalWrite (driveMotorpin2, LOW);
walk = false;
}
void driveTowardsBumper() {
digitalWrite (driveMotorpin1, HIGH);
digitalWrite (driveMotorpin2, LOW);
CWdriveDirection = towardsBumper;
walk = true;
}
void driveTowardsCharger() {
digitalWrite (driveMotorpin1, LOW);
digitalWrite (driveMotorpin2, HIGH);
CWdriveDirection = towardsCharger;
walk = true;
}
void stopWinchMotor() {
digitalWrite (winchMotorpin1, LOW);
digitalWrite (winchMotorpin2, HIGH);
}
void climbDown() {
digitalWrite (winchMotorpin1, LOW);
digitalWrite (winchMotorpin2, HIGH);
}
void climbUp() {
digitalWrite (winchMotorpin1, HIGH);
digitalWrite (winchMotorpin2, LOW);
}
void myStepChain() {
currentMillis = millis();
if (walk && BumpButtonPin == HIGH) {
driveTowardsCharger();
}
if (walk && ChargeButtonPin == HIGH) {
driveTowardsCharger();
}
switch (myStateVar) {
case StartDriving:
if (ChargeButtonPin == HIGH) {
driveTowardsBumper();
}
else {
driveTowardsCharger();
}
drivingStarted = currentMillis;
myStateVar = driveUntilStopForLowering;
break; // break; is nescessary to make the execution mutually exclusive
case driveUntilStopForLowering:
if (currentMillis - drivingStarted >= driveInterval) {
stopDriverMotor();
myStateVar = StartLowering;
}
break;
case StartLowering:
climbDown();
loweringStarted = currentMillis;
myStateVar = Lowering;
break;
case Lowering:
if (currentMillis - loweringStarted >= climbDownInterval) {
waitLowStarted = currentMillis;
myStateVar = WaitAtLowPosition;
}
break;
case WaitAtLowPosition:
stopWinchMotor();
if (currentMillis - waitLowStarted >= dwellDownInterval) {
myStateVar =StartWindup;
}
break;
case StartWindup:
climbUp();
myStateVar = CheckWinchButton;
break;
case CheckWinchButton:
if (MiniWinchPin == HIGH) {
stopWinchMotor();
HangOutStarted = currentMillis;
myStateVar = HangOutAtTop;
}
break;
case HangOutAtTop:
if (currentMillis - HangOutStarted >= HangOutInterval) {
myStateVar = ResumeDriving;
}
break;
case ResumeDriving:
if (CWdriveDirection == towardsBumper) {
driveTowardsBumper();
}
if (CWdriveDirection == towardsCharger) {
driveTowardsCharger();
}
drivingStarted = currentMillis;
myStateVar = driveUntilStopForLowering;
break;
} // switch
}
void setup() {
Serial.begin(115200);
// initialize the pushbutton pins as inputs:
pinMode (BumpButtonPin, INPUT);
pinMode (ChargeButtonPin, INPUT);
pinMode (MiniWinchPin, INPUT);
pinMode (driveMotorpin1, OUTPUT);
pinMode (driveMotorpin2, OUTPUT);
pinMode (winchMotorpin1, OUTPUT);
pinMode (winchMotorpin2, OUTPUT);
Serial.print("volts X 100");
Serial.println( "\r\n\r\n" );
while (digitalRead (BumpButtonPin) == LOW) {
stopDriverMotor();
stopWinchMotor();
};
//pause everything and wait for bump button to initialize sequence.
driveTowardsBumper(); //initiate movement away from charger
walk = true;
}
void loop() {
myStepChain();
}
best regards Stefan