简体   繁体   English

将数组数据从处理发送到Arduino

[英]Sending array data from Processing to Arduino

I successfully managed to send a single integer from processing to Arduino but now I want to send an array of three integers and I can't get it working. 我成功地将一个整数从处理过程发送到了Arduino,但现在我想发送一个由三个整数组成的数组,但我无法使其正常工作。 I want to create a buzzer feedback with Arduino which processing will control which buzzer to activate. 我想使用Arduino创建蜂鸣器反馈,该处理将控制要激活的蜂鸣器。 For example, the data send from processing should be [1,0,1] meaning sensor 1 and 3 should start working. 例如,从处理发送的数据应为[1,0,1],这意味着传感器1和3应该开始工作。 The buzzers should be able to be activated simultaneously in case that [1,1,1] goes through. 如果[1,1,1]通过,则蜂鸣器应该能够同时被激活。

This is the code I have so far: I am trying to understand what data is being sent back to Arduino to know how to use it and I keep getting either a null value or a random integer. 到目前为止,这是我的代码:我试图了解将哪些数据发送回Arduino以了解如何使用它,并且我一直获取空值或随机整数。

I'm trying to learn how to do this so apologies if the code is bad. 我正在尝试学习如何做到这一点,如果代码不好,那么抱歉。

Arduino Arduino的

void setup(){
  Serial.begin(9600); // Start serial communication at 9600 bps
}

void loop(){
  if (Serial.available()){ 
     const char data = Serial.read();
     char noteBuzzer[] = {data}; 
  for (int i = 0 ; i < sizeof(noteBuzzer); i++) {
  }
   Serial.print(noteBuzzer[1]);
  }
 }

Processing 处理

import processing.serial.*;
String notes[];
String tempo[];
Serial myPort;  
String val;

void setup(){
  size(200,200); 
  String portName = Serial.list()[0]; 
  myPort = new Serial(this, portName, 9600);
  notes = loadStrings("data/notes.txt");
 tempo = loadStrings("data/tempo.txt");
}

 void draw() {
    if (keyPressed == true) 
     {                          
      if (key == '1') {
         println("Start"); 
        readNotes();
      } 
    }
 }

 void readNotes(){
   for (int i = 0 ; i < notes.length; i++) {
   println(notes[i]);
   //println(tempo[i]);
   myPort.write(notes[i]);
   delay(int(tempo[i])); //this will be the tempo? 
    if ( myPort.available() > 0) 
     {  
      val = myPort.readStringUntil('\n');         
       println("Arduino",val); 
     } 
 }

} }

If you're data is an array that always has 3 items and each of those items are always either 1 or 0 (bits), you could store that whole data in a single byte (and still have 5 more bits to spare). 如果您的数据是一个始终包含3个项目的数组,并且每个项目始终为1或0(位),则可以将整个数据存储在一个字节中(还有5个备用位)。 Sending and receiving a byte is pretty simple with Arduino. 使用Arduino发送和接收字节非常简单。

Here's a basic sketch that shows you how to flip 3 bits in a single byte: 这是一个基本草图,向您展示如何在单个字节中翻转3位:

// the state as a byte
byte buzzerState = 0B000;

void setup(){
  textFont(createFont("Courier New",18),18);
}

void draw(){
  background(0);
  text("DEC: " + buzzerState + 
     "\nBIN:" + binary(buzzerState,3),10,40);
}

void keyPressed(){
  if(key == '1'){
    buzzerState = flipBit(buzzerState,0);
  }
  if(key == '2'){
    buzzerState = flipBit(buzzerState,1);
  }
  if(key == '3'){
    buzzerState = flipBit(buzzerState,2);
  }
}

// flips a bit at a given index within a byte and returns updated byte
byte flipBit(byte state,int index){
  int bit = getBitAt(state,index);
  int bitFlipped = 1 - bit;
  return setBitAt(state,index,bitFlipped);
}
// returns the integer value of a bit within a byte at the desired index
int getBitAt(byte b,int index){
  index = constrain(index,0,7);
  return b >> index & 1;
}
// sets an individual bit at a desired index on or off (value) and returns the updated byte
byte setBitAt(byte b,int index, int value){
  index = constrain(index,0,7);
  value = constrain(value,0,1);

  if(value == 1) b |= (1 << (index));
  else           b &= ~(1 << (index));

  return b;
}

Use keys '1','2' and '3' to flip the bits. 使用键“ 1”,“ 2”和“ 3”翻转位。

Note that in keypress we're always updating the same byte. 请注意,在按键操作中,我们总是在更新相同的字节。 The text will display the decimal value first and the binary value bellow. 文本将首先显示十进制值,然后显示二进制值。

处理位设置演示:以二进制和十进制显示字节的前3位

This is the most efficient way to send your data and the simplest in terms of serial communication. 就串行通信而言,这是发送数据的最有效方法,也是最简单的方法。 On the Arduino side you can simply use bitRead() on the byte you get from Serial.read() . 在Arduino方面,您可以简单地在从bitRead()获得的字节上使用bitRead() Serial.read() For more on binary/bits/bytes be sure to read the BitMath Arduino tutorial . 有关二进制/位/字节的更多信息,请务必阅读BitMath Arduino教程 Binary may seem intimidating at first, but it's really not that bad once you practice a bit and it's totally worth knowing. 二进制一开始看上去似乎很吓人,但是一旦您进行了一些练习,它实际上并没有那么糟糕,这完全值得一读。

Here's an updated version of the code above that sends the byte to Arduino on the first available serial port (be sure to change Serial.list()[0] with what makes sense for your setup and press 's' to send an update to Arduino: 这是上面代码的更新版本,该代码将字节发送到第一个可用串行端口上的Arduino(请确保对Serial.list()[0]进行设置有意义的更改,然后按“ s”将更新发送至Arduino的:

import processing.serial.*;

// the state as a byte
byte buzzerState = 0B000;

Serial port;

void setup(){
  textFont(createFont("Courier New",18),18);

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

void draw(){
  background(0);
  text("DEC: " + buzzerState + 
     "\nBIN:" + binary(buzzerState,3),10,40);
}

void keyPressed(){
  if(key == '1'){
    buzzerState = flipBit(buzzerState,0);
  }
  if(key == '2'){
    buzzerState = flipBit(buzzerState,1);
  }
  if(key == '3'){
    buzzerState = flipBit(buzzerState,2);
  }
  if(key == 's'){
    if(port != null){
      port.write(buzzerState);
    }else{
      println("serial port is not open: check port name and cable connection");
    }
  }
}

// flips a bit at a given index within a byte and returns updated byte
byte flipBit(byte state,int index){
  int bit = getBitAt(state,index);
  int bitFlipped = 1 - bit;
  return setBitAt(state,index,bitFlipped);
}
// returns the integer value of a bit within a byte at the desired index
int getBitAt(byte b,int index){
  index = constrain(index,0,7);
  return b >> index & 1;
}
// sets an individual bit at a desired index on or off (value) and returns the updated byte
byte setBitAt(byte b,int index, int value){
  index = constrain(index,0,7);
  value = constrain(value,0,1);

  if(value == 1) b |= (1 << (index));
  else           b &= ~(1 << (index));

  return b;
}

And here's a super basic Arduino sketch: 这是一个超级基本的Arduino草图:

byte buzzerState;

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

  //test LEDs setup
  pinMode(10,OUTPUT);
  pinMode(11,OUTPUT);
  pinMode(12,OUTPUT);
}

void loop() {
  if(Serial.available() > 0){
    buzzerState = Serial.read();

    bool bit0   = bitRead(buzzerState,0);
    bool bit1   = bitRead(buzzerState,1);
    bool bit2   = bitRead(buzzerState,2);

    //test LEDs update
    digitalWrite(10,bit0);
    digitalWrite(11,bit1);
    digitalWrite(12,bit2);

  }  
}

If you connect 3 LEDs to pins 10,11,12 you should them toggle as you press keys '1','2','3' then 's' in Processing 如果将3个LED连接到引脚10、11、12,则在按“ 1”,“ 2”,“ 3”然后在处理中按“ s”时,它们应该切换

One way around binary in Processing could be using a String representation of your data (eg "00000101" for [1,0,1] ) and unbinary() to convert that String to an integer value you can write to serial, but it will be a bit annoying to getting and setting a character at an index (and potentially parsing that char to it's integer value and back) 处理中二进制的一种方法是使用数据的字符串表示形式(例如[1,0,1] "00000101" )和unbinary()字符串转换为可以写入串行的整数值,但是它将在索引处获取并设置一个字符会有些烦人(并可能将该char解析为它的整数值并返回)

When you need to send more than a byte things get a bit more complicated as you need to handle data corruption/interruptions, etc. In these situations it's best to setup/design a communication protocol based on your needs and this isn't easy if you're just getting started with Arduino, but not impossible either. 当您需要发送多于一个字节的数据时,事情会变得更加复杂,因为您需要处理数据损坏/中断等问题。在这种情况下,最好根据您的需求来设置/设计通信协议,如果您才刚刚开始使用Arduino,但也不是没有。 Here 's an example, there are many more online. 是一个示例,在线上还有更多。

One quick and dirty thing you could try is sending that data as string terminated by a new line character ( \\n ) which you could buffer until in Arduino then read 4 bytes at a time, discarding the \\n when parsing: 您可以尝试的一种快速而又肮脏的事情是,将数据作为字符串发送,并以换行符( \\n )终止,您可以对其进行缓冲,直到在Arduino中读取一次,然后一次读取4个字节,在解析时会丢弃\\n

eg sending "101\\n" from Processing, representing [1,0,1] then on the Arduino side use Serial.readStringUntil('\\n') and a combination of charAt() and toInt() to access each integer within that that string. 例如,从Processing发送“ 101 \\ n”,代表[1,0,1],然后在Arduino端使用Serial.readStringUntil('\\n')以及charAt()toInt()来访问其中的每个整数该字符串。

Here's an example Processing sketch: 这是一个示例处理草图:

import processing.serial.*;

// the state as a byte
String buzzerState = "010\n";

Serial port;

void setup(){
  textFont(createFont("Courier New",18),18);

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

}

void draw(){
  background(0);
  text(buzzerState,30,50);
}

void keyPressed(){
  if(key == '1'){
    buzzerState = flipBit(buzzerState,0);
  }
  if(key == '2'){
    buzzerState = flipBit(buzzerState,1);
  }
  if(key == '3'){
    buzzerState = flipBit(buzzerState,2);
  }
  if(key == 's'){
    if(port != null){
      port.write(buzzerState);

    }else{
      println("serial port is not open: check port name and cable connection");
    }
  }
}

String flipBit(String state,int index){
  index = constrain(index,0,2);
  // parse integer from string
  int bitAtIndex = Integer.parseInt(state.substring(index,index+1));
  // return new string concatenating the prefix (if any), the flipped bit (1 - bit) and the suffix
  return state = (index > 0 ? state.substring(0,index) : "") + (1 - bitAtIndex) + state.substring(index+1);
}

And an Arduino one based on Arduino > File > Examples > 04.Communication > SerialEvent : 还有一个基于Arduino>文件>示例> 04.Communication> SerialEvent的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.

 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
boolean stringComplete = false;  // whether the string is complete

void setup() {
  // initialize serial:
  Serial.begin(9600);
  // reserve 200 bytes for the inputString:
  inputString.reserve(200);

  // test LEDs setup
  pinMode(10,OUTPUT);
  pinMode(11,OUTPUT);
  pinMode(12,OUTPUT);
}

void loop() {
  // print the string when a newline arrives:
  if (stringComplete) {
    Serial.println(inputString);
    // process string
    bool bit0   = inputString.charAt(2) == '1';
    bool bit1   = inputString.charAt(1) == '1';
    bool bit2   = inputString.charAt(0) == '1';

    //test LEDs update
    digitalWrite(10,bit0);
    digitalWrite(11,bit1);
    digitalWrite(12,bit2);


    // 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 == '\n') {
      stringComplete = true;
    }
  }
}

Note this is more prone to error and used 4 times as much data as the the single byte option. 请注意,这更容易出错,并且使用的数据量是单字节选项的4倍。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM