error during using ArduinoPC2 program with ComArduino2

After i run the ComArduino2.py from my pc terminal, i’m getting following error:

Serial port /dev/ttyACM0 opened  Baudrate 9600
Arduino is ready

Sent from PC -- LOOP NUM 0 TEST STR <LED1,200,0.2>
Reply Received  Msg LED1 NewFlash 200 SrvFrac 0.20 SrvPos 42 Time 1
===========
Traceback (most recent call last):
  File "pyserial.py", line 170, in <module>
    runTest(testData)
  File "pyserial.py", line 118, in runTest
    sendToArduino(teststr)
  File "pyserial.py", line 60, in sendToArduino
    ser.write(sendStr)
  File "/usr/lib/python2.7/dist-packages/serial/serialposix.py", line 489, in write
    raise SerialException('write failed: %s' % (v,))
serial.serialutil.SerialException: write failed: [Errno 5] Input/output error

I am using ubuntu 14.04, xenomai patched linux, arduino uno, with latest arduino ide.
I was following this link.
When i don’t connect the servo, the program runs fine. But after i connect the servo and attach it with pin 8, it shows above error.

Please post your complete Python program and your complete Arduino program.

...R

ArduinoPC2.ino:

#include <Servo.h>

Servo myServo;
byte servoPin = 3;
byte servoMin = 10;
byte servoMax = 170;
byte servoPos = 0;
byte newServoPos = servoMin;

const byte numLEDs = 2;
byte ledPin[numLEDs] = {12, 13};
unsigned long LEDinterval[numLEDs] = {200, 400};
unsigned long prevLEDmillis[numLEDs] = {0, 0};

const byte buffSize = 40;
char inputBuffer[buffSize];
const char startMarker = '<';
const char endMarker = '>';
byte bytesRecvd = 0;
boolean readInProgress = false;
boolean newDataFromPC = false;

char messageFromPC[buffSize] = {0};
int newFlashInterval = 0;
float servoFraction = 0.0; // fraction of servo range to move


unsigned long curMillis;

unsigned long prevReplyToPCmillis = 0;
unsigned long replyToPCinterval = 1000;

//=============

void setup() {
  Serial.begin(9600);
  
    // flash LEDs so we know we are alive
  for (byte n = 0; n < numLEDs; n++) {
     pinMode(ledPin[n], OUTPUT);
     digitalWrite(ledPin[n], HIGH);
  }
  delay(500); // delay() is OK in setup as it only happens once
  
  for (byte n = 0; n < numLEDs; n++) {
     digitalWrite(ledPin[n], LOW);
  }
  
    // initialize the servo
  myServo.attach(servoPin);
  moveServo();
  
    // tell the PC we are ready
  Serial.println("<Arduino is ready>");
}

//=============

void loop() {
  curMillis = millis();
  getDataFromPC();
  updateFlashInterval();
  updateServoPos();
  replyToPC();
  flashLEDs();
  moveServo();
}

//=============

void getDataFromPC() {

    // receive data from PC and save it into inputBuffer
    
  if(Serial.available() > 0) {

    char x = Serial.read();

      // the order of these IF clauses is significant
      
    if (x == endMarker) {
      readInProgress = false;
      newDataFromPC = true;
      inputBuffer[bytesRecvd] = 0;
      parseData();
    }
    
    if(readInProgress) {
      inputBuffer[bytesRecvd] = x;
      bytesRecvd ++;
      if (bytesRecvd == buffSize) {
        bytesRecvd = buffSize - 1;
      }
    }

    if (x == startMarker) { 
      bytesRecvd = 0; 
      readInProgress = true;
    }
  }
}

//=============
 
void parseData() {

    // split the data into its parts
    
  char * strtokIndx; // this is used by strtok() as an index
  
  strtokIndx = strtok(inputBuffer,",");      // get the first part - the string
  strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC
  
  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  newFlashInterval = atoi(strtokIndx);     // convert this part to an integer
  
  strtokIndx = strtok(NULL, ","); 
  servoFraction = atof(strtokIndx);     // convert this part to a float

}

//=============

void replyToPC() {

  if (newDataFromPC) {
    newDataFromPC = false;
    Serial.print("<Msg ");
    Serial.print(messageFromPC);
    Serial.print(" NewFlash ");
    Serial.print(newFlashInterval);
    Serial.print(" SrvFrac ");
    Serial.print(servoFraction);
    Serial.print(" SrvPos ");
    Serial.print(newServoPos);
    Serial.print(" Time ");
    Serial.print(curMillis >> 9); // divide by 512 is approx = half-seconds
    Serial.println(">");
  }
}

//============

void updateFlashInterval() {

   // this illustrates using different inputs to call different functions
  if (strcmp(messageFromPC, "LED1") == 0) {
     updateLED1();
  }
  
  if (strcmp(messageFromPC, "LED2") == 0) {
     updateLED2();
  }
}

//=============

void updateLED1() {

  if (newFlashInterval > 100) {
    LEDinterval[0] = newFlashInterval;
  }
}

//=============

void updateLED2() {

  if (newFlashInterval > 100) {
    LEDinterval[1] = newFlashInterval;
  }
}

//=============

void flashLEDs() {

  for (byte n = 0; n < numLEDs; n++) {
    if (curMillis - prevLEDmillis[n] >= LEDinterval[n]) {
       prevLEDmillis[n] += LEDinterval[n];
       digitalWrite( ledPin[n], ! digitalRead( ledPin[n]) );
    }
  }
}

//=============

void updateServoPos() {

  byte servoRange = servoMax - servoMin;
  if (servoFraction >= 0 && servoFraction <= 1) {
    newServoPos = servoMin + ((float) servoRange * servoFraction);
  }
}

//=============

void moveServo() {
  if (servoPos != newServoPos) {
    servoPos = newServoPos;
    myServo.write(servoPos);
  }
}

and Comarduino2.py:

def sendToArduino(sendStr):
  ser.write(sendStr)


#======================================

def recvFromArduino():
  global startMarker, endMarker
  
  ck = ""
  x = "z" # any value that is not an end- or startMarker
  byteCount = -1 # to allow for the fact that the last increment will be one too many
  
  # wait for the start character
  while  ord(x) != startMarker: 
    x = ser.read()
  
  # save data until the end marker is found
  while ord(x) != endMarker:
    if ord(x) != startMarker:
      ck = ck + x 
      byteCount += 1
    x = ser.read()
  
  return(ck)


#============================

def waitForArduino():

   # wait until the Arduino sends 'Arduino Ready' - allows time for Arduino reset
   # it also ensures that any bytes left over from a previous message are discarded
   
    global startMarker, endMarker
    
    msg = ""
    while msg.find("Arduino is ready") == -1:

      while ser.inWaiting() == 0:
        pass
        
      msg = recvFromArduino()

      print msg
      print
      
#======================================

def runTest(td):
  numLoops = len(td)
  waitingForReply = False

  n = 0
  while n < numLoops:

    teststr = td[n]

    if waitingForReply == False:
      sendToArduino(teststr)
      print "Sent from PC -- LOOP NUM " + str(n) + " TEST STR " + teststr
      waitingForReply = True

    if waitingForReply == True:

      while ser.inWaiting() == 0:
        pass
        
      dataRecvd = recvFromArduino()
      print "Reply Received  " + dataRecvd
      n += 1
      waitingForReply = False

      print "==========="

    time.sleep(5)


#======================================

# THE DEMO PROGRAM STARTS HERE

#======================================

import serial
import time

print
print

# NOTE the user must ensure that the serial port and baudrate are correct
serPort = "/dev/ttyACM0"
baudRate = 9600
ser = serial.Serial(serPort, baudRate)
print "Serial port " + serPort + " opened  Baudrate " + str(baudRate)


startMarker = 60
endMarker = 62


waitForArduino()


testData = []
testData.append("<LED1,200,0.2>")
testData.append("<LED1,800,0.7>")
testData.append("<LED2,800,0.5>")
testData.append("<LED2,200,0.2>")
testData.append("<LED1,200,0.7>")

runTest(testData)


ser.close

It is same as the files provided by the link described in the link given in question. This kind of error i.e input output error, also used to come when i was using ros_serial and ros_arduino_bridge, when communicating arduino with ros nodes. Firs the servo moves, than suddently error comes.

Thanks.

Going back to your description of the problem

When i don't connect the servo, the program runs fine. But after i connect the servo and attach it with pin 8, it shows above error.

can you also post the exact version of the Arduino program that does NOT cause the problem.

I can't immediately think why the Arduino program should cause a problem with the Python code. It's a long time since I wrote the demo.

...R

The program is same as i've given above. The problem is that after attaching servo motors, i got the error. At first, when i run the python program, the servo moves, than the error comes. Than i don't know somehow the port name changes from /dev/ttyACM0 to /dev/ttyACM1 and it contenious. If i again remove and reinsert the usb cable, than again the port name changes to /dev/ttyACM0. I am using python 2.7.

dineshlama: The program is same as i've given above. The problem is that after attaching servo motors, i got the error. At first, when i run the python program, the servo moves, than the error comes. Than i don't know somehow the port name changes from /dev/ttyACM0 to /dev/ttyACM1 and it contenious.

That sounds like you are powering the servo from the Arduino 5v pin and it is drawing too much current which causes the voltage to fall and the Arduino to reset - hence the change of port. It can also damage the Arduino.

Give the servos a separate power supply with the servo GND connected to the Arduino GND.

...R

Ok thanks, solved the problem. Since the servo motor didn't have mentioned any current specification in its document, i forgot about the current and only saw the voltage. I am using this motor.

dineshlama: Ok thanks, solved the problem.

Good to hear. It means I don't have to examine my code :)

The annoying thing about the problem you experienced is that the symptoms do look like a software issue.

...R