Я использую 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, и наоборот, или я просто получу дваодин