Send Commands to serial device and receiving response - c

Am trying to send a command to a serial device (arduino) and receive a response, the command goes through but I don't get a response from the target device.
I want the C program to control the serial device by sending & receiving data.
Arduino Code:
void setup() {
// initialize serial communication:
Serial.begin(9600);
}
void loop() {
if (Serial.available() > 0) {
int inByte = Serial.read();
switch (inByte) {
case 'H':
Serial.print("75864d63001bebaa");
break;
}
}
}
C Code:
#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>
int main(int argc, char *argv[]) {
int fd, n, i;
char buf[64] = "temp text";
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, B9600);
cfsetospeed(&toptions, B9600);
/* 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);
/* Send byte to trigger Arduino to send string back */
write(fd, "H", 1);
/* Receive string from Arduino */
n = read(fd, buf, 64);
/* insert terminating zero in the string */
buf[n] = 0;
printf("%i bytes read, buffer contains: %s\n", n, buf);
return 0;
}

Related

Reading arduino serial in linux using C

I want to read serial from arduino. I use this code :
#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
#include <sys/ioctl.h>
int main(){
char data[1024];
char dev[] = "/dev/ttyACM1";
int fd = open(dev, O_RDWR | O_NOCTTY | O_NDELAY);
fcntl(fd, F_SETFL, FNDELAY);
struct termios options;
tcgetattr(fd, &options);
cfsetispeed(&options, B9600);
cfsetospeed(&options, B9600);
options.c_cflag |= CS8;
options.c_cflag |= CS8;
options.c_cflag &= ~CRTSCTS;
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
tcsetattr(fd, TCSANOW, &options);
ioctl(fd, TCFLSH, 2);
while(1){
read(fd, data, sizeof(data));
printf(data);
}
//write(fd, data, sizeof(data));
}
My arduino runs very simple sketch :
int x;
void setup() {
Serial.begin(9600);
}
void loop() {
Serial.println("DO YOU HEAR ME ??");
delay(1000);
}
and output of this combinatin is that :
??OU HEAR ME ??
DO YOU HEAR ME ??
DO YOU HEAR ME ??
A¹­þ
??OU HEAR ME ??
DO YOU HEAR ME ??
DO YOU HEAR ME ??
A¹­þ
??OU HEAR ME ??
DO YOU HEAR ME ??
DO YOU HEAR ME ??
My question is how to make order out of chaos. I found that this issue occurs when buffer ends and new one begins(bigger buffer less junk data) but I can't have a infinite buffer. Also there is a lot of junk when it reads for the first time.. Is there a way to sync it or something ?
(Also I am not native English sorry for any mistakes.)
I found answer to my own problem. I used this time c++ to organize it in class (very poor one because it doesn't handle any errors and doesn't use c++ in the most..) Here is the code :
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <strings.h>
#include <cstring>
#include <iostream>
//Here I define some vars
#define BAUDRATE B9600
#define MODEMDEVICE "/dev/ttyACM0"
#define _POSIX_SOURCE 1
class serial{
public:
serial(){
fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY );
if (fd <0) {perror(MODEMDEVICE); exit(-1); }
// Improvement No. 1 I save old setting and clean the new one
tcgetattr(fd,&oldtio);
bzero(&newtio, sizeof(newtio));
// Here I set all the flags to vars at once
newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
newtio.c_iflag = IGNPAR | ICRNL;
newtio.c_oflag = 0;
newtio.c_lflag = ICANON;
//here I set some new flags..
newtio.c_cc[VINTR] = 0; /* Ctrl-c */
newtio.c_cc[VQUIT] = 0; /* Ctrl-\ */
newtio.c_cc[VERASE] = 0; /* del */
newtio.c_cc[VKILL] = 0; /* # */
newtio.c_cc[VEOF] = 4; /* Ctrl-d */
newtio.c_cc[VTIME] = 0; /* inter-character timer unused */
newtio.c_cc[VMIN] = 1; /* blocking read until 1 character arrives */
newtio.c_cc[VSWTC] = 0; /* '\0' */
newtio.c_cc[VSTART] = 0; /* Ctrl-q */
newtio.c_cc[VSTOP] = 0; /* Ctrl-s */
newtio.c_cc[VSUSP] = 0; /* Ctrl-z */
newtio.c_cc[VEOL] = 0; /* '\0' */
newtio.c_cc[VREPRINT] = 0; /* Ctrl-r */
newtio.c_cc[VDISCARD] = 0; /* Ctrl-u */
newtio.c_cc[VWERASE] = 0; /* Ctrl-w */
newtio.c_cc[VLNEXT] = 0; /* Ctrl-v */
newtio.c_cc[VEOL2] = 0; /* '\0' */
// and I finally save the settings
tcflush(fd, TCIFLUSH);
tcsetattr(fd,TCSANOW,&newtio);
}
~serial(){
close(fd);
}
std::string sread(){
res = read(fd,buf,255);
buf[res]=0;
return buf;
}
void swrite(const char* input){
write(fd,input,std::strlen(input));
}
private:
int fd,c,res;
struct termios oldtio,newtio;
char buf[255];
};
int main(){
serial s;
s.swrite("Light");
std::string buf = s.sread();
std::cout << buf;
}
This is more of a ripoff from "Serial programming HOW TO" : http://tldp.org/HOWTO/Serial-Programming-HOWTO/ (form the example code..)
And here is the new poor arduino code :
int x;
String buff;
int lpin = A0;
int tpin = A1;
int data;
void setup() {
Serial.begin(9600);
pinMode(lpin,INPUT);
pinMode(tpin,INPUT);
}
void loop() {
if(Serial.available() == 1)
{
buff = Serial.readString();
if(buff == "Light"){
data = analogRead(lpin);
Serial.print(data);
Serial.print("\n");
}else if(buff == "Temp"){
data = analogRead(tpin);
Serial.print(data);
Serial.print("\n");
}else{
Serial.print("Something went wrong !");
Serial.print("\n");
}
}
delay(1);
}

read from serial port fails when called twice

Resolved Bellow: Wrong number of characters in read/write
I am attempting to read and write to a serial port, and I don't have much experience in C/C++.
My port is connected to a motion controller/driver that requires the following settings:
Baudrate: 57600
Data bits: 8
Parity: None
Stop bits: 1
Flow control: Xon/Xoff
Terminator CRLF
Problem: The code will write and read my first command,but it hangs on the second read call. I am currently blocking until I receive at least one character, but each written command should generate a return.
Additional information: I can only run the first write/read if I first unplug the remote and plug it back in. Alternatively, I can open a cool term window, setup my serial port and run a few commands. When I close the cool term window I will be able to write/read once.
Current Code:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <time.h>
#include <iostream>
using namespace std;
int open_port(void)
{
int fd;
// open file descriptor
fd = open("/dev/cu.USA19H41P1.1", O_RDWR | O_NOCTTY);
// if unsucessful
if (fd == -1)
{
printf("open_port: unable to open port. \n");
}
else
{
// remains open across executables
fcntl(fd, F_SETFL, 0);
printf("port is open. \n");
}
return (fd);
}
int configure_port(int fd)
{
// store terminal port settings
struct termios port_settings;
memset(&port_settings, 0, sizeof port_settings);
if(tcgetattr(fd, &port_settings) !=0)
{
printf("error tcgetattr \n");
cout << errno;
}
port_settings.c_iflag = 0;
port_settings.c_oflag = 0;
port_settings.c_lflag = 0;
port_settings.c_cflag = 0;
// flush
tcflush(fd, TCIOFLUSH);
// set baud rate
cfsetispeed(&port_settings, B57600);
cfsetospeed(&port_settings, B57600);
// xon/xoff requirment
port_settings.c_iflag |= IXON;
port_settings.c_iflag |= IXOFF;
// no parity requirement
port_settings.c_cflag &= ~PARENB;
// one stop bin requirement
port_settings.c_cflag &= ~CSTOPB;
// turn on read
port_settings.c_cflag |= CREAD;
port_settings.c_cflag |= CLOCAL;
// no character processing and 8 bit input
port_settings.c_cflag &= ~CSIZE;
port_settings.c_cflag |= CS8;
// one character blocking
port_settings.c_cc[VMIN] = 1;
port_settings.c_cc[VTIME] = 5;
// apply above settings
if(tcsetattr(fd,TCSANOW, &port_settings) != 0)
{
printf("error tcsetattr \n");
cout << errno;
}
// flush buffers one more time
tcflush(fd, TCIOFLUSH);
return(fd);
}
int read_write(int fd)
{
// write to serial port
ssize_t size=write(fd, "1va?\r\n", 8);
// wait until output is transmitted
tcdrain(fd);
// read from serial port
char buf[100];
memset(buf, '\0', sizeof buf);
ssize_t size2=read(fd, &buf, sizeof(buf));
cout << buf << endl;
return(fd);
}
int main(void)
{
// open port
int fd = open_port();
// store old settings
struct termios old_settings;
memset(&old_settings, 0, sizeof old_settings);
tcgetattr(fd,&old_settings);
// configure port
configure_port(fd);
// write/read first command ("1va?\r\n")
read_write(fd);
// write read second command ("1pa?\r\n")
ssize_t size=write(fd, "1pa?\r\n", 8);
tcdrain(fd);
char buf[100];
memset(buf, '\0', sizeof buf);
ssize_t size3=read(fd, &buf, sizeof(buf));
cout << buf;
//close serial port
close(fd);
tcsetattr(fd, TCSANOW, &old_settings);
return 0;
}
Here is some example code on working with Serial ports setting the correct flags and the baud rate:
Provide your code and and more thorough explanation for us to resolve your issue. What do you mean by write and read my first command? Is your device still responsive after this command? Isn't the second command sent?

read() in c raspberry pi gsm-module

I am working on a project where i can send sms with my raspberry pi thats connected to a sim300s module thrue a usb to serial connection.
problem:
sim300 doesnt detect the simcard , harware malfunction, i have ordered a new one. Until then i want to check if the connection works between the 2.
Now i want to send at command and receive OK(or something like that) Here is my code:
the value that is stored in string buf is TATATATAT.... etc.. etc..
Can someone explain why i am not getting OK back? Am i doing something wrong?
#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
/*
* 'open_port()' - Open serial port 1.
*
* Returns the file descriptor on success or -1 on error.
*/
int main(int argc, char* argv[])
{
puts("start open_port");
open_port();
puts("open_port started ");
}
int
open_port(void)
{
char reply;//not shure if its gonna be used
struct termios options;
int n=0;
int fd; /* File descriptor for the port */
char buf[50];
int valueBytes;
int x = 0;
fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY ); //| O_NDELAY);
if (fd == -1)
{//could not open port
fprintf(stderr, "open_port: Unable to open /dev/ - %s\n",
strerror(errno));
}
printf("%d",fd);
tcgetattr(fd, &options); //get current options for port
puts("test1");
cfsetispeed(&options, B9600);//set baud rate
cfsetospeed(&options, B9600);//set baud rate
puts("\n2");
options.c_cflag |= (CLOCAL | CREAD | CRTSCTS);//enable the receiver and set local mode
puts("\n3");
options.c_cflag &= ~PARENB;//disable parity generation and detection
options.c_cflag &= ~CSTOPB;//Use one stop bit per character
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;//use 8 bits to send or receive characters
options.c_lflag &= ~(ICANON | /* Enable canonical input (else raw) */
ECHO | /*Enable echoing of input characters */
ECHOE | /*Echo erase character as BS-SP-BS*/
ISIG); /*Enable SIGINTR, SIGSUSP, SIGDSUSP, and SIGQUIT signals*/
tcsetattr(fd, TCSANOW, &options);//TCSANOW change values immediately
puts("4");
n = write(fd, "AT\r", 4); // n = write(fd, "AT+CMGF=1\r", 10);
if (n < 0){
puts("write() of 4 bytes failed!");}
if(read(fd, buf, 2) < 0){
puts("it doesnt work"); }
fcntl(fd, F_SETFL, FNDELAY);
valueBytes=read(fd, buf,50);
printf("%d",valueBytes);
if(valueBytes < 0){
printf(strerror(errno));}
puts("6.3");
for(x; x<50;x++){
printf("%c",buf[x]);
}
close(fd);
puts("7");
return (fd);
puts("8");
}

Serial communication between linux and 8051 microcontroller board using rs-232 in c

I have problem in sending data serially using RS-232 from linux OS to uc 8051.
8051 setting:
baudrate = 9600;
comport = port1.
parity = none
stop bit = one
// my code for receiving data on 8051 uc
#include <reg51.h>
unsigned char value;
int i,j;
void ini()
{
TMOD=0x20; //Timer1, mode 2, baud rate 9600 bps
TH1=0XFD;
SCON=0x50;
TR1=1;
}
void delay()
{
for(i=0;i<=1000;i++)
for (j=0;j<=300;j++);
}
void recieve()
{
unsigned char value;
while(RI==0);
value=SBUF;
P1=value;
RI=0;
}
void main()
{
while(1)
{
ini();
recieve();
}
}
// and code which run on linux is as following
#include <stdio.h> // standard input / output functions
#include <string.h> // string function definitions
#include <unistd.h> // UNIX standard function definitions
#include <fcntl.h> // File control definitions
#include <errno.h> // Error number definitions
#include <termios.h> // POSIX terminal control definitionss
#include <time.h> // time calls
int open_port(void)
{
int fd; // file description for the serial port
fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1) // if open is unsucessful
{
//perror("open_port: Unable to open /dev/ttyS0 - ");
printf("open_port: Unable to open /dev/ttyS0. \n");
}
else
{
fcntl(fd, F_SETFL, 0);
printf("port is open.\n");
}
return(fd);
} //open_port
int configure_port(int fd) // configure the port
{
struct termios port_settings; // structure to store the port settings in
cfsetispeed(&port_settings, B9600); // set baud rates
cfsetospeed(&port_settings, B9600);
port_settings.c_cflag &= ~PARENB; // set no parity, stop bits, data bits
port_settings.c_cflag &= ~CSTOPB;
port_settings.c_cflag &= ~CSIZE;
port_settings.c_cflag |= CS8;
tcsetattr(fd, TCSANOW, &port_settings); // apply the settings to the port
return(fd);
} //configure_port
int query_modem(int fd) // query modem with an AT command
{
char n;
fd_set rdfs;
struct timeval timeout;
// initialise the timeout structure
timeout.tv_sec = 10; // ten second timeout
timeout.tv_usec = 0;
// Create byte array
unsigned char send_bytes[] = { 0x00, 0xff};
write(fd, send_bytes, 2); //Send data
printf("Wrote the bytes. \n");
// do the select
n = select(fd + 1, &rdfs, NULL, NULL, &timeout);
// check if an error has occured
if(n < 0)
{
perror("select failed\n");
}
else if (n == 0)
{
puts("Timeout!");
}
else
{
printf("\nBytes detected on the port!\n");
}
return 0;
} //query_modem
int main(void)
{
int fd = open_port();
configure_port(fd);
query_modem(fd);
return(0);
} // main
But I have problem .. so plz help me out and tell me in which format linux sends data through rs-232. Also receiving format of 8051 micro-controller.
Need sample code in C.
I recomment basic fault finding
make sure you use correct cables (2 & 3 crossed out, no handshake lines to start with)
seperate the devices, i.e. connect your Linux machine to a PC running a terminal
program and try to establish 2-way communication - work on the Linux / C code until you achieve
connect your 8051 to a PC running a terminal program ....
connect Linux and 8051 only if they both work against a known and proven device
If your 8051 code sample represents all code .... how would the 8051 respond to the AT .... it can only receive.
good luck

Reading and writing from serial port,through loopback in c in linux

I am on a program to read and write from and to serial port using serial crosscable and loopback by soring 2nd and 3rd pin of cable. I am able to write but not able to read.
in read output it is showing 0 as the no. of bytes read by it. It is not showing error as -1 .
#include <stdio.h> // standard input / output functions
#include <string.h> // string function definitions
#include <unistd.h> // UNIX standard function definitions
#include <fcntl.h> // File control definitions
#include <errno.h> // Error number definitions
#include <termios.h> // POSIX terminal control definitionss
#include <time.h> // time calls
#include <sys/ioctl.h>
int open_port(void)
{
int fd; // file description for the serial port
fd = open("/dev/ttyS1", O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
if(fd == -1) // if open is unsucessful
{
perror("open_port: Unable to open /dev/ttyS0 - ");
}
else
{
fcntl(fd, F_SETFL, 0);
}
printf("%d",fd);
return(fd);
}
int configure_port(int fd) // configure the port
{
struct termios port_settings; // structure to store the port settings in
cfsetispeed(&port_settings, B9600); // set baud rates
cfsetospeed(&port_settings, B9600);
port_settings.c_cflag |= ( CLOCAL | CREAD );
port_settings.c_cflag &= ~PARENB; // set no parity, stop bits, data bits
port_settings.c_cflag &= ~CSTOPB;
port_settings.c_cflag &= ~CSIZE;
port_settings.c_cflag |= CS8;
tcflush( fd, TCIOFLUSH );
tcsetattr(fd, TCSANOW, &port_settings); // apply the settings to the port
return(fd);
}
int main()
{
int fd= open_port();
int d=configure_port(fd);
printf("%d",d);
int bytes;
char mk[10];
scanf("%s",&mk);
int w=write(fd,mk,strlen(mk));
int y=ioctl(fd,FIONREAD,&bytes);
printf("%d\n",w);
perror("write");
printf("%d",y);
char buffer[80];
char *data;
int nbytes;
data=buffer;
nbytes=read(fd,data,5);
printf("the outputis \n%d\n\n",nbytes);
perror("read");
while(nbytes > 0)
{printf("datmukun %d\n\n",nbytes);
data+=nbytes;
if (data[-1]=='\n'||data[-1]=='\r')
break;
}
return 0;
}
Depending on your TTY-driver the O_NDELAY and O_NONBLOCK can cause read to behave in a non-blocking manner. Therefore, it is very likely that the data has not been received by the time you call read. If you remove those flags, you should block in read until at least one character is available.
you must wait for a while for the data to become available. you can do this like the following:
very simply and just for test purpose by creating a small delay using a while loop and a sleep() function inside it and possibly a counter to try for a number of times.
you can use select() function on your file descriptor to let your process go to sleep for a while and get notified when the data is available or the timeout has reached.

Resources