Infinite while loop only runs once

Hi there

I am fairly new to arduino coding. I am sending strings via serial port to and from a python program. on the Arduino code no matter what i do or command after the serial run , it skips through it. To check parts of the code, i have placed an infinite while loop after the serial communication is done. Interestingly this while loop only runs once and then goes back to the top of void loop. By that I mean the LED at pin 6 only flashes once. it even does not even flash for a second. That means it does not even execute the delay functions as well.

Please help!

Here is the code.


#include "Communicate.h"
#include "Sort.h"
String data;
Communicate Com;
Sort sr;

void setup() {
 Serial.begin(115200);
 Serial.setTimeout(1);
 pinMode(LED_BUILTIN, OUTPUT);
 pinMode(5,OUTPUT);
pinMode(6,OUTPUT);
pinMode(7,OUTPUT);
}

void loop() {
digitalWrite(5,LOW);
digitalWrite(6,LOW);
digitalWrite(7,LOW);
int s=0;
String p;
while(!Serial.available()){
    digitalWrite(5, HIGH); 
    delay(200);
    digitalWrite(5, LOW); 
    delay(200);}
if (Serial.available()>0)
{
s=Com.InOut(data); /*reads from serial and prints it*/

while(Serial.available()>0){char dump=Serial.read();} /*makes sure input buffer is clean*/
}
while(1){
  digitalWrite(6,HIGH); 
  delay(100);
  digitalWrite(7,LOW); 
  delay(100);} /*somehow this loop only runs once. this led blinks only once*/
}

Yeah. pin6 light up?

Wow. pin7 is become LOW.
What? pin6 is Where? :roll_eyes:

corrected that. Still the same

Hello
call Serial.available() once per loop and ckeck.

I removed "Com" from your code and tested it on my Nano.
Because I don't have that.
I was able to confirm that I entered a while loop where the LED of pin6 blinks at high speed when serial data is received once.
Can't be reproduced in my environment...

Where is Communicate.h? Did you download it from somewhere? Or write it yourself?

In future, please use tools->autoformat in the IDE before copying code; this looks currently like a big mess.

Thanks for using code tags (in your frst post).

Communication.InOut() is a method written by me. This time I am running it without the method calling. Rather I wrote the method body into the Serial.availble() block. It receives and echoes the data just like the method call. but the problem with the while(1) loop is still the same. Here is the code right now.

#include "Communicate.h"
#include "Sort.h"
String data;
Communicate Com;
Sort sr;

void setup() {
 Serial.begin(115200);
 Serial.setTimeout(1);
 pinMode(LED_BUILTIN, OUTPUT);
 pinMode(5,OUTPUT);
pinMode(6,OUTPUT);
pinMode(7,OUTPUT);
}

void loop() {
digitalWrite(5,LOW);
digitalWrite(6,LOW);
digitalWrite(7,LOW);
int s=0;
String p;
while(!Serial.available()){
    digitalWrite(5, HIGH); 
    delay(200);
    digitalWrite(5, LOW); 
    delay(200);}
if (Serial.available()>0)
{
  if(Serial.available())
  {
  String _str=Serial.readStringUntil("\n");
  delay(1000);
  Serial.print(_str);
  Serial.print("\n");
  Serial.flush();
  }
while(Serial.available()>0){char dump=Serial.read();} /*makes sure input buffer is clean*/
}
while(1){
  digitalWrite(6,HIGH); 
  delay(3000);
  digitalWrite(6,LOW); 
  delay(3000);} /*somehow this loop only runs once. this led blinks only once*/
}

I did some changes in the codes and it seems like whenever I open the serial from python the arduino code goes at the top of the void loop(). As if opening the serial port in the python program works as an interrupt and automatically breaks the while(1) loop in Arduino.

arduino code:

#include "Communicate.h"
#include "Sort.h"
String data;
Communicate Com;
Sort sr;

void setup() {
  Serial.begin(115200);
  Serial.setTimeout(1);
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
}

void loop() {
  digitalWrite(5, LOW);
  digitalWrite(6, LOW);
  digitalWrite(7, LOW);
  int s = 0;
  String p;
  while (!Serial.available()) {
    digitalWrite(5, HIGH);
    delay(200);
    digitalWrite(5, LOW);
    delay(200);
  }
  if (Serial.available() > 0)
  {
    if (Serial.available())
    {
      String _str = Serial.readStringUntil("\n");
      delay(1000);
      Serial.print(_str);
      Serial.print("\n");
      Serial.flush();
    }
    while (Serial.available() > 0) {
      char dump = Serial.read(); /*makes sure input buffer is clean*/
    }
  }
  while (1) {
    digitalWrite(6, HIGH);
    delay(3000);
    digitalWrite(6, LOW);
    delay(3000);
  } /*somehow this loop only runs once. this led blinks only once*/
}

the python code :

import serial
import time
import io
import codecs

arduino = serial.Serial(port='COM4', baudrate=115200, timeout=None)
def write_read(x):
    arduino.write(bytes(x, 'utf-8'))

arduino.close()

i=1
while i==1:
    arduino.open()
    strng = input("Write a line: ") # Taking input from user
    strng="0123456789012345678901234567890123456789012 \n"
    write_read(strng)
    print('waiting for arduino')
    value=arduino.read_until()
    value=codecs.decode(value, 'UTF-8')
    print(value) # printing the value
    
    if value==strng:
        print("success \n")
        arduino.reset_output_buffer()
        arduino.close()
        
    else:
        print("arduino timed out")

   

    arduino.close()
    i=0
time.sleep(10)
i=1
while i==1:
    arduino.open()
    strng = input("Write a line: ") # Taking input from user
    strng="0123456789012345678901234567890123456789012 \n"
    write_read(strng)
    print('waiting for arduino')
    value=arduino.read_until()
    value=codecs.decode(value, 'UTF-8')
    print(value) # printing the value
    
    if value==strng:
        print("success \n")
        arduino.reset_output_buffer()
        arduino.close()
        
    else:
        print("arduino timed out")

    arduino.close()

during the 10 second delay in python serial communication. the LED pin at pin 6 blinks.
But when python opens the serial port. the while(1) loop breaks in arduino. this is working like an interrupt that i have not set up.

Please help!

This is a problem on the Python code side.
The Arduino has a built-in auto reset circuit that is automatically reset by the DTR when the serial port is opened.
Not because it's out of the while loop, it means that the same to pressing the reset button when COM open.
Don't close or open the port at repeatedly.
Please COM open at first of code, and close COM when terminate it...

I don't know if you mentioned which Arduino you use. But most Arduinos reset when you open the serial port.

I'm not a python programmer; under Windows it should be possible to prevent this from happening. Check if there are options in python to setup the port without forcing DTR; it should be something in the line of DTRenable or so. Or open the port outside the while-loop

If you would have posted you python code in the beginning, somebody would probably straight away have been able to tell you :slight_smile:

2 Likes
arduino = serial.Serial(port='COM4', baudrate=115200, timeout=None, dsrdtr=True)

This is the when solve with this method.

Or as a counterpart for clone boards that still use RTS to auto reset, add even RTS.

arduino = serial.Serial(port='COM4', baudrate=115200, timeout=None, dsrdtr=True, rtscts=True)
2 Likes

This is an uno board. Thanks a lot mentioning the fact that the board resets when serial port is opened. This was the problem here. Now I am trying to work around it at the python code.

Thank you very very much.

Thank you very much for the direction. I am now trying to repair the python code. You guys are awsome!!!!!!

Thanks for that; I was aware that some boards referred to it as RTS, but thought it was actually meant to be DTR :wink:

Yes, it may be.
Well, there are not cause other problems, so it may be better to add both.

BTW, In the olden days...
The first official produced boards used RTS for auto reset.

1 Like

Error:

In function 'void loop()':
sketch_jul01a:35:44: error: invalid conversion from 'const char*' to 'char' [-fpermissive]
   35 |       String _str = Serial.readStringUntil("\n");
      |                                            ^~~~
      |                                            |
      |                                            const char*

You meant:
String _str = Serial.readStringUntil('\n');
Note the use of 'single quotes' for a character constant instead of "double quotes" for a string constant.

Here is the sketch simplified by removing redundant and unused code. It blinks the built-in LED fast until I send a message from Serial Monitor. Then it echoes the message and switches to blinking slowly.

void setup()
{
  Serial.begin(115200);
  Serial.setTimeout(1);  // 1 millisecond?
  
  pinMode(LED_BUILTIN, OUTPUT);  // Not used
  digitalWrite(LED_BUILTIN, LOW);
}

void loop()
{
  while (!Serial.available())
  {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(200);
    digitalWrite(LED_BUILTIN, LOW);
    delay(200);
  }

  String _str = Serial.readStringUntil('\n');
  Serial.println(_str);
  Serial.flush();

  /* makes sure input buffer is clean */
  while (Serial.available())
    Serial.read();

  while (1)
  {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(3000);
    digitalWrite(LED_BUILTIN, LOW);
    delay(3000);
  } /*somehow this loop only runs once. this led blinks only once*/
}