Arduino и обработка вызова и ответа не работает

Я пытался разработать соединение от arduino IDE к обработке, чтобы я мог отправлять данные, измеренные на выводах arduino, в обработку для отображения.

Сначала я упаковал 10-битные целые числа, которые я получал от arduino, в символы, каждый со своим собственным байтом. Например, 1023 было 10-битным целым числом, которое я упаковал в 4 8-битных символа: 1, 0, 2 и 3. Затем они могли быть отправлены через последовательный порт и восстановлены на другом конце путем обработки.

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

Я использовал пример кода, приведенный на сайте arduino, который прекрасно работает сам по себе. Но когда я пытаюсь внедрить в него упаковку символов, он перестает работать. Выход в обработке всегда пропускает первую пару символов.

Более того, я удалил myPort.print('A') из кода обработки, и arduino все еще многократно отправлял данные, несмотря на то, что обработка не отправляла ответ обратно.

Это неопределенный вопрос, но где я ошибся при реализации упаковочного кода? и почему arduino продолжает посылать данные независимо от того, отвечает ли обработка?

Большое спасибо

===================================

Код Arduino:

int inByte = 0;

//void establishContact();

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  establishContact();
}

void loop() {
  // put your main code here, to run repeatedly:

  if (Serial.available() > 0) {
    // get incoming byte:
    //inByte = Serial.read();

      int MzValue = analogRead(A0);
      int FzValue = analogRead(A1);
      int FyValue = analogRead(A2);


      char Mz_Str[10];
      char Fz_Str[10];
      char Fy_Str[10];

      sprintf(Mz_Str, "%d", MzValue);
      sprintf(Fz_Str, "%d", FzValue);
      sprintf(Fy_Str, "%d", FyValue);
      // Now str contains the integer as characters

      Serial.write(Mz_Str);
      Serial.write(",");
      Serial.write(Fz_Str);
      Serial.write(",");
      Serial.write(Fy_Str);
      Serial.write(",");
      Serial.write("\n");

      delay(20);
  } 
  else {
    delay(20);
  }
}

void establishContact() {
  while (Serial.available() <= 0) {
    Serial.print('A');   // send a capital A
    delay(1000);
  }
}

=================================== Код обработки:

import processing.serial.*;

  Serial myPort;                       // The serial port
  boolean firstContact = false;        // Whether we've heard from the microcontroller
  String val;     // Data received from the serial port
  int numValues = 3;
  float[] values = new float[numValues];
  int inByte = 0;

  void setup() {
    size(256, 256);  // Stage size
    noStroke();      // No border on the next thing drawn

    // Print a list of the serial ports for debugging purposes
    // if using Processing 2.1 or later, use Serial.printArray()
    println(Serial.list());

    // I know that the first port in the serial list on my Mac is always my FTDI
    // adaptor, so I open Serial.list()[0].
    // On Windows machines, this generally opens COM1.
    // Open whatever port is the one you're using.
    String portName = Serial.list()[0];
    myPort = new Serial(this, portName, 9600);
  }

  void draw() {
    // read a byte from the serial port:
    if ( myPort.available() > 0) {
    inByte = myPort.read();
    }
    //print(inByte);
    // if this is the first byte received, and it's an A, clear the serial
    // buffer and note that you've had first contact from the microcontroller.
    // Otherwise, add the incoming byte to the array:
    if (firstContact == false) {
      if (inByte == 'A') {
        myPort.clear();          // clear the serial port buffer
        firstContact = true;     // you've had first contact from the microcontroller
        myPort.write('A');       // ask for more
        println(inByte);
      }
    }
    else {
        val = myPort.readStringUntil('\n');         // read it and store it in val
        println(val); //print it out in the console
        values = float(splitTokens(val, ","));

        myPort.write('A');
        delay(20);
      }
    }

, 👍1

Обсуждение

Serial.print(MzValue); сделает то же самое, что и ваша "упаковка символов", @Juraj

вы не читаете доступный символ, поэтому он остается доступным, @Juraj

Processing + Firmata также является потенциальным решением., @Dave Newton


1 ответ


1

Почему бы просто не отправить все данные сразу, в списке, разделенном запятыми, с символом \n в качестве разделителя "конец сообщения"?

Вот 2 тестовых скетча. Скетч Arduino отправляет значения от A0 до A2 в последовательный режим каждые 500 мс, а скетч обработки отображает полученные данные. Анализ полученных данных в целочисленный массив-это скорее вопрос Java, а не Arduino, поэтому я оставлю это на ваше усмотрение.

Ардуино

// Отправляйте значения A0, A1 и A3
// на последовательный каждые 500 мс.
// 2416 байт.
char data[20];
char buffer[6];

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

void loop(){
  itoa(analogRead(A0), buffer, 10);
  strcat(data, buffer);
  strcat(data, ",");
  itoa(analogRead(A1), buffer, 10);
  strcat(data, buffer);
  strcat(data, ",");
  itoa(analogRead(A2), buffer, 10);
  strcat(data, buffer);
  strcat(data, "\n");
  Serial.write(data);
  memset(data, 0, sizeof(data));
  delay(500);
}

Обработка

// Отображение данных, полученных из последовательного порта, отправляемых через
// 500 мс от Arduino. Значения, отправленные из A0, A1
// и A2, были отправлены вместе в виде запятых
// разделенный список, за которым следует символ \n.
import processing.serial.*;
import java.awt.TextArea;
Serial myPort;
TextArea myTextArea;
String input;

void setup(){

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

  myTextArea = new TextArea("", 23, 49, 1);
  this.add(myTextArea);

  size(500, 380);

}

void draw(){

  if(myPort.available() > 0){
    input = myPort.readStringUntil('\n');
    myTextArea.append(input);
  }

}

Обновление

Как упоминает Юрай в своих комментариях, я мог бы просто использовать Serial.print() 6 раз вместо массивов символов. Вот второй скетч Arduino, который использует Serial.print(). Прежде чем использовать его, имейте в виду, что его размер компиляции на 288 байт больше, чем метод массива символов. Представьте себе это :)

// Отправляйте значения A0, A1 и A3
// на последовательный каждые 500 мс.
// 2704 байта.
void setup(){
  Serial.begin(9600);
}

void loop(){
  Serial.print(analogRead(A0));
  Serial.print(",");
  Serial.print(analogRead(A1));
  Serial.print(",");
  Serial.print(analogRead(A2));
  Serial.print("\n");
  delay(500);
}
,

Почему бы не "распечатать" данные в Serial как " Serial.print(analogRead(A0)); Serial.print(',');`...?, @Juraj

@Juraj, это тоже сработало бы :), @VE7JRO

это будет 6 простых строк. никаких буферов, никаких функций языка C. и почему снова мемсет?, @Juraj

вам нужно только buffer[0] = 0; в начале цикла, чтобы "очистить" строку, @Juraj

Я знаю. Мне нравится использовать memset() для установки всего массива в 0. Как насчет этого: memset(данные, 0, 1); Это приводит к тому же размеру компиляции, что и буфер[0] = 0; и делает то же самое. Конечно, никто не заставляет вас использовать " memset()`., @VE7JRO