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);
}
}
1 Answer 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);
}
-
Why not
print
the data to Serial asSerial.print(analogRead(A0)); Serial.print(',');
...?2019年04月27日 17:56:44 +00:00Commented Apr 27, 2019 at 17:56 -
@Juraj That would work too :)VE7JRO– VE7JRO2019年04月27日 18:01:48 +00:00Commented Apr 27, 2019 at 18:01
-
it would be 6 simple lines. no buffers, no C functions. and why memset again?2019年04月27日 18:18:13 +00:00Commented Apr 27, 2019 at 18:18
-
you need only
buffer[0] = 0
; at the start of the loop to 'clear' the string2019年04月28日 03:55:04 +00:00Commented 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 asbuffer[0] = 0;
and does the same thing. Of course, no one is forcing you to usememset()
.VE7JRO– VE7JRO2019年04月28日 04:24:37 +00:00Commented Apr 28, 2019 at 4:24
Serial.print(MzValue);
will do the same as your 'character packaging'