USB / Serial connection problem with arduino to rasp pi

Hi,

I am experiencing a problem connecting my Arduino mega to a raspberry pi via the usb. When I run firmata on the Arduino, the connection is guaranteed. When I run my own code on the Arduino, I run into problems connecting with the PI. Same code run on the Arduino, it has no problem with usb connection with a PC, but with the rasp pi usb I get the error that the port is temporarily unavailable. If I unplug the usb and plug it back in, then the connection occurs.

Any idea why my code has problems with the usb port on the pi, showing temporarily unavailable, but never a problem with a PC? Same hardware but running firmata, it always connects with the PI.

As well, there is never a problem interacting with the code on the Arduino using the Arduino ide serial monitor.

[code]
// This consists of
// #1 - parsing serial receive with start and end markers to two integers from format <7,180>
// #2 - writing the parsed integers to servos in the format of <pin number,degrees>
// #3 - incorporating NewPing library with 15 sensors, and writing the results to serial
// #4 - read analog pins

// Start #1

const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars];        // temporary array for use when parsing
// variables to hold the parsed data
int servoNumber = 0;
int servoPosition = 0;
boolean newData = false;

// end #1

// my servo addition

#include <Servo.h>
Servo mys[20]; //Now we have 20 servos but only use 2-19 (ie 18 servos)
//

//Start #3 Ping code addition
#include <NewPing.h>

#define SONAR_NUM     4 // Number or sensors.
#define MAX_DISTANCE 200 // Maximum distance (in cm) to ping.
#define PING_INTERVAL 33 // Milliseconds between sensor pings (29ms is about the min to avoid cross-sensor echo).

unsigned long pingTimer[SONAR_NUM]; // Holds the times when the next ping should happen for each sensor.
unsigned int cm[SONAR_NUM];         // Where the ping distances are stored.
uint8_t currentSensor = 0;          // Keeps track of which sensor is active.

NewPing sonar[SONAR_NUM] = {     // Sensor object array.
  NewPing(41, 42, MAX_DISTANCE), // name cm[0] left   Each sensor's trigger pin, echo pin, and max distance to ping.
  NewPing(43, 44, MAX_DISTANCE), // name cm[1] center
  NewPing(45, 46, MAX_DISTANCE), // name cm[2] right
  NewPing(47, 48, MAX_DISTANCE), // name cm[3] rear
  //NewPing(23, 24, MAX_DISTANCE),
  //NewPing(25, 26, MAX_DISTANCE),
  //NewPing(27, 28, MAX_DISTANCE),
  //NewPing(29, 30, MAX_DISTANCE),
  //NewPing(31, 32, MAX_DISTANCE),
  //NewPing(34, 33, MAX_DISTANCE),
  //NewPing(35, 36, MAX_DISTANCE),
  //NewPing(37, 38, MAX_DISTANCE),
  //NewPing(39, 40, MAX_DISTANCE),
  //NewPing(50, 51, MAX_DISTANCE),
  //NewPing(52, 53, MAX_DISTANCE)
};
// end #3 newping addition============

// analog pin reading

int valAnalog0 = 0;           // variable to store the value read A0
int valAnalog1 = 0;           // variable to store the value read A1
int valAnalog2 = 0;           // variable to store the value read A2

 // end analog pin reading

int valpin50 = 0;       // variable to store the read value

 
void setup() {
  Serial.begin(115200);
  // message for #1 Serial.println("This demo expects 2 pieces of data - two integers");
  // Serial.println("Enter data in this style <1,180>  ");
  //  Serial.println();
  
  // my addition for servo array
  for (int i = 2; i < 20; i++)
  {
    mys[i].attach(i);
    mys[i].write(90);
  }
  // end my addition servo array

  // Start #3 Ping code void setup addition

  // already done   Serial.begin(115200);
  pingTimer[0] = millis() + 75;           // First ping starts at 75ms, gives time for the Arduino to chill before starting.
  for (uint8_t i = 1; i < SONAR_NUM; i++) // Set the starting time for each sensor.
    pingTimer[i] = pingTimer[i - 1] + PING_INTERVAL;
  // end #3 ping code addition============

  pinMode (50,INPUT); // sets pin 50 to read a digital input from Rasp PI pin 13 for decision making later in code
}
void loop() {
  recvWithStartEndMarkers();
  if (newData == true) {
    strcpy(tempChars, receivedChars);
    // this temporary copy is necessary to protect the original data
    //   because strtok() used in parseData() replaces the commas with \0
    parseData();
    
    // showParsedData();
    //
    servoMove();
    newData = false;
  }
  // #3 Ping code addition to void loop

  {
    for (uint8_t i = 0; i < SONAR_NUM; i++) { // Loop through all the sensors.
      if (millis() >= pingTimer[i]) {         // Is it this sensor's time to ping?
        pingTimer[i] += PING_INTERVAL * SONAR_NUM;  // Set next time this sensor will be pinged.
        if (i == 0 && currentSensor == SONAR_NUM - 1) oneSensorCycle(); // Sensor ping cycle complete, do something with the results.
        sonar[currentSensor].timer_stop();          // Make sure previous timer is canceled before starting a new ping (insurance).
        currentSensor = i;                          // Sensor being accessed.
        cm[currentSensor] = 0;                      // Make distance zero in case there's no ping echo for this sensor.
        sonar[currentSensor].ping_timer(echoCheck); // Do the ping (processing continues, interrupt will call echoCheck to look for echo).
      }
    }
    // The rest of your code would go here.

    // analog pin reading
    
valAnalog0 = analogRead(0);     // read the input pin (IR front)
valAnalog1 = analogRead(1);     // read the input pin (IR rear)
valAnalog2 = analogRead(2);     // read the input pin  (batvoltage)

    // end analog pin reading
  }
  // end #3 Ping code addition to void loop

  valpin50 = digitalRead(50);     // read the input pin

}

//====#1========

void recvWithStartEndMarkers() {
  static boolean recvInProgress = false;
  static byte ndx = 0;
  char startMarker = '<';
  char endMarker = '>';
  char rc;

  while (Serial.available() > 0 && newData == false) {
    rc = Serial.read();

    if (recvInProgress == true) {
      if (rc != endMarker) {
        receivedChars[ndx] = rc;
        ndx++;
        if (ndx >= numChars) {
          ndx = numChars - 1;
        }
      }
      else {
        receivedChars[ndx] = '\0'; // terminate the string
        recvInProgress = false;
        ndx = 0;
        newData = true;
      }
    }

    else if (rc == startMarker) {
      recvInProgress = true;
    }
  }
}

//=====#1=======

void parseData() {      // split the data into its parts

  char * strtokIndx; // this is used by strtok() as an index

  strtokIndx = strtok(tempChars, ",");     // get the first part - the string
  servoNumber = atoi(strtokIndx); // my addition convert first part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  servoPosition = atoi(strtokIndx);     // convert this part to an integer

}

//====#1========

void showParsedData() {
  Serial.print("Servo Number ");
  Serial.println(servoNumber);
  Serial.print("Servo Position ");
  Serial.println(servoPosition);

}
// start my addition for writing to servo
void servoMove() {
  mys[servoNumber].write(servoPosition); //write servo position
  // end my addition
}

//===#3====
void oneSensorCycle() { // Sensor ping cycle complete, do something with the results.
  for (uint8_t i = 0; i < SONAR_NUM; i++) {
    // Serial.print(i);
    // Serial.print("=");
    // Serial.print(cm[i]);
    // Serial.print("cm ");
    
    // writing JSON to serial

if (valpin50==1){
    Serial.print ("{\"leftDistance\":");
    Serial.print (cm[0]);
    Serial.print (",");
    Serial.print ("\"centerDistance\":");
    Serial.print (cm[1]);
    Serial.print (",");
    Serial.print ("\"rightDistance\":");
    Serial.print (cm[2]);
    Serial.print (",");
    Serial.print ("\"rearDistance\":");
    Serial.print (cm[3]);
    Serial.print (",");
    Serial.print ("\"batteryVoltage\":");
    Serial.print (valAnalog2);

    
    Serial.println ("}"); // end of JSON
}

    // end write JSON to serial
  }
 }
 
 //====#3=====
void echoCheck() { // If ping received, set the sensor distance to array.
  if (sonar[currentSensor].check_timer())
    cm[currentSensor] = sonar[currentSensor].ping_result / US_ROUNDTRIP_CM;
}

[/code]

What happens if you create a simple "hello world" program on your Mega and connect it to your RPi

I don't have an RPi myself but I use Linux on this laptop and I never have a problem connecting to my Arduinos.

...R

I just ran this code that is an example of serial printing some numbers, and it does the same thing. It gives me an error message on the pi that "resource unavailable, port temporarily unavailable, cannot lock port".

Then, when I unplug the usb cable and plug it back in, the port becomes opened, and it gives me error messages that the numbers are unexpected in json. That part is just fine, and to be accepted, as it doesn't recognize what is being printed to the serial port. It's the "cannot lock port" until I unplug and replug in the usb that is the problem.

Edit: I just tried it with firmata, and it causes the same error, "cannot lock port".

Sounds like Raspberry Pi problem.

.

Yes, I am beginning to suspect the problem lies in the node-red flow I am running on the raspberry pi. I never had the problem before when I ran firmata on the Arduino and node red on the pi, when I used node red flows using their Arduino nodes, which are designed to communicate with an Arduino running firmata. But I am now using their serial nodes, which are of course more generic, and now can't get it to connect to the simplest sketch, except by unplugging the usb plug and plugging it back in each time I reboot the pi.

Problem solved. It turns out that node red keeps deleted communication nodes running, unless you not only remove them from the flow (essentially the program you design), but from the whole editor. I deleted the Arduino nodes, and everything connects reliably now.

The old Arduino serial nodes (designed to interface with firmata on an Arduino) were interfering with the generic serial nodes I was using for input / output.

The above C++ code works great. It receives a servo command as <pin number,movement> and writes that to the servos. It reads sensor values and formats them as JSON and writes them to the serial port, so they can be parsed and distributed as desired by the receiver.

Thank You!

I have been troubleshooting this exact problem for hours. I'm so glad I finally found your post.