Go Down

Topic: Another Loop Breaking Problem (Read 815 times) previous topic - next topic

lkacenja

Hi, I'm working on some led fading XBee networked organisms. Ideally, I want it to work where if a wireless "H" is sent through the serial port it will do function 1, conversely if a "L" is sent through the serial port, function 2. My problem seems to be, that the program gets stuck in either function 1 or 2, depending on what the first value sent is. I can't seem to figure out how to stop one function and start the other based on the serial data. I've read around and seen some stuff about recursion, but I think it that were the only problem I'd eventually see the modes switch. Currently, it never changes. I'd really appreciate some help. This project is supposed to be installed in the next few days. Thanks very much.

Code: [Select]
/*
 Physical Pixel

An example of using the Arduino board to receive data from the
computer.  In this case, the Arduino boards turns on an LED when
it receives the character 'H', and turns off the LED when it
receives the character 'L'.

The data can be sent from the Arduino serial monitor, or another
program like Processing (see code below), Flash (via a serial-net
proxy), PD, or Max/MSP.

The circuit:
* LED connected from digital pin 13 to ground

created 2006
by David A. Mellis
modified 14 Apr 2009
by Tom Igoe and Scott Fitzgerald

http://www.arduino.cc/en/Tutorial/PhysicalPixel
*/

const int ledPin = 9; // the pin that the LED is attached to
int incomingByte;      // a variable to read incoming serial data into
int progress = 0;
int fnum = 0;
int num = 1;
int currentPos = 1;
int lastPos = 0;




void setup() {
 // initialize serial communication:
 Serial.begin(9600);
 // initialize the LED pin as an output:
 pinMode(ledPin, OUTPUT);
 pinMode(13, OUTPUT);
}

void loop() {
 // see if there's incoming serial data:
 if (Serial.available() > 0) {
   // read the oldest byte in the serial buffer:
   incomingByte = Serial.read();
   // if it's a capital H (ASCII 72), turn on the LED:
   if (incomingByte == 'H') {
     flash();
   }
   // if it's an L (ASCII 76) turn off the LED:
   if (incomingByte == 'L') {
     randomsequence();
   }
 }
}


void flash(){
 while(progress <= (num*510)){
   // fade in from min to max in increments of 5 points:
   for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=5) {
     // sets the value (range from 0 to 255):
     analogWrite(ledPin, fadeValue);        
     // wait for 30 milliseconds to see the dimming effect    
     delay(30);
     progress +=5;    
   }

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

 if(progress >= (num*510)){
   progress = 0;
   delay(5000);
   num = fibsequence();
 }
}

int fibsequence(){
 int fnum;
 fnum = currentPos + lastPos;
 lastPos = currentPos;
 currentPos = fnum;
 return fnum;
 if(fnum >= 34){
   int fnum = 0;
   int num = 1;
   int currentPos = 1;
   int lastPos = 0;
 }
}

void randomsequence(){

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

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

}

Spinlock

Hi lkacenja...

You need to re-think how you are going about doing things.  What you are essentially telling the processor in your code is 'did you see an H?, if so, go and flash the led for x amount of times, and come back when you are done.'  The processor is busy in your LED flashing routine when you send a stop command (or any other...)

What you need to do is more like   'Did I see an H?  Yup?  Ok, mark down the LED should be flashing.  Then, based on the variables, what do I need to do just this time through the loop?'

I have put together something like that in the code like below.  There are other samples like that on the learning website - check out nodelay, for example.  Notice how delay() isn't called, and while, for, etc...  I simply just check to see if it is time to do anything new, if not, I happily return and try again next turn.

Code: [Select]

#define LEDPIN 13
#define PERIOD 1000

bool bFlashLed = false;
int bLastLedState = LOW;
unsigned long uLastChange =0;

void loop()
{
   // read serial, set state of our device.  Don't do the work yet, just mark our
   // variables.
   char c;
   if(Serial.available())
  {
     c = Serial.read();
     if(c=='H')
         bFlashLed = true;
     else if(c=='L')
         bFlashLed = false;
  }
 // call our worker functions that do stuff.
  DoWork();
}

void DoWork()
{
   DoLED();
  // if we had a servo to work with, we could call DoServo or any other work functions here.  
}

// handle our actual work here.
void DoLED()
{
  if(bFlashLed)
  {
     if(millis()-PERIOD>=uLastChange)
    {  
         uLastChange = millis();
         bLastLedState=(bLastLedState == HIGH? LOW:HIGH);
         digitalWrite(LEDPIN, bLastLedState);
    }
  }
  else if(bLastLedState == HIGH)
 {
    // in case we cancelled with the LED on, reset it.
    bLastLedState = false;
    digitalWrite(LEDPIN, bLastLedState);
 }
}

lkacenja

Hi and thanks Spinlock,

I see what you are getting at. However, I'm confused as to how I would approach achieving fades. Also, I'd like to be able to control how many times an led fades. Any thoughts on how to achieve this stuff without any loops? Thank you very much.

ill_switch

lkacenja,

I'm working on a similar problem but don't quite have it sorted yet. However, maybe I can help a bit, since I've taken the route Spinlock suggested.

Basically, you need to add some variables to Spinlock's example to keep track of "where" in your fade you are for each iteration.

Let's say for function 1, you want to fade from 0 - 255 X amount of times at a certain rate a, and for function 2, you want to fade from 0 - 255 Y amount of times at a different rate, b.

The approach I took is to write a single generic "fade" function that takes in the led pin, the desired amount of fades, the desired fade rate, and two variables to describe the point in the whole function the led was at for the last iteration of the main loop. Then, it figures out if the led should be fading (and by how much) or turning off, and does an analogwrite to the pin. It then increments the "state" variables, so the next time through the loop, it knows where to pick up from.

You could take this same approach. In the beginning of your main loop, you would check for an H or L from the wireless chip.

The H or L signals from the wireless chip would reset the "state" variables and the variables to indicate fade rate and number of blinks. Then, pass all these variables to the fade function, and the led responds accordingly. Next time through the loop, it'll either pick up where it left off from (it knows this thanks to the state variables), or abandon the current state and switch to the other desired fade sequence if a different value has been received from the wireless chip.

This is a really shoddy plain-english explanation, hopefully it makes sense.

Go Up