Serial.write() has huge delay until I open serial monitor

Hi everyone,

Thanks for coming in.

I use my arduino uno to read encoders' value of my motor then tried to send the counting number to raspberry pi using serial.write() in 20hz. However, it has up to 10 second's delay until I open my serial monitor. Serial monitor seems stop the buffering and make the delay disappear. I tried press the reset button on the board since opening serial monitor reset the board, but it doesn't work.

The communication is done via usb connection. Pin 0 & 1 don't involve in this program.

Encoders is very sensitive with timing. And I think it is odd to open my serial monitor whenever I try to start my car :frowning: .

Do anyone have any idea about how to resolve this? The part of code I used to send message shown below.

serial.write() part:

void setup() {
   Serial.begin(115200);
}
void loop() {
  time1 = millis();
  dt = time1 - time2;
  if (dt >= 50){  // To make it run every 50ms
    time2 = millis();

   if (encoder1Pos>=0){
      Serial.write(11); // flag: positive & encoder1
      Serial.write(255); //flag
      Serial.write(byte(abs(encoder1Pos)));  // encoder counter
    }
    if (encoder1Pos<0){
      Serial.write(1); // flag: negative & encoder1
      Serial.write(255); //flag
      Serial.write(byte(abs(encoder1Pos)));  // encoder counter
    }
  }
}

Full version:

#include <PID_v1.h>
// motor one
int enA = 5;
int in1 = 9;
int in2 = 8;
// motor two
int enB = 11;
int in3 = 7;
int in4 = 6;

double steering, motor_speed1, motor_speed2, joy_speed;
double max_angularspeed1=0, max_angularspeed2=0;

// twelve servo objects can be created on most boards


int encoder1PinA = 2;
int encoder1PinB = 4;
int encoder2PinA = 3;
int encoder2PinB = 12;
//int powerpin = 1;
int groundpin = 13;
int endpoint = 140;
//
volatile int encoder1Pos = 0;
volatile int encoder2Pos = 0;
int time1 = 0;
int time2 = 0;
double dt;
double pi = 3.141592653589;
double angular_speed1;
double angular_speed2;
int time_gap = 50;
PID myPID1(&angular_speed1, &motor_speed1, &joy_speed,4.1,0,0.32, DIRECT);
PID myPID2(&angular_speed2, &motor_speed2, &joy_speed,4.1,0,0.32, DIRECT);
void setup() {

  Serial.begin(115200);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT);
  pinMode(enA, OUTPUT);
  pinMode(enB, OUTPUT);

  pinMode (encoder1PinA, INPUT);
  pinMode (encoder1PinB, INPUT);
  pinMode (encoder2PinA, INPUT);
  pinMode (encoder2PinB, INPUT);

  attachInterrupt(digitalPinToInterrupt(encoder1PinA), counter1, CHANGE);
  attachInterrupt(digitalPinToInterrupt(encoder2PinA), counter2, CHANGE);
  //turn the PID on
  myPID1.SetMode(AUTOMATIC);
  myPID2.SetMode(AUTOMATIC);
  myPID1.SetSampleTime(time_gap);
  myPID2.SetSampleTime(time_gap);
}

void loop() {

  


  char buffer[] = {' ',' ',' '};
  if (Serial.available() > 0) {
    //read the incoming byte:
    Serial.readBytesUntil('n', buffer, 3);
    
//    Serial.print("I received: ");
//    Serial.println(buffer[0], DEC);
//    Serial.println(buffer[1], DEC);
//    Serial.println(buffer[2], DEC);

    steering = map(abs(int(buffer[0])), 0, 100, 0, endpoint);
    joy_speed = map(abs(int(buffer[1])), 0, 100, 0, endpoint);

    if(buffer[1] < 0 && steering < 50){
      digitalWrite(in1, HIGH);
      digitalWrite(in2, LOW);
      digitalWrite(in3, HIGH);
      digitalWrite(in4, LOW);
    } 
    if(buffer[1] > 0 && steering < 50){
      digitalWrite(in1, LOW);
      digitalWrite(in2, HIGH);
      digitalWrite(in3, LOW);
      digitalWrite(in4, HIGH);
    }

    if(buffer[0] < 0 && motor_speed1 < 50){
      digitalWrite(in1, HIGH);
      digitalWrite(in2, HIGH);      
      digitalWrite(in3, LOW);
      digitalWrite(in4, HIGH);
      analogWrite(enA, steering); // Send PWM signal to motor A
//      Serial.print (buffer[0]);
//      Serial.print ("/");
//      Serial.print (motor_speed1);
//      Serial.print ("/");
//      Serial.println (steering);
    }
    if(buffer[0] >= 0 && motor_speed1 < 50){
      digitalWrite(in1, LOW);
      digitalWrite(in2, HIGH);
      digitalWrite(in3, HIGH);
      digitalWrite(in4, HIGH);
      analogWrite(enB, steering); // Send PWM signal to motor B 
//      Serial.print (buffer[0]);
//      Serial.print ("/");
//      Serial.print (motor_speed1);
//      Serial.print ("/");
//      Serial.println (steering);
    }   
        //debug pid control
//    Serial.print(joy_speed);
//    Serial.print ("---");
//    Serial.println(angular_speed1/4);
//    Serial.print ("/");
//    Serial.println(angular_speed2/4);

//    Serial.print("+++");
//    Serial.print(motor_speed1);
//    Serial.print ("/");
//    Serial.println(motor_speed2);    
//      Serial.println(encoder1Pos); 
  }

  time1 = millis();
  dt = time1 - time2;
  if (dt >= time_gap){
    time2 = millis();
    angular_speed1 = (2*pi*abs(encoder1Pos))/(2*390*(dt/1000))*4;
//    Serial.print(dt/1000);
//    Serial.print ("/");
//    Serial.println(encoder1Pos);
//    Serial.print ("/");
//    Serial.println (angular_speed1*180/(pi));
    
    if (encoder1Pos>=0){
      Serial.write(byte(11)); // flag: positive & encoder1
      Serial.write(byte(255));
      Serial.write(byte(abs(encoder1Pos)));
    }
    if (encoder1Pos<0){
      Serial.write(byte(1)); // flag: negative & encoder1
      Serial.write(byte(255));
      Serial.write(byte(abs(encoder1Pos)));
    }
    encoder1Pos = 0;
    
    angular_speed2 = (2*pi*abs(encoder2Pos))/(2*390*(dt/1000))*4;
//    Serial.print(dt/1000);
//    Serial.print ("'+'");
//    Serial.print(encoder2Pos);
//    Serial.print ("'+'");
//    Serial.println (angular_speed2*180/(pi));
    if (encoder2Pos>=0){
      Serial.write(byte(12)); // flag: positive & encoder2
      Serial.write(byte(255));
      Serial.write(byte(abs(encoder2Pos)));
    }
    if (encoder2Pos<0){
      Serial.write(byte(2)); // flag: negative & encoder2
      Serial.write(byte(255));
      Serial.write(byte(abs(encoder2Pos)));
    }
//    Serial.flush();
    encoder2Pos = 0;
    
    myPID1.Compute();
    myPID2.Compute();
//    angular_speed1 = map(angular_speed1, 0, max_angularspeed1, 0, endpoint);
//    angular_speed2 = map(angular_speed2, 0, max_angularspeed2, 0, endpoint);
    if(steering < 50){
      analogWrite(enA, motor_speed1); // Send PWM signal to motor A
      analogWrite(enB, motor_speed2); // Send PWM signal to motor B 
//      Serial.print ("/");
    }


  }

}
//
void counter1(){
  if (digitalRead(encoder1PinB) == digitalRead(encoder1PinA)) {
    encoder1Pos++;
  } else {
    encoder1Pos--; //--
  }
}

void counter2(){
  if (digitalRead(encoder2PinB) == digitalRead(encoder2PinA)) {
    encoder2Pos--; //--
  } else {
    encoder2Pos++;
  }
}

That isn't your complete code.

.

Bet the full code will show the use of pins 0 and 1 to communicate with Raspberry pi.

Paul

Paul_KD7HB:
Bet the full code will show the use of pins 0 and 1 to communicate with Raspberry pi.

Paul

Hi Paul,

I removed any feature in pin 0 & 1, but still has the same issue. The full version now attached above.

Richard

ieee488:
That isn't your complete code.

.

Hi ieee,

I just updated the full version.

Richard

I just solved it. It turns out that my receive end in raspberry pi has delay receiving data, which cause the data to be buffered and accumulated. When I open the serial monitor, it somehow clear the buffer so that the receiving end looks reacting in real time.

The truth is raspberry pi only receives part of the data when I open serial monitor.

Richard_lzm:
I just solved it. It turns out that my receive end in raspberry pi has delay receiving data, which cause the data to be buffered and accumulated. When I open the serial monitor, it somehow clear the buffer so that the receiving end looks reacting in real time.

The truth is raspberry pi only receives part of the data when I open serial monitor.

More research will show you the Arduino is reset when the serial monitor is opened.

Paul