【问题标题】:Jetson TX2, Arduino Uno Serial communicationJetson TX2,Arduino Uno 串行通信
【发布时间】:2019-03-05 16:03:20
【问题描述】:

我正在使用 Jetson TX2 和 Arduino Uno 尝试通过 USB 串行通信,前提是我正在使用 Arduino 与一些激光 ToF 传感器和热电堆进行通信。

Jetson 正在运行 Ubuntu 16.04 以实现 ros 兼容性,因为这最终会绑定到 ros 节点

仅使用 Arduino IDE,对其进行串行监控,调用和响应按预期工作,但是一旦我尝试使用 Jetson 使调用和响应正常工作,则数据无法正确写入终端上。

arduino 准备好接收时会向 Jetson 打印一个字节“9”,而当 Jetson 想要分别接收飞行时间或热传感器数据时,它会通过串行打印一个“1”或“2”。

预期的通信是让 Jetson 从 ToF 传感器接收 5 个逗号分隔的浮点值,然后从热传感器接收 64 个逗号分隔的浮点值,但是我得到以下信息:

发送 1 个 ToF 数据

读取数据

读取1个字节,缓冲区包含:

发送 2 以获取热数据

读取数据

读取 35 字节,缓冲区包含:Thermal/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 数据时的热数据,反之亦然,否则我只会得到两个中的一个

【问题讨论】:

    标签: c++ linux arduino ubuntu-16.04 nvidia-jetson


    【解决方案1】:

    在read_data() 中,您不能指望通过一次n = read(fd, buf, BUFFER_SIZE) 调用获得所有数据。显然,第一个read 调用仅产生第一个数据字节,因此您必须继续读取数据并将其附加到buf,直到所有数据到达。 (当然,为此您必须知道发送了多少字节或如何识别结束。)

    【讨论】:

      【解决方案2】:

      继阿玛利之后,

      我设法通过计算我发送了多少字节来让它工作,幸运的是它们始终保持不变,然后我只是保持 Jetson 读取直到正确数量的字节到达,使用我认识到的串行输出在 Arduino 发送所有数据之前,Jetson 实际上经历了几个周期,我相信这是由于在 Arduino 代码中使用了串行打印。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-06-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-17
        相关资源
        最近更新 更多