I am trying to get a program which is designed to record data received over serial link via HC12 modules (433 mhz serial link) to behave as I want. As there is a possibility of data being lost over the wireless link I would like to get the termios receive function to time out if it does not receive data within a certain anount of time so that the program does not hang waiting for data. I am using a Raspberry Pi for the data logging. The request for data from a remote sensor is initiated by the Raspberry Pi sendin a "#" character followed by a letter. (The sensor address) The sensor then responds with a ASCII text string. I am pretty useless at "C" programming so there are probably ways the the code could be improved. The is the code in it's present state.
When the program hangs if data is list is the line " readBytes(fd, 12); " which is just after the line "printf("Now about to read data \r\n");" (These printf lines were added to find out where the program was hanging.)
Les.
Code:
/*
* 12/03/17 Code being added to write the data to a file.
* 13/03/17 Being modified to extract raw humidity an temperature
* 13/03/17 Being modified for voltage monitor
* 14/03/17 Being modified to enter time between readings and number of readings.
* 18/03/17 Serial input buffer now beinig flushed at and of read
* with "tcflush(fd, TCIFLUSH);" instruction
* 23/12/17 Moving TCIFLUSH) to just before sending # character.
* 24/12/17 Added a 500 mS delay between sending station address and
* reading input string.This prevents it only reading the
* first 8 bytes of the input string.
* Added a 10 mS delay at the start of the main "do"
* loop before the "displayDecoderValues(fd);" This seems to stop the
* program hanging intermittently.
* 31/12/17 Attempting to test if the first character in "serialBuff_i" is 0x00
* If so then request a new read of data from remote station.
*
* Test010b.c
*
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <termios.h>
#include <errno.h>
void writeBytes(int descriptor, int count);
void readBytes(int descriptor, int count);
void displayDecoderValues(int fd);
char serialBuff_i[30]; // Serial buffer sto store data for I/O
char serialBuff_o[30];
char outbuff[30];
char vbuff[10];
char F_name[25]; //Disk file name
int rnum = 1;
int S_time = 1; // Time between readings
int samples = 100; // Number of readings to be taken.
int main(int argc, char **argv)
{
int fd; // File descriptor of port we will talk to
char *portName = "/dev/ttyAMA0"; // Name of the UART port on the Raspberry pi
struct termios options;
struct termios oldtio, newtio;
char buf[255];
// Port options
fd = open(portName, O_RDWR | O_NOCTTY); // Open port for read and write not making it a controlling terminal
if (fd == -1)
{
perror("openPort: Unable to open port "); // If open() returns an error
}
tcgetattr(fd, &options);
cfsetispeed(&options, B9600); // Set baud rate
cfsetospeed(&options, B9600);
// cfmakeraw(&options);
newtio.c_lflag = 0; //Set non canonical
options.c_cc[VTIME] = 10; //struct termios
options.c_cc[VMIN] = 10;
tcflush(fd, TCIFLUSH);
tcsetattr(fd, TCSANOW, &options); //End of UART setup
usleep(10000); // Sleep for UART to power up and set options
printf ("Name of file to hold readings ? ");
scanf ("%s", F_name);
printf ("Time between readings ? (Integer minutes.) ");
scanf ("%d", &S_time);
printf ("\nNumber of readings ? ");
scanf ("%d", &samples);
int a = 0;
do
{
printf("new ");
usleep(10000);
displayDecoderValues(fd);
serialBuff_o[0] = 0x0A;
serialBuff_o[1] = 0x0D;
writeBytes(fd, 2);
// sleep(S_time * 60);
sleep(S_time);
a++;
} while (a < samples);
close(fd);
printf ("Exit\r\n");
return 0;
}
void writeBytes(int descriptor, int count) {
if ((write(descriptor, serialBuff_o, count)) == -1) { // Send data out
perror("Error writing");
close(descriptor); // Close port if there is an error
exit(1);
}
}
void readBytes(int descriptor, int count) {
if (read(descriptor, serialBuff_i, count) == -1) { // Read back data into buf[]
perror("Error reading ");
printf("Read error");
close(descriptor); // Close port if there is an error
exit(1);
}
}
void displayDecoderValues(int fd) {
tcflush(fd, TCIFLUSH);
serialBuff_o[0] = ' '; // space character (To wake up UART)
serialBuff_o[1] = '#'; // # character
serialBuff_o[2] = 'D'; // Station ID // Command to return encoder values
writeBytes(fd, 3);
usleep(100000);
printf("Now about to read data \r\n");
readBytes(fd, 12); //
usleep(500000);
printf("Data read \r\n");
if (serialBuff_i[0] ==0x00)
{
printf("Null character at start of input buffer \r\n");
}
// sleep(2);
strcpy (outbuff, serialBuff_i);
outbuff[16] = 0x00; // Write 0x00 to terminate string
printf(" \r\n");
printf (outbuff); //Print to screen
vbuff[0] = outbuff[0];
vbuff[1] = outbuff[1];
vbuff[2] = outbuff[2];
vbuff[3] = outbuff[3];
vbuff[4] = outbuff[4];
vbuff[5] = outbuff[5];
vbuff[6] = 0x2C; // Comma character
vbuff[7] = 0x00; //End of string marker
printf ("\n%d,", rnum);
printf (vbuff);
// Setup for writing to disk
FILE *fp;
int value;
fp = fopen (F_name , "ab"); // "ab" append binary
if (fp)
{
fprintf (fp,"\n%d,", rnum);
rnum ++;
fprintf (fp, vbuff);
fclose (fp); //close disk file
}
printf(" \r\n");
printf("Next ");
fflush(stdout); // Flush output
}
When the program hangs if data is list is the line " readBytes(fd, 12); " which is just after the line "printf("Now about to read data \r\n");" (These printf lines were added to find out where the program was hanging.)
Les.