Termios C ++串行读取不读取arduino串行

时间:2019-03-16 23:07:56

标签: c++ serial-port arduino-uno termios

我正在尝试从Arduino Uno读取串行数据。我正在使用Termios结构,并遵循this tutorial。我没有收到Arduino串行数据作为回报,有人可以帮助我吗?第一次使用c ++读取串行。以下是c ++代码(我正在使用ROS)和arduino代码。

c ++代码

#include <ros.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <termios.h>
#include <csignal>
#include <sstream>
#include <algorithm>
#include <iterator>

const char *arduino_path = "/dev/ttyACM0";
int serial_port;
struct termios tty;

void init_serial(){
    //do cereal things https://blog.mbedded.ninja/programming/operating-systems/linux/linux-serial-ports-using-c-cpp/
    serial_port = open(arduino_path, O_RDWR | O_NOCTTY | O_NDELAY);
    if (serial_port < 0) {
        ROS_ERROR("Error %i from open: %s", errno, strerror(errno));
    }

    memset(&tty, 0, sizeof tty);

    if(tcgetattr(serial_port, &tty) != 0) {
        printf("Error %i from tcgetattr: %s\n", errno, strerror(errno));
    }

    //set flags
    tty.c_cflag &= ~PARENB;
    tty.c_cflag |= CS8; // 8 bits per byte (most common)
    tty.c_cflag &= ~CRTSCTS;
    tty.c_cflag |= CREAD | CLOCAL;
    tty.c_lflag &= ~ICANON;
    tty.c_lflag &= ~ECHO; // Disable echo
    tty.c_lflag &= ~ECHOE; // Disable erasure
    tty.c_lflag &= ~ECHONL; // Disable new-line echo
    tty.c_lflag &= ~ISIG;
    tty.c_iflag &= ~(IXON | IXOFF | IXANY);
    tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL);
    tty.c_oflag &= ~OPOST; // Prevent special interpretation of output bytes (e.g. newline chars)
    tty.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed
    tty.c_cc[VTIME] = 10;    // Wait for up to 1s (10 deciseconds), returning as soon as any data is received.
    tty.c_cc[VMIN] = 0;
    cfsetispeed(&tty, B9600);
    cfsetospeed(&tty, B9600);

    if (tcsetattr(serial_port, TCSANOW, &tty) != 0) {
        printf("Error %i from tcsetattr: %s\n", errno, strerror(errno));
    }
}

std::string read_port(){
    // Allocate memory for read buffer, set size according to your needs
    char read_buf [256];
    memset(&read_buf, '\0', sizeof(read_buf));

    int n = read(serial_port, &read_buf, sizeof(read_buf));
    std::string ret(read_buf);
    return ret;
}

int main(int argc, char **argv){
    ros::init(argc, argv, "sensor_handler");
    ros::NodeHandle n;

    init_serial();

    while(ros::ok()){
        cout << read_port() << std::endl;
    }
}

Arduino代码:

bool startup;

//Soil pins
const int soil_sensor_A0_AI = 0;
const int soil_sensor_A0_P = 0;
const int soil_sensor_A1_AI = 1;
const int soil_sensor_A1_P = 1;
const int soil_sensor_B0_AI = 2;
const int soil_sensor_B0_P = 2;
const int soil_sensor_B1_AI = 3;
const int soil_sensor_B1_P = 3;
int no_soil_sensors = 4;

//timer for the water
double water_timer;
int hours_delay = 4;

//water level vars
int water_level_sensor_pin = 5; //must be a PWM pin
int water_level;  //in mm^3
double min_water = 20;

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

  //Setup soil moisture power pins as outputs
  pinMode(soil_sensor_A0_P, OUTPUT);
  pinMode(soil_sensor_A1_P, OUTPUT);
  pinMode(soil_sensor_B0_P, OUTPUT);
  pinMode(soil_sensor_B1_P, OUTPUT);

  pinMode(water_level_sensor_pin, INPUT);

  //init timer
  water_timer = micros();
  startup = true;
}

void loop() {

  //check if starting up
  if(startup){
    check_water();
    check_soil();
    startup = false;
    water_timer = micros();
  }

  /*
   * if last check+delay in micros is less than or equal to current time then it means it is time to run a soil check.
   */
  if(water_timer + (3600000000*hours_delay) <= micros() ){
    check_water();
    check_soil();
    water_timer = micros();
  }

  //keep checking water, good way to monitor for leaks
  check_water();
}

void check_soil() {
  Serial.print("$SOIL:");

  if(water_level < min_water){
    Serial.println("E, Water level is too low to water the plants");
    return;
  }
  for(int i = 0; i<no_soil_sensors; i++){
    switch(i){
      case soil_sensor_A0_AI:
        digitalWrite(soil_sensor_A0_P, HIGH);
        Serial.print("A0,");
        Serial.print(analogRead(soil_sensor_A0_AI));
        Serial.print(";");
        digitalWrite(soil_sensor_A0_P, LOW);
        break;
      case soil_sensor_A1_AI:
        digitalWrite(soil_sensor_A1_P, HIGH);
        Serial.print("A1,");
        Serial.print(analogRead(soil_sensor_A1_AI));
        Serial.print(";");
        digitalWrite(soil_sensor_A1_P, LOW);
        break;  
     case soil_sensor_B0_AI:
        digitalWrite(soil_sensor_B0_P, HIGH);
        Serial.print("B0,");
        Serial.print(analogRead(soil_sensor_B0_AI));
        Serial.print(";");
        digitalWrite(soil_sensor_B0_P, LOW);
        break;
     case soil_sensor_B1_AI:
        digitalWrite(soil_sensor_B1_P, HIGH);
        Serial.print("B1,");
        Serial.print(analogRead(soil_sensor_B1_AI));
        Serial.print(";");
        digitalWrite(soil_sensor_B1_P, LOW);
        break;
     default:
        Serial.println("E, SOIL_SENSORS");
        break;
    }
  }
  Serial.println("");
}

void check_water(){
  //I don't know the math behind this yet but it will be in here
  Serial.print("$WATER:");
  double water_voltage = digitalRead(water_level_sensor_pin);
  //math
  double water_level = 0;
  Serial.print(water_level);

  if(water_level <= min_water){
    Serial.print(";E, Water Level Low"); 
  }

  Serial.println("");
}

0 个答案:

没有答案