LED staying on after digitalWrite(*LED*, LOW)

I’m trying to get my photon to switch between a red and green light depending on whether or not pressure is applied to a pressure sensor (pressure = red, no pressure = green). But when I run this the red LED is always on, and seems to differ in intensity slightly rather than turning off fully. I’ve tried other LEDs and switching it with the yellow one, it seems to stay the same regardless of the pin it’s plugged into or the LED used. I’ve tried analogWrite, made no difference. The green light, however, works fine, turning off and on exactly as it should, so I’m really at a loss now.

const int pressurePad = D0;
const int yellowPin = A1;
const int greenPin = A2;
const int redPin = A3;
bool reserved = false;
int pressure = 0;
void setup() {
  pinMode(yellowPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(redPin, OUTPUT);
  pinMode(pressurePad, INPUT);
}
void loop() {
  pressure = digitalRead(pressurePad);
  if (reserved == false) {
    if (pressure == HIGH) {
      digitalWrite(redPin, LOW);
      digitalWrite(greenPin, HIGH);
      // digitalWrite(yellowPin, LOW);
    } else if (pressure == LOW) {
      digitalWrite(redPin, HIGH);
      digitalWrite(greenPin, LOW);
      // digitalWrite(yellowPin, LOW);
    }
  } else if (reserved == true) {
    digitalWrite(yellowPin, HIGH);
    digitalWrite(redPin, LOW);
    digitalWrite(greenPin, LOW);
  }
}

BONUS QUESTION: I want to eventually get it to the point where if there has been pressure, the red light will stay on a while before switching back to green. Any ideas?

Just a side note:
If you have an expression like this, that can only have two possible outcomes,

 if (reserved == false)

there is no need to explicitly test for the oposite as you do there

  else if (reserved == true) 

Just remove the if (...) part.
Being over restrictive with your tests can even lead to uncaught situations. For that reason it’s always good to have an unconditional else (or default for switch-case constructs) in place to catch all otherwise uncaught cases.

While this should not change a thing with your problem, the actual reason will be addressed at the end :wink:


Another tip:
As you are using similar values for your test and your actions (HIGH/LOW), you can safe yourself some work by changing your code to this

void loop() {
  if (!reserved) {
    pressure = digitalRead(pressurePad);  // only used here
    digitalWrite(redPin   , !pressure);   // invers state of pressure
    digitalWrite(greenPin , pressure);
    digitalWrite(yellowPin, LOW);
  } else {
    digitalWrite(yellowPin, HIGH);
    digitalWrite(redPin   , LOW);
    digitalWrite(greenPin , LOW);
  }
}

or even shorter (but maybe less readable)

void loop() {
  pressure = digitalRead(pressurePad);
  digitalWrite(redPin   , !reserved && !pressure);
  digitalWrite(greenPin , !reserved &&  pressure);
  digitalWrite(yellowPin,  reserved);
}

As for your sustaining red question, you could use this

uint32_t msSustainDuration = 1000; // keep on for 1sec
uint32_t msSustainTime;

void loop() {
  pressure = digitalRead(pressurePad);

  if (millis() - msSustainTime > msSustainDuration)
    digitalWrite(redPin   , !reserved && !pressure);
  
  digitalWrite(greenPin , !reserved &&  pressure);
  digitalWrite(yellowPin,  reserved);

  if (!pressure)  // prepare to not update red for a while
    msSustainTime = millis();
}

I guess the actual reason for the behaviour you see is that you have something called a floating pin on your pressure sensor.
When you are not applying any pressure the sensor pin has no defined level (neither HIGH nor LOW) but it floats and is sometimes read as HIGH and other times as LOW, which keeps triggering both of your conditions pop up causing the dimmed (rapidly flickering) LEDs. If you add a delay(100); at the end of your code, you’ll see the flickering more clearly.

To ensure you have a defined level, even without having anything attached to the pin you’d set the pin like this pinMode(pressurePad, INPUT_PULLUP);

3 Likes

Thank you, you beautiful human, you.

1 Like

You do make me :flushed: :blush:

Cheeky extra question, if you’re up for it: any ideas on setting the reserved value remotely? What would you recommend using? Or any tutorials you can link me to? I’m looking at Blynk and a few other things but so far I can only see ways to read variables rather than set them (I’m very new at this and finding it quite hard to find what I need).

Either way thanks so much for all your help! :smile:

Read about particle.functions.

https://docs.particle.io/reference/firmware/photon/#particle-function-

Yup, Peter’s suggestion is the easiest and common route to go.

Am I on the right track here? (And should I make this a new topic or is this ok?) I’ve tried

https://api.particle.io/v1/devices/[device id]/res -d access_token=[access token] -d "args=1"

But it’s just saying

{
  "error": "invalid_request",
  "error_description": "The access token was not found"
}

Code:

const int pressurePad = D0;
const int yellowPin = A1;
const int greenPin = A2;
const int redPin = A3;
bool reserved = false;
int reserve(String command);
int pressure = 0;

void setup() {
    Particle.function("res", reserve);
    pinMode(yellowPin, OUTPUT);
    pinMode(greenPin, OUTPUT);
    pinMode(redPin, OUTPUT);
    pinMode(pressurePad, INPUT_PULLUP);
}
uint32_t msSustainDuration = 5000; // keep on for 1sec
uint32_t msSustainTime;

void loop() {
  pressure = digitalRead(pressurePad);
 digitalWrite(yellowPin,  reserved);
  if (millis() - msSustainTime > msSustainDuration){
    digitalWrite(redPin   , !reserved && !pressure);
    digitalWrite(greenPin , !reserved &&  pressure);
    }
 

  if (!pressure)  // prepare to not update red for a while
    msSustainTime = millis();
}


int reserve(String command){
     if(command == "0"){
         reserved = false;
         return 0;
     }
      else if(command == "1"){
          reserved = true; 
          return 1;
      }
      else {return -1;}
}

It sort of look OK and testing it on my own device works too.

You can’t just type that url into your browsers address line, you’d need a tool to issue a HTTP POST request (rather than GET, which a browser usually does).
For this you could use curl but niceer way to test your cloud functions is by use of one of these links
http://suda.github.io/particle-web-interface/
http://jordymoors.nl/interface/

Just one question about this alteration

  if (millis() - msSustainTime > msSustainDuration){
    digitalWrite(redPin   , !reserved && !pressure);
    digitalWrite(greenPin , !reserved &&  pressure);
    }

I understood this so that you only wanted to have the red LED stay on, which it did with my code.
When pressure was taken off the red LED stayed on for 3sec while the green immediately came back on (causing an RGB-LED to show yellow)

But with your alterations the green LED is also “time-trapped”.

And I’d also set msSustainTime = millis() - msSustainDuration; inside your res function to ensure that the red and green LED get updated once res changes.

1 Like

Without the brackets the red light was delayed in coming back on, but the green light came on instantly, when I wanted them to switch. I don’t really know, the brackets worked :sweat_smile:

Hmm, one possible reason for this might be the direction you have switched your LEDs.
I’m for example using a common anode RGB-LED, meaning that the switching signal needs to pull the cathode of the respective color LED low to actually light it up.

For this way of wiring it, you’d need to invert the logic.

But to be sure, can you just describe how you’ve wired your LEDs?
A1 -> resistor -> LED -> 3V3 or A1 -> resistor -> LED -> GND

Made a diagram here: http://imgur.com/plETxWo
I should warn you - it’s not pretty :sweat_smile:
Does this help?

OK, I’ve now copied your wiring and with this code it just works as I understood how you want it:
No pressure: green ON, red OFF
Pressure applied: immedeately green OFF, red ON
Pressure released: immedeately green ON, red stays on for 3sec and goes of then

Call Res function “1”: immedeately green OFF, red OFF, yellow ON
Call Res function “0”: immedeately yellow OFF, red and green as above

void loop() {
  pressure = digitalRead(pressurePad);
  
  digitalWrite(yellowPin,  reserved);
  if (millis() - msSustainTime > msSustainDuration)
    digitalWrite(redPin   , (!reserved && !pressure));
  digitalWrite(greenPin , (!reserved &&  pressure));

  if (!pressure)  // prepare to not update red for a while
    msSustainTime = millis();
}


int reserve(String command){
    msSustainTime = millis() - msSustainDuration;
    if(command == "0"){
      reserved = false;
      return 0;
    }
    else if(command == "1"){
      reserved = true; 
      return 1;
    }
    else {return -1;}
}

I guess you didn’t have this line in place msSustainTime = millis() - msSustainDuration;