Отправка данных массива из Обработки в Arduino - PullRequest
0 голосов
/ 28 ноября 2018

Мне удалось отправить одно целое число из обработки в 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 голосов
/ 02 декабря 2018

Если ваши данные - это массив, в котором всегда имеет 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 вы можете просто использовать bitRead() в байте, который вы получаете от Serial.read().Для получения дополнительной информации о двоичных файлах / битах / байтах обязательно прочитайте учебник по BitMath 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;
}

А вот супер базовый эскиз 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 светодиода к контактам 10,11,12, вы должны переключать их при нажатии клавиш.1 ',' 2 ',' 3 'then' s 'в обработке

Одним из способов обработки двоичного кода в обработке может быть использование строкового представления ваших данных (например, "00000101" для [1,0,1]) и unbinary() для преобразования этого String в целочисленное значение, которое вы можете записать в последовательный порт, но это будет немного раздражать при получении и установке символа в индексе (и, возможно, при анализе этого символа вэто целочисленное значение и обратно)

Когда вам нужно отправить больше байта, все становится немного сложнее, так как вам нужно обрабатывать повреждение / прерывание данных и т. д. В этих ситуациях лучше всего настроить / спроектировать коммуникациюпrotocol основан на ваших потребностях, и это непросто, если вы только начинаете работать с Arduino, но и не невозможно. Вот пример , есть еще много онлайн.

Одна быстрая и грязная вещь, которую вы можете попробовать, это отправить эти данные в виде строки, оканчивающейся символом новой строки (\n), которыйВы можете буферизовать до Arduino, затем читать 4 байта за раз, отбрасывая \n при разборе:

, например, посылая «101 \ n» из Processing, представляя [1,0,1], затем в Arduinoсторона использует Serial.readStringUntil('\n') и комбинацию charAt() и toInt() для доступа к каждому целому числу в этой строке.

Вотпример Эскиз обработки:

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

и Arduino на основе Arduino> Файл> Примеры> 04.Communication> SerialEvent :

/*
  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;
    }
  }
}

Примечание это более подвержено ошибкам и использует в 4 раза больше данных, чем опция одиночного байта.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...