Serial Programming for POSIX, non-standard baud rate - serial-port

I am implementing a simple program in unix that takes a RS232 input and saves it into a file.
I've used these references:
http://en.wikibooks.org/wiki/Serial_Programming/Serial_Linux and
http://www.easysw.com/~mike/serial/serial.html
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <string.h>
int main(int argc,char** argv)
{
struct termios tio;
struct termios stdio;
int tty_fd;
fd_set rdset;
FILE *file;
unsigned char c;
memset(&tio,0,sizeof(tio));
tio.c_iflag=0;
tio.c_oflag=0;
tio.c_cflag=CS8|CREAD|CLOCAL; // 8n1, see termios.h for more information
tio.c_lflag=0;
tio.c_cc[VMIN]=1;
tio.c_cc[VTIME]=5;
tty_fd=open("/dev/ttyS1", O_RDWR | O_NONBLOCK);
speed_t baudrate = 1843200; //termios.h: typedef unsigned long speed_t;
cfsetospeed(&tio,baudrate);
cfsetispeed(&tio,baudrate);
tcsetattr(tty_fd,TCSANOW,&tio);
file = fopen("out.raw", "wb");
while (1)
{
if (read(tty_fd,&c,1)>0) {
fwrite(&c, 1, 1, file);
fflush(file);
}
}
//close(tty_fd);
}
I've tried at 921'600 bps and at 1'843'200 bps, and it works correctly.
However, it does not work if I set-up a non-standard baud rate, for instance 1'382'400 bps.
i.e., this works:
cfsetospeed(&tio,1843200); cfsetispeed(&tio,1843200);
but this doesn't (it gets random data):
cfsetospeed(&tio,1382400); cfsetispeed(&tio,1382400);
What can be the problem?
I've tried with WinXP (using the WIN32 functions CreateFile, SetCommState and ReadFile),
and it works correctly (with 1'843'200 bps and also with the non-standard 1'382'400 bps)
ps: if you ask why I need to set-up this non-standard baud-rate, it's because of a special machine that works only at this speed.
Regards,
David

According to mans cfsetospeed accepts macros, B0, B50 , B75 and so on which are not equal to actual baudrate values (B9600 is equal to 15 e.g.). So passing random integer will cause undefined behaviour.
cfsetospeed() sets the output baud rate stored in the termios
structure pointed to by termios_p to speed, which must be one of
these constants: B0, B50 and so on

Related

3rd argument is ignored when I use memcpy in C

I'm a beginner in C and try to use memcpy to send byte in order to transfer data to server. It seems like no matter what I choose for 3rd argument. It's always the same.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char myChar[100] = "Hello world! ABC is an online sandbox that makes it easy to try out";
char myChar2[100];
memcpy(myChar2, myChar, 3);
printf("%s", myChar);
return 0;
}
This is the result.
Hello world! ABC is an online sandbox that makes it easy to try out
memcpy is working correctly.
The problem with your code is that you are printing myChar instead of myChar2.
printf("%s", myChar2); // Hel
Working example

'dht' does not name a type

I'm running this code and it keeps giving me this error. Below I'm putting the code. It's a weather station arduino code. I already added and imported the libraries but I keep getting the same error.
#include <stdlib.h>
#include <SoftwareSerial.h>
#include <DHT.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP085_U.h>
#define SSID "DroidSpot" //replace XXXXX by your router SSID
#define PASS "gggg" //replace YYYYY by your router password
#define IP "184.106.153.149" // thingspeak.com IP
#define DHT22_PIN 2
String GET = "GET /update?key=GDQ0LAAXLDGYMXW1&field1="; //replace ZZZZZ by your ThingSpeak channel write key
SoftwareSerial monitor(10, 11); //Serial communication to ESP8266 module (RX, TX)
dht DHT;
Adafruit_BMP085_Unified bmp = Adafruit_BMP085_Unified(10085);
.....
//read other sensors
char buffer[10];
//light sensor
float luminance = analogRead(luminancePin);
//UV sensor
float uv = analogRead(uvPin);
uv = uv * 0.0049; //convert values to volts
uv = uv * 307; //convert to mW/m²
uv = uv/200; //calculate UV index
//temperature and humidity
int chk = DHT.read22(DHT22_PIN);
float humidity = DHT.humidity;
float temperature = DHT.temperature;
//pressure and temperature1
sensors_event_t event;
bmp.getEvent(&event);
float pressure = 0;
float temperature1 = 0;
if (event.pressure)
{
pressure = event.pressure;
bmp.getTemperature(&temperature1);
}
The error is in the dht DHT; line. It is:
'dht' does not name a type
Check which library you are using. You might be trying to combine two different source code examples using two different libraries.
The body of your code seems to suggest you want a different library. This library defines the type you want: https://github.com/RobTillaart/DHTstable with the appropriate fields as Juraj has pointed out.
You'll have to change your header(s) as well, as here. Especially:
#include <dht.h>
If you do intend to use the Adafruit library, as your includes seem to suggest:
As the error says, there's no class or type definition for dht. The class name is DHT, not dht.
See DHT.h in the Github repo, and this example in the same repo.
Switch the tokens around:
DHT dht;
and refactor all other DHT to dht. You'll also need to make sure you're calling the right class method, as read22 is not defined in this library.

What is the baudrate limit in the termios.h?

This is a quick snippet of code from a serial program I've been working with to interface with a microcontroller. The code has been verified to work but I want to add the global define to make the code more modular. The excerpt shown works, until I replace the 'B1000000' in the 'cfsetispeed' with the global 'BAUDRATE'.
// Globals
struct termios tty;
char BAUDRATE = B1000000; // 1,000,000
// All of the other details omitted ( int main (), etc. )
cfsetospeed (&tty, BAUDRATE);
cfsetispeed (&tty, B1000000);
So two questions come to mind:
1) I read that Termios only allows for select baudrates, the max listed is 230,400. How is it that 1,000,000 is allowed?
2) Why would cfsetispeed( ) not allow a global char definition as an argument?
Termios accepts baudrates as a bit flag but there are other baud rates available to the speed_t structure in termbits.h (linked code for kernel v5.3.11) that are not listed on the man7 page or linux.die.net that range from 460800 to 4000000.
EDIT: The previous link provided died and I managed to find the equivalent in the newer version so here is the excerpt in case it dies again:
#define CBAUDEX 0010000
#define BOTHER 0010000
#define B57600 0010001
#define B115200 0010002
#define B230400 0010003
#define B460800 0010004
#define B500000 0010005
#define B576000 0010006
#define B921600 0010007
#define B1000000 0010010
#define B1152000 0010011
#define B1500000 0010012
#define B2000000 0010013
#define B2500000 0010014
#define B3000000 0010015
#define B3500000 0010016
#define B4000000 0010017
cfsetispeed accepts baud rates as being of type speed_t. speed_t is typedef'ed to be an object of type "unsigned int" in termbits.h, which is larger (32-bits vs 8-bits) than the char you are passing in.

qUncompress: Z_DATA_ERROR: Input data is corrupted

I am using the qUncompress of Qt and head to a problem I cant find more information to solve it.
Here is my code:
#include <QCoreApplication>
#include <QByteArray>
#include <QFile>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QFile f("/user/XXXXX/home/AgeRegression"); // hided
if (f.exists())
qDebug() << "File exists";
else
qDebug() << "Missing file";
f.open(QIODevice::ReadOnly);
QByteArray qb = f.readAll();
qb = qUncompress(qb);
qDebug()<<"Successfully";
const char *qt_version = qVersion();
qDebug()<< QString(qt_version);
return a.exec();
}
Here is the output:
File exists
qUncompress: Z_DATA_ERROR: Input data is corrupted
Successfully
"5.3.2"
From the documentation of Qt(you can find here):
Note: If you want to use this function to uncompress external data that was compressed using zlib, you first need to prepend a four byte header to the byte array containing the data. The header must contain the expected length (in bytes) of the uncompressed data, expressed as an unsigned, big-endian, 32-bit integer.
So what exactly should I do here? Do I have to find the length of uncompressed data (is there a way? I just have compressed data.)? An example would be appreciated.
qUncompress is not a general-purpose decompression function. It should only be used with data compressed with qCompress.
If your data was compressed using something other than qCompress, you must decompress it in the same way - using zlib directly, using an external utility, etc.
By using qUncompress like you do, you're relying on an implementation detail that may change at any moment. Don't do that. Simply assume that qCompress is a black box and uses an alien compressor implementation that nobody else does.

printf byte to hex string strange output

The following simple code produces strange output:
#include <stdio.h>
#include <string.h>
#include "/tmp/sha.h"
#define DIGEST 64
//taken from coreutils 8.5 - produces 64-byte sha digest and puts it into resblock
extern int sha512_stream(FILE *stream, void *resblock);
int main(int argc, char** argv) {
char sha[DIGEST];
memset(sha, 0, DIGEST);
FILE *stream;
stream = fopen("/bin/less", "r");
sha512_stream(stream, (void *) sha);
fclose(stream);
char buf[2] = {10, 32};
printf("%02x\n", sha[0]);
printf("%02x\n", buf[0]);
return 0;}
Gives the output:
ffffffa9 0a
The first byte of sha is A9, but where are the padding F's coming from?
On Ubuntu Linux 10.10 with gcc 4.4.5.
(char) defaults to (signed char) on Linux x86, and because printf() uses stdarg the (signed char) is being promoted implicitly to (int) resulting in sign extension. You'll need to declare it (unsigned char) to get the expected behavior. (There is no way to pass type information through stdarg, so default promotions are performed on arguments.)

Resources