I did not want to clutter up the issue with extraneous detail, since it seemed to me to a straight-forward issue of syntax. However, I will give you as much detail as I can. I had over-written the original code with the inelegant work-around, but have reconstituted it as best I can. The note by redcar that the original (digitalRead(BottomLevelSwitch)== LOW is not quite the same as the (later) (BottomLevelRead == LOW), is quite correct. I had added a variable to hold the value, in the hopes that this would fix the problem. It didn't.
It may be useful to specify what is happening here. There is an insulating curtain under the glazing in my solar greenhouse, which closes at night to retain the heat captured through the day. The two switches are micro-switches mounted on the tracks under the curtain. The lower level switch is closed when the curtain reaches the bottom limit. (The upper level switch will also be closed as soon as the curtain has started to descend.) With the raising, the upper switch will be closed until the curtain has rolled above it, and allowed it to open, (dropping the pin to LOW
Code:
/*
Program flow:
In loop, initialize State to ST_Init. This then leads to Switch, which is entered with State at ST_Init,
and first time through gets set to ST_LOWERING. Program then goes back to beginning of switch loop.
This will drop through case ST_INIT into ST_LOWERING. If conditions for this to run are met, this runs,
State gets reset to ST_LOWERED, and loops back to beginning of Loop.
This continues until and unless program drops through all levels of Switch, at which time,
it drops through end of Switch loop, and returns back to beginning of main loop. Correct?
*/
/* Connections:
Connect photo sensor:
One side to 5V (No polarity)
Other leg to Pin A0 on Arduino
10K pull-down resistor between return from photoresistor and Gnd
Conect both limit switches with 10K resistors between 5V and control pin, with
limit switch on far side of resistor, connected to Gnd. (Ie. 10K resistor acts as pull-up)
Top level switch is wired as Normally Open. As long as curtain is higher than switch,
(ie fully open), TopLevelSwitch pin,(Pin 7), will be HIGH. (Will drop to LOW
as soon as curtain starts to close.)
Bottom Level switch similarly wired as Normally Open. When curtain is fully down,
BottomLevelSwitch pin, (Pin 8), will drop to LOW.
(Both switches wll be closed, and both read pins will be LOW)
When curtain is fully up, both switches will be open, and both pins will be HIGH
Raise and Lower pins trigger relay to activate when they go LOW.
(At rest, both pins are set to HiGH)
Timing: TimeNow is set to millis() at top of loop. TimeStart on firat iteration
starts at blank value, so any test of timing will be false. With trigger event,
(ST-Raised, or ST-Lowered), StartTime gets set to current millis, pgm drops through to action,
(Raising or Lowering), and start time remains fixed, while TimeNow augments with each iteration
through the loop, until condition is met, at which point relay is turned off and pgm drops through
to next state.
To run display portion, connect Arduino, then choose Port,(7), under Tools
Then, also under Tools, choose Serial Monitor, (or Ctrl-Shift-M)
*/
// VARIABLES
int
PhotocellPin = A0, // Define input pin
TopLevelRead, // Values of levels of switch pins
BottomLevelRead;
const float
LowerLightLevel = 300,
UpperLightLevel = 700;
const unsigned long
TimeRaise = 115000, // Measured time, 1'55"
TimeLower = 130000; // Increased Jan 6, 2023
const int // Limit switches
TopLevelSwitch = 7, // These 2 are inputs & change with state of limit switches
BottomLevelSwitch = 8,
RaisePin = 2, // These 2 control relays to run motor
LowerPin = 3;
unsigned long
TimeStart,
TimeNow;
enum // States
{
ST_INIT = 0,
ST_RAISING,
ST_RAISED,
ST_LOWERING,
ST_LOWERED
};
// End Variables
void setup( )
{
//set control pins to OUTPUT, and initialise to HIGH. (They will default to LOW otherwise)
digitalWrite(RaisePin, HIGH);
digitalWrite(LowerPin, HIGH);
pinMode(RaisePin, OUTPUT);
pinMode(LowerPin, OUTPUT);
pinMode (PhotocellPin, INPUT);
pinMode (TopLevelSwitch, INPUT);
pinMode (BottomLevelSwitch, INPUT);
// Initialize display of readings
Serial.begin(9600);
} // end of setup
void loop( void )
{
static byte
State = ST_INIT;
TimeNow = millis();
//Go get reading for LightValue
int LightValue = analogRead(PhotocellPin);
// Get values of read pins
TopLevelRead = digitalRead(TopLevelSwitch),
BottomLevelRead = digitalRead(BottomLevelSwitch),
// Print light value to serial output, for debugging only
Serial.print("Light Value: ");
Serial.println(LightValue);
Serial.print("TimeStart: ");
Serial.print(TimeStart);
Serial.print(" ");
Serial.print("TimeNow: ");
Serial.println(TimeNow);
Serial.print("Top Switch: ");
Serial.print(TopLevelRead);
Serial.print(" ");
Serial.print("Bottom Switch: ");
Serial.println(BottomLevelRead);
Serial.println (" ");
delay (2000);
// And now drop into case ST_INIT
switch ( State )
{
case ST_INIT:
Serial.print("State = ST_INIT: ");
// Initialize to "home" the curtain closed if it is not already at bottom
if (( BottomLevelRead) == HIGH ) // Curtain is not at bottom .
{
digitalWrite (RaisePin, HIGH); // Raise relay is off
digitalWrite(LowerPin, LOW); //Lower relay on. Curtain is going down
TimeStart = TimeNow ; // Set TimeStart at beginning of lowering
State = ST_LOWERING;
} //end of "if" testing whether curtain is at lower limit
if (BottomLevelRead == LOW) // Curtain is already closed and lower level switch is closed
{
digitalWrite(LowerPin, HIGH); //Lower relay off, (which it should be by default anyway)
digitalWrite (RaisePin, HIGH);
State = ST_LOWERED;
} //end of "if" testing whether curtain has reached lower limit
break; // Exit from case
case ST_LOWERING:
Serial.print("State = ST_LOWERING: ");
if (((TimeNow - TimeStart) >= TimeLower) || (digitalRead (BottomLevelSwitch) == LOW ))
{
digitalWrite(LowerPin, HIGH); // Turn off Lower relay
State = ST_LOWERED;
}
break;
case ST_LOWERED:
Serial.print("State = ST_LOWERED ");
if ( LightValue >= UpperLightLevel ) // Curtain is down, dawn has broken
{
TimeStart = TimeNow ; //Set start time for raising
digitalWrite(LowerPin, HIGH);
digitalWrite(RaisePin, LOW); //Raise relay on
State = ST_RAISING;
} //end of 'if'
break;
case ST_RAISING:
Serial.print("State = ST_RAISING: ");
if (((TimeNow - TimeStart) >= TimeRaise) || (digitalRead (TopLevelSwitch) == LOW ))
{
digitalWrite(RaisePin, HIGH); // Turn off Raise relay
State = ST_RAISED;
} // end of 'if'
break;
case ST_RAISED:
Serial.print("State = ST_RAISED: ");
if ( LightValue <= LowerLightLevel ) // Darkness has fallen
{
TimeStart = TimeNow; // Set start time for lowering
digitalWrite(LowerPin, LOW); //Lowering relay on
State = ST_LOWERING;
} // end of if
break;
} //end of switch
} // End of main loop
I have created a circuit diagram, (just below), but have not bothered to put in the detail of the relay circuit. Suffice it to say that the signals from the Raise and Lower pins trigger one or other of the paired relays, which are wired cross-wise, reversing the polarity of the current sent to the motor which raises and lowers the rolled-up curtain. I also removed the jumper on the relay module, and added an independent 5V power block to drive the relays themselves, (to avoid back-current interference). (And this part of the circuit has never been a problem.)
Circuit diagram:
And photograph, (for whatever you feel it is worth ) The various wires going off the block run to the photocell and the two switches.
(And, yes, the connector block has just come loose today. And the curtain is still going up and down, so the connections are still intact.)