Execute one time only in the loop

so i've been in a code recently for an automatisation of a lamp throught a light sensor.

i wanna get the message "lampe allumable " (it's french) only when the sensor is detecting the necessary lux but i wanna get the "lampe allumée" (lamp on) when it's on and i get the allumable instead (which means, "can get turn on".
i assume that it's because of the print on line 30 of my program so i would like to know if i could only run it once every time i get on the if of the line 28?
here's the program ;
(if i use a complicated way to use the button it's cuz it's a weird pushbutton don't mind it)

#include <LiquidCrystal.h>
#include <Wire.h>  // inclure la bibliothèque permettant la communication par le protocole I2C
#include "rgb_lcd.h"

rgb_lcd lcd;

const int ledPin = A3; // Pin digitale pour la LED
bool ledOn = false;  // variable
bool capteur = false;
const int touchPin = A2;
const int lightSensorPin = A0; 

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  lcd.begin(16, 2); // Initialise l'écran LCD avec 16 colonnes et 2 lignes
  lcd.setCursor(0, 0); // positionner le "curseur" de l'afficheur LCD
  
  pinMode(touchPin, INPUT);
  pinMode(ledPin, OUTPUT);
  lcd.clear(); // Efface l'écran LCD
}

void loop() {
  int lightLevel = analogRead(lightSensorPin); // Lit la valeur de la lumière sur la pin analogique
  int touchVal = digitalRead(touchPin); // lecture de la valeur du capteur Grove - Touch Sensor
  
  if (lightLevel < 100) {
    lcd.setCursor(0, 0); // Positionne le curseur en haut à gauche de l'écran LCD
    lcd.print("Lampe allumable ");

    if (touchVal == HIGH) { // si le capteur est touché
      delay(100); // attendre un court instant pour éviter les faux déclenchements
      touchVal = digitalRead(touchPin); // lire à nouveau la valeur du capteur
      if (touchVal == HIGH && ledOn == true) { // si le capteur est toujours touché et que la LED est allumée
        ledOn = false; // éteindre la LED
        lcd.setCursor(0, 0); // positionner le "curseur" de l'afficheur LCD
        lcd.print("Lampe allumable "); // affiche "Lampe allumable" sur l'écran LCD
      
      } else 
      
        if (touchVal == HIGH && ledOn == false) { // si le capteur est toujours touché et que la LED est éteinte
        ledOn = true; // allumer la LED
        lcd.setCursor(0, 0); // positionner le "curseur" de l'afficheur LCD
        lcd.clear(); // Efface l'écran LCD
        lcd.print("Lampe allumee"); // affiche "Lampe allumee" sur l'écran LCD
      }
    }
  } else { 
    lcd.setCursor(0, 0); // Positionne le curseur en haut à gauche de l'écran LCD
    lcd.print("soleil present  "); // affiche "soleil present" sur l'écran LCD
    digitalWrite(ledPin, LOW); // éteindre la LED
    ledOn = false; // mettre à jour l'état de la LED
  }

  digitalWrite(ledPin, ledOn); // mettre à jour l'état de la LED
}

thank you if u can help me !

Yes.

Hello gogoss54

I have checked the code a little.
This sketch seems to have grown organically through nested and dupilcate function calls.
This leads to spaghetti code and nodes in the logic that are functionally undesirable.

What to do.
There are two options.
Debug, using multiple Serial.println()'s to see what happens under different conditions. Nodes can be solved this way, but new ones can also be created in the process.
The second option is to rearrange the sketch. Based on the IPO model, structure the desired function of the sketch into basic functions. Take a sheet of paper and a pencil and draw a programme structure to identify the required functions, e.g. button, timer and display functions. All these functions can be coded and tested separately. To complete the project, you also need to design a control structure that uses events to call the above functions. In this way keep in mind to design objects and related services thus handle input/output actions.
That is all that needs to be done. Try them out.

Have a nice day and enjoy coding in C++.

int RunOnce = 0;

loop() {
if (RunOnce == 0) {
// do something
RunOnce == 1;
}
}

First of all you are working on a medium advanced functionality.
And this somehow advanced functionality requires quite some programming knowledge.
As you can see from your actual code applying if elseif else-statements leads to a complicated code.

With learning a new coding-method such functionalities can be achieved in a better way
Though you need to learn something new.

Your automated lamp has different modes of operation

The minimum is:

  • mode 1: enough daylight don_t react on button-touches

  • mode 2:light is OFF combined with ambient light below threshold -value do react on button-touching to switch light on

  • mode 3:light is ON combined with ambient light below threshold -value do react on button-touching to switch light off

a bit more advanced would be

  • mode 1a: measured daylight is above threshold-value show message "enough daylight"
    still in mode 1 if button is touched show a message "to bright for switching on" for let's say 5 seconds then go back to show the message "enough daylight"

so this means there is a mode

  • mode1b : measured daylight is above threshold-value and button was pressed

which switches to a

  • mode 1c: show message "enough daylight" and start a 5-second timer

then switch to a

  • mode 1d: wait until 5 seconds have passed by (shows the message for 5 seconds)
    then switch to mode 1a

  • mode 2:light is OFF combined with ambient light below threshold -value do react on button-touching to switch light on

  • mode 3:light is ON combined with ambient light below threshold -value do react on button-touching to switch light off

As soon as you have more than two modes of operation one solution to realise such a functionality is to use
mode of operation-selector or you could call it mode-switching

The advantage of the different modes is that in each mode only that part of the code is executed that is nescessary in this mode.

This reduces the number of required if-conditions to a minimum.
The code that realises this is the switch-case-break-statement

The break is bolded because addding a break inside each case is essential to make it work.
Forgetting a break at the end of a case leads to a different behaviour than the wanted behaviour.

Using different modes of operation in informatic terms is called a state-machine
each mode is a state. There are a lot of online tutorials about state-machines.
I have written one too which you can read here:

best regards Stefan

do you really mean just once? if so do it in setup()

but i think you mean once every time the lightLevel drops below 100. if so, then some flag needs to be set indicating that the message is reported and that flag needs to be reset when the lightLevel rises above 100

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.