Jetson TX2, Arduino Uno Последовательная связь - PullRequest
0 голосов
/ 05 марта 2019

Я использую Jetson TX2 и Arduino Uno, чтобы попытаться установить связь через последовательный порт USB. Предполагается, что я использую Arduino для связи с некоторыми лазерными датчиками ToF и Thermopile.

Jetson использует Ubuntu 16.04 для совместимости с ros, поскольку в конечном итоге он будет связан с узлом ros

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

Arduino печатает байту "9" в Jetson, когда он готов к приему, и Jetson печатает "1"или" 2 "по серийному номеру, когда он хочет получить данные о времени полета или датчике температуры соответственно.

Предполагается, что Jetson получит 5 запятых, значения с плавающей запятой от датчиков ToF, затемна 64 значения с плавающей запятой от термодатчика, однако я получаю следующее:

Se1 для данных ToF

Чтение данных

1 байт считано, буфер содержит:

Отправка 2 для тепловых данных

Чтение данных

35 байт считано, буфер содержит: Данные датчика температуры / ToF

Код для Arduino следующий:

#include <Wire.h>
#include <VL53L1X.h>
#include <Adafruit_AMG88xx.h>



#define SensorNum 5 // Change number if you have less sensors, just be aware that the digital pins count down, so you may need to move the starting pin number up from pin 6
#define DEBUG 0 // Change to one if you want additional debugging information printed to the serial out.
#define SFX 0  // Set to 0 if you don't want to hear the set-up pips when the ToF sensors are being configured
#define Wait_For_Read 1 // Determines if the Arduino waits for a bit to be sent by Jetson before sending sensor data


VL53L1X sensors[SensorNum];

Adafruit_AMG88xx amg;

float pixels[AMG88xx_PIXEL_ARRAY_SIZE]; // Pixel array size is 64, as it is an 8x8 thermopile array
int M_pixels[8][8];

/* Change these values below to alter what the bands the temperature is classified as
 *  these values are output into a 8x8 array with numbers of 0 to 5, with temperatures below the lower threshold being 0
 *  this is done because its a lot easier to read at a glance a small array of numbers and it's easy to visualise where the heat is compared to the 8x8 of floating numbers
 *  the values are in degrees celsius
 */

float LowerThresh = 25.0; 
float LowerMidThresh = 27.5;
float MidThresh = 30.0; 
float UpperMidThresh = 32.5;
float UpperThresh = 35.0; 
int speakerpin = 10; // digital pin for the piezo to output small pips for user convinience, if SFX is diabled this pin is not used and can be reassigned.


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

  if (SFX){
  pinMode(speakerpin, OUTPUT);
  PlayTone(5, 2, 250); // Plays a small pip to let user know arduino is running, plays 5 rapid pips
  }

  Wire.begin();
  delay(500);
  Serial.println("Setting up sensors");
  Serial.println("Beginning VL53L1X ToF sensor set-up");
  ToF_Setup();
  Serial.println("Beginning AMG8833 Thermal sensor set-up");
  Thermal_Setup();
  Serial.println("Sensors initialised");

Serial.println ("Scanning I2C addresses"); // Outputs address to serial, addressess 0x28, 0x2A, 0x2C, 0x2E, 0x30, and 0x69 should be seen
  int count = 0;

  for (int i = 1; i < 120; i++)
  {

    Wire.beginTransmission (i);
    if (Wire.endTransmission () == 0)
    {
      Serial.print ("Found address: ");
      Serial.print (i, DEC);
      Serial.print (" (0x");
      Serial.print (i, HEX);
      Serial.println (")");
      count++;
      delay (1);
    }
  } 
  Serial.print ("Found ");
  Serial.print (count, DEC);
  Serial.println (" device(s).");
  byte rdy = 9;

  Serial.println(rdy);

}

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


  byte output = 0;
  if (Wait_For_Read){

    if (Serial.available()){
      output = Serial.read();
    }

  }
  else output = 49;

 // Serial.println(output);
  if(output == 49){
    ToF_Read();


  }
  if(output == 50){

    Thermal_Read();

  }
  if (DEBUG) {

    ToF_Read_Debug();
    Thermal_Read_Debug();
    delay(1000); // delay to allow reading in arduino serial monitor

  }
  Serial.flush();
  delay(100);
}

void ToF_Setup(){

int address = 0x28; // first address that the first sensor will be set to

for (int i = 6; i > 1; i--){ // sets up pins 6 to 2, for the XSHUT pin on VL53L1X to allow for address change

  pinMode(i, OUTPUT);
  digitalWrite(i, LOW);
  delay(100);

}

Wire.begin();

for (int j = 0; j < SensorNum; j++){

      if (DEBUG){
      Serial.print("Pin: ");
      Serial.println(6 - j);
      Serial.print("Current address: ");
      Serial.println(address, HEX);
      }
      if (SFX) PlayTone(j+1, 6, 500);  // plays pips according to which sensor is being set-up, 1 pip for sensor 1, 2 pips for sensor 2, etc..

      pinMode(6 - j, INPUT); 
      delay(150);
      sensors[j].init(true);
      delay(100);
      sensors[j].setAddress(address);
      Serial.print("Sensor: ");
      Serial.print(j+1);
      Serial.println(" address set.");

      address += 2;
      delay(200);

      sensors[j].setDistanceMode(VL53L1X::Long);
      sensors[j].setMeasurementTimingBudget(50000);
      sensors[j].startContinuous(50);
      sensors[j].setTimeout(100);
    }

  delay(150);
  Serial.println("ToF's initialised");

}

void Thermal_Setup(){

  Serial.println(F("AMG88xx pixels"));
  Serial.println(AMG88xx_PIXEL_ARRAY_SIZE);

  bool status;

    // default settings
    status = amg.begin();
    if (!status) {
        Serial.println("Could not find a valid AMG88xx sensor, check wiring!");
        while (1);
    }

    Serial.println("Thermal sensor initialised");

    Serial.println();

    delay(100); // let sensor boot up


}

void ToF_Read(){

  for (int i = 0; i < SensorNum; i++){
    if(i == (SensorNum-1)){
      Serial.println(sensors[i].read()/1000.0, 4); // converts mm reading to meter, 4 signicant figures
    }
    else{
      Serial.print(sensors[i].read()/1000.0, 4); // converts mm reading to meter, 4 signicant figures
      Serial.print(",");
    }
    if (sensors[i].timeoutOccurred()) { 
      Serial.print("8000"); 
      Serial.print(",");
    }
  }

}

void Thermal_Read(){

  amg.readPixels(pixels);

  for (int i = 1; i <= AMG88xx_PIXEL_ARRAY_SIZE; i++) {
    if(i == (AMG88xx_PIXEL_ARRAY_SIZE)){
      Serial.println(pixels[i - 1]);
    }
    else{
      Serial.print(pixels[i - 1]);
    }
    if (i < AMG88xx_PIXEL_ARRAY_SIZE) Serial.print(",");
  }

}

void PlayTone(int repetition, int duration, int hold){
  for (int j = 0; j < repetition; j++){
    for (long i = 0; i < duration * 1000 ; i += 600){
     digitalWrite(speakerpin, HIGH);
     delayMicroseconds(1915);
     digitalWrite(speakerpin, LOW);
     delayMicroseconds(1915);
    }
    delay(hold);
   }
}

void check_pixels() {
  int row;
  int col;
  int val;
  // clear all previous pixels for next refresh
  for (int j = 0; j < 8; j++) {
    for  (int h = 0; h < 8; h++) {
      M_pixels[j][h] = 0;
    }
  }
  // if a pixel is above the temp threshold set to high
  for (int i = 0; i < AMG88xx_PIXEL_ARRAY_SIZE; i++) {

    row = round(i / 8);
    if (i % 8 == 0) {
      col = 0;
    }
    else
    {
      col = i % 8;
    }
    if (DEBUG) {
//    Serial.print(row);
//     Serial.print(',');
//    Serial.println(col);
    }
    if (pixels[i] >= UpperThresh) {
      val = 5;
    }
    else if (pixels[i] >= UpperMidThresh) {
      val = 4;
    }
    else if (pixels[i] >= MidThresh) {
      val = 3;
    }
    else if (pixels[i] >= LowerMidThresh) {
      val = 2;
    }
    else if (pixels[i] >= LowerThresh) {
      val = 1;
    }
    else {
      val = 0;
    }
    if (DEBUG) {
     Serial.print(i);
     Serial.print(',');
     Serial.print(pixels[i]);
     Serial.print(',');
     Serial.println(val);

    }
    M_pixels[row][col] = val;
  }
  if (DEBUG) { pixels_debug();}

  //This will print out all the pixels that should be turned on to
  //movesensor();
}


void pixels_debug() {

  for (int i = 0; i < 8; i++) {
    for  (int j = 0; j < 8; j++) {
      Serial.print(M_pixels[i][j]);
      Serial.print(',');
    }
    Serial.println(' ');
  }
}

void ToF_Read_Debug(){

  for (int i = 0; i < SensorNum; i++){
  Serial.print("Sensor ");
  Serial.print(i+1);
  Serial.print(": ");
  Serial.print(sensors[i].read());
  if (sensors[i].timeoutOccurred()) { Serial.print(" TIMEOUT"); }
  Serial.println();
  }

}

void Thermal_Read_Debug(){

  amg.readPixels(pixels);

  Serial.print("[");
  for (int i = 1; i <= AMG88xx_PIXEL_ARRAY_SIZE; i++) { 
    Serial.print(pixels[i - 1]);
    Serial.print(", ");
    if ( i % 8 == 0 ) Serial.println();
  }
  Serial.println("]");
  Serial.println();

  if (DEBUG) check_pixels();

}

Код дляJetson:

H файл:

 #include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <stdbool.h>

#define BUFFER_SIZE 1024
#define DEBUG 1

// Adapted from Canonical Arduino read by Chris Heydrick - 
// https://github.com/cheydrick/Canonical-Arduino-Read/blob/master/canonicalarduinoread.c



int init();
bool get_tof(int fd);
bool get_thermal(int fd);
bool read_data(int fd);
bool chk_rdy(int fd);

C ++ Файл:

    #include "SensorSuite.h"



int main(int argc, char *argv[]){

int fd;
bool rdy = 0;




fd = init();

while (!rdy) {
    rdy = chk_rdy(fd);
}


rdy = get_tof(fd);

while (!rdy) {
    rdy = read_data(fd);
}

rdy = get_thermal(fd);

while (!rdy) {
    rdy = read_data(fd);
}

close(fd);

}

int init(){

  int fd;
  struct termios toptions;

  /* open serial port */
  fd = open("/dev/ttyACM0", O_RDWR | O_NOCTTY);
  printf("fd opened as %i\n", fd);

  /* wait for the Arduino to reboot */
  usleep(3500000);

  /* get current serial port settings */
  tcgetattr(fd, &toptions);
  /* set 9600 baud both ways */
  cfsetispeed(&toptions, B115200);
  cfsetospeed(&toptions, B115200);
  /* 8 bits, no parity, no stop bits */
  toptions.c_cflag &= ~PARENB;
  toptions.c_cflag &= ~CSTOPB;
  toptions.c_cflag &= ~CSIZE;
  toptions.c_cflag |= CS8;
  /* Canonical mode */
  toptions.c_lflag |= ICANON;
  /* commit the serial port settings */
  tcsetattr(fd, TCSANOW, &toptions);

  return fd;

}

bool get_tof(int fd){

    if(DEBUG) printf("\nSending 1 for ToF Data\n");

    write(fd, "1", 1);
    tcdrain(fd);
    usleep(2000000);

    return 0;

}

bool get_thermal(int fd){

    if(DEBUG) printf("\nSending 2 for Thermal Data\n");


    write(fd, "2", 1);
    tcdrain(fd);
    usleep(2000000);

    return 0;

}

bool read_data(int fd){

    int n;
    char buf[BUFFER_SIZE] = "temp text";

    if(DEBUG) printf("\nReading data\n");
    n = read(fd, buf, BUFFER_SIZE);
    buf[n] = 0;
    // if(n!=1)


    if (n < 35) return 0;
    else {
    if (DEBUG) printf("%i bytes read, buffer contains: %s\n", n, buf);
    return 1;
    }
}

bool chk_rdy(int fd){

    int n;
    char buf[BUFFER_SIZE] = "temp text";

    n = read(fd, buf, BUFFER_SIZE);
    buf[n] = 0;

if ((buf[0] == '9') && (n == 2)) return 1;

else return 0;


}

Мне удалось решить пустое возвращаемое сообщение в Jetson, добавив в ifоператор (исправленный код c ++), чтобы ничего не печатать до тех пор, пока не будет возвращено ожидаемое количество байтов, но это попало, так как теперь иногда я получаю тепловые данные, когда мне нужно получить данные tof, и наоборот, или я просто получу дваодин

Ответы [ 2 ]

0 голосов
/ 19 марта 2019

Вслед за Армали,

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

0 голосов
/ 06 марта 2019

В read_data() вы не можете ожидать, что получите все данные одним вызовом n = read(fd, buf, BUFFER_SIZE). По-видимому, первый вызов read дает только первый байт данных, поэтому вы должны продолжить чтение и добавление данных в buf до тех пор, пока не будут получены все данные. (Конечно, для этого вам нужно либо знать, сколько байтов отправлено, либо как определить конец.)

...