Problema di interfaciamento tra arduino e processing

Come da titolo ho un problema di interfacciamento tra arduino e processing, sto realizzando un piccolo oggettino per un amico e non riesco a farlo andare , il giocatollo in oggetto è il seguente:
Parte 1: http://luckylarry.co.uk/arduino-projects/arduino-processing-make-a-radar-screen-to-visualise-sensor-data-from-srf-05-part-1-setting-up-the-circuit-and-outputting-values/
Parte 2: http://luckylarry.co.uk/arduino-projects/arduino-processing-make-a-radar-screen-to-visualise-sensor-data-from-srf-05-part-2-visualising-the-data/

Tutta la parte che riguarda arduino funziona a meraviglia ma da lato PC non ne vengo fuori, se cambio la seguente stringa :

  myPort = new Serial(this, Serial.list()[1], 9600);

in
 myPort = new Serial(this, Serial.list()[3], 9600);
inserendo la reale porta assegnata ad arduino mi viene fuori una sfilza d'errori...

allora ho riscritto così :

  myPort = new Serial(this,"COM3", 9600);

non mi da errore, il programma parte ma non fà nulla...

strano O.o io avevo scritto un pò di processing e avevo lo stesso tuo errore, poi però ho risolto come hai fatto te...

Il codice processing non l'hai toccato per niente? molte volte ci può essere qualche errore li...

non l'ho nemmeno sfiorato apparte in quella parte... non cè verso che vada , ho passato due ore e mezzo su quel codice stamattina, va a fainire che me lo scrivo io :smiley:

ratto93:
non l'ho nemmeno sfiorato apparte in quella parte... non cè verso che vada , ho passato due ore e mezzo su quel codice stamattina, va a fainire che me lo scrivo io :smiley:

bella! io di solito provo a "isolare" il codice ovvero cerco di crearmi uno script minimale per capire dove può esserci l'errore.

Mi hai fatto incuriosire questa sera provo a vedere come ho risolto io, poi te lo posto...ti premetto che non sono un esperto, non ti aspettare che ti risolvo il problema a occhi chiusi :smiley:

Grazie :slight_smile:

è che come linguaggio sebbene molto simile a java, non lo conosco molto :slight_smile:

premetto che sono su linux... però ho messo la porta usb assegnata ad arduino:

myPort = new Serial(this, "dev/ttyACM0", 9600);

se ti consola, anche a me, da lo stesso errore tuo... il programma si avvia ma non si muove niente.
Provo a smacchinare pure io se ho novità ti faccio un fischio

Io son obbligato ad usarlo sotto win...
ho paura che sia proprio il programma ad aver qualche problemino, se combini qualcosa fammi sapere :slight_smile: grazie intanto :slight_smile:

a me in serialEvent() puzza questa cosa qui:

  String xString = myPort.readStringUntil('n');  // read the serial port until a new line

così continua a leggere finchè trova una "n" non un una new line, prova a sostituire con '\n' che è il carattere che indica la new line:

  String xString = myPort.readStringUntil('\n');  // read the serial port until a new line

Poi come debug puoi usare print() e println() in cui inserisci le stringhe o i numeri ricavati che scrive direttamente nella "striscia nera sotto l'IDE" (che non so come si chiama), tipo:

/* get values from serial port /
void serialEvent (Serial myPort) {
String xString = myPort.readStringUntil('\n'); // read the serial port until a new line
if (xString != null) { // if theres data in between the new lines
xString = trim(xString); // get rid of any whitespace just in case
String getX = xString.substring(1, xString.indexOf("V")); // get the value of the servo position
String getV = xString.substring(xString.indexOf("V")+1, xString.length()); // get the value of the sensor reading
println("getX : "+ getX + "\tgetY: " + getY);
degree = Integer.parseInt(getX); // set the values to variables
value = Integer.parseInt(getV);
oldValue[degree] = newValue[degree]; // store the values in the arrays.
newValue[degree] = value;
/
sets a counter to allow for the first 2 sweeps of the servo */
firstRun++;
if (firstRun > 360) {
firstRun = 360; // keep the value at 360
}
}
}

Ora provo grazie della dritta...

@Federico hai ragione.
Ho fatto una ricerca sui carattero escape (mi pare si chiamano cosi)
Sono arrivato alla conclusione:
in windows \r\n
in linux \n
in mac \n\r

Correggetemi se sbaglio... ratto tu provali vedi quello che funziona.

è sufficiente intercettare '\n' perchè println aggiunge solo \n alla fine della trasmissione

println("testo");

è la scrittura compatta di:

print("testo\n");

avete sostituito le librerie TXRX di processing con quelle di arduino?

lesto:
avete sostituito le librerie TXRX di processing con quelle di arduino?

nel caso non andassero bene avrebbero avuto qualche errore e poi su windows non serve e spesso neanche su linux

serve solo su linux per fargli vedere la UNO (ttyACMX) (caso di albyy911, se non erro)

non dà errore di compilazione, ma di runtime e su un thread differente, quindi il programma continua a girare ma non la comunicazione seriale

Le librerie per la comunicaazione seriale non le ho cambiate, arduino ha le sue così come processing....
ho fatto qualche prova ma non cambia nulla... il grafico prodotto da processing è immobile...
posso però comfermare che arduino lavora correttamente perchè aprendo il serial monitor mi dà i valori della posizione del servo e della distanza rilevata correttie in contiunuo aumento/diminuzione... il problema è quindi del solo processing...

ok, allora puoi postare il codice completo che stai usando?

Certo eccolo....

Lato Processing:

import processing.serial.*;     // import serial library
Serial myPort;                  // declare a serial port
float x, y;                       // variable to store x and y co-ordinates for vertices
int radius = 350;               // set the radius of objects
int w = 300;                    // set an arbitary width value
int degree = 0;                 // servo position in degrees
int value = 0;                  // value from sensor
int motion = 0;                 // value to store which way the servo is panning
int[] newValue = new int[181];  // create an array to store each new sensor value for each servo position
int[] oldValue = new int[181];  // create an array to store the previous values.
PFont myFont;                   // setup fonts in Processing
int radarDist = 0;              // set value to configure Radar distance labels
int firstRun = 0;               // value to ignore triggering motion on the first 2 servo sweeps

/* create background and serial buffer */
void setup(){
  // setup the background size, colour and font.
  size(750, 450);
  background (0); // 0 = black
  myFont = createFont("verdana", 12);
  textFont(myFont);
  // setup the serial port and buffer
  myPort = new Serial(this, "COM1", 9600);
  myPort.bufferUntil('\n');
}

/* draw the screen */
void draw(){
  fill(0);                              // set the following shapes to be black
  noStroke();                           // set the following shapes to have no outline
  ellipse(radius, radius, 750, 750);    // draw a circle with a width/ height = 750 with its center position (x and y) set by the radius
  rectMode(CENTER);                     // set the following rectangle to be drawn around its center
  rect(350,402,800,100);                // draw rectangle (x, y, width, height)
  if (degree >= 179) {                  // if at the far right then set motion = 1/ true we're about to go right to left
    motion = 1;                         // this changes the animation to run right to left
  }
  if (degree <= 1) {                    // if servo at 0 degrees then we're about to go left to right
    motion = 0;                         // this sets the animation to run left to right
  }
  /* setup the radar sweep */
  /*
  We use trigonmetry to create points around a circle.
  So the radius plus the cosine of the servo position converted to radians
  Since radians 0 start at 90 degrees we add 180 to make it start from the left
  Adding +1 (i) each time through the loops to move 1 degree matching the one degree of servo movement
  cos is for the x left to right value and sin calculates the y value
  since its a circle we plot our lines and vertices around the start point for everything will always be the center.
  */
  strokeWeight(7);                      // set the thickness of the lines
  if (motion == 0) {                    // if going left to right
    for (int i = 0; i <= 20; i++) {     // draw 20 lines with fading colour each 1 degree further round than the last
      stroke(0, (10*i), 0);             // set the stroke colour (Red, Green, Blue) base it on the the value of i
      line(radius, radius, radius + cos(radians(degree+(180+i)))*w, radius + sin(radians(degree+(180+i)))*w); // line(start x, start y, end x, end y)
    }
  } else {                              // if going right to left
    for (int i = 20; i >= 0; i--) {     // draw 20 lines with fading colour
      stroke(0,200-(10*i), 0);          // using standard RGB values, each between 0 and 255
      line(radius, radius, radius + cos(radians(degree+(180+i)))*w, radius + sin(radians(degree+(180+i)))*w);
    }
  }
  /* Setup the shapes made from the sensor values */
  noStroke();                           // no outline
  /* first sweep */
  fill(0,50,0);                         // set the fill colour of the shape (Red, Green, Blue)
  beginShape();                         // start drawing shape
    for (int i = 0; i < 180; i++) {     // for each degree in the array
      x = radius + cos(radians((180+i)))*((oldValue[i])); // create x coordinate
      y = radius + sin(radians((180+i)))*((oldValue[i])); // create y coordinate
      vertex(x, y);                     // plot vertices
    }
  endShape();                           // end shape
  /* second sweep */
  fill(0,110,0);
  beginShape();
    for (int i = 0; i < 180; i++) {
      x = radius + cos(radians((180+i)))*(newValue[i]);
      y = radius + sin(radians((180+i)))*(newValue[i]);
      vertex(x, y);
    }
  endShape();
  /* average */
  fill(0,170,0);
  beginShape();
    for (int i = 0; i < 180; i++) {
      x = radius + cos(radians((180+i)))*((newValue[i]+oldValue[i])/2); // create average
      y = radius + sin(radians((180+i)))*((newValue[i]+oldValue[i])/2);
      vertex(x, y);
    }
  endShape();
  /* if after first 2 sweeps, highlight motion with red circle*/
  if (firstRun >= 360) {
    stroke(150,0,0);
    strokeWeight(1);
    noFill();
      for (int i = 0; i < 180; i++) {
        if (oldValue[i] - newValue[i] > 35 || newValue[i] - oldValue[i] > 35) {
          x = radius + cos(radians((180+i)))*(newValue[i]);
          y = radius + sin(radians((180+i)))*(newValue[i]);
          ellipse(x, y, 10, 10);
        }
      }
  }
  /* set the radar distance rings and out put their values, 50, 100, 150 etc.. */
  for (int i = 0; i <=6; i++){
    noFill();
    strokeWeight(1);
    stroke(0, 255-(30*i), 0);
    ellipse(radius, radius, (100*i), (100*i));
    fill(0, 100, 0);
    noStroke();
    text(Integer.toString(radarDist+50), 380, (305-radarDist), 50, 50);
    radarDist+=50;
  }
  radarDist = 0;
  /* draw the grid lines on the radar every 30 degrees and write their values 180, 210, 240 etc.. */
  for (int i = 0; i <= 6; i++) {
    strokeWeight(1);
    stroke(0, 55, 0);
    line(radius, radius, radius + cos(radians(180+(30*i)))*w, radius + sin(radians(180+(30*i)))*w);
    fill(0, 55, 0);
    noStroke();
    if (180+(30*i) >= 300) {
      text(Integer.toString(180+(30*i)), (radius+10) + cos(radians(180+(30*i)))*(w+10), (radius+10) + sin(radians(180+(30*i)))*(w+10), 25,50);
    } else {
      text(Integer.toString(180+(30*i)), radius + cos(radians(180+(30*i)))*w, radius + sin(radians(180+(30*i)))*w, 60,40);
    }
  }
  /* Write information text and values. */
  noStroke();
  fill(0);
  rect(350,402,800,100);
  fill(0, 100, 0);
  text("Degrees: "+Integer.toString(degree), 100, 380, 100, 50);         // use Integet.toString to convert numeric to string as text() only outputs strings
  text("Distance: "+Integer.toString(value), 100, 400, 100, 50);         // text(string, x, y, width, height)
  text("Radar screen code at luckylarry.co.uk", 540, 380, 250, 50);
  fill(0);
  rect(70,60,150,100);
  fill(0, 100, 0);
  text("Screen Key:", 100, 50, 150, 50);
  fill(0,50,0);
  rect(30,53,10,10);
  text("First sweep", 115, 70, 150, 50);
  fill(0,110,0);
  rect(30,73,10,10);
  text("Second sweep", 115, 90, 150, 50);
  fill(0,170,0);
  rect(30,93,10,10);
  text("Average", 115, 110, 150, 50);
  noFill();
  stroke(150,0,0);
  strokeWeight(1);
  ellipse(29, 113, 10, 10);
  fill(150,0,0);
  text("Motion", 115, 130, 150, 50);
}

/* get values from serial port */
void serialEvent (Serial myPort) {
  String xString = myPort.readStringUntil('n');  // read the serial port until a new line
    if (xString != null) {  // if theres data in between the new lines
        xString = trim(xString); // get rid of any whitespace just in case
        String getX = xString.substring(1, xString.indexOf("V")); // get the value of the servo position
        String getV = xString.substring(xString.indexOf("V")+1, xString.length()); // get the value of the sensor reading
        degree = Integer.parseInt(getX); // set the values to variables
        value = Integer.parseInt(getV);
        oldValue[degree] = newValue[degree]; // store the values in the arrays.
        newValue[degree] = value;
        /* sets a counter to allow for the first 2 sweeps of the servo */
        firstRun++;
        if (firstRun > 360) {
          firstRun = 360; // keep the value at 360
        }
  }
}

Lato arduino :

#include  <Servo.h>           // include the standard servo library
Servo leftRightServo;         // set a variable to map the servo
int leftRightPos = 0;         // set a variable to store the servo position
const int numReadings = 10;   // set a variable for the number of readings to take
int index = 0;                // the index of the current reading
int total = 0;                // the total of all readings
int average = 0;              // the average
int echoPin = 2;              // the SRF05's echo pin
int initPin = 3;              // the SRF05's init pin
unsigned long pulseTime = 0;  // variable for reading the pulse
unsigned long distance = 0;   // variable for storing distance
 
/* setup the pins, servo and serial port */
void setup() {
  leftRightServo.attach(10);
  // make the init pin an output:
  pinMode(initPin, OUTPUT);
  // make the echo pin an input:
  pinMode(echoPin, INPUT);
  // initialize the serial port:
  Serial.begin(9600);
} 
 
/* begin rotating the servo and getting sensor values */
void loop() {
  for(leftRightPos = 0; leftRightPos < 180; leftRightPos++) {  // going left to right.
    leftRightServo.write(leftRightPos);
      for (index = 0; index<=numReadings;index++) {            // take x number of readings from the sensor and average them
        digitalWrite(initPin, LOW);
        delayMicroseconds(50);
        digitalWrite(initPin, HIGH);                           // send signal
        delayMicroseconds(50);                                 // wait 50 microseconds for it to return
        digitalWrite(initPin, LOW);                            // close signal
        pulseTime = pulseIn(echoPin, HIGH);                    // calculate time for signal to return
        distance = pulseTime/58;                               // convert to centimetres
        total = total + distance;                              // update total
        delay(10);
      }
    average = total/numReadings;                               // create average reading
 
    if (index >= numReadings)  {                               // reset the counts when at the last item of the array
      index = 0;
      total = 0;
    }
    Serial.print("X");                                         // print leading X to mark the following value as degrees
    Serial.print(leftRightPos);                                // current servo position
    Serial.print("V");                                         // preceeding character to separate values
    Serial.println(average);                                   // average of sensor readings
  }
  /*
  start going right to left after we got to 180 degrees
  same code as above
  */
  for(leftRightPos = 180; leftRightPos > 0; leftRightPos--) {  // going right to left
    leftRightServo.write(leftRightPos);
    for (index = 0; index<=numReadings;index++) {
      digitalWrite(initPin, LOW);
      delayMicroseconds(50);
      digitalWrite(initPin, HIGH);
      delayMicroseconds(50);
      digitalWrite(initPin, LOW);
      pulseTime = pulseIn(echoPin, HIGH);
      distance = pulseTime/58;
      total = total + distance;
      delay(10);
    }
    average = total/numReadings;
    if (index >= numReadings)  {
      index = 0;
      total = 0;
    }
    Serial.print("X");
    Serial.println(leftRightPos);
    Serial.print("V");
    Serial.println(average);
   }
}

ratto93:
Certo eccolo....

Lato Processing:

import processing.serial.*;     // import serial library

Serial myPort;                  // declare a serial port
float x, y;                       // variable to store x and y co-ordinates for vertices
int radius = 350;               // set the radius of objects
int w = 300;                    // set an arbitary width value
int degree = 0;                 // servo position in degrees
int value = 0;                  // value from sensor
int motion = 0;                 // value to store which way the servo is panning
int[] newValue = new int[181];  // create an array to store each new sensor value for each servo position
int[] oldValue = new int[181];  // create an array to store the previous values.
PFont myFont;                   // setup fonts in Processing
int radarDist = 0;              // set value to configure Radar distance labels
int firstRun = 0;               // value to ignore triggering motion on the first 2 servo sweeps

/* create background and serial buffer */
void setup(){
 // setup the background size, colour and font.
 size(750, 450);
 background (0); // 0 = black
 myFont = createFont("verdana", 12);
 textFont(myFont);
 // setup the serial port and buffer
 myPort = new Serial(this, "COM1", 9600);
 myPort.bufferUntil('\n');
}

/* draw the screen /
void draw(){
 fill(0);                              // set the following shapes to be black
 noStroke();                           // set the following shapes to have no outline
 ellipse(radius, radius, 750, 750);    // draw a circle with a width/ height = 750 with its center position (x and y) set by the radius
 rectMode(CENTER);                     // set the following rectangle to be drawn around its center
 rect(350,402,800,100);                // draw rectangle (x, y, width, height)
 if (degree >= 179) {                  // if at the far right then set motion = 1/ true we're about to go right to left
   motion = 1;                         // this changes the animation to run right to left
 }
 if (degree <= 1) {                    // if servo at 0 degrees then we're about to go left to right
   motion = 0;                         // this sets the animation to run left to right
 }
 /
setup the radar sweep /
 /

 We use trigonmetry to create points around a circle.
 So the radius plus the cosine of the servo position converted to radians
 Since radians 0 start at 90 degrees we add 180 to make it start from the left
 Adding +1 (i) each time through the loops to move 1 degree matching the one degree of servo movement
 cos is for the x left to right value and sin calculates the y value
 since its a circle we plot our lines and vertices around the start point for everything will always be the center.
 /
 strokeWeight(7);                      // set the thickness of the lines
 if (motion == 0) {                    // if going left to right
   for (int i = 0; i <= 20; i++) {     // draw 20 lines with fading colour each 1 degree further round than the last
     stroke(0, (10
i), 0);             // set the stroke colour (Red, Green, Blue) base it on the the value of i
     line(radius, radius, radius + cos(radians(degree+(180+i)))w, radius + sin(radians(degree+(180+i)))w); // line(start x, start y, end x, end y)
   }
 } else {                              // if going right to left
   for (int i = 20; i >= 0; i--) {     // draw 20 lines with fading colour
     stroke(0,200-(10
i), 0);          // using standard RGB values, each between 0 and 255
     line(radius, radius, radius + cos(radians(degree+(180+i)))w, radius + sin(radians(degree+(180+i)))w);
   }
 }
 /
Setup the shapes made from the sensor values /
 noStroke();                           // no outline
 /
first sweep /
 fill(0,50,0);                         // set the fill colour of the shape (Red, Green, Blue)
 beginShape();                         // start drawing shape
   for (int i = 0; i < 180; i++) {     // for each degree in the array
     x = radius + cos(radians((180+i)))
((oldValue[i])); // create x coordinate
     y = radius + sin(radians((180+i)))
((oldValue[i])); // create y coordinate
     vertex(x, y);                     // plot vertices
   }
 endShape();                           // end shape
 /
second sweep /
 fill(0,110,0);
 beginShape();
   for (int i = 0; i < 180; i++) {
     x = radius + cos(radians((180+i)))
(newValue[i]);
     y = radius + sin(radians((180+i)))(newValue[i]);
     vertex(x, y);
   }
 endShape();
 /
average /
 fill(0,170,0);
 beginShape();
   for (int i = 0; i < 180; i++) {
     x = radius + cos(radians((180+i)))
((newValue[i]+oldValue[i])/2); // create average
     y = radius + sin(radians((180+i)))((newValue[i]+oldValue[i])/2);
     vertex(x, y);
   }
 endShape();
 /
if after first 2 sweeps, highlight motion with red circle*/
 if (firstRun >= 360) {
   stroke(150,0,0);
   strokeWeight(1);
   noFill();
     for (int i = 0; i < 180; i++) {
       if (oldValue[i] - newValue[i] > 35 || newValue[i] - oldValue[i] > 35) {
         x = radius + cos(radians((180+i)))(newValue[i]);
         y = radius + sin(radians((180+i)))
(newValue[i]);
         ellipse(x, y, 10, 10);
       }
     }
 }
 /* set the radar distance rings and out put their values, 50, 100, 150 etc.. /
 for (int i = 0; i <=6; i++){
   noFill();
   strokeWeight(1);
   stroke(0, 255-(30
i), 0);
   ellipse(radius, radius, (100i), (100i));
   fill(0, 100, 0);
   noStroke();
   text(Integer.toString(radarDist+50), 380, (305-radarDist), 50, 50);
   radarDist+=50;
 }
 radarDist = 0;
 /* draw the grid lines on the radar every 30 degrees and write their values 180, 210, 240 etc.. /
 for (int i = 0; i <= 6; i++) {
   strokeWeight(1);
   stroke(0, 55, 0);
   line(radius, radius, radius + cos(radians(180+(30
i)))w, radius + sin(radians(180+(30i)))w);
   fill(0, 55, 0);
   noStroke();
   if (180+(30
i) >= 300) {
     text(Integer.toString(180+(30i)), (radius+10) + cos(radians(180+(30i)))(w+10), (radius+10) + sin(radians(180+(30i)))(w+10), 25,50);
   } else {
     text(Integer.toString(180+(30
i)), radius + cos(radians(180+(30*i)))w, radius + sin(radians(180+(30i)))w, 60,40);
   }
 }
 /
Write information text and values. */
 noStroke();
 fill(0);
 rect(350,402,800,100);
 fill(0, 100, 0);
 text("Degrees: "+Integer.toString(degree), 100, 380, 100, 50);         // use Integet.toString to convert numeric to string as text() only outputs strings
 text("Distance: "+Integer.toString(value), 100, 400, 100, 50);         // text(string, x, y, width, height)
 text("Radar screen code at luckylarry.co.uk", 540, 380, 250, 50);
 fill(0);
 rect(70,60,150,100);
 fill(0, 100, 0);
 text("Screen Key:", 100, 50, 150, 50);
 fill(0,50,0);
 rect(30,53,10,10);
 text("First sweep", 115, 70, 150, 50);
 fill(0,110,0);
 rect(30,73,10,10);
 text("Second sweep", 115, 90, 150, 50);
 fill(0,170,0);
 rect(30,93,10,10);
 text("Average", 115, 110, 150, 50);
 noFill();
 stroke(150,0,0);
 strokeWeight(1);
 ellipse(29, 113, 10, 10);
 fill(150,0,0);
 text("Motion", 115, 130, 150, 50);
}

/* get values from serial port /
void serialEvent (Serial myPort) {
 String xString = myPort.readStringUntil('n');  // read the serial port until a new line
   if (xString != null) {  // if theres data in between the new lines
       xString = trim(xString); // get rid of any whitespace just in case
       String getX = xString.substring(1, xString.indexOf("V")); // get the value of the servo position
       String getV = xString.substring(xString.indexOf("V")+1, xString.length()); // get the value of the sensor reading
       degree = Integer.parseInt(getX); // set the values to variables
       value = Integer.parseInt(getV);
       oldValue[degree] = newValue[degree]; // store the values in the arrays.
       newValue[degree] = value;
       /
sets a counter to allow for the first 2 sweeps of the servo */
       firstRun++;
       if (firstRun > 360) {
         firstRun = 360; // keep the value at 360
       }
 }
}

aggiungi il backslash "" anche dentro la funzione che vedi alla fine "void serialEvent (Serial myPort)" è proprio questa funzione che va a leggere ed interpretare la seriale, non il:

myPort.bufferUntil('\n');

che hai già modificato nel setup()

...per dubbi riguardati il reply #7

Fatto :smiley:

Non cambia -_-" è immobile...