Problem with atoi()

Hey guys

I need to convert a char array to int and i made use of atoi(). The values from the char array comes from a serial communication(Python Code) and the conversion is made inside if(Seria.available>0). This new value int will be used further in my loop to check one condition.However, I noticed that when I print the value outside the if(Serial.available()>0) it is zero.

How could I solve this problem?

Thanks

//#include<SoftwareSerial.h>

//SoftwareSerial newSerial (8,9)
int inPin = 2;
int i;
long int dataIn;

volatile unsigned long timeout[4];
volatile int idx = 0;
volatile unsigned long actTime;

const byte numChars = 5;
char receivedChars[numChars];
boolean newData = false;
static byte ndx = 0;
char endMarker = '\n';
char rc;



void setup() {

 pinMode(inPin,INPUT); // set pinD2 up to input
 DDRD = 1 << DDD7; // set pinD7 up to output
 Serial.begin(9600); 
 //newSerial.begin(9600);
 attachInterrupt(digitalPinToInterrupt(inPin),peakID,RISING); // declarying the interrupt to be triggered

  
}

void loop() {

if(Serial.available()>0){
    rc = Serial.read();
    if(rc!=endMarker){
      receivedChars[ndx] = rc;
      ndx++;
        if(ndx >= numChars){
           ndx = numChars - 1;
        }
    
    }
    else{
      receivedChars[ndx] = '\0';
      ndx = 0;
      newData = true;
      
    }
     if(newData == true){
      int dataIn = atoi(receivedChars);
      Serial.println(dataIn);
      newData = false;
      }
      
} 
 // Serial.println(dataIn);
      
      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
              PORTD = 1 << PD7; // HIGH
              delayMicroseconds(50); // pulse width
              PORTD = 0 << PD7; // LOW
              delayMicroseconds(50);
           
          }
        
      } 

}    
    
 

//   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
//          PORTD = 1 << PD7; // HIGH
//          delayMicroseconds(50); // pulse width
//          PORTD = 0 << PD7; // 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;
   }
   
}
int dataIn = atoi(receivedChars);

You are hiding the global dataIn variable in the scope of the if block. Remove the 'int' in that line and you should be good to go. Also atoi returns an int, so change your global dataIn variable type from long int to int.

You are redeclaring the variable "dataIn" in the block "if (newData) { .. }".

Thanks guys, this problem was solved.

Another Question :

I dont know why, but the income data from the serial com is probably not entering the buffer. Here how the value that is supposed to be written is declared in Python.

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

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

How I read in Arduino:

 rc = Serial.read();

Could you help me out?

Crespo94:
I dont know why, but the income data from the serial com is probably not entering the buffer.

Just call Serial.print to see whats actually in the buffer.

Crespo94:
Thanks guys, this problem was solved.

You have solved the problem (to see SM shows the integer value) by--

1. Changing the code line long int dataIn; into int dataIn; in the global space and changing the code line int dataIn; into dataIn; in the loop() function.

OR

2. By enabling the 'Newline' Tab in the Serial Monitor.

OR

3. Doing both Step-1 and Step-2.

LightuC:
Just call Serial.print to see whats actually in the buffer.

The problem is that as the serialCom with Python is established, I'm unable to open the serial monitor in Arduino IDE to check the output.

I'm unable to open the serial monitor in Arduino IDE to check the output.

Not while the serial port is connected to the Python program. You can have only one thing connected to the serial port at a time. You could get a USB to TTL serial converter and set up a software serial port (or use an extra hardware port if available) to connect to serial monitor for debugging.

serialCom.write(str(tau).encode('ascii'))

What do you suppose the str() and encode() bits are doing? If you guessed that they are converting the value 200 to the string "200", you win no prize. If you guessed anything else, you loose.

 rc = Serial.read();

This function is reading one byte/character, NOT the entire string "200". And, it is certainly NOT reading the string "200" and making an int of it

The simplest solution to your problem is to stop having Python convert the value to string.

PaulS:

serialCom.write(str(tau).encode('ascii'))

What do you suppose the str() and encode() bits are doing? If you guessed that they are converting the value 200 to the string "200", you win no prize. If you guessed anything else, you loose.

 rc = Serial.read();

This function is reading one byte/character, NOT the entire string "200". And, it is certainly NOT reading the string "200" and making an int of it

The simplest solution to your problem is to stop having Python convert the value to string.

Thanks for the reply Paul. So I will probably have to just code like: serialCom.write(tau), right?

Crespo94:
Thanks for the reply Paul. So I will probably have to just code like: serialCom.write(tau), right?

That's one approach. It may, or may not, be the simplest, depending on what else the Python program is doing. Sending all binary data, as that change will do, or sending all ASCII data, as the original code did,is easier than mixing ASCII and binary data.

I tried what I suggested, but I didnt get any change. It seems like the reading function in Arduino is not working for the application

It seems like the reading function in Arduino is not working for the application

This is not even close to true.

Post the code you have now, and some proof that the value 200 is not being sent and read correctly.

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

tau = 200 #desired delay in ms
serialCom.write(tau) #write on serialCom
void loop() {

if(Serial.available()>0){
    rc = Serial.read();
    if(rc!=endMarker){
      receivedChars[ndx] = rc;
      ndx++;
        if(ndx >= numChars){
           ndx = numChars - 1;
        }
    
    }
    else{
      receivedChars[ndx] = '\0';
      ndx = 0;
      newData = true;
      
    }
     if(newData == true){
      dataIn = atoi(receivedChars);
      //Serial.println(dataIn);
      newData = false;
      }
       
} 
      
     
      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
              PORTD = 1 << PD7; // HIGH
              delayMicroseconds(50); // pulse width
              PORTD = 0 << PD7; // LOW
              delayMicroseconds(50);
           
          }
        
      } 

}

If it was correctly read, the red pulse should be in 200ms delayed in comparison to the peak in blue wave

    if(rc!=endMarker){

You are sending binary data. I see no point in comparing the value to endMarker. Nor, do I see any value in then storing the characters read in an array to be processed later. That is useful when you are sending ASCII data, where the "to be processed later" code converts the strings to ints or floats.

The code to read the data MUST match the code to send the data. You can't send ASCII data, as you were doing, and use binary methods to read it. You can't send binary data and use ASCII processes to read it.

If I stick to that previous method, where I converted tau to string and encoded it as ascii, I can maintain the Serial.read(), right?

Before moving to Python, I tried to send a value via serial monitor on Arduino IDE and it worked out really good.

These data types make me go out of my mind, because I think they are so complicated to deal with.

Crespo94:
If it was correctly read, the red pulse should be in 200ms delayed in comparison to the peak in blue wave

I think you confused some things. The Serial interface bus can only transmit one byte at a time. This is why, when you want to send anything larger than one byte, you need to buffer the incoming data. You are doing this with this line:

receivedChars[ndx++] = rc;

This will "append" rc to the array of received characters. At some point you received all characters, but this will solely depend on what you are sending and how you are sending it. If you are sending the number 200, it might be enough to read only one byte from the serial stream and use it directly. If you are a message int the format #200* you know you have received everything, when you find a '*' to be received.

Now that received data has to be decoded somehow, but that is something only you know how to do.

In pyhton, write:

'200'.encode('utf-8')

This will send '2' '0' '0' down the serial line. In your receiver code, you count the bytes you have received and when the count hits 3 you add a '\0' to your received character array and give that to atoi.

I changed a bit the code, where ndx is the parameter that I use to verify if the amount of desired bytes has arrived.

if(Serial.available()>0){
    rc = Serial.read();
    receivedChars[ndx] = rc;
    ndx++;
    if(ndx >= numChars){
       ndx = numChars - 1;
       receivedChars[ndx] = '\0';
       ndx = 0;
       newData = true;
     }
    
    if(newData == true){
      dataIn = atoi(receivedChars);
      //Serial.println(dataIn);
      newData = false;
      }
       
}

Looks better now?

It does. Did you try it?

I tried, but nothing new happened. The response is the same as before. I also coded in Python like you said