Python (communicating with Arduino) breaks after first line in 'if'-loop - python-2.7

Currently I am using an Arduino in combination with Python. I am writing the Python code now and for an unknown reason it breaks halfway an if-loop. I think the reason might be the serial communication... I'll try to explain it with my code.
For easy reading: the parts of the code that are of interest are between rows of '====='. I put the rest of the code in for context.
Arduino Code
const int mPin = 2; // Pin attached to the Mark button
const int cPin = 3; // Pin attached to the Capture button
const int qPin = 4; // Pin attached to the Quit button
const int solAPin = 6; // Solenoid logic pin A - RELEASE PIN
const int solBPin = 7; // Solenoid logic pin B - CLOSE PIN
const int ledPin = 13; // Onboard LED
boolean lastmButton = 0;
boolean currmButton = 0;
boolean lastcButton = 0;
boolean currcButton = 0;
boolean lastqButton = 0;
boolean currqButton = 0;
void setup() {
// Initial code, run at startup
pinMode(mPin, INPUT); // Reads button press
pinMode(cPin, INPUT); // Reads button press
pinMode(qPin, INPUT); // Reads button press
pinMode(solAPin, OUTPUT);
pinMode(solBPin, OUTPUT);
pinMode(ledPin, OUTPUT);
digitalWrite(solAPin, LOW);
digitalWrite(solBPin, LOW);
digitalWrite(ledPin, LOW);
Serial.begin(9600); // Open Python communication line
}
boolean debounce(boolean last, int Pin) {
boolean current = digitalRead(Pin);
if (last != current)
{
delay(5);
current = digitalRead(Pin);
}
return current;
}
void loop() {
// Main code, continious loop
currmButton = debounce(lastmButton, mPin);
currcButton = debounce(lastcButton, cPin);
currqButton = debounce(lastqButton, qPin);
// ===========================================================
if (currmButton == HIGH && lastmButton == LOW) {
mark();
}
if (currcButton == HIGH && lastcButton == LOW) {
Serial.print("C");
}
if (currqButton == HIGH && lastqButton == LOW) {
Serial.print("Q");
}
lastmButton = currmButton;
lastcButton = currcButton;
lastqButton = currqButton;
}
//==============================================================
void mark() {
digitalWrite(solBPin, HIGH); // Close Pin, pencil moves down
delay(300);
digitalWrite(solBPin, LOW);
digitalWrite(solAPin, HIGH); // Release Pin
delay(100);
digitalWrite(solAPin, LOW); // Neutral
Serial.print("M");
}
The debounce-code is not optimal, but it works for now. As you can see; the Arduino writes M/C/Q to Python when respectively the M/C/Q buttons is pressed. This all works fine.
Now the problem:
Python Code
if (__name__ == '__main__' and fail == False):
# Create directory
print("Startup")
index = 1 # Image counter
if os.path.exists(image_path) == False:
os.makedirs(image_path)
# Find the Arduino Port
try:
portname = ""
ports = list(serial.tools.list_ports.comports())
for p in ports:
if "Arduino" in p[1]:
portname = p[0]
break
print("Arduino found on " + portname)
except:
print("Setup failed:\n Arduino not found")
fail = True
# Open Arduino serial communication
try:
arduino = serial.Serial(portname, baudrate=9600, timeout=1)
arduino.close()
arduino.open()
print("Arduino Connected")
except serial.SerialException:
print("Setup failed:\n Could not connect to Arduino")
fail = True
# Find and open the camera stream
try:
for i in range (10):
cap = cv2.VideoCapture(i)
if (cap.read()):
if cap.isOpened() == False:
cap.open()
break
print("Camera Connected\n")
except:
print("Setup failed:\n Camera not found")
fail = True
#%%# MAIN LOOP
#====================================================================
while True:
k = arduino.readline()
if k == 'M': # Mark & capture
print('Arduino: Marked')
print ("Python Captured\n")
elif k == 'C':# Capture
print "Arduino: Python, capture this dot please" # This line is executed when K == C (button pressed on Arduino)
print "Python: Captured!\n" # This line is not executed directly afterwards, but appears together with the line above when the button is pressed for the SECOND time!
elif k == 'Q': # Quit
print "Arduino: Quit the program"
break
#=====================================================================
When running the Python code, the Arduino connection is set up. When one of the buttons is pressed, the Arduino sends the correct signal to Python, so far so good. But: only the first row of the if-loop is executed. The remaining rows are executed when the button is pressed for the second time, followed by the first row again (since the button is pressed for a second time).
For instance, running the code and pressing 'C' twice results in the following console output:
Startup
Arduino found on COM4
Arduino Connected
Camera Connected
[button C is pressed for first time]
Arduino: Python, capture this dot please
[buttong C is pressed for second time]
Python: Captured!
Arduino: Python, capture this dot please
What I've tried so far:
Placing delays in the Arduino code
Placing 'Serial.flush()' in the Arduino code
Adjusting the way the info is printed, different quotes/brackets etc.
So this is where I'm stuck and I don't really know where to look for the bug. If any extra information is necessary, I'm happy to provide it. I hope someone here can help me!
EDIT:
As I mentioned in the comments, placing a print-command in the while loop magically fixes the issue:
k = arduino.readline()
print k
if k == 'M': # Mark & capture
But why this resolves the issue is still unclear to me.
Thanks in advance,
Stijn

Related

Update speed while going to position

Need to update potentiometer values all time not only once, try different ways but nothing works :(
I think that main problem is that this function while(digitalRead(gotoPositionAPin)); blocks
Now it's read value and save speed
workflow of code
press button right save position a
press button left save position b
update pot speed (set speed)
update pot acceleration (set accel)
press button go to position A (its going with previous set of speed and acceleration)
press button go to position B (its going with previous set of speed and acceleration)
#include <AccelStepper.h>
// Define some steppers and the pins the will use
AccelStepper stepper1(1, 12, 11);
#define stepsPerRev 1600
#define stepPin 12
#define dirPin 11
#define ledPin 13
#define rotateLeftPin 7
#define rotateRightPin 6
#define savePositionAPin 5
#define savePositionBPin 4
#define gotoPositionAPin 3
#define gotoPositionBPin 2
#define maxSpeedPin 0
#define accelPin 1
// Set this to zero if you don't want debug messages printed
#define printDebug 0
// These are the constants that define the speed associated with the MaxSpeed pot
#define MAX_STEPS_PER_SECOND 1000 // At 200 s/r and 1/8th microstepping, this will be 333 rev/minute
#define MIN_STEPS_PER_SECOND 27 // At 200 steps/rev and 1/8th microstepping, this will be 1 rev/minute
// Change this value to scale the acceleration pot's scaling factor
#define ACCEL_RATIO 1
int buttonState = 0;
int stepNumber = 0;
int curSpeed = 100;
int dir = 0;
int maxSpeed = 0;
int accel = 0;
long savedPosA = 0;
long savedPosB = 0;
int loopCtr = 0;
float fMaxSpeed = 0.0;
float fStepsPerSecond = 0.0;
void setup()
{
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);
pinMode(ledPin, OUTPUT);
pinMode(rotateLeftPin, INPUT);
pinMode(rotateRightPin, INPUT);
pinMode(savePositionAPin, INPUT);
pinMode(savePositionBPin, INPUT);
pinMode(gotoPositionAPin, INPUT);
pinMode(gotoPositionBPin, INPUT);
if (printDebug)
{
// Initialize the Serial port
Serial.begin(9600);
}
// blink the LED:
blink(2);
stepper1.setMaxSpeed(800.0);
stepper1.setAcceleration(600.0);
// Grab both speed and accel before we start
maxSpeed = analogRead(maxSpeedPin);
// Do the math to scale the 0-1023 value (maxSpeed) to
// a range of MIN_STEPS_PER_SECOND to MAX_STEPS_PER_SECOND
fMaxSpeed = maxSpeed / 1023.0;
fStepsPerSecond = MIN_STEPS_PER_SECOND + (fMaxSpeed * (MAX_STEPS_PER_SECOND - MIN_STEPS_PER_SECOND));
if (fStepsPerSecond > 1000)
{
fStepsPerSecond = 1000;
}
accel = analogRead(accelPin)/ACCEL_RATIO;
}
void loop()
{
// First, we need to see if either rotate button is down. They always take precidence.
if(digitalRead(rotateLeftPin))
{
stepper1.setSpeed(-fStepsPerSecond);
while(digitalRead(rotateLeftPin))
{
CheckPots();
stepper1.runSpeed();
stepper1.setSpeed(-fStepsPerSecond);
}
}
else if (digitalRead(rotateRightPin))
{
stepper1.setSpeed(fStepsPerSecond);
while(digitalRead(rotateRightPin))
{
CheckPots();
stepper1.runSpeed();
stepper1.setSpeed(fStepsPerSecond);
}
}
// Go see if we need to update our analog conversions
CheckPots();
// Check to see if user is trying to save position A or B
if(digitalRead(savePositionAPin))
{
savedPosA = stepper1.currentPosition();
if (printDebug)
{
Serial.print("Saved A at :");
Serial.println(savedPosA);
}
while(digitalRead(savePositionAPin));
}
if(digitalRead(savePositionBPin))
{
savedPosB = stepper1.currentPosition();
if (printDebug)
{
Serial.print("Saved B at :");
Serial.println(savedPosB);
}
while(digitalRead(savePositionBPin));
}
// Check to see if the user wants to go to position A or B
if (digitalRead(gotoPositionAPin))
{
if (printDebug)
{
// Yup, let's go to position A
Serial.print("cur pos = ");
Serial.println(stepper1.currentPosition());
Serial.print("Going to A = ");
Serial.println(savedPosA);
Serial.print("Speed = ");
Serial.println(fStepsPerSecond);
Serial.print("Accel = ");
Serial.println(accel);
}
stepper1.setAcceleration(0);
stepper1.runToNewPosition(stepper1.currentPosition());
stepper1.setMaxSpeed(fStepsPerSecond);
stepper1.setAcceleration(accel);
stepper1.runToNewPosition(savedPosA);
if (printDebug)
{
Serial.print("new pos = ");
Serial.println(stepper1.currentPosition());
}
while(digitalRead(gotoPositionAPin));
}
else if (digitalRead(gotoPositionBPin))
{
// Yup, let's go to position B
if (printDebug)
{
Serial.print("cur pos = ");
Serial.println(stepper1.currentPosition());
Serial.print("Going to B = ");
Serial.println(savedPosB);
Serial.print("Speed = ");
Serial.println(fStepsPerSecond);
Serial.print("Accel = ");
Serial.println(accel);
}
stepper1.setAcceleration(0);
stepper1.runToNewPosition(stepper1.currentPosition());
stepper1.setMaxSpeed(fStepsPerSecond);
stepper1.setAcceleration(accel);
stepper1.runToNewPosition(savedPosB);
if (printDebug)
{
Serial.print("new pos = ");
Serial.println(stepper1.currentPosition());
}
while(digitalRead(gotoPositionBPin));
}
}
// Blink the reset LED:
void blink(int howManyTimes)
{
int i;
for (i=0; i < howManyTimes; i++)
{
digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);
delay(200);
}
}
void CheckPots(void)
{
loopCtr++;
// Only read these once in a while because they take a LONG time
if (loopCtr == 100)
{
maxSpeed = analogRead(maxSpeedPin);
// Do the math to scale the 0-1023 value (maxSpeed) to
// a range of MIN_STEPS_PER_SECOND to MAX_STEPS_PER_SECOND
fMaxSpeed = maxSpeed / 1023.0;
fStepsPerSecond = MIN_STEPS_PER_SECOND + (fMaxSpeed * (MAX_STEPS_PER_SECOND - MIN_STEPS_PER_SECOND));
if (fStepsPerSecond > 1000)
{
fStepsPerSecond = 1000;
}
}
// Read in the acceleration analog value
// This needs to be scaled too, but to what?
if (loopCtr >= 200)
{
accel = analogRead(accelPin)/ACCEL_RATIO;
loopCtr = 0;
}
}
If you're looking into "continuous operation" but don't want to introduce interrupts into your code (which will have special requirements in and of itself) there are a couple of things you need to get rid of:
Endless loops like: while(digitalRead(savePositionAPin));
System waits like: delay(200); as in your blink()
and instead use state variables. State variables are more or less what the name says: variables that hold the state of something, so you know what value the button, or timer, or counter had last time.
So, instead of a while-loop waiting for a button to be released, just set a global or static boolean that knows what state you were in the last time loop() ran, so you don't trigger the button action again. You need one boolean flag for each button.
And instead of delays, either create a state variable that holds "passed time" which you can get from millis() for example. So don't wait but instead you should just check if a certain amount of time has passed so you can toggle the state of the LED.
Adding a blinking LED to loop() - (untested example):
#define LEDWAIT 300
unsigned long myTime = 0;
bool onoff = false;
loop()
{
if (myTime == 0)
myTime = millis();
if ((millis() - myTime) > LEDWAIT) {
digitalWrite(ledPin, onoff ? HIGH : LOW);
onoff = !onoff;
myTime = millis();
}
// do other things
}
It is not entirely clear to me what your program is supposed to do and what the error is, so please correct me if I am wrong: You want to update a value based on which button is pressed? What is your opinion on using interrupts for triggering the updates?
You may want to edit the formating of your question.

Arduino - Measuring the time interval between one button press and release - Add Velocity to MIDI Keyboard

I hope you are doing all really well, I am trying to make a MIDI Piano Keyboard, Pretty basic I press a key the MIDI signal is send and the sounds comes.
But I want to add the velocity to the my keys, there are one contacts per key (the keyboard I am using is Fatar Keyboard).
I need to calculate the time interval between the first contact and then the second contact ( Circuit Diagram is attached below).
All the keys are in set as input pull_up
when a key is pressed it goes low … Of course
Mentioned Below is the function where I am reading the keys. what do I need to do to get the following situation done
[they are 49 keys which are arranged in to two diode matrices. There are actually 98 switches in the matrix. The reason for this is that there are two switches under each key. When a key is pressed, one of the switches closes slightly before the other one. By measuring the time of flight between the switches we can derive the velocity]
Situation 1
Key is pressed
Start Time
Time for how long its pressed
Key Released
Code
void read_keys() {
for (uint8_t key = 0; key < 49; key ++) {
digitalWrite(output_main[key], LOW); //turn off output main key
if (digitalRead(input_pullup[key]) == LOW) {
//check main input key is presses
//check with key_activated array
firstcontactdownmills = millis();
Serial.println(key);
Velocity = map(currentmills - firstcontactdownmills, 0, 256, 127, 0);
if (key_activated[key] == 0) {
//send midi on command
my_midi.sendNoteOn(key + note_offset, Velocity, 1);
main_midi.sendNoteOn(key + note_offset, Velocity, 1);
//update array
key_activated[key] = 1;
}
}
else { //if key released
//check with key_activated array
if (key_activated[key] == 1) {
//send midi off command
my_midi.sendNoteOff(key + note_offset, 0, 1);
main_midi.sendNoteOff(key + note_offset, 0, 1);
//update array
key_activated[key] = 0;
}
}
digitalWrite(output_main[key], HIGH); //turn on output main key
}
}
Circuit Diagram of the Keyboard
You can add a state variable to your keys, that keeps track of where your key is. You can then start the timer at the transition from not_pressed to half_pressed. You then evaluate the velocity at a transition from half_pressed to full_pressed.
You should also add a timeout that resets it back to unpressed in case a key press is missed.
But I am not sure if your loop will be fast enough after adding this kind of logic.
Here's an idea that assumes that if a keyboard player is holding down a key, the contact pin will stay LOW and that there will be 3 interesting state changes
First HIGH->LOW : First contact - record the current time using millis()
Second HIGH->LOW : Second contact - calculate velocity and send key on.
Third HIGH->LOW : Release contact - send key off
Since it doesn't seem possible to actually know if it's contact1 or contact2 that causes the pin to go LOW, it's very sensitive. If you start the program while holding down a key, that will cause the program to think it's the first contact - and everything after that will be messed up.
First, you need something to convert the time between two contact events into velocity. Here's a linear conversion funciton. You'll need to find the proper constants for min and max for your keyboard by measuring.
unsigned char calc_velocity(unsigned ms) {
static constexpr unsigned min = 2; // the fastest time you've measured
static constexpr unsigned max = 80; // the slowest time you've measured
static constexpr unsigned mul = 127000 / (max - min);
if(ms < min) return 127; // harder than "possible", log and recalibrate
if(ms > max) return 0; // softer than "possible", log and recalibrate
return (127000 - ((ms - min) * mul)) / 1000; // 0(min vel) - 127(max vel)
}
Then, you could create a class to keep track of the state for one key alone. It makes it easier than to have a lot of separate arrays.
// an enum for keyboard events
enum class Event { ev_nothing, ev_key_on, ev_key_off };
struct Key {
unsigned long first_contact{};
int contact_count = 0;
unsigned char velocity{};
bool contact_state = false;
// set contact state and return an Event to act upon
Event set(bool contact) { // false = no contact, true = contact
// if the state has not changed, do nothing
if(contact == contact_state) return Event::ev_nothing;
contact_state = contact; // set the new state
// only care about when state changes to having contact
if(contact_state) {
// count HIGH->LOW transitions
contact_count = (contact_count + 1) % 3;
// 1 = first contact
// 2 = second contact (key on)
// 0 = release contact (key off)
switch(contact_count) {
case 2: // second contact
velocity = calc_velocity(millis() - first_contact);
return Event::ev_key_on;
case 0: return Event::ev_key_off; // release contact
case 1: first_contact = millis(); // first contact
}
}
return Event::ev_nothing;
}
};
Then define these globally:
constexpr std::uint8_t kNumberOfKeys = 49;
Key keys[kNumberOfKeys];
With that, your read_keys() function could look this this:
void read_keys() {
for (uint8_t key = 0; key < kNumberOfKeys; ++key) {
digitalWrite(output_main[key], LOW); //turn off output main key
// Do a digitalRead() and call the set() function for that key which will
// return an Event.
switch(keys[key].set( digitalRead(input_pullup[key]) == LOW )) {
case Event::ev_key_on:
my_midi.sendNoteOn(key + note_offset, keys[key].velocity, 1);
main_midi.sendNoteOn(key + note_offset, keys[key].velocity, 1);
break;
case Event::ev_key_off:
my_midi.sendNoteOff(key + note_offset, 0, 1);
main_midi.sendNoteOff(key + note_offset, 0, 1);
break;
case Event::ev_nothing:
default:
break;
}
digitalWrite(output_main[key], HIGH); //turn on output main key
}
}
This could be made so that each Key object would know which key number it actually is and so that it could read its own pin etc. It could also return an Event object which starts by turning off output main key and turns it back on when it's destroyed - but I think this leaves it more open since I don't know much about why the output main key should be turned off and on.
Disclaimer: I've ofcourse not been able to test this - so see it as building blocks.

How to get a input that continuously gives data to output a single digit integer value

To give a short summary of my project, it’s a smart parking system where I let a parking user know whether a parking lot is vacant or not. I’m implementing an XBee network containing 1 coordinator and 2 routers. I have two sensors, 1 sensor at the exit and 1 at the entrance. Those two sensors are the routers and whatever data they gather is being transmitted to the coordinator (output). The two routers have the same code which is:
INPUT CODE (TRANSMITTING):
#include<SoftwareSerial.h>
#define Sensor 8
void setup() {
pinMode(Sensor,INPUT);
Serial.begin(9600);
}
void loop()
{
bool Detection = digitalRead(Sensor);
int carexit=1;
if(Detection == HIGH)
{
Serial.println("Car Exit");
Serial.write(carexit);
}
if(Detection == LOW)
{
Serial.println("Clear");
}
}
It’s a very simple code where it detects a car coming in or out. Since the two routers are the same we’ll use the sensor for the cars exiting. When I open the serial monitor, the word “Clear” will keep on being outputted continuously nonstop until detection is found which will show an output of “Car Exit” for about 3 seconds and then return to “Clear” continuously. This data is being transmitted to the coordinator. What I’m trying to do is take that continuous data and have the serial monitor at the coordinator input a single integer value. For example, at the entrance, the sensor will sense the car and transmit the data to the coordinator where it'll increment. The result will show something like this if there’s only 1 vacant slot available:
Vacant slots: 1
and when the car exits the router at the exit, it will transmit a code to the coordinator decrementing it:
Vacant slots: 0
So, the input(router) would be transmitting continuous data while the output(transmitter) will detect it and just register it for a single-digit value. The output code(receiving) by the way is shown below:
OUTPUT CODE(RECEIVING):
#include "SoftwareSerial.h"
// RX: Arduino pin 2, XBee pin DOUT. TX: Arduino pin 3, XBee pin DIN
void setup()
{
Serial.begin(9600);
}
void loop()
{
if (Serial.available() > 0)
{
Serial.write(Serial.read());
}
}
The output code is pretty simple as well. Let me know if there’s any possible way to implement what I’m trying to do and if there are any other details I left out, let me know as well.
Thank you!
This is a very common problem, best solved at the source, in your sensor transmit code.
//...
bool PreviousDetection = false;
void loop()
{
bool Detection = digitalRead(Sensor);
// do not do anything when state hasn't changed.
if (Detection != PreviousDetection)
{
if (Detection)
Serial.println("Car Exit");
else
Serial.println("Clear");
}
PreviousDetection = Detection;
}
You may want to add some debouncing to reduce the risk of false readings.
//...
// Debounce thresholds the number depends on the frequency of readings,
// speeed of cars, sensitivity and placement of your sensor...
// Dirt, sun exposure, etc... may influence readings in the long term.
const int LowDebounceThreshold = 3;
const int HighDebounceThreshold = 3;
bool PreviousDetection = false;
int DebounceCounter = 0;
bool DebouncedPreviousDetection = false;
void loop()
{
bool Detection = digitalRead(Sensor);
//
if (Detection == PreviousDetection)
++DebounceCounter; // this will rollover, but will not affect
// DebouncedDetection in any meaningfull way.
else
DebounceCounter = 0;
PreviousDetection = Detection;
bool DebouncedDetection = PreviousDebouncedDetection;
if (Detection && DebounceCounter >= HighDebounceThreshold)
DebouncedDetection = true;
else if (!Detection && DebounceCounter >= LowDebounceThreshold)
DebouncedDetection = false;
if (DebouncedDetection != PreviousDebouncedDetection)
{
PreviousDebouncedDetection = DebouncedDetection;
if (DebouncedDetection)
Serial.println("Car Exit");
else
Serial.println("Clear");
}
}

Stop arduino loop when a condition is active

I need my code to stop in the loop, i have tried to put in a break but the method sendToGCM() continues. I only want the method to be executed once, the stop while the condition
void loop()
{
// Other code here giving temp a value
if (temp > 22)
{
status = false;
value["status"] = status;
while (temp > 22)
{
sendToGCM(); // Sends push notification
break;
}
}
else
{
status = true;
value["status"] = status;
}
}
So if I understood you correctly, if the temperature goes 22 degrees you want to send a message, but only the first time. If you break the loop, you still enter it if you the loop() function is executed again.
In order to achieve what you want to do, you code will need to look something like this
boolean message_sent;
void loop() {
...
if(temperature > 22 && !message_sent) {
sendToGCM();
message_sent = true;
}
}
If you want to send a message every time the temperature rises over 22 degrees you would need something like this
boolean message_sent;
boolean was_under_22;
void setup() {
...
was_under_22 = function_that_checks_if_temp_is_under_22();
...
}
void loop() {
...
if(temperature > 22 && was_under_22) {
if(!message_sent) {
sendToGCM();
message_sent = true;
was_under_22 = false;
}
} else {
was_under_22 = true;
message_sent = false;
}
}
EDIT: slightly adapted the code in response to Patrick Trentin's comment. The code assumes you only want to capture if the temperature rises above 22 degrees and that if the Arduino starts with over 22 degrees then no message is sent.
Your problem is that you are setting temp, then entering the loop that checks that value. A simple solution would be to update the temp value inside the while loop, to give the application a chance to break out of the while loop.
Example:
void loop()
{
// Other code here giving temp a value
if (temp > 22)
{
status = false;
value["status"] = status;
while (temp > 22)
{
sendToGCM(); // Sends push notification
//Additional code to set the value of temp, allowing the value to
//be greater than 22.
}
}
else
{
status = true;
value["status"] = status;
}
}
Please note that the above example is intended to continuously send the push notification while the temp value is over 22. If that's not the intention, just remove the sendToGCM() from the while loop. You will still only send it if the temp is greater than 22, since you have the if check.

Controling Light With Photoresistor And Serial Communication - Arduino

I'm trying to turn a light "On" and "Off" with Arduino using a Relay, Photo-resistor and Serial Communication. The problem come in to play when I try to turn the light Off when the Photo-resistor is receiving a low value and has received an instruction via Serial Communication to prevent the "IF" statement from activating, it simply doesn't not work as the light is kept on.
I'm using 4 "IF" statement to control the light: auto light using Photo-resistor and serial value resumed in "ON/OFF", turn light on using serial value "h", turn light off using serial value "l" and another serial value to control the auto light statement using "a" to control the first statement.
How can I use a value to control light based on a sensor and serial output at the same time. In other words, how can I stop light from turning on automatically?? What I'm doing wrong or what I left?
Here is my simple code:
char val;
boolean setAuto=true; // Automatic Light Status Value
int ldr;
int relayPin=4;
void setup() {
pinMode(relayPin, OUTPUT);
Serial.begin(9600);
}
void loop() {
ldr = analogRead(A0); // Read value from Photoresistor
if ( Serial.available()) {
val = Serial.read(); // Get serial value
}
if ( setAuto == true && ldr < 50 ) { // Here is the main problem
digitalWrite(relayPin, HIGH);
}
else if ( val == 'h' ) {
digitalWrite(relayPin, HIGH); // Work
}
else if ( val == 'l') {
digitalWrite(relayPin, LOW); // Work
}
else if (val == 'a') { // Here is the other part of the problem
setAuto = !setAuto; // Changing value for automatic light
}
}
The first if statement:
if ( setAuto == true && ldr < 50 ) { // Here is the main problem
digitalWrite(relayPin, HIGH);
} else {
takes precedence over the next two if statements. Since setAuto is ALWAYS true and so when ldr < 50 the light thru relayPin is ON.
Think about how you might want to setAuto to false.
Hint. You might want to evaluate val just after it is read:
if ( Serial.available()) {
val = Serial.read(); // Get serial value
if (val == ..... logic to affect the course of events.....
}