0

I'm workin on a node for blender to control an arduino. I notice it goes really slow after a while so I isolated the problem. It is good in maintaining 60 frames a second, then after around 40 seconds (pretty exact), it drops to a pretty exact 1 fps for some reason.

What could be going on?

import serial
import time

ser = serial.Serial('COM3', 115200)

c = 0

while True:
    c+=1
    print("ok ", c)
    numIn = "100n"
    ser.write(numIn.encode('ascii'))
    time.sleep(1./60)

arduino code:

// special thx to Nick Gammon

const unsigned int MAX_INPUT = 50;


unsigned long delay_time = 300;
unsigned long last_toggle_time = 0;
int current_state = LOW;

void setup () {
  Serial.begin (115200);
  pinMode(12, OUTPUT);

} 


void process_data (const char * data) {
  Serial.println (data);
  delay_time = atoi(data);
} 

void processIncomingByte (const byte inByte) {
  static char input_line [MAX_INPUT];
  static unsigned int input_pos = 0;

  switch (inByte) {

    case 'n':   // end of text
      input_line [input_pos] = 0;  // terminating null byte
      process_data (input_line);
      input_pos = 0;
      break;

    case 'r':   
      break;

    default:
      if (input_pos < (MAX_INPUT - 1))
        input_line [input_pos++] = inByte;
      break;

  } 
} 

void loop() {

  while (Serial.available () > 0) {
    processIncomingByte (Serial.read ());
  }

  unsigned long m  = millis();

  if (m > last_toggle_time + delay_time) {
      current_state = current_state == HIGH ? LOW : HIGH;
      digitalWrite(12, current_state);         
      last_toggle_time = m;
  }

}  
clankill3r
  • 219
  • 2
  • 6
  • 12
  • Hint: Check "if (m > last_toggle_time + delay_time)" and what happens when millis() as int wraps? – Mikael Patel Apr 06 '16 at 21:55
  • I changed it to unsigned long now and it's still the case. – clankill3r Apr 06 '16 at 22:24
  • Also, the blinking is not the problem, that keeps going well. It's the serial communication that slows down. – clankill3r Apr 06 '16 at 22:27
  • 1
    What happens if you remove the Serial.print() from process_data()? What does your Python script do with serial input? – Mikael Patel Apr 06 '16 at 22:41
  • Cool, if I remove the print then the problem is gone. However, eventually I want python to read the input. Now python hangs on ser.readLine(). Maybe a new topic for the hanging? – clankill3r Apr 07 '16 at 07:28
  • Now we need an explanation not dive directly into the next issue :) What was the problem, really? The Arduino prints. The host (Python) script does not read and internal USB/USART buffers are filled. And what happens on the Arduino side when the Serial output buffer is filled? Check the code - it is open-source :) – Mikael Patel Apr 07 '16 at 09:12
  • BW: Be a good stackexchange user and write an answer and mark this question as answered. – Mikael Patel Apr 07 '16 at 09:14
  • I guess it goes in a second delay :) – clankill3r Apr 07 '16 at 15:57
  • @MikaelPatel "Serial" output data unclaimed by the host could only potentially be a cause for slowdown in the case for a Leonardo board or something else where the USB is implemented directly in the application processor, and even there it is a bit uncertain. It is definitely not the case for an Uno or something where the application processor has a UART connection to a USB converter, as in such case the UART data is blindly transmitted, regardless if the receiver is able to handle it or not. – Chris Stratton Jun 06 '16 at 18:14
  • Please state which Arduino you are using. There is some confusion by responders as to whether outgoing communications would block if you fill up the buffer. – Nick Gammon Jun 06 '16 at 21:29
  • I just want to point out that you are using n as a delimiter in a rather unusual way. In my code it was \n and \r (newline and carriage return). When you do Serial.println (data); you are adding two more bytes (println adds a carriage-return and linefeed) so you are printing 6 bytes for every four you receive. It doesn't totally surprise me that something fills up after 40 seconds, however at 115200 baud that shouldn't really be an issue for 60 x 6 bytes. – Nick Gammon Jun 06 '16 at 21:31
  • Bit bang it with a delay loop before the next bit gets sent. Delay loop variable will have to be tested to not be too quick. Sync it with baud rate. I developed a product which was trademarked as "Bit Banger" which was a serial I/O controller before you were mostly born back in 1997. Then again it may help that My 1st real job was peripheral controller tech for a 16 bit computer company in the early 70's. Intel had jusr released the 4004 4 bit slicer. By 74 they came out with tge 8080. Harry – Harry Regician Jun 15 '19 at 22:53

1 Answers1

0

If you print from arduino to serial and you don't read it then the buffer gets full. Causing it to go in a second delay. So make sure you read as well when you send data over.

A short sleep is required between the sleep and the read for some reason. Else it hangs.

import serial
from time import sleep

ser = serial.Serial('COM3', 115200)
sleep(1)

c = 0

while True:
    c+=1
    print("ok ", c)
    numIn = "100"
    ser.write((numIn + '\r\n').encode())
    sleep(1./120)

    inp = ser.readline()
    print(inp.decode("utf-8"))
    sleep(1./120)
clankill3r
  • 219
  • 2
  • 6
  • 12
  • The theory behind this answer is quite dubious, and if you have a conventional Uno type Arduino or something with a distinct USB-serial converter, impossible. – Chris Stratton Jun 06 '16 at 18:17