0

I have a file with numbers called fginputs.txt. For example it could be something like this:

4958
4154
4154
4154
4154
4154
4154
4154
4154
4154
4154
4154
4154
4154
4154
4154
4154
4958

I want python to send each number to arduino via serial port. After each number is received, arduino should print back an acknowledgment number, indicating that it got a valid number, and then store that number in a dynamic array, because I could create larger files. When there are no more numbers left, send a '-1' to finish transmission.

Here's my arduino code:

// save some unsigned ints 
uint16_t SIZE, *inputList, cont = 0;
boolean inputsReady = false;

void setup()
{
 // initialize serial communication at 9600 bits per second:
 Serial.begin(9600);
  
 //free dynamic array memory
 free(inputList); 
 //counter for how many numbers I've received starts at 0
 cont = 0;
 //This is true when there are no more numbers to receive, meanwhile false
 inputsReady = false;
 setupInputList();
 }

/* If there's not enough space, resize the array by one unit and store the number 
   */
void growAndInsert(int currentSize, int newInt){
    if(currentSize > SIZE)
        inputList = (uint16_t *)realloc(inputList, (currentSize + 1)*sizeof(uint16_t));
    inputList[currentSize] = newInt;
}
/**
  init inputList with 100 blocks
 */
void setupInputList(){
  SIZE = 10;
  inputList = (uint16_t *)malloc(sizeof(uint16_t) * SIZE);
}

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

/**
Listens in serial port for an integer that represents a new input and returns it.
If it doesn't get anything useful from serial, return 0
*/
  int getNewInputFromSerial(){
   if (Serial.available() > 0) {
    delay(100);
    // look for the next word 
    int cmd = Serial.parseInt();
    clearBuffer();

    if(cmd == 4958)
        Serial.write("4");
    else if(cmd == 4154)
        Serial.write("5");
    else
        Serial.write("0");
    return cmd;
   }
  return 0;

}

void loop()
{
     if(!inputsReady){
        int newInput = getNewInputFromSerial();
        if(newInput == 0)
            return;
        if(newInput != -1)
            growAndInsert(cont++, newInput);
        else{
            inputsReady = true;
            //initTimer(); 
        }
    }


}

and the python script:

global arduino
PORT = '/dev/ttyACM0'
FILENAME = "fginputs.txt"
#Read file with inputs
with open(FILENAME) as f:
        content = f.readlines()
#init serial port
arduino = serial.Serial(PORT, 9600, timeout=1);
time.sleep(2);

#write
for input in content:
    arduino.flush()
    arduino.write(input)
    time.sleep(.1);
    resp = arduino.read();
    print "i got " + resp

#Finish transmission with -1
arduino.flush()
arduino.write("-1")
#done
arduino.close();

The fist time I execute the script I get this:

i got 4
i got 5
i got 5
i got 5
i got 5
i got 5
i got 5
i got 5
i got 5
i got 5
i got 5
i got 5
i got 5
i got 5
i got 5
i got 5
i got 5
i got 4

Which is great. But if I run it a second time I get this:

i got 0
i got 4
i got 0
i got 0
i got 0
i got 0
i got 0
i got 0
i got 0
i got 0
i got 0
i got 0
i got 0
i got 0
i got 0
i got 0
i got 0
i got 0

Which is terribly wrong because the file hasn't changed. I don't know what is going on here. If I unplug and plug back in the USB cable, transmission works flawlessly again.

2 Answers 2

3
// save some unsigned ints 
uint16_t SIZE, *inputList, cont = 0;
boolean inputsReady = false;

void setup()
{
 // initialize serial communication at 9600 bits per second:
 Serial.begin(9600);

 //free dynamic array memory
 free(inputList); 

You are freeing a NULL pointer which is an undefined operation not necessary here, since it was never allocated.


  if (Serial.available() > 0) {
    delay(100);
    // look for the next word 
    int cmd = Serial.parseInt();
    clearBuffer();

This is going to just throw data away, I'm not surprised stuff goes missing.

Read this: How to process incoming serial data without blocking - you need to get rid of the delay, and the clearBuffer() for a start.


Example code for reading from Serial without blocking and without using delay:

// how much serial data we expect before a newline
const unsigned int MAX_INPUT = 50;

void setup ()
  {
  Serial.begin (115200);
  } // end of setup

// here to process incoming serial data after a terminator received
void process_data (const char * data)
  {
  // for now just display it
  // (but you could compare it to some value, convert to an integer, etc.)
  Serial.println (data);
  }  // end of process_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

      // terminator reached! process input_line here ...
      process_data (input_line);

      // reset buffer for next time
      input_pos = 0;  
      break;

    case '\r':   // discard carriage return
      break;

    default:
      // keep adding if not full ... allow for terminating null byte
      if (input_pos < (MAX_INPUT - 1))
        input_line [input_pos++] = inByte;
      break;

    }  // end of switch

  } // end of processIncomingByte  

void loop()
  {
  // if serial data available, process it
  while (Serial.available () > 0)
    processIncomingByte (Serial.read ());

  // do other stuff here like testing digital input (button presses) ...

  }  // end of loop

In process_data in my example is where you would call atoi to convert the incoming string into an int (or atol if it is going to be longer).

2
  • free(NULL) is ok; per man malloc re void free(void *ptr), “If ptr is NULL, no operation is performed.” Aug 2, 2015 at 22:42
  • Ach, you are right. Still, a pointless thing to do in setup. Post amended.
    – Nick Gammon
    Aug 2, 2015 at 22:58
1

You could have a look at this.

It's a python program which does record/playback of key-presses, through an UNO.

It already implements:

  • serial communication with error checking
  • ACK: each message has its own ID, so you can keep track of what was lost, should anything bad happen
  • synchronization, in case your Arduino is powered up after the python program is started

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.