End mid loop() @ sensor input, how?

Been struggling with this a couple of days.
I want a LED-fading loop to end as soon as it gets a sensor input.
So far I've only been able to get it register if sensor == high when it ends and therefore not run again.

The only solution I can some up with is to add a:
if (sensor == "wanted value", return)-string
every other line in the code to keep looking for the sensor.

Is there any better way to do this? I need the function at several places in my code and to use the "If"-method will make the code extremely crowded..

I've tried to google but I don't know what I'm looking for :confused:

1 Like

Can't see your code.

Is there any better way to do this?

Yes

I need the function at several places in my code

No you don't

Use millis() to implement non blocking timing and you can read the input each time through loop().

Save the millis() value at the time that the start action happens, such as setting the PWM value for an LED. Then, each time through loop(), check whether the required wait period has elapsed by subtracting the start time from the millis() value now. If the period has elapsed then change the PWM level save the start time for the next time. If not, then go round loop() again taking other actions such as reading inputs, but don't block the free running of loop().

The demo Several Things at a Time illustrates the use of millis() to manage timing without blocking. It may help with understanding the technique.

Have a look at Using millis() for timing. A beginners guide if you need more explanation.

...R

Thank you all! I'm new to this and haven't rly looked in to millis() yet. I honestly had no clue you could use it that way, now I know what to do the rest of the evening ^^

I've gone through several books but most of them centers around given projects and don't rly get in to the more general code usage.

The book (PDF: Beginning Arduino Programming by Brian Evans ((free download)) ) I'm on right now is the first1 i've read that actually takes time to explain the code in a broader perspective.

On chapter 5 so far so haven't gotten to millis() yet. I'll skip ahead and see if it makes me any wiser.

Thx again for fast replys on (what I guess is) noob questions. Hopefully I can post my current project here soon. With working code ^^

Sry for reposting here but I’m truly stuck :confused:

Been looking in to millis() w/o getting any smarter and been looking at hardware interrupt and a bunch of other
ideas.

//LEDpins
int redPin = 11;
int greenPin = 10;
int bluePin = 9;

//SENSORpins
int HALL = 2;
int BALL = 3;
int TAP = 4;

//Other
int Mood;              // Random mood
int brightness = 0;    // how bright the LED is
int fadeAmount = 5;    // how many points to fade the LED by

  
void setup(){
  //LEDpins
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);
  setColourRgb(0,0,0); 
  
  //Sensors
  pinMode(HALL, INPUT_PULLUP);
  pinMode(BALL, INPUT_PULLUP);
  pinMode(TAP, INPUT_PULLUP);

  Serial.begin(9600);
}


void loop() {
Mood = random(11);
  //Randomise Mood
if (Mood <=1) Angry();

else if (Mood == 2 && Mood <= 5) Calm();
  
else if (Mood == 6 && Mood <= 8) Play();
  
else
{
  Serial.println("rgbFade"); 
for (int i=0; i <= 1; i++)
{
    unsigned int rgbColour[3];
    
 // Start off with red.
  rgbColour[0] = 255;
  rgbColour[1] = 0;
  rgbColour[2] = 0;  

  // Choose the colours to increment and decrement.
  for (int decColour = 0; decColour < 3; decColour += 1) {
    int incColour = decColour == 2 ? 0 : decColour + 1;

    // cross-fade the two colours.
    for(int i = 0; i < 255; i += 1) {
      rgbColour[decColour] -= 1;
      rgbColour[incColour] += 1;
      
      setColourRgb(rgbColour[0], rgbColour[1], rgbColour[2]);
      delay(20);
    }
  }
}
  Serial.println("rgbFade End");  
return;
}

//End void loop
}

 void setColourRgb(unsigned int red, unsigned int green, unsigned int blue) {
  analogWrite(redPin, red);
  analogWrite(greenPin, green);
  analogWrite(bluePin, blue);
}


void Angry(){
 Serial.println("Angry"); 
  //for (int i=0; i <= 10; i++){
   // fade in from min to max in increments of 5 points:
  for (int fadeValue = 0 ; fadeValue <= 255; fadeValue += 2) {
    // sets the value (range from 0 to 255):
    analogWrite(redPin, fadeValue);
    // wait for 30 milliseconds to see the dimming effect
    delay(30);
  }

  // fade out from max to min in increments of 5 points:
  for (int fadeValue = 255 ; fadeValue >= 0; fadeValue -= 2) {
    // sets the value (range from 0 to 255):
    analogWrite(redPin, fadeValue);
    // wait for 30 milliseconds to see the dimming effect
    delay(30);

     }
Serial.println("Angry End wrong");

  //exit Angry
  if (digitalRead (BALL) == LOW && digitalRead (TAP) == LOW) {
     Serial.println("Angry End right");
    return;
  }
else Angry();
  }
  
  

  

void Calm(){
   Serial.println("Calm");


  //code for Calm

   // fade in from min to max in increments of 5 points:
  for (int fadeValue = 0 ; fadeValue <= 255; fadeValue += 2) {
    // sets the value (range from 0 to 255):
    analogWrite(greenPin, fadeValue);
    // wait for 30 milliseconds to see the dimming effect
    delay(30);
  }

  // fade out from max to min in increments of 5 points:
  for (int fadeValue = 255 ; fadeValue >= 0; fadeValue -= 2) {
    // sets the value (range from 0 to 255):
    analogWrite(greenPin, fadeValue);
    // wait for 30 milliseconds to see the dimming effect
    delay(30);
    Serial.println("Calm end wrong");
  }
  if (digitalRead (BALL) == LOW) {
    Serial.println("Calm end right");
    return;}
  }
  
  
void Play(){

  //code for Play 
  Serial.println("play"); 
 // fade in from min to max in increments of 5 points:
  for (int fadeValue = 0 ; fadeValue <= 255; fadeValue += 2) {
    // sets the value (range from 0 to 255):
    analogWrite(bluePin, fadeValue);
    // wait for 30 milliseconds to see the dimming effect
    delay(30);
  }

  // fade out from max to min in increments of 5 points:
  for (int fadeValue = 255 ; fadeValue >= 0; fadeValue -= 2) {
    // sets the value (range from 0 to 255):
    analogWrite(bluePin, fadeValue);
    // wait for 30 milliseconds to see the dimming effect
    delay(30);
     Serial.println("play end wrong");
  }
  if (digitalRead (HALL) == LOW) {
     Serial.println("play end right");
    return;
  }
  }

I want the If-statements @ the end of every moodloop to execute as soon as the sensor gets a signal. Not having to time the sensor interaction with the end of the loop and the check of the sensorstate…

I’m at a total loss here, short of adding the If-statement every other line of the code to constantly check for a reading. There has to be a better way, doesn’t it?!

1 Like

You still have those blocking for loops. It seems all of your functions insist on finishing their whole job all the way through before they will return. You can't do that if you want things to be responsive. Keep track of the state of things and rely on calling those functions over and over in rapid succession to let them finish their job. See the links in #3.

Instead of for() loops, just increment a counter for fadeValue.
Let loop() do its thing and loop, do not use delay().
Use millis() to determine if enough time has passed to increment fadeValue.

Check the sensor input every time around loop()

Oh.. That actually made sense.

Time for a rewrite of the code (again) ^^

If you study the code in Several Things at a Time you will see that each function runs very briefly and returns to loop() so the next one can be called. And there may be dozens of calls to a function before it is actually time for it to do anything.

...R

I think I've gotten the hang of the switch side of things now :slight_smile:
Had to build the LED part of the circuit to get it, far from what I've seen in my books this one.
I just have to check how much of a bounce my sensors have to set the read interval of the pin.

Still a lot of job left to rewrite the fade in "1 line at a time" but I think i'm on the right track here...

Thanks for all the help, hopefully my next attempt will be more successful :slight_smile:

Thankfully the RGBfade won't need any stop command, just a counter.

tobbeef:
Thankfully the RGBfade won't need any stop command, just a counter.

I worry that you may think it is OK to use blocking code for the RGBfade because it does not need a stop command. However if you want the rest of the program to be responsive you must not use blocking code in any part of the program.

...R

Ok...
So I can't use the RGB-fade version above? It isn't "in use" when I'm running any of the mood-fades (the ones that need the inputs) but runs for the main part of the program.

I haven't had time to do any changes to my code yet so dunno if/how it will interfere with the rest.

I do think I've found a way to do the mood-fades though:

If needed I'll have to have a look at the main rgb-fade too, this sure became a much bigger project then I had thought from the start...

But if nothing else it serves as a good lesson in problem solving and googling :stuck_out_tongue:

I've learned a lot of other useful things during this project so the next one will hopefully go smoother.

tobbeef:
So I can't use the RGB-fade version above?

I have not looked at it so I don't know.

...R

  if (Mood <= 1) Angry();

  else if (Mood == 2 && Mood <= 5) Calm();

  else if (Mood == 6 && Mood <= 8) Play();

I’m pretty sure that if Mood ==2 that it will be less than 5, also if it == 6 then it will be less than 8.