Control a relay in context with brightness and if/else

Dear all,
I dont understand why my relay click in both cases: also if brightness light of lower and higher then 10.
Do I have a problem with my control structure if/else? Check pls (light < lightgrenze). Thx for your feedback!

// This #include statement was automatically added by the Particle IDE.
#include <blynk.h>

// Quelle:  http://diotlabs.daraghbyrne.me/7-communicating-events/pir/
//          https://learn.adafruit.com/pir-passive-infrared-proximity-motion-sensor/using-a-pir
//          https://gist.github.com/zsup/9496462
//          http://community.garadget.com/t/instructions-for-home-grown-garadget-clone/69 --> Relay Belegung und Schaltung

int inputPin = D0;              // choose the input pin (for PIR sensor)
int ledPin = D1;                // LED Pin
int pirState = LOW;             // we start, assuming no motion detected
int val = 0;                    // variable for reading the pin status
int boardLed = D7;              // photon onBoard LED
int boardRelay = D2;            // Relay
int calibrateTime = 10000;      // wait for the thingy to calibrate
int light;                      // Wert des aktuellen Lichts
int lightgrenze = 10;           // Schwellwert bei dem Dunkelerheit erkannt und Licht eingeschaltet werden soll
int light_sensor_pin = A0;

char auth[] = "123"; // photon2

void setup()
{
    // Start Blynk
    //Serial.begin(115200);
    Blynk.begin(auth);

    
  pinMode(boardLed,OUTPUT); // on-board LED 
  pinMode( ledPin, OUTPUT );
  pinMode(inputPin, INPUT);     // declare sensor as input
  pinMode(boardRelay,OUTPUT);   // declare Relay
  
      // Now flash the D7 LED on and off 
  digitalWrite(boardLed,HIGH); // Start der Kallibrierung mit D7 on
  Particle.publish("PIR-Status","now online",100,PRIVATE);
  digitalWrite(boardLed,LOW); // Start der Kallibrierung mit D7 off
}


void loop()
{
  // Start Blynk
  Blynk.run();
  
  // if the sensor is calibrated
  if ( calibrated() )
  {
  // get the data from the sensor
    readTheSensor();

    // report it out, if the state has changed
    reportTheData();
  }
  
}

void readTheSensor() {
  val = digitalRead(inputPin);
}

bool calibrated() {
  return millis() - calibrateTime > 0;
}

void reportTheData() {

  // if the sensor reads high
  // or there is now motion
  if (val == HIGH) {


    // the current state is no motion
    // i.e. it's just changed
    // announce this change by publishing an event
    if (pirState == LOW) {
      // we have just turned on --> es wurde zwar auf Wärme hin detektiert und gefunden, jedoch wird nur bei geringem Umgebungslicht der LED Streifen angeknipst.
      Particle.publish("PIR-Status","motion detected", 60, PRIVATE);
      
       // Überprüfung der Hellingkeit, da nur im Dunkeln der LED Streifen einzuschalten ist
       float light_measurement = analogRead(light_sensor_pin);
       light = (int(light_measurement/4096*100));
       delay(300);
       Particle.publish("light", String(light), PRIVATE);
       Blynk.virtualWrite(V1, String(light));
      
        if (light < lightgrenze) {
          Particle.publish("light","Licht an", PRIVATE);
          // Update the current state
          pirState = HIGH; // hang tight here until motion stops
          setLED( pirState ); // Aufruf der Funktion unten mit (An-)Schaltung des Relays
          //digitalWrite(boardLed,HIGH);
           
          //delay(1000);
          //digitalWrite(boardLed,LOW);
          //digitalWrite(boardRelay, HIGH);
          delay(15000); // Leuchtdauer
          //digitalWrite(boardRelay, LOW);
          return;
        }
        else {
            Particle.publish("light","Licht ist aus", PRIVATE);
            return;
        }
    }
  } else {
    if (pirState == HIGH) {
      // we have just turned of
      // Update the current state
      pirState = LOW;
      setLED( pirState );
      //digitalWrite(boardLed,LOW);
      //digitalWrite(boardRelay, LOW);
    }
  }
}

void setLED( int state )
{
  digitalWrite(ledPin,state); 
  digitalWrite(boardLed,state);
  digitalWrite(boardRelay,state);
}

A couple of quick questions:

  1. What do you mean by "relay click"? Do you mean the relay engages/closes?
  2. What do you mean by "if brightness of lower or higher than 10"? Isn't that all brightness levels that are not exactly 10?

It would be good to have a more detailed description of the experience you are having and what issues you have with it

to 1.) yes, the relay engages in both cases: if light is < and > threshold “lightgrenze” (in my case 10).
to 2.) After the detection, the ambient light is measured and the threshold value is used to determine whether the relay closes the circuit for a lamp or leaves it open.
In my case, however, the relay always closes. It makes me confused.

What do you see in the console logs? Is “Particle.publish(“light”,“Licht an”, PRIVATE);” firing everytime motion is detected? if so, can you log the values of light and lightgrenze?

I got this error
/src/mypir.cpp:89:66: error: invalid conversion from ‘int’ to ‘const char*’ [-fpermissive]

I tested code with this command:if (light < lightgrenze) {
Particle.publish(“PIR-light into if”,“Licht an”, PRIVATE);
Particle.publish(“PIR-light into if value”, light, PRIVATE);
Particle.publish(“PIR-light in if threshold”, lightgrenze, PRIVATE);

The control structure works in general; I got this error as I changed the publish event:
Particle.publish(“PIR-light into if value”, String(light), PRIVATE);

It might be that I have a problem with chars and values.

Now I tested
Particle.publish(“PIR-light into if value”, String(light), PRIVATE)
Particle.publish(“PIR-light into if threshold”, String(lightgrenze), PRIVATE);

threshold is not fireing into console log.

Need a bit more context. Where do these lines go in your code now?

    if (pirState == LOW) {
      // we have just turned on --> es wurde zwar auf Wärme hin detektiert und gefunden, jedoch wird nur bei geringem Umgebungslicht der LED Streifen angeknipst.
      Particle.publish("PIR-Status","motion detected", 60, PRIVATE);
      
       // Überprüfung der Hellingkeit, da nur im Dunkeln der LED Streifen einzuschalten ist
       float light_measurement = analogRead(light_sensor_pin);
       light = (int(light_measurement/4096*100));
       delay(300); // only 1 value of actual brightness is necessary to decide in the if clause
       Particle.publish("PIR-light vorher", String(light), PRIVATE);
       Blynk.virtualWrite(V1, String(light));
      
        if (light < lightgrenze) {
          Particle.publish("PIR-light into if","Licht an", PRIVATE);
          Particle.publish("PIR-light into if value", String(light), PRIVATE);
          Particle.publish("PIR-light into if threshold", String(lightgrenze), PRIVATE);
          // Update the current state
          pirState = HIGH; // hang tight here until motion stops
          setLED( pirState ); // Aufruf der Funktion unten mit (An-)Schaltung des Relays
          delay(15000); // Leuchtdauer
          return;
        }
        else {
            Particle.publish("PIR-light into if","Licht ist aus", PRIVATE);
            Particle.publish("PIR-light into if value", String(light), PRIVATE);
            Particle.publish("PIR-light into if threshold", String(lightgrenze), PRIVATE);
            return;
        }
    }
  } else {
    if (pirState == HIGH) {
      // we have just turned of
      // Update the current state
      pirState = LOW;
      setLED( pirState );
    }
  }
}

void setLED( int state )
{
  digitalWrite(ledPin,state); 
  digitalWrite(boardLed,state);
  digitalWrite(boardRelay,state);
}

Two things:

  1. How about you move those new Particle publishes out and above of the if/else (ie, right after Blynk.virtualWrite(V1, String(light));).
  2. Instead of a publish I suggest you try using Serial.print since it is a bit more reliable.

Same:

       delay(300); // only 1 value of actual brightness is necessary to decide in the if clause
       Particle.publish("PIR-light vorher", String(light), PRIVATE);
       Blynk.virtualWrite(V1, String(light));
          Particle.publish("PIR-light before if","Licht an", PRIVATE);
          Particle.publish("PIR-light before if value", String(light), PRIVATE);
          Particle.publish("PIR-light before if threshold", lightgrenze, PRIVATE);
      
        if (light < lightgrenze) {
------------
case1: Particle.publish("PIR-light before if threshold", **String(lightgrenze**), PRIVATE);
= no console log entry

case2: Particle.publish("PIR-light before if threshold", lightgrenze, PRIVATE);
= fire this error in console log:
/src/mypir.cpp:88:81: error: invalid conversion from 'int' to 'const char*' [-fpermissive]
In file included from ../wiring/inc/spark_wiring.h:48:0,
                 from ./inc/application.h:36,
                 from /src/mypir.cpp:2:
../wiring/inc/spark_wiring_cloud.h:227:17: error:   initializing argument 2 of 'bool CloudClass::publish(const char*, const char*, PublishFlag)' [-fpermissive]
     inline bool publish(const char *eventName, const char *eventData, PublishFlag eventType=PUBLIC)
                 ^

make[1]: *** [../build/target/user/platform-6src/mypir.o] Error 1
make: *** [user] Error 2

Im crying - its a simple if/else statement.
want light in the dark (relay closed, lamp on).
if it is daylight - no lamp is necessary.

If that's the case then I seriously suggest you move towards using Serial.print statements and then connect to your device over serial

You should incorporate your three publishes into just one, to avoid hitting the rate limit of 1/sec.

  Particle.publish("PIR-light before if",String::("Licht an (%d/%d)", light, lightgrenze), PRIVATE);

And instead of

 light = (int(light_measurement/4096*100));

I’d rather write

  light = ((100*light_measurement)/4095));

Since all your variables and number literals are int you will only get an int division and since any analogRead() result will be less or equal 4095 a division by 4096 will always result in 0.
And int() does not round but truncate, so even int(0.999999) would still give you 0.

2 Likes

Thanks for your feedback. Probably I have a fundamental error in the construction of the experiment with the light sensor. This throws values above the threshold value in darkness and therefore the relay switches. The if / else construct works.

1 Like