It's a bit confusing what you're trying to do, but from what I can gather the confusion is around serial communication.
here's how I understand how the communication works with your current code and a few issues with that:
1. Truncation
You're writing px
which is mapped to the sketch dimensions (which I can't see anywhere, so guessing it's the default 100x100 ?).
If the dimensions are bigger than 255 this may be a problem.
Even through Processing Serial write(int) takes an int, behind the scenes it's using jssc.Serial.writeInt() which takes a value from 0 to 255.
(Essentially it writes a single byte, but within 0-255 range, where as the byte
type in Processing java is from -127 to 128).
If you want to send values greater than 255 you would need to split them into individual bytes. (see the ARGB value split example using bit shifting and AND masking and using OR to put the individual bytes together into a multiple byte integer)
2. Repetition
px
is sent again in the for loop: myPort.write(lista[i]);
The code is commented anyway, but it's something to be mindful of.
Personally I make new simple test sketches solving individual simple problems instead of large unused blocks which make the code harder to read/navigate and ultimately debug.
I encourage you to split the bigger problem into multiple simpler single problems, and solving one at a time.
3. Data termination
The commented code attempts to send 4 integers, but there is no way for Arduino to know in which order the data arrives. If anything goes wrong it will be very hard to tell what's the order.
There are multiple ways to do this. Ideally you would write a communication protocol.
(and there are many resources on this topic.)
It sounds like a fun project to learn about working with bits/bytes/byte arrays and putting together a communication protocol from scratch with some form of data verification (checksum / CRC / etc.)
If you're tight on time and you simply want to drive a servo without worrying too much about reliably sending multiple (potentially) large values over serial I recommend trying Firmata Processing
You would need to flash the Firmata firmware to your Arduino then use the Firmata Processing library to connect to the serial port (with the correct baud rate) and call arduino.servoWrite()
as required. See the library's arduino_servo
example as well.
Based on your comment on mapped values between 0 -> 100, you could use repurpose the SerialEvent example using any other character > 100 to differentiate data from the string terminator char. Bare in mind you wil be loosing precision:
getValue()
returns a float
which has 32bit precision
- You could in theory use the same technique with 0-254 (using 255 as the terminator character). 0-100 range uses 6 bits
Here is a rough example of what might look like in code, taking into account the code has not been tested with actual devices:
Processing:
import processing.serial.*;
import org.gamecontrolplus.gui.*;
import org.gamecontrolplus.*;
import net.java.games.input.*;
Serial myPort;
ControlIO control;
ControlDevice stick;
float px, py, pz, pw;
// px,py,pz,pw remapped to 0-100 range
int[] lista = new int[4];
// px,py,pz as bytes + terminator character (255)
byte[] toArduino = {0,0,0,0,(byte)255};
public void setup() {
size(100,100);
lista = new int[4];
String portName = Serial.list()[2];
try{
myPort = new Serial(this, portName, 9600);
}catch(Exception e){
println("error connecting to serial port: " + portName);
e.printStackTrace();
}
surface.setTitle("GCP Joystick example");
control = ControlIO.getInstance(this);
try{
stick = control.filter(GCP.STICK).getMatchedDevice("joystick");
}catch(Exception e){
e.printStackTrace();
}
if (stick == null) {
println("No suitable device configured");
}
}
public void getUserInput() {
if(stick == null){
return;
}
// map values
px = map(stick.getSlider("X").getValue(), -1, 1, 0, width);
py = map(stick.getSlider("Y").getValue(), -1, 1, 0, height);
pz = map(stick.getSlider("Z").getValue(), -1, 1, 0, width);
pw = map(stick.getSlider("W").getValue(), -1, 1, 0, height);
// cast to int
lista[0] = (int)px;
lista[1] = (int)py;
lista[2] = (int)pz;
lista[3] = (int)pw;
// update bytearray
toArduino[0] = (byte)lista[0];
toArduino[1] = (byte)lista[1];
toArduino[2] = (byte)lista[2];
toArduino[3] = (byte)lista[3];
}
// Event handler for the SHADOW button
public void draw() {
getUserInput(); // Polling the input device
background(255, 255, 240);
fill(0, 0, 255, 32);
noStroke();
text("px: " + px
+"\npy: " + py
+"\npz: " + pz
+"\npw: " + pw
,5,15);
if(myPort != null){
myPort.write(toArduino);
}
}
Arduino:
/*
Serial Event example
When new serial data arrives, this sketch adds it to a String.
When a newline is received, the loop prints the string and clears it.
A good test for this is to try it with a GPS receiver that sends out
NMEA 0183 sentences.
NOTE: The serialEvent() feature is not available on the Leonardo, Micro, or
other ATmega32U4 based boards.
created 9 May 2011
by Tom Igoe
This example code is in the public domain.
http://www.arduino.cc/en/Tutorial/SerialEvent
*/
String inputString = ""; // a String to hold incoming data
bool stringComplete = false; // whether the string is complete
const char TERMINATOR = (char)255;
void setup() {
// initialize serial:
Serial.begin(9600);
// reserve 200 bytes for the inputString:
inputString.reserve(200);
}
void loop() {
// in case serialEvent() isn't called automatically
serialEvent();
// print the string when a newline arrives:
if (stringComplete) {
// process string
uint8_t px = inputString.charAt(0);
uint8_t py = inputString.charAt(1);
uint8_t pz = inputString.charAt(2);
uint8_t pw = inputString.charAt(3);
// TODO: pass this to servos
// debug print
Serial.print("px:");
Serial.print(px);
Serial.print("\tpy:");
Serial.print(py);
Serial.print("\tpz:");
Serial.print(pz);
Serial.print("\tpw:");
Serial.println(pw);
// clear the string:
inputString = "";
stringComplete = false;
}
}
/*
SerialEvent occurs whenever a new data comes in the hardware serial RX. This
routine is run between each time loop() runs, so using delay inside loop can
delay response. Multiple bytes of data may be available.
*/
void serialEvent() {
while (Serial.available()) {
// get the new byte:
char inChar = (char)Serial.read();
// add it to the inputString:
inputString += inChar;
// if the incoming character is a newline, set a flag so the main loop can
// do something about it:
if (inChar == TERMINATOR) {
stringComplete = true;
}
}
}