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

时间:2018-11-28 03:53:07

标签: arduino processing serial-communication

我成功地将一个整数从处理过程发送到Arduino,但现在我想发送一个由三个整数组成的数组,但我无法使其正常工作。我想使用Arduino创建蜂鸣器反馈,该处理将控制要激活的蜂鸣器。例如,从处理发送的数据应为[1,0,1],这意味着传感器1和3应该开始工作。如果[1,1,1]通过,蜂鸣器应该能够同时启动。

这是我到目前为止的代码: 我试图了解将什么数据发送回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]);
  }
 }

正在处理

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); 
     } 
 }

}

1 个答案:

答案 0 :(得分:0)

如果您的数据是一个总是的数组,且该数组始终包含3个项目,并且每个项目始终为1或0(位),则可以将整个数据存储在一个字节中(并且还有5位备用)。使用Arduino发送和接收字节非常简单。

下面是一个基本草图,向您展示了如何在单个字节中翻转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;
}

使用键“ 1”,“ 2”和“ 3”翻转位。

请注意,在按键操作中,我们总是在更新相同的字节。 文本将首先显示十进制值,然后显示二进制值。

Processing bit set demo: displaying the first 3 bits in a byte in binary and decimal

这是发送数据的最有效方法,并且是串行通信中最简单的方法。在Arduino方面,您只需在从Serial.read()获得的字节上使用bitRead()。有关二进制/位/字节的更多信息,请确保阅读BitMath Arduino tutorial。二进制一开始看上去似乎很吓人,但是一旦您进行了一些练习,它实际上并没有那么糟糕,这完全值得一读。

这是上面代码的更新版本,该代码将字节发送到第一个可用串行端口上的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;
}

这是一个超级基本的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);

  }  
}

如果将3个LED连接到引脚10、11、12,则应在按“ 1”,“ 2”,“ 3”然后在处理时按“ s”的同时切换它们。

处理二进制文件的一种方法是使用数据的字符串表示形式(例如"00000101"代表[1,0,1])和unbinary()String转换为整数值您可以写序列号,但是在索引处获取并设置一个字符会有点烦(并且有可能将该char解析为它的整数值并返回)

当您需要发送多于一个字节的数据时,事情会变得更加复杂,因为您需要处理数据损坏/中断等。在这种情况下,最好根据您的需求来设置/设计通信协议,而这是'如果您刚开始使用Arduino,这很容易,但也不是没有。 Here是一个例子,在线上还有更多。

您可以尝试的一种快速而又肮脏的事情是将数据作为字符串发送,并以新行字符(\n终止,可以将其缓冲直到在Arduino中然后一次读取4个字节,并丢弃{{1 }}解析时:

例如从Processing发送“ 101 \ n”,代表[1,0,1],然后在Arduino端使用Serial.readStringUntil('\n')以及charAt()toInt()的组合来访问其中的每个整数字符串。

这是一个示例处理草图:

\n

还有一个基于 Arduino>文件>示例> 04.Communication> SerialEvent 的Arduino:

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);
}

注意,这更容易出错,并且使用的数据量是单字节选项的4倍。