1

I have been trying to develop a connection from the arduino IDE to Processing so I can send data measured on the arduino Pins to processing to display.

I first packaged the 10-bit integers I was receiving from the arduino into characters each with their own byte. For example, 1023 was a 10-bit integer which i packaged into 4 8-bit characters, 1, 0, 2 and 3. These could then be sent over the serial port and were reconstructed on the other end by processing.

However, I have been trying to make a call and response relationship between the two where after one program is done receiving and processing the data, it asks the other to send the next set.

I used the example code given on the arduino website which works fine on its own. But when i try and implement the character packaging to it, it stops working. The output in processing always miss out the first couple of characters.

Whats more is that i deleted the myPort.print('A') from the processing code, and arduino was still sending data repeatedly, despite processing not sending it's response back.

It is a vague question, but where have i gone wrong when implementing the packaging code? and why does the arduino keep sending data regardless of whether processing responds.

Thanks a lot

===================================

Arduino Code:

int inByte = 0;

//void establishContact();

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  establishContact();
}

void loop() {
  // put your main code here, to run repeatedly:

  if (Serial.available() > 0) {
    // get incoming byte:
    //inByte = Serial.read();

      int MzValue = analogRead(A0);
      int FzValue = analogRead(A1);
      int FyValue = analogRead(A2);


      char Mz_Str[10];
      char Fz_Str[10];
      char Fy_Str[10];

      sprintf(Mz_Str, "%d", MzValue);
      sprintf(Fz_Str, "%d", FzValue);
      sprintf(Fy_Str, "%d", FyValue);
      // Now str contains the integer as characters

      Serial.write(Mz_Str);
      Serial.write(",");
      Serial.write(Fz_Str);
      Serial.write(",");
      Serial.write(Fy_Str);
      Serial.write(",");
      Serial.write("\n");

      delay(20);
  } 
  else {
    delay(20);
  }
}

void establishContact() {
  while (Serial.available() <= 0) {
    Serial.print('A');   // send a capital A
    delay(1000);
  }
}

=================================== Processing Code:

import processing.serial.*;

  Serial myPort;                       // The serial port
  boolean firstContact = false;        // Whether we've heard from the microcontroller
  String val;     // Data received from the serial port
  int numValues = 3;
  float[] values = new float[numValues];
  int inByte = 0;

  void setup() {
    size(256, 256);  // Stage size
    noStroke();      // No border on the next thing drawn

    // Print a list of the serial ports for debugging purposes
    // if using Processing 2.1 or later, use Serial.printArray()
    println(Serial.list());

    // I know that the first port in the serial list on my Mac is always my FTDI
    // adaptor, so I open Serial.list()[0].
    // On Windows machines, this generally opens COM1.
    // Open whatever port is the one you're using.
    String portName = Serial.list()[0];
    myPort = new Serial(this, portName, 9600);
  }

  void draw() {
    // read a byte from the serial port:
    if ( myPort.available() > 0) {
    inByte = myPort.read();
    }
    //print(inByte);
    // if this is the first byte received, and it's an A, clear the serial
    // buffer and note that you've had first contact from the microcontroller.
    // Otherwise, add the incoming byte to the array:
    if (firstContact == false) {
      if (inByte == 'A') {
        myPort.clear();          // clear the serial port buffer
        firstContact = true;     // you've had first contact from the microcontroller
        myPort.write('A');       // ask for more
        println(inByte);
      }
    }
    else {
        val = myPort.readStringUntil('\n');         // read it and store it in val
        println(val); //print it out in the console
        values = float(splitTokens(val, ","));

        myPort.write('A');
        delay(20);
      }
    }
3
  • Serial.print(MzValue); will do the same as your 'character packaging'
    – Juraj
    Apr 26, 2019 at 16:28
  • you don't read the available character, so it is remains available
    – Juraj
    Apr 26, 2019 at 16:32
  • Processing + Firmata is also a potential solution. May 16, 2021 at 23:30

1 Answer 1

1

Why not just send all the data at once, in a comma separated list, with a \n char as a "end of message" delimiter?

Here are 2 test sketches. The Arduino sketch sends the A0 to A2 values to serial every 500ms, and the Processing sketch displays the received data. Parsing the received data into an integer array is more of a Java question, not an Arduino one, so I'll leave that up to you.

Arduino

// Send the values of A0, A1 and A3
// to serial every 500ms.
// 2416 bytes.
char data[20];
char buffer[6];

void setup(){
  Serial.begin(9600);
}

void loop(){
  itoa(analogRead(A0), buffer, 10);
  strcat(data, buffer);
  strcat(data, ",");
  itoa(analogRead(A1), buffer, 10);
  strcat(data, buffer);
  strcat(data, ",");
  itoa(analogRead(A2), buffer, 10);
  strcat(data, buffer);
  strcat(data, "\n");
  Serial.write(data);
  memset(data, 0, sizeof(data));
  delay(500);
}

Processing

// Display the data received from the serial port, sent every
// 500 ms from the Arduino. The values sent are from A0, A1
// and A2, and were sent concatenated together, as a comma
// separated list, followed by a \n char.
import processing.serial.*;
import java.awt.TextArea;
Serial myPort;
TextArea myTextArea;
String input;

void setup(){

  try{
    myPort = new Serial(this, Serial.list()[0], 9600);
  }
  catch(Exception e){
    System.err.println(e);
    e.printStackTrace();
  }

  myTextArea = new TextArea("", 23, 49, 1);
  this.add(myTextArea);

  size(500, 380);

}

void draw(){

  if(myPort.available() > 0){
    input = myPort.readStringUntil('\n');
    myTextArea.append(input);
  }

}

EDIT

As Juraj mentions in his comments, I could have just used Serial.print() 6 times instead of the char arrays. Here is a second Arduino sketch that uses Serial.print(). Before you use it, be aware that it's compile size is 288 bytes more than the char array method. Imagine that :)

// Send the values of A0, A1 and A3
// to serial every 500ms.
// 2704 bytes.
void setup(){
  Serial.begin(9600);
}

void loop(){
  Serial.print(analogRead(A0));
  Serial.print(",");
  Serial.print(analogRead(A1));
  Serial.print(",");
  Serial.print(analogRead(A2));
  Serial.print("\n");
  delay(500);
}
5
  • Why not print the data to Serial as Serial.print(analogRead(A0)); Serial.print(',');...?
    – Juraj
    Apr 27, 2019 at 17:56
  • @Juraj That would work too :)
    – VE7JRO
    Apr 27, 2019 at 18:01
  • it would be 6 simple lines. no buffers, no C functions. and why memset again?
    – Juraj
    Apr 27, 2019 at 18:18
  • you need only buffer[0] = 0; at the start of the loop to 'clear' the string
    – Juraj
    Apr 28, 2019 at 3:55
  • I know. I like using memset() to set the entire array to 0's. How about this: memset(data, 0, 1); It results in the same compile size as buffer[0] = 0; and does the same thing. Of course, no one is forcing you to use memset().
    – VE7JRO
    Apr 28, 2019 at 4:24

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.