【发布时间】: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