Это немного сбивает с толку то, что вы пытаетесь сделать, но из того, что я могу понять, путаница связана с последовательной связью.
вот как я понимаю, как связь работает с вашим текущим кодом и несколько проблем с этим:
1. Усечение
Вы пишете px
, который сопоставлен с размерами эскиза (который я нигде не вижу, поэтому думаю, что это значение по умолчанию 100x100?).
Если размеры больше 255, это может быть проблемой.
Даже при обработке Serial write (int) принимает int, за кулисами он использует jss c .Serial.writeInt () , который принимает значение из От 0 до 255. (По сути, он записывает один байт, но в диапазоне 0-255, где в качестве типа byte
в обработке java от -127 до 128).
Если вы хотите отправить значения больше 255, вам нужно разделить их на отдельные байты. (см. пример разделения значения ARGB с использованием сдвига битов и маскировки И и использованием ИЛИ , чтобы объединить отдельные байты в многобайтовое целое число)
2 , Повторение
px
отправляется снова в течение для l oop: myPort.write(lista[i]);
Код все равно комментируется, но об этом следует помнить. Лично я делаю новые простые тестовые зарисовки, решающие отдельные простые задачи вместо больших неиспользуемых блоков, которые затрудняют чтение / навигацию и в конечном итоге отладку кода. Я призываю вас разбить большую проблему на несколько более простых одиночных задач и решать по одной за раз.
3. Завершение данных
Закомментированный код пытается отправить 4 целых числа, но Arduino не может узнать, в каком порядке поступают данные. Если что-то пойдет не так, очень сложно определить порядок.
Существует несколько способов сделать это. В идеале вы должны написать протокол связи. (и есть много ресурсов по этой теме c.)
Звучит как забавный проект, чтобы узнать о работе с битами / байтами / байтовыми массивами и составлении протокола связи из позаботьтесь о какой-либо форме проверки данных (контрольная сумма / CR C / et c.)
Если у вас мало времени и вы просто хотите управлять сервоприводом, не слишком заботясь о надежной отправке нескольких (потенциально) большие значения по сравнению с последовательным интерфейсом. Я рекомендую попробовать Firmata Processing
. Вам понадобится прошить sh прошивку Firmata на Arduino, а затем использовать библиотеку Firmata Processing для подключения к последовательному порту. (с правильной скоростью передачи) и, если требуется, наберите arduino.servoWrite()
. См. Также пример библиотеки arduino_servo
.
Исходя из вашего комментария к отображенным значениям в диапазоне от 0 до> 100, вы можете использовать перенаправление примера SerialEvent , используя любой другой символ> 100, чтобы дифференцировать данные из строкового терминатора char. Не забывайте, что вы потеряете точность:
getValue()
возвращает float
с 32-битной точностью - Теоретически вы можете использовать ту же технику с 0-254 (используя 255 в качестве символа-терминатора). Диапазон 0-100 использует 6 битов
Вот примерный пример того, как может выглядеть код, учитывая, что код не был протестирован на реальных устройствах:
Обработка:
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:
/ * Пример последовательного события
Когда поступают новые последовательные данные, этот эскиз добавляет их в строку. При получении новой строки l oop печатает строку и очищает ее.
Хороший тест для этого - попробовать его с приемником GPS, который отправляет предложения NMEA 0183.
ПРИМЕЧАНИЕ. Функция serialEvent () недоступна на платах на базе Leonardo, Micro или других платах на базе ATmega32U4.
, созданный 9 мая 2011 года Томом Айго
Этот пример кода находится в публикации c домен.
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;
}
}
}