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.

asked Aug 2, 2015 at 21:03

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).

answered Aug 2, 2015 at 21:55
2
  • free(NULL) is ok; per man malloc re void free(void *ptr), "If ptr is NULL, no operation is performed." Commented Aug 2, 2015 at 22:42
  • Ach, you are right. Still, a pointless thing to do in setup. Post amended. Commented 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
answered Aug 3, 2015 at 0:44

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.