Получите 3 значения от обработки до Arduino
У меня есть программа отслеживания цвета в обработке, которая работает с Kinect. Когда я щелкаю где-нибудь на картинке, он сохраняет этот цвет и рисует вокруг него эллипс. Я просто хочу отправить 3 значения типа int (одно для красного, зеленого и синего) через myPort.write() в Arduino и сохранить эти 3 значения в Arduino в 2 переменных. Моя цель состоит в том, чтобы зажечь красный светодиод, если красная переменная самая высокая, и зеленый светодиод, если зеленый самый высокий, и так далее.
Я пробовал несколько примеров, которые я нашел, когда гуглил, но ничего не работает. Я не знаю, как Arduino должен получить правильные значения в переменных!
РЕДАКТИРОВАТЬ: Здесь у вас есть мой код обработки. Я склеил его из нескольких других уроков, пока чуть не заплакал.
import processing.serial.*;
Serial myPort;
import SimpleOpenNI.*;
SimpleOpenNI kinect;
// Frame
PImage currentFrame;
color trackColor;
int r1, g1, b1, r2, g2, b2;
void setup()
{
size(640, 480);
String portName = Serial.list()[0]; //change the 0 to a 1 or 2 etc. to match your port
myPort = new Serial(this, portName, 9600);
kinect = new SimpleOpenNI(this);
kinect.enableRGB();
trackColor = color (255, 0, 0);
smooth ();
currentFrame = createImage (640, 480, RGB);
}
void draw()
{
kinect.update();
currentFrame = kinect.rgbImage ();
image(currentFrame, 0, 0);
currentFrame.loadPixels();
// Before we begin searching, the "world record" for closest color is set to a high number that is easy for the first pixel to beat.
float worldRecord = 500;
// XY coordinate of closest color
int closestX = 0;
int closestY = 0;
// Begin loop to walk through every pixel
for (int x = 0; x < currentFrame.width; x ++ ) {
for (int y = 0; y < currentFrame.height; y ++ ) {
int loc = x + y*currentFrame.width;
// What is current color
color currentColor = currentFrame.pixels[loc];
r1 = (int)red(currentColor);
g1 = (int)green(currentColor);
b1 = (int)blue(currentColor);
r2 = (int)red(trackColor);
g2 = (int)green(trackColor);
b2 = (int)blue(trackColor);
// Using euclidean distance to compare colors
float d = dist(r1, g1, b1, r2, g2, b2); // We are using the dist( ) function to compare the current color with the color we are tracking.
// If current color is more similar to tracked color than
// closest color, save current location and current difference
if (d < worldRecord) {
worldRecord = d;
closestX = x;
closestY = y;
}
}
}
// We only consider the color found if its color distance is less than 10.
// This threshold of 10 is arbitrary and you can adjust this number depending on how accurate you require the tracking to be.
if (worldRecord < 10) {
// Draw a circle at the tracked pixel
fill(trackColor);
strokeWeight(4.0);
stroke(0);
ellipse(closestX, closestY, 30, 30);
}
if (mousePressed == true) {
color c = get(mouseX, mouseY);
//println("r: " + red(c) + " g: " + green(c) + " b: " + blue(c));
// Save color where the mouse is clicked in trackColor variable
int loc = mouseX + mouseY*(currentFrame.width);
trackColor = currentFrame.pixels[loc];
println("red " + r2);
println("green " + g2);
println("blue " + b2);
int colors[] = {r2, g2, b2};
for(int i=0; i < 3; i++) {
myPort.write(colors[i]);
}
}
println("ClosestX " + closestX);
myPort.write(closestX);
}
И мой код Arduino, где я не знаю, как получить несколько значений.
int val;
int ledPin = 13;
int freq;
int piezoPin = 9;
int redLED = 3;
int greenLED = 5;
int blueLED = 7;
int red, green, blue;
void setup() {
pinMode(ledPin, OUTPUT); // Set pin as OUTPUT
Serial.begin(9600); // Start serial communication at 9600 bps
digitalWrite(ledPin, LOW);
}
void loop() {
if (Serial.available() > 0)
{ // If data is available to read,
val = Serial.read(); // read it and store it in val
}
if(red > green && red > blue) {
digitalWrite(redLED, HIGH); //light Red LED
}
if(green > red && green > blue) {
digitalWrite(greenLED, HIGH); //light Red LED
}
if(blue > red && blue > green) {
digitalWrite(blueLED, HIGH); //light Red LED
}
//Piezo buzzing higher when X-Position of tracked color is higher.
if (val < 100) {
freq = 50;
}
else if (val < 200) {
freq = 200;
}
else if (val < 300) {
freq = 400;
}
else if (val < 400) {
freq = 600;
}
else if (val < 500) {
freq = 800;
}
else (freq = 1000);
tone(piezoPin, freq);
}
EDIT2: Да, помимо зажигания светодиодов, я также хочу получить звук от пьезо-зуммера, но это работает довольно хорошо, так что никаких вопросов по этому поводу... пока нет.
Помогите, пожалуйста!!
1 ответ
Последовательная связь с вашим Arduino работает с одним байтом за раз. По счастливой случайности, три компонента Обрабатывающего Цвета также составляют три байта.
- Один для красных (0-255)
- Один для зеленых (0-255)
- Один для синего (0-255)
Теперь все, что нам нужно, это немного больше информации, чтобы мы могли держать их отдельно.
Поскольку минимальные и максимальные значения байта равны 0-255, мы не можем использовать безопасный символ для отслеживания трех разных байтов, поэтому нам нужен способ выяснить, где отправляемая нами информация начинается и заканчивается.
Простой способ сделать это - установить заголовок и нижний колонтитул для ваших сообщений; что-то вроде:
<color>[byte (red)][byte (green)][byte (blue)]</color>
Если мы собираемся читать и расшифровывать сообщения, отформатированные таким образом, нам понадобится небольшой буфер, в котором будут храниться значения, которые мы получаем от обработки, поэтому мы можем прочитать их обратно и посмотреть, можем ли мы соответствовать формату сообщения.
Итак, на стороне Arduino нам нужно это:
String buffer = "";
String messageBegin = "<color>";
String messageEnd = "</color>";
//we read our serial data in the SerialEvent() function
//this is called *after* a loop(), and only if there is serial data in the buffer.
void serialEvent()
{
while(Serial.available())
{
buffer += (char)Serial.read();
}
}
void loop()
{
//now, inside loop, we no longer need to worry about gathering data from serial.
//we do still need to figure out if our message is complete, and then parse it.
//if our buffer contains both the beginning and the end of a message
//in the right order.
int beginIndex = buffer.lastIndexOf(messageBegin);
int endIndex = buffer.lastIndexOf(messageEnd);
if(beginIndex != -1 && endIndex != -1 && beginIndex < endIndex)
{
//we have a complete message!
//our red color starts 7 characters after where the message begins,
//because our "messageBegin" is 7 characters long
string lastMessage = buffer.substring(beginIndex+7);
//this is arguably not the prettiest way to get our byte values back.
//see if you can do better for bonus points!
byte messageAsBytes[80];
lastMessage.getBytes(messageAsBytes, messageAsBytes.length());
//we can now finally reconstruct the value we had from processing!
byte r = (byte)messageAsBytes[0];
byte g = (byte)messageAsBytes[1];
byte b = (byte)messageAsBytes[2];
//if we get a complete message, we can clear our buffer. (don't forget to do this!)
buffer = "";
}
}
На стороне обработки все, что нам нужно сделать, это убедиться, что наши messagebegin и messageend отправлены вместе для поездки:
myPort.write("<color">);
for(int i=0; i < 3; i++) {
myPort.write(colors[i]);
}
myPort.write("</color">);