c++arduinolightfastled

If statement only works once


Here is my code:

#include <FastLED.h>

#define LED_PIN     7
#define NUM_LEDS    20

CRGB leds[NUM_LEDS];

void setup() {
    pinMode(A0, INPUT_PULLUP);
    FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
}

void loop() {
    if (digitalRead(A0) == HIGH) {
        TEST ();
    }

}
void TEST() {

    leds[0] = CRGB(255, 0, 0);
    FastLED.show();
    delay(500);
    leds[1] = CRGB(0, 255, 0);
    FastLED.show();
    delay(500);
    leds[2] = CRGB(0, 0, 255);
    FastLED.show();
    delay(500);
    leds[3] = CRGB(150, 0, 255);
    FastLED.show();
    delay(500);
    leds[4] = CRGB(255, 200, 20);
    FastLED.show();
    delay(500);
    leds[5] = CRGB(85, 60, 180);
    FastLED.show();
    delay(500);
    leds[6] = CRGB(50, 255, 20);
    FastLED.show();

}

Here's what I'm stuck on: The code is supposed to detect voltage on the A0 pin, ad trigger my test function to make the LEDs glow sequentially. My current issue is that it works, but only once. If I remove the voltage and retry it, the function does not execute. I'm not really sure what I am doing wrong. My end goal is to create code for sequential taillights for my car, this is just a proof of concept. Basically what I want to happen is for the Arduino to detect the voltage from the car's signal and create a sequential animation. I know for that to work I can't use the delay function, but I cat figure out how to make a timer that I can reset to zero. So any help with that issue would also be appreciated. Sorry if this is worded poorly or a simple solution, I am new to arduino.


Solution

  • According to the rule of writing code, the description of the called function should be higher than the place of its call. I mean that the TEST() function should be between setup() and loop()

    You need to turn off the LEDs after they have been turned on, this can be achieved with specific function from the FastLED library or as follows:

    void loop() {
        for(size_t i = 0; i != 7; ++i) {
            leds[i] = CRGB(0, 0, 0);
        }    
    
        // your code
    }
    

    It is not necessary to compare the digital result with the HIGH signal value. If the value from the sensor is HIGH, then this is automatically converted to 1, which is true in the programming language and the condition is met. If the signal is LOW, then 0 is false and the condition is not met.

    You can simply write it like this:

    if (digitalRead(A0)) {
        TEST ();
    }
    

    Also, make sure what signal the sensor produces.

    I see that in the pinMode(pin, mode) function you have connected the sensor to an analog pin that has a range of values ​​from 0 to 1023, but in the condition you are reading a digital signal with values ​​of 0 or 1.

    You use the work mode in INPUT_PULLUP mode in pinMode(), it works in reverse. For example, if the button is pressed, then it gives a LOW signal, and if it is not pressed, then a HIGH one. If you need ordinary logic, then you should use the INPUT mode. But it all depends on your connection, and you can not get hung up on this.

    It is desirable to connect digital sensors to digital pins, and analog sensors to analog ones. Moreover, if you have an analog sensor, then you do NOT need to write a pinMode().

    Thus, if your analog signal outputs a value of 0, then it will be LOW for digital, and all other values ​​are converted to a HIGH signal. It would be more correct to read the analog signal with the analogRead() function.

    Voltage-free analog signals can produce some kind of signal, so it's worth taking this into account in your program. It is necessary to measure a certain threshold after which your function should work, for example, if in a calm state the signal is not higher than 20-30, then you can write the condition as follows:

    if (analogRead(A0) > 50) {
        TEST ();
    }
    

    Also note that you have delays in the function and during this time the voltage may drop, and the condition will not work the next time.

    You can use a boolean variable that will capture the voltage and convert the value to true or false. Or you can use a counter.

    Code:

    #include <FastLED.h>
    
    #define LED_PIN     7
    #define NUM_LEDS    20
    
    CRGB leds[NUM_LEDS];
    
    void setup() {
        // if you have an analog sensor, then you do NOT need to write a pinMode()
        pinMode(A0, INPUT_PULLUP);    // maybe INPUT_PULLUP -> INPUT 
        FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
    }
    
    void TEST() {
        leds[0] = CRGB(255, 0, 0);
        FastLED.show();
        delay(500);
        leds[1] = CRGB(0, 255, 0);
        FastLED.show();
        delay(500);
        leds[2] = CRGB(0, 0, 255);
        FastLED.show();
        delay(500);
        leds[3] = CRGB(150, 0, 255);
        FastLED.show();
        delay(500);
        leds[4] = CRGB(255, 200, 20);
        FastLED.show();
        delay(500);
        leds[5] = CRGB(85, 60, 180);
        FastLED.show();
        delay(500);
        leds[6] = CRGB(50, 255, 20);
        FastLED.show();
    }
    
    void loop() {
        // turn off the LEDs
        for(size_t i = 0; i != 7; ++i) {
            leds[i] = CRGB(0, 0, 0);
        }  
    
        // make sure what signal the sensor produces
        if (analogRead(A0)) {
            TEST ();
        }
    }