I'm trying to sendo datas from Arduino Uno to RaspberryPi 3B. I need to send 14 int (max value: 6000) from Arduino as soon as Raspberry ask for them. Each one of this 14 number came from ad ADC (SPI communication).
ARDUINO SIDE
#include "SPI.h"
byte incomingByte = 0; // for incoming serial data
const int N_SENSORI=14;
const int DATAOUT = 11;
const int DATAIN = 12;
const int SPICLOCK = 13;
const int SLAVESELECT = 10;
//===============SPI COMMUNICATION================
short write_read_spi16(short what) {
digitalWrite(SS, LOW);
short res = SPI.transfer16(what);
digitalWrite(SS, HIGH);
return res;
}
//===============CONVERT INT IN BYTE AND SEND IT================
void longInt2Byte( int x){
unsigned char buf[sizeof( int)];
memcpy(buf,&x,sizeof(int));
Serial.write(buf,sizeof(buf));
}
//=======================================
void setup() {
Serial.begin(115200);
SPI.begin();
pinMode(DATAOUT, OUTPUT);
pinMode(DATAIN, INPUT);
pinMode(SPICLOCK,OUTPUT);
pinMode(SLAVESELECT,OUTPUT);
}
void loop() {
if (Serial.available() > 0) {
incomingByte= Serial.read();
if (incomingByte=='E') {
write_read_spi16(0b1000001101110000); //THIS IS FOR THE ADC COMMUNICATION
for (int i = 1; i<N_SENSORI+1; i++) { //DONE 14 TIMES.
short s = write_read_spi16(0b1000001101110000 | (i<<10));
int Data = s&0xFFF;
longInt2Byte(Data);
}
}
}}
// C++ SIDE
void stimulationController::SetupDario(){
cout<<"Dentro al setupDario"<<endl<<flush;
buffer=new char [1000];
const char* _portNameSensorsDario="/dev/ttyACM1";
//SERIAL PORT FOR HAND SENSORS
struct termios options;
SerialHandleSensors=open(_portNameSensorsDario, O_RDWR | O_NOCTTY | O_NDELAY); //SerialHandleSensors=open(_portNameSensors, O_RDWR | O_NOCTTY | O_NDELAY); non blocking
if (SerialHandleSensors == -1 )
{
cout<<endl<<"......ERROR: Unable to open: "<<_portNameSensorsDario<<endl;
return;
}
else
{
fcntl(SerialHandleSensors, F_SETFL,0);
cout<<"......OPENED PORT: Succesfully opened: "<<_portNameSensorsDario<<endl;
}
//GET THE OPTIONS, MODIFY AND SET
tcgetattr(SerialHandleSensors,&options);
cfsetispeed(&options,B115200); //BAUD RATE IN
cfsetospeed(&options,B115200); //BAUD RATE OUT
// options.c_lflag |= (ICANON | ECHO | ECHOE);
options.c_cflag |= (CLOCAL | CREAD);
options.c_cflag &= ~PARENB;
options.c_cflag |= CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
tcsetattr(SerialHandleSensors,TCSANOW,&options);
usleep(3000000);
cout<<"Fine Setup"<<endl<<flush;
}
int stimulationController::Dario( )
{
{
cout<<" NUOVA FUNZIONE"<<endl;
unsigned char bytes[4];
bytes[0]=0x45; // 'E'
int tempWrite=write(SerialHandleSensors,bytes,1);
if(tempWrite==-1)
{
cout<<"......ERROR: PROBLEM WRITING TO ROBOTIC HAND"<<endl;
failure=true;
return 0;
}
int value=0;
int tempRead=read(SerialHandleSensors,buffer,28);
if(tempRead==-1)
{
cout<<"......ERROR: PROBLEM READING FROM ROBOTIC HAND"<<endl;
failure=true;
return 0;
}
int j=0;
for( int i=0; i<28; i=i+2){
value= buffer[i] | ((int)buffer[i+1]<<8);
//ensorDataFoot.push_back(value); //Aggiunge un elemento
j=j+1;
cout<<"Dato "<<j <<"vale: "<<value<<endl<<flush;
}
return value;
}
}
The problem is that or the raspberry side some time it prints the right values, some time (the most of the times, actually) it doesn't. Data seems to be repeated or (2500 insted of 2000 for example).
I can't figure it out the problem.Could it be a matter of timing between the request of sending data and the reading? if so, there is a way to get rid of it?
I've added a do-while cycle in order to be sure that all the 28 bytes are read
int TotByte=28;
int ByteRead=0;
int TempRead=0;
do{ TempRead= read(SerialHandleSensors, buffer, (TotByte-ReadByte));
ReadByte= ReadByte+TempRead;
cout<<"ReadByte is: "<<ReadByte<<endl<<flush;
}while(ByteRead<TotByte);
Output:
ReadByte is: 5
ReadByte is: 15
ReadByte is: 25
and then it stay like that without doing anything
(Posted answer on behalf of the OP):
I figured it out; the problem were the settings of the serial port. For future reference, here is the working version.
bufferTemp=new char [1000];
bufferDEF = new char[1000];
const char* _portNameSensorsBT="/dev/rfcomm0";
struct termios options;
SerialHandleSensorsFoot=open(_portNameSensorsBT, O_RDWR ); //SerialHandleSensors=open(_portNameSensors, O_RDWR | O_NOCTTY | O_NDELAY); non blocking
if (SerialHandleSensorsFoot == -1 )
{
cout<<endl<<"......ERROR: Unable to open: "<<_portNameSensorsBT<<endl;
return 0;
}
else
{
fcntl(SerialHandleSensorsFoot, F_SETFL,0);
cout<<"......OPENED PORT: Succesfully opened: "<<_portNameSensorsBT<<endl;
}
//GET THE OPTIONS, MODIFY AND SET
tcgetattr(SerialHandleSensorsFoot,&options);
cfsetispeed(&options,B115200); //BAUD RATE IN
cfsetospeed(&options,B115200); //BAUD RATE OUT
// options.c_lflag |= (ICANON | ECHO | ECHOE);
options.c_iflag = IGNBRK | IGNPAR;
options.c_oflag = 0;
options.c_lflag = 0;
options.c_cflag |= (CLOCAL | CREAD);
options.c_cflag &= ~PARENB;
options.c_cflag |= CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
tcsetattr(SerialHandleSensorsFoot,TCSAFLUSH,&options);
usleep(5000000);
with these setting I'm able to communicate with bluetooth even though there might be some velocity problem.
Related
GOAL:
Configure a serial port /dev/ttyTHS1 on Linux 18 Jetson NANO with interrupter and non-standard baud rate for Sbus. The funny part is that it worked perfectly until today. The backup had no effect.
PS: the code was combined from several files for testing purposes, so i could make a few mistakes.
#include <iostream>
#include <asm/termios.h>
#include <asm/ioctls.h>
#include <sys/signal.h>
#include <stropts.h>
#include <unistd.h>
using namespace std;
bool Ports::setup_port_Sbus(Info* port)
{
//> check descriptor
if (!isatty(fd)) { throw "File description is NOT a serial port!"; }
//> read fole descriptor config
struct termios2 config = { 0 };
//> for interrupt
struct sigaction saio;
sigset_t mskvar;
sigfillset(&mskvar);
sigprocmask(SIG_SETMASK, &mskvar, NULL);
sigdelset(&mskvar, SIGIO);
saio.sa_handler = signal_io_handler;
saio.sa_flags = 0;
saio.sa_restorer = NULL;
sigaction(SIGIO, &saio, NULL);
if (ioctl(fd, TCGETS2, &config) < 0) { throw "Could not read config of FD!"; }
config.c_cflag |= PARENB; // enable parity
config.c_cflag &= ~PARODD; // even parity
config.c_cflag |= CSTOPB; // enable 2 stop bits
config.c_cflag &= ~CSIZE; // clear character size mask
config.c_cflag |= CS8; // 8 bit characters
config.c_cflag &= ~CRTSCTS; // disable hardware flow control
config.c_cflag |= CREAD; // enable receiver
config.c_cflag |= CLOCAL; // ignore modem lines
config.c_lflag &= ~ICANON; // receive characters as they come in
config.c_lflag &= ~ECHO; // do not echo
config.c_lflag &= ~ISIG; // do not generate signals
config.c_lflag &= ~IEXTEN; // disable implementation-defined processing
config.c_iflag &= ~(IXON | IXOFF | IXANY); // disable XON/XOFF flow control
config.c_iflag |= IGNBRK; // ignore BREAK condition
config.c_iflag |= INPCK; // enable parity checking
config.c_iflag |= IGNPAR; // ignore framing and parity errors
config.c_iflag &= ~ISTRIP; // do not strip off 8th bit
config.c_iflag &= ~INLCR; // do not translate NL to CR
config.c_iflag &= ~ICRNL; // do not translate CR to NL
config.c_iflag &= ~IGNCR; // do not ignore CR
config.c_oflag &= ~OPOST; // disable implementation-defined processing
config.c_oflag &= ~ONLCR; // do not map NL to CR-NL
config.c_oflag &= ~OCRNL; // do not map CR to NL
config.c_oflag &= ~(ONOCR | ONLRET); // output CR like a normal person
config.c_oflag &= ~OFILL; // no fill characters
// Apply baudrate
speed_t br = 100000;
config.c_ispeed = br;
config.c_ospeed = br;
config.c_cc[VMIN] = 0;
config.c_cc[VTIME] = 0;
//> Finally, apply the configuration
if (ioctl(fd, TCSETS2, &config) < 0) { throw "Could not set configuration of fd!"; }
// Done!
return true;
}
void port_init(){
const char* _name = "/dev/ttyTHS1";
int fd = -1;
fd = open(_name, O_RDWR | O_NOCTTY );
if (fd < 0) { throw "File is not open!"; }
else{
fcntl(fd, F_SETFL, O_NONBLOCK|O_ASYNC);
}
bool setup = setup_port_Sbus(fd);
if (!setup) { throw "Could not configure port"; }
if (fd <= 0) { throw "Connection attempt to port failed, exiting"; }
}
struct Sbus_data{
bool lost_frame;
int failsafe;
bool ch17;
bool ch18;
static int8_t SBUS_NUM_CH = 16;
int last_ch[SBUS_NUM_CH] = {};
int ch[SBUS_NUM_CH] = {};
};
int main(){
try{
port_init();
}
catch(const char* err){
cout << "ERR: " << err << endl;
}
uint8_t byte;
uint8_t sb_buf[SBUS_PACKET_LEN] = {};
const int8_t SBUS_PACKET_LEN = 25;
const int8_t SBUS_NUM_SBUS_CH = 16;
const uint8_t SBUS_HEADER = 0x0F;
const uint8_t SBUS_FOOTER = 0x00;
const uint8_t SBUS_FOOTER2 = 0x04;
const uint8_t SBUS_CH17_MASK = 0x01;
const uint8_t SBUS_CH18_MASK = 0x02;
const uint8_t SBUS_LOST_FRAME_MASK = 0x04;
const uint8_t SBUS_FAILSAFE_MASK = 0x08;
Sbus_data sb_data;
int sb_state = 0;
do{
count_read_symb = read(port->file_descriptor, &byte, 1);
if(count_read_symb <= 0)
{
cout << "byte: " << byte << " | errno: "<< errno << endl;
continue;
}
//> wrong start
if(sb_state == 0 && byte != SBUS_HEADER)
{
continue;
}
sb_buf[sb_state++] = byte;
//> index done
if(sb_state == SBUS_PACKET_LEN)
{
sb_state = 0;
if(sb_buf[24] != SBUS_FOOTER)
{
continue;
}
sb_data.ch[0] = ((sb_buf[1] |sb_buf[2]<<8) & 0x07FF);
sb_data.ch[1] = ((sb_buf[2]>>3 |sb_buf[3]<<5) & 0x07FF);
sb_data.ch[2] = ((sb_buf[3]>>6 |sb_buf[4]<<2 |sb_buf[5]<<10) & 0x07FF);
sb_data.ch[3] = ((sb_buf[5]>>1 |sb_buf[6]<<7) & 0x07FF);
sb_data.ch[4] = ((sb_buf[6]>>4 |sb_buf[7]<<4) & 0x07FF);
sb_data.ch[5] = ((sb_buf[7]>>7 |sb_buf[8]<<1 |sb_buf[9]<<9) & 0x07FF);
sb_data.ch[6] = ((sb_buf[9]>>2 |sb_buf[10]<<6) & 0x07FF);
sb_data.ch[7] = ((sb_buf[10]>>5|sb_buf[11]<<3) & 0x07FF);
sb_data.ch[8] = ((sb_buf[12] |sb_buf[13]<<8) & 0x07FF);
sb_data.ch[9] = ((sb_buf[13]>>3|sb_buf[14]<<5) & 0x07FF);
sb_data.ch[10] = ((sb_buf[14]>>6|sb_buf[15]<<2|sb_buf[16]<<10) & 0x07FF);
sb_data.ch[11] = ((sb_buf[16]>>1|sb_buf[17]<<7) & 0x07FF);
sb_data.ch[12] = ((sb_buf[17]>>4|sb_buf[18]<<4) & 0x07FF);
sb_data.ch[13] = ((sb_buf[18]>>7|sb_buf[19]<<1|sb_buf[20]<<9) & 0x07FF);
sb_data.ch[14] = ((sb_buf[20]>>2|sb_buf[21]<<6) & 0x07FF);
sb_data.ch[15] = ((sb_buf[21]>>5|sb_buf[22]<<3) & 0x07FF);
((sb_buf[23]) & 0x0001) ? sb_data.ch[16] = 2047: sb_data.ch[16] = 0;
((sb_buf[23] >> 1) & 0x0001) ? sb_data.ch[17] = 2047: sb_data.ch[17] = 0;
if ((sb_buf[23] >> 3) & 0x0001) { sb_data.failsafe = 1; }
else { sb_data.failsafe = 0; }
cout << "DONE!" << endl;
}
}
while(count_read_symb > 0);
}
I checked ports buffer with sudo sh 'cat < /dev/ttyTHS1' and Putty, and all data was there but the read() returns zero.
Port is in dialout group to which i have access, it is configured for -rw-, and no error in port initialization stage was caught.
Moreover, i have /dev/ttyUSB1 and ../ttyUSB0 with slightely different flags (no parity/ br=115200/ 1 stop bit) for TTL but they are working perfectly.
Thanks to #SKi, I checked the flags.
The solution:
// Apply baudrate
speed_t br = 100000;
config.c_ispeed = br;
config.c_ospeed = br;
config.c_cflag &= ~CBAUD; // !!!!!
config.c_cflag |= BOTHER; // !!!!!
config.c_cc[VMIN] = 0;
config.c_cc[VTIME] = 0;
For some reason, the code used to work without those 2 lines. They are required now.
I am trying to read serial data from an Arduino Uno. I am using the Termios struct and followed this tutorial. I am not receiving the Arduino serial data in return, can anyone help me? First time using c++ to read serial. Following is the c++ code (i'm using ROS), and the arduino code.
c++ code
#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 code:
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("");
}
I got a problem with a posix signal, that I use for reading serial data. First here is a small example code how I initialize my serial port, my signal and a shared memory.
#include <unistd.h>
#include <termios.h>
#include <sys/signal.h>
#include <stdint.h>
#include <cassert>
#include <cstdio>
#include <fcntl.h>
#include <iostream>
#include <QSharedMemory>
int fd;
struct termios termAttr;
struct sigaction saio;
char buff[255];
QSharedMemory QShare("IDSTRINGOFTHISMEMORY");
void signal_handler_IO (int status)
{
std::cout << "Got Serial Data!" << std::endl;
int si = read(fd, &buff[0], 255);
if(true) // Works with false here, but then the shared memory ist not used!
{
char TWrite = 't';
QShare.lock();
char *to = (char*)QShare.data();
const char *from = reinterpret_cast<char*>(&TWrite);
memcpy(to, from, 1);
QShare.unlock();
}
}
int main()
{
// Create SharedMemory:
QShare.create(1);
fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1)
{
return -1;
}
saio.sa_handler = signal_handler_IO;
saio.sa_flags = 0;
saio.sa_restorer = NULL;
sigemptyset(&saio.sa_mask);
sigaddset(&saio.sa_mask, SIGINT);
sigaction(SIGIO,&saio,NULL);
fcntl(fd, F_SETFL, FNDELAY|FASYNC);
fcntl(fd, F_SETOWN, getpid());
tcgetattr(fd,&termAttr);
cfsetospeed(&termAttr,B57600);
cfsetispeed(&termAttr,B57600);
termAttr.c_cflag &= ~PARENB;
termAttr.c_cflag &= ~CSTOPB;
termAttr.c_cflag &= ~CSIZE;
termAttr.c_cflag |= CS8;
termAttr.c_cflag |= (CLOCAL | CREAD);
termAttr.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
termAttr.c_iflag &= ~(IXON | IXOFF | IXANY);
termAttr.c_oflag &= ~OPOST;
termAttr.c_cc[VMIN] = 5;
tcsetattr(fd,TCSANOW,&termAttr);
while(true)
{
usleep(1000000);
}
return 0;
}
I had this code in use for a while and it did work quite well. Now for a different project I want to store the serial data in shared memory block, so I can read the current datapoint from multiple processes. In the signal_handler_IO I try to write the data to a shared memory that is created by sys/shm.h. The moment I started using shared memory the posix signal stopped working. Since I was unsure about the use of the shared memory I also tried to use the QSharedMemory class from qt, which created the same result.
Can you tell me, what the shared memory does to my posix signal?
I am attempting to read data over serial from a Pixhawk flight controller which communicates via the Mavlink protocol. It sends 17 bytes, the first three being 0xFE, 0x09 followed by a counter that increments every message. I have confirmed this with GtkTerm.
However when I run the following code, 0x09 (the second byte) is always skipped so only 16 bytes of each 17 byte message is received.
Any ideas?
Thanks, James.
LibSerial::SerialStream pixhawkSerial;
pixhawkSerial.Open("/dev/ttyACM0");
pixhawkSerial.SetBaudRate( LibSerial::SerialStreamBuf::BAUD_57600 ) ;
pixhawkSerial.SetCharSize( LibSerial::SerialStreamBuf::CHAR_SIZE_8 );
pixhawkSerial.SetNumOfStopBits(1);
pixhawkSerial.SetParity( LibSerial::SerialStreamBuf::PARITY_NONE ) ;
pixhawkSerial.SetFlowControl( LibSerial::SerialStreamBuf::FLOW_CONTROL_NONE );
char next_byte [100];
int i = 0;
while (i<100){
if( pixhawkSerial.rdbuf()->in_avail() > 0 ){
pixhawkSerial >> next_byte[i];
i++;
}
else cout << "No data" << endl;
}
Wasn't able to get libserial to work, however I gave temios a go and it worked without issues.
Attached is the working code.
int fd;
struct termios oldAtt, newAtt;
fd = open("/dev/ttyACM0", O_RDWR | O_NOCTTY | O_NDELAY);
tcgetattr(fd, &oldAtt);
memset(&newAtt, 0, sizeof(newAtt));
newAtt.c_cflag = CRTSCTS | CS8 | CLOCAL | CREAD;
newAtt.c_iflag = IGNPAR;
newAtt.c_ispeed = B57600;
newAtt.c_oflag = 0;
newAtt.c_ospeed = B57600;
newAtt.c_lflag = 0;
newAtt.c_cc[VTIME] = 0;
newAtt.c_cc[VMIN] = 1;
tcflush(fd, TCIOFLUSH);
tcsetattr(fd, TCSANOW, &newAtt);
char rBuffer;
char next_byte [100];
int i=0;
int dataReceived;
while (i<100) {
dataReceived = read(fd,&rBuffer,1);
if (dataReceived>0){
next_byte[i] = rBuffer;
i++;
}
}
tcsetattr(fd,TCSANOW,&oldAtt);
close(fd);
I wrote a code to connect, throught a serial port, mi computer to arduino.
This is arduino's code:
#include <Servo.h>
Servo servo;
const int pinServo = 2;
unsigned int angle;
void setup()
{
Serial.begin(9600);
servo.attach(pinServo);
servo.write(0);
}
void loop()
{
if(Serial.available()>0)
{
angle = Serial.read();
if(angle <= 179)
{
servo.write(angle);
}
}
}
And this is c++'s:
#include <iostream>
#include <unistd.h>
#include <fstream>
#include <termios.h>
using namespace std;
int main()
{
unsigned int angle;
ofstream arduino;
struct termios ttable;
cout<<"\n\ntest1\n\n";
arduino.open("/dev/tty.usbmodem3a21");
cout<<"\n\ntest2\n\n";
if(!arduino)
{
cout<<"\n\nERR: could not open port\n\n";
}
else
{
if(tcgetattr(arduino,&ttable)<0)
{
cout<<"\n\nERR: could not get terminal options\n\n";
}
else
{
ttable.c_cflag &= ~PARENB;
ttable.c_cflag &= ~CSTOPB;
ttable.c_cflag &= ~CSIZE;
ttable.c_cflag |= CS8;
ttable.c_cflag &= ~CRTSCTS;
ttable.c_cflag |= CREAD | CLOCAL;
ttable.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
ttable.c_oflag &= ~OPOST;
ttable.c_cc[VMIN] = 0;
ttable.c_cc[VTIME] = 0;
cfsetospeed(&ttable,9600);
if(tcsetattr(arduino,TCSANOW,&ttable)<0)
{
cout<<"\n\nERR: could not set new terminal options\n\n";
}
else
{
do
{
cout<<"\n\ninsert a number between 0 and 179";
cin>>angle;
arduino<<angle;
}while(angle<=179);
arduino.close();
}
}
}
}
It should connect to arduino , then ask me a number between 0 an 179 and the send that number to arduino which aplly that number as an angle to a servo motor;
But it stops at arduino.open("/dev/tty.usbmodem3a21") .What can i do ?
I think your problems appear in these lines of code
if(tcgetattr(arduino,&ttable)<0) {
// ...
}
else {
// ...
if(tcsetattr(arduino,TCSANOW,&ttable)<0) {
// ...
}
}
The arduino variable is of type ofstream, where tcgetattr() and tcsetattr() expect a file descriptor obtained with open() at this point.
ofstream provides an automatic conversion to bool and thus int implicitely. Supposed the
arduino.open("/dev/tty.usbmodem3a21");
went OK, you are effectively passing 1 to tcgetattr() and tcsetattr(), which is the standard input file descriptor.
Solution is not to use a ofstream for arduino, but an ordinary file descriptor
int arduino = open("/dev/tty.usbmodem3a21",O_WRONLY);