[英]Jetson TX2, Arduino Uno Serial communication
I'm using a Jetson TX2, and a Arduino Uno to try and communicate over USB serial, the premise is I'm using a Arduino to communicate with some Laser ToF sensors, and a Thermopile. 我正在使用Jetson TX2和Arduino Uno尝试通过USB串行进行通信,前提是我正在使用Arduino与某些Laser ToF传感器和Thermopile进行通信。
The Jetson is running Ubuntu 16.04 for ros compatability as this will eventually tie into a ros node Jetson运行Ubuntu 16.04以实现ros兼容性,因为这最终会与ros节点绑定
Using just the Arduino IDE, serial monitor it the call and response works as intended, however once I try to get the call and response working using the Jetson that's where the data isn't get correctly written printed on the terminal. 仅使用Arduino IDE,对其进行串行监控,呼叫和响应即可按预期工作,但是一旦我尝试使用Jetson来使呼叫和响应正常工作,则无法正确在终端上打印数据。
The arduino prints a byte "9" to the Jetson when it's ready to receive, and the Jetson prints a "1" or a "2" over serial when it wants to receive the time of flight or thermal sensor data respectively. 当准备好接收时,arduino会向Jetson打印一个字节“ 9”,而当Jetson想要分别接收飞行时间或热传感器数据时,它会串行打印“ 1”或“ 2”。
The intended communication is for the Jetson to recieve 5 comma separated, float values from the ToF Sensors, followed by 64 comma separated float values from the thermal sensor, however I get the following: 预期的通信方式是让Jetson从ToF传感器接收5个逗号分隔的浮点值,然后从热传感器接收64个逗号分隔的浮点值,但是我得到以下信息:
Sending 1 for ToF Data
发送1的ToF数据
Reading data
读取数据
1 bytes read, buffer contains:
读取1个字节,缓冲区包含:
Sending 2 for Thermal Data
发送2个热数据
Reading data
读取数据
35 bytes read, buffer contains: Thermal/ToF sensor data
读取35个字节,缓冲区包含: 热/ ToF传感器数据
The code for the Arduino is as follows: 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();
}
The code for the Jetson is: Jetson的代码是:
H file: 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++ File: 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;
}
I've managed to solve the empty return message on Jetson by adding in a if statement (c++ code amended) to not print anything until the expected number of bytes is returned but this is hit and miss as now sometimes I get the thermal data when I should get the tof data and vice versa or I'll just get two of one 我设法通过添加一个if语句(已修改c ++代码)解决了Jetson上的空返回消息,直到返回了预期的字节数之前都不打印任何内容,但这种方法会遇到麻烦,因为现在有时我会得到热数据我应该得到tof数据,反之亦然,或者我只得到其中之一
In read_data()
, you cannot expect that you get all the data with one n = read(fd, buf, BUFFER_SIZE)
call. 在
read_data()
,您不能期望通过一次n = read(fd, buf, BUFFER_SIZE)
调用来获取所有数据。 Apparently the first read
call yields only the first data byte, so you have to continue reading and appending data into buf
until all data arrived. 显然,第一个
read
调用仅产生第一个数据字节,因此您必须继续读取数据并将其追加到buf
直到所有数据到达为止。 (Of course for this you either have to know how many bytes are sent or how the end can be identified.) (为此,您当然必须知道发送了多少字节或如何标识结尾。)
Following on from Armali, 从阿玛利出发,
I managed to get it working by working out how many bytes I was was sending, luckily they were constant throughout, I then simply kept the the Jetson reading until the correct amount of bytes had arrived, using the serial output I recognized that the Jetson actually went through a few cycles before the Arduino had sent all the data, I believe this was due to using serial prints in the Arduino code. 我设法弄清楚我正在发送多少个字节来使它正常工作,幸运的是,它们在整个过程中都是恒定的,然后我使用串行输出我一直保持Jetson读数直到正确的字节数到达为止,使用串行输出,我认识到Jetson实际上是在Arduino发送所有数据之前经历了几个周期,我相信这是由于在Arduino代码中使用了串行打印。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.