Arduino Nano reads until a specific value from the serial com

Hey guys

I need to read values that are coming from Python via USB serial. In Python this value is as string ascii encoded and in the arduino I read the incoming string via readString() and the convert it to int using toInt(). However, I’m only able to read until 240(I’m measuring with a oscilloscope). After this value, the output on pin D8 is zero. Why is this happening?

Arduino

String dataPy;
int inPin = 2;
int i;
int dataIn;
volatile unsigned long timeout[4];
volatile int idx = 0;
volatile unsigned long actTime; 

void setup() {
 //mySerial.begin(115200);
 pinMode(inPin,INPUT); // set pinD2 up to input
 DDRB = 1 << DDB0; // set pinD8 up to output
 Serial.begin(115200); 
 attachInterrupt(digitalPinToInterrupt(inPin),peakID,RISING); // declarying the interrupt to be triggered

}


void loop() {

    if(Serial.available()>0){ //Serial communication 
       //mySerial.write(itoa(dataIn,str,10)); //convert int to char array in a decimal base and sends to ard2
       dataPy = Serial.readString(); // read the string inside the buffer
       dataIn = dataPy.toInt(); // convert income string to int
       
      }

      actTime = millis(); // actTime stores the amount of time since the program started
       
      for(i=0; i<4; i=i+1){
          if(actTime - timeout[i] == dataIn){
          timeout[i]=0; //guarantee that the pulse is generated just one time
          PORTB = 1 << PORTB0; // HIGH
          delayMicroseconds(50); // pulse width
          PORTB = 0 << PORTB0; // LOW
          delayMicroseconds(50);
           
          }
        
      }
    
}

 
void peakID(){ // triggered interrupt

   timeout[idx] = millis(); // assign the time when the interrupt is called to an array
   
   if (idx == 3){ // pointer setup
    idx = 0;
    }
   else{
    idx = idx+1;
   }
   
}

Python - I’m using serialCom1 for tests

import serial
import time as t

   
serialCom = serial.Serial(port = 'COM9', baudrate = 115200, bytesize = serial.EIGHTBITS, parity=serial.PARITY_NONE, timeout=1) #initializing serialCom
t.sleep(1)

serialCom1 = serial.Serial(port = 'COM8', baudrate = 115200, bytesize = serial.EIGHTBITS, parity=serial.PARITY_NONE, timeout=1) #initializing serialCom
t.sleep(1)

tau = 250 #desired delay in ms
serialCom.write(str(tau).encode('ascii')) #write on serialCom
#serialCom.close()

tau1 = 180 #desired delay in ms
serialCom1.write(str(tau1).encode('ascii'))
#serialCom1.close()

Thanks

However, I’m only able to read until 240(I’m measuring with a oscilloscope).

That code should never be transmitted if you’re transmitting in ASCII.

 pinMode(inPin,INPUT); // set pinD2 up to input
 DDRB = 1 << DDB0; // set pinD8 up to output

Why are you using pinMode() and direct register manipulations in the same sketch?

Please describe what you’re trying to achieve with this sketch. My guess is that the following line is wrong:

          if(actTime - timeout[i] == dataIn){

Probably the ‘==’ should be a ‘>’ but even then the sketch doesn’t really make sense to me but as I wrote, I have no clue what it’s intended to do.

Hi pylon

The pinD2 is related to an interrupt and D8 to a output. My code is generating a delayed pulse of 50us width every time I detect a spike with my interrupt. In order to turn the process of generating pulse into something faster, I manipulated the port instead of using digitalWrite() and digitalRead().

Regarding the > or ==, a couple of days ago I was using this code and it was working perfectly. Every value from Python was being transmitted , in ASCII.

I dont know why, but it stopped working as I desire.

Have a look at the examples in Serial Input Basics - simple reliable ways to receive data. The second example works with a terminating character.

...R

The pinD2 is related to an interrupt and D8 to a output. My code is generating a delayed pulse of 50us width every time I detect a spike with my interrupt. In order to turn the process of generating pulse into something faster, I manipulated the port instead of using digitalWrite() and digitalRead().

That's the reason to use the direct port manipulations when producing the pulse but that's no reason to do the same when setting the pinMode. There the few microseconds are absolutely no problem but may be confusing while reading the code.

    if(Serial.available()>0){ //Serial communication
       dataPy = Serial.readString(); // read the string inside the buffer
       dataIn = dataPy.toInt(); // convert income string to int

This code has at least two problems:

  • You're using the String class. The String class is not well suited for microcontrollers with little RAM as most parts of the Arduino world. It fragments the memory in a short time and sooner than you think your code doesn't get the memory it requests. As that is not detected it simply starts to act unpredictable.

  • You have a timing issue. Lets say you transfer the string "250" from the PC. At the time the "if" statement is reached in the code the first two characters were already transferred. So your code reads them and stores the value 25 in dataIn. In the next round it will have the next character received ("0"), which is read and dataIn is now 0. Probably not what you expected.