Room automation light control - programming problem

Hello people,

I started 2 months ago building myself a device to control my lights in my room.
I know a bit about electronics but very little about programming. Now i have finished up my device which is running on a Arduino controller. The only problem I'am facing now is the programming part.

I build a switch next to my door which is turns on/off when the door is open/closed.
With the value of that switch i want to turn on my main light in my room depending on the amount of light which is being detected by the light sensor. So that it's only turned on when it's dark in my room.

My main room light is being controlled by a wireless remote which I hacked so that I can control it with my Arduino pins. That means that the pin running from the Arduino to the remote only needs to be HIGH for 2/1 seconds.

My problem is that I can't get it to work the way I want it to. When the Arduino receives a HIGH value from the door switch, I want the Arduino to sent out a HIGH signal to the remote controller of the main light. But every time I try to write a program, it keeps on repeating sending a HIGH value to my remote. But it only needs to be send one time, each time the value of the door switch changes.

I hope my problem is clear, I live in the Netherlands en my English may not always be that good. Here is a the beginning of my program. Maybe it's very easy to solve, but I couldn't figure it out myself. :frowning:

Arduino Version 1.0.1

int mainLightOn = 2;
int mainLightOff = 4;

int doorSensor = 5;

int lightSensor = 2;

int doorSensorValue;

void setup() {

  Serial.begin(9600); 

  pinMode(mainLightOn, OUTPUT);
  pinMode(mainLightOff, OUTPUT);

  pinMode(doorSensor, INPUT);
  pinMode(lightSensor, INPUT);
}

void loop() {
  doorSensorValue = analogRead(doorSensor);
  Serial.println(doorSensorValue);
  
back:
  if (doorSensor == true){
    Serial.println("Door Sensor True");
    digitalWrite(mainLightOn, HIGH);
    delay(1500);
    digitalWrite(mainLightOn, LOW);
    goto back;
  }
  if (doorSensor == false){
    Serial.println("Door Sensor False");
    digitalWrite(mainLightOff, HIGH);
    delay(1500);
    digitalWrite(mainLightOff, LOW);
    goto back;

  }
}

Moderator edit: colour tags swapped for code tags

  pinMode(doorSensor, INPUT);

Is this the door switch? If so, you aren't using the internal pullup resistor. This means you have an external resistor, right?

back:
  if (doorSensor == true){
    Serial.println("Door Sensor True");
    digitalWrite(mainLightOn, HIGH);
    delay(1500);
    digitalWrite(mainLightOn, LOW);
    goto back;

NO! NO! NO! There is no reason whatsoever to be using a goto. The loop function will be called again. There is no reason to use convoluted logic to get back to the start of loop().

My problem is that I can't get it to work the way I want it to.

How is that? What is the code doing?

doorSensorValue = analogRead(doorSensor);
  
if (doorSensor == true) {

You either have to use digitalRead(doorSensor) or you need to compare the analogRead() result to some threshold.

(And forget about gotos, as PaulS said. They're evil and should be banned from the language.)

They're evil and should be banned from the language.

Evil? No, I don't think so. Bad? Most of the time, yes.

Banned? No, I don't think so. They can almost always be avoided, but there ARE rare cases where they are needed. On an Arduino? I don't think so, but they should not be removed from the C language.

Thanks for the fast reply,
@PaulS

  • I'm using a external resister. I have connected my doorSensor (doorswitch) to an analog input since I din't had any digital inputs left on my Arduino board.
  • Ok, I won't be using a goto any more.
  • What my code needs to do is this.
  • I reads the analogInput from the doorSwitich.
  • When the Arduino receives a HIGH doorSwitchValue it needs to respond.
  • The respond will be that it sends a HIGH value to one of my wireless remote pins.
  • But it only needs to send that signal for 1 time, so the wireless remote pin will only be HIGH for 2/1 seconds and then stops sending a signal to my main light.

@tuxduino
When my door is closed, my doorSwitch is sending a 0 value to my Arduino. Can I not use that as a false. And when my door is open (the switch is closed), I receive a value from around 300. Isn't that value not automatically transformed to a true value?

I hope this makes a bit more clear about my problem. :~

int doorSensor = 5;

doorSensor variable get assigned value 5

pinMode(doorSensor, INPUT);

Pin 5 is configured as input

if (doorSensor == true){
Serial.println("Door Sensor True");
digitalWrite(mainLightOn, HIGH);
delay(1500);
digitalWrite(mainLightOn, LOW);
goto back;
}

I don't see how can this works comparing doorSensor which have a value of 5, since a boolean state is always true to a value different from 0.
This if is will always be running since 5 is different from 0 and so considerer true!!

  • I'm using a external resister. I have connected my doorSensor (doorswitch) to an analog input since I din't had any digital inputs left on my Arduino board.

That's fine to use a analog input pin, however just use it like any other digital pin (that is allowed) by doing a digitalRead(A0);

@HugoPT
Ooooh crap, I see what you mean. doorSensor needs to be doorSensorValue! :.
But how will I be able to run this part of the program only one time, without repeating it over and over again. Since that my door probably will be open longer then 1,5 seconds i don't want my Arduino to keep on sending a signal to my mainlight.

if (doorSensor == true){
Serial.println("Door Sensor True");
digitalWrite(mainLightOn, HIGH);
delay(1500);
digitalWrite(mainLightOn, LOW);

@retrolefy
Thanks for the good advice. I will use it as an digital pin. I also prefer that a lot more.
But do i still need to at this line:
pinMode(doorSensor, INPUT)

But how will I be able to run this part of the program only one time, without repeating it over and over again. Since that my door probably will be open longer then 1,5 seconds i don't want my Arduino to keep on sending a signal to my mainlight.

You need to detect when the switch transitions from released to pressed, or from released to pressed. How do you detect this?

Simple. The current state of the switch is not the same as the previous state of the switch. This implies, of course, that you need to keep track of the previous state of the switch.

And this is a good time to point out that meaningful names for variables are a really good idea.

doorSensor is not a good name. Is that supposed to be a pin number or a state? A good name would eliminate that ambiguity. doorSensorPin and doorSensorState would be better names. Of course, the door sensor is really a switch, so doorSwitchPin and doorSwitchState would be even better.

@retrolefy
Thanks for the good advice. I will use it as an digital pin. I also prefer that a lot more.
But do i still need to at this line:
pinMode(doorSensor, INPUT)

Not really required, as all pins upon power up or reset default to input pins, however it's best to do it anyway in my opinion as it gives the reader (and even you a year from now) of your code a clear understanding of what pins are being used later in the sketch.

Lefty

PaulS:

They're evil and should be banned from the language.

Evil? No, I don't think so. Bad? Most of the time, yes.

Banned? No, I don't think so. They can almost always be avoided, but there ARE rare cases where they are needed. On an Arduino? I don't think so, but they should not be removed from the C language.

PaulS, of course you're right. But there was a hidden :stuck_out_tongue: at the end of my comment. Too bad I took my hands of the keyboard right before it made it to the screen... :stuck_out_tongue:

Hej!

I worked out a new code, and it works fine. Thanks for the help everybody, I probably have a question in the near future about a programming problem. But from now on I'll be fine.

[tt]int mainLightOn = 2;
int mainLightOff = 4;

boolean doorSwitch;


int LastdoorSwitch = 0;

void setup() {
  // initialize serial communication:
  Serial.begin(9600); 

  pinMode(mainLightOn, OUTPUT);
  pinMode(mainLightOff, OUTPUT);
  pinMode(doorSwitch, INPUT);
}

void loop() {
  delay(1000);
  doorSwitch = digitalRead(3);
  Serial.println(doorSwitch);

  if (doorSwitch != LastdoorSwitch) {

    if (doorSwitch == LOW) {
      Serial.println("Door Switch HIGH");
      digitalWrite(mainLightOn, HIGH);
      delay(1500);
      digitalWrite(mainLightOn, LOW);
    }
    else if (doorSwitch == HIGH) {
      Serial.println("Door Switch LOW");
      digitalWrite(mainLightOff, HIGH);
      delay(1500);
      digitalWrite(mainLightOff, LOW);
    }
  }

  LastdoorSwitch = doorSwitch; 
}

[/tt]

boolean doorSwitch;

void setup() {
  pinMode(doorSwitch, INPUT);
}

I wouldn't recommend sending an uninitialized variable to a function that does something based on it's value.

I also would say it's better to avoid mixing the usage of variables for readings/states with pins:

const int myInputPin = 4;

int myInputState;

void setup()
{
  pinMode(myInputPin, INPUT);
}

void loop()
{
  myInputState = digitalRead(myInputPin);
  // Do something with my input
}

An error easily avoided if the OP followed PaulS's suggestions about variable names...