Stuck in a loop

I'm developing a system that works as follows.

  1. There is a text file with a number stored in it.

  2. A processing 3 program reads the text file. If the number meets the initial condition (in this case if the number is 131) then send a '1' to the Arduino. If the number does not meet the initial condition send a '0'.

  3. If the Arduino program receives a '1' from the Processing 3 software, blink the on board LED on and off repeatedly. If the Arduino program receives a '0' from the Processing 3 program, turn off the on board LED.

The problem I'm runnning into is I'm getting stuck in the loop when the Arduino receives a '1' from the Processing 3 program. When I run the programs, if the Processing 3 program initially sends a '0' the LED stays off. Then while both programs are running if I change the text document so the processing 3 program sends a '1' to the Arduino the LED will blink. From there if I change the text document back so the Processing 3 program once again sends a '0' the LED remains on and blinking. It won't just shut off when the Processing 3 program sends a '0' to the Arduino after a '1' has been sent.

I have tested the Processing 3 program and it is functioning properly, sending a '1' when the condition is met and sending a '0' otherwise.

Here is the code I've been working with for the Arduino.

char val; // Data received from the serial port
int ledPin = 13; // Set the pin to digital I/O 13

void setup() {
  pinMode(ledPin, OUTPUT); // Set pin as OUTPUT
  Serial.begin(9600); // Start serial communication at 9600 bps
}

void loop() {
  if (Serial.available()) { // If data is available to read,
    val = Serial.read();    // read it and store it in val
  }
  if (val == '1') {             // If 1 was received
    digitalWrite(ledPin, HIGH); // turn the LED on
    delay (1000);               // Wait for one second
    digitalWrite(ledPin, LOW);  // turn the LED off
    delay (1000);

  } else {
    digitalWrite(ledPin, LOW); // otherwise turn it off
  }
  delay(10); // Wait 10 milliseconds for next reading
}
delay(10); // Wait 10 milliseconds for next reading

And if there is nothing to read, repeat the action based on what was read last time. Is that what you want? If not, set val to something other than what the serial port will supply.

You have some pretty big delays in there. It is possible that the serial data coming in is being lost because the loop is busy blinking LEDs instead of monitoring the serial input regularly. In fact, it spends the vast majority of its runtime dealing with blinking the LED. This is backwards. You should try to write it without using any delays so the serial input can be the main focus of the code execution time. The serial interface does not buffer input as far as I know, so if you aren't there to read it, it will fall off the Earth into oblivion.

Try this (untested not compiled):

bool blinking = false;
bool ledState = LOW;
unsigned long timer = millis();


void loop()
{ if (Serial.available()) val = Serial.read();           // If data is available to read, read it and store it in val
  
  if( val != '1' )                                       // if we get anything other than '1', turn everything off.
  { blinking = false;
    digitalWrite( ledPin, ledState = LOW );
  }
  else                                                   // otherwise we have a '1' on the input
  { if( blinking )                                       // if we are already blinking, just continue doing it.
    { if( (millis() - timer) >= 1000 )                   // only change the LED if 1 second has passed.
      { digitalWrite( ledPin, ledState = !ledState );    // toggle the LED and its state.
        timer = millis();                                // reset the timer for another 1 second wait.
      }
    }
    else                                                 // we have a '1' and we are not blinking. So start blinking.
    { blinking = true;
      timer = millis();                                  // reset the timer for a 1 second wait.
      digitalWrite( ledPin, ledState = HIGH );           // start the blink cycling with an ON condition.
    }
  }
  delay(10);                                             // Wait 10 milliseconds for next reading
}

I would get rid of the 10ms delay at the end completely as well. It isn't really necessary to wait there I don't think. It only serves to give the serial input additional time to lose any data coming in.

The logical size of the standard input and output buffers for Serial is 63.
The physical size of the buffers is 64.

Well that's good to know. Still I am quite certain that it is a time sensitive deal working with it. I'd bet the data does not stay in that buffer for very long. Two seconds is a very long time.

I suspect you would be much better using millis() to manage your blink timing without blocking. This is illustrated in Several Things at a Time

Also, you should ensure that your Processing program only sends a 1 or a 0 when something changes. It is not a good idea to send a stream of 1s or 0s and it is quite unnecessary.

...R

When I run the programs, if the Processing 3 program initially sends a '0' the LED stays off. Then while both programs

You're referring to 'programs'. It's not clear to me how many Processing3 programs you're running at the same time. One or two (or even more)? If it is not 'one', they probably have a conflict in using the serial port on the PC.

PS
Please edit your opening post and place the code between [code] and [/code]

sterretje:
You're referring to 'programs'. It's not clear to me how many Processing3 programs you're running at the same time. One or two (or even more)?

Sorry, I'm still a little green with all of this. Point 2 in my original post was intended to explain there is one Processing 3 program and only one Processing 3 program running in this system. When I refer to "programs" in the later comment I mean having the Processing 3 and Arduino IDEs both running the code for the system.

Thanks a bunch for all the help everyone. I’m still VERY green with all of this so I appreciate you all taking the time. I’ll try to address the suggestions as best I can.

PaulS:

delay(10); // Wait 10 milliseconds for next reading

And if there is nothing to read, repeat the action based on what was read last time. Is that what you want? If not, set val to something other than what the serial port will supply.

What I want the system to do is if Arduino is getting a ‘1’ sent to it, blink the LED. If the Arduino gets a ‘0’ sent to it, turn off the LED. I hadn’t really thought of what happens when the Arduino gets no signal at all. I guess I’d want the LED off if that were the case.

AxeMurderer:
You have some pretty big delays in there. It is possible that the serial data coming in is being lost because the loop is busy blinking LEDs instead of monitoring the serial input regularly. In fact, it spends the vast majority of its runtime dealing with blinking the LED. This is backwards. You should try to write it without using any delays so the serial input can be the main focus of the code execution time. The serial interface does not buffer input as far as I know, so if you aren’t there to read it, it will fall off the Earth into oblivion.

I would get rid of the 10ms delay at the end completely as well. It isn’t really necessary to wait there I don’t think. It only serves to give the serial input additional time to lose any data coming in.

The delays are just me trying to copy the example program Blink. To be completely honest I don’t know if I really need the LED to blink, I just thought it looked cool. What I’m working on now is a proof of concept project so if the LED just simply turned on when the Arduino was sent a ‘1’ and off when it was sent a ‘0’ that would be fine.

The 10ms delay comes from some sample code I found online. As far as I understand it’s in there for “system stability” but I’ll be honest and say I don’'t really understand conceptually why it needs to be there.

Robin2:
I suspect you would be much better using millis() to manage your blink timing without blocking. This is illustrated in Several Things at a Time

Also, you should ensure that your Processing program only sends a 1 or a 0 when something changes. It is not a good idea to send a stream of 1s or 0s and it is quite unnecessary.

…R

Thanks for the link, examples to follow are always welcome :slight_smile:

dtools22:
Sorry, I'm still a little green with all of this. Point 2 in my original post was intended to explain there is one Processing 3 program and only one Processing 3 program running in this system. When I refer to "programs" in the later comment I mean having the Processing 3 and Arduino IDEs both running the code for the system.

OK, you're still a bit confused :wink: The IDE does nothing except compiling and uploading and only if you tell it to do so. You just as ell can have it closed if you don't use it. The only thing that can be interfering with the Process3 program is the Serial Monitor; if you did not start the latter, there should be no issue.

For the given purpose. I do not see a problem with your code; I advise to base it on the BlinkWithoutDelay example that comes with the IDE. Tested your code using Serial Monitor and it works as expected.