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.
Related
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.
I'm trying to simply get an analog reading from A0 on my arduino Pro mini, but I cannot get the values stored in the adc register.
What is supposed to happen is the analog signal will be put in registers ADCL & ADCH and then the ADC interrupt will trigger.
I have a voltage divider set up on A0 that should just read 2.5V but my interrupt is not triggering and i cannot get values from ADCH or ADCL. I could get a reading in arduino so I know the hardware works. when i run this program i get a continuous print of 0 to my terminal which tells me the values of low and high never change as they should in the interrupt.
Here is my code:
# define F_CPU 16000000L
#include "time.h"
#include <avr/io.h>
#include <math.h>
#include <util/delay.h> // including the avr delay lib
#include <util/delay.h> // Including the avr delay lib
#include "usart.h"
#include "usart.cpp"
#include <stdio.h>
#include <avr/interrupt.h>
uint8_t low,high;
int main(void)
{
TCCR0B = (1<<CS02) | (1<<CS00);
USART_Init(MYUBRR);
DDRC = 0x0 ;
ADCSRA = (1<<ADEN) | (0<<ADIF); //activate adc & clear ADIF
ADMUX = (0<<ADLAR); //keep right adjusted
ADMUX = (1<<REFS0) | (0<<MUX2) | (0<<MUX1) | (0<<MUX0);//set ref as vcc, input as 0
ADCSRA = (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);//enable adc interrupt & divide clock by 124
DIDR0 = (0<<ADC0D);
sei();
ADCSRA = (1<<ADSC);//begin conversion
while (1)
{
while(ADSC==1)//wait for conversion to complete
{
sei();
}
USART_Send_int(low);
USART_Send_int(high);
_delay_ms(100);
ADCSRA = (1<<ADSC);
}
}
ISR(ADC_vect) //interrupt to trigger when conversion is complete
{
low = ADCL;
high = ADCH;
//ADCSRA = (1<<ADSC);
}
You should declare low and high as volatile since you are accessing them from an interrupt and the main loop:
volatile uint8_t low;
volatile uint8_t high;
Otherwise, the compiler is free to optimize your loop by moving the readings of those variables to be before the loop.
Alternatively, you could try putting a memory barrier in your loop, but that is the less-traveled road: most embedded developers tend to just use volatile.
I didn't test your code so there might still be other errors.
To debug this further, you should try putting low = 44; and high += 1; in your interrupt just to make sure the interrupt is running.
I'm experiencing unexpected results using wiringPi's wiringPiI2CWriteReg16() function, and I'm not sure if it's due to incorrect usage, or something else. This is the declaration for the function:
extern int wiringPiI2CWriteReg16 (int fd, int reg, int data);
There are notes within the wiringPiI2C.c file that state it resembles Linux's SMBus code, if that helps.
On my Arduino (both an Uno R3 and a Trinket Pro), I am running this pared-down sketch:
#include <Wire.h>
#define SLAVE_ADDR 0x04
void receive_data (int num_bytes){
Serial.print("bytes in: ");
Serial.println(num_bytes);
while(Wire.available()){
int data = Wire.read(); // tried char, uint8_t etc
Serial.println(data);
}
Serial.print("\n");
}
void setup() {
Serial.begin(9600);
Wire.begin(SLAVE_ADDR);
Wire.onReceive(receive_data);
}
void loop() {
delay(500);
}
I would think that Wire.read() would break things apart at the byte boundary, but that's not occurring in my case. Perhaps this is my issue... a misunderstanding.
Nonetheless, I have this C code (requires wiringPi v2.36+ to be installed):
// word.c
#include <wiringPiI2C.h>
void main (){
int fd = wiringPiI2CSetup(0x04);
wiringPiI2CWriteReg16(fd, 0x00, 255);
wiringPiI2CWriteReg16(fd, 0x01, 256);
}
Compiled like this:
gcc -o word word.c -lwiringPi
When run, ./word, I receive the following on my Arduino's serial output:
bytes in: 3
0
255
0
bytes in: 3
1
0
1
In the first call to wiringPiI2CWriteReg16(), I expect the first byte in the output to be zero (0x00) as that's the register address I'm requesting. The second byte (255) is also correct. The third byte (0) is meaningless from what I can tell (as I'm only sending in one byte as data).
However, in the second call to that function, I do get the correct output for the register (first byte as 0x01 == 1), but the second byte is zero, and the third byte has what appears to be the correct remainder (255 == one byte, + 1). The problem is, is that the second byte is 0.
The exact same effect happens if I pass in 511 or for that matter, any number as the data in the call.
My question is whether I'm missing something glaringly obvious (I'm relatively new to C and Arduino), and/or if I can get some pointers on how to troubleshoot this more thoroughly.
I found that the problem was in my Arduino code. In the official Raspi forums, Gordon tipped me off that the bytes are read in separately, LSB first. Throughout all of my searching, I hadn't come across that, and really didn't quite understand what was happening. After changing my I2C read loop code in my Arduino sketch to this:
while(Wire.available()){
Wire.read(); // throw away register byte
int16_t data = Wire.read(); // LSB
data += Wire.read() << 8; // MSB
Serial.print("data: ");
Serial.println(data);
}
...everything works. In effect, that's at least one way to read two-byte values over I2C on the Arduino and put the bytes back together.
My question is self-explanatory. I'm grepping for ages and I can't find it ...
-------------------------------------------------------------------------------
lispobj is not a struct, just a typedef. It is defined in src/runtime/runtime.h currently after line 234:
#if 64 == N_WORD_BITS
#define LOW_WORD(c) ((pointer_sized_uint_t)c)
#define OBJ_FMTX "lx"
typedef uintptr_t lispobj;
#else
#define OBJ_FMTX "x"
#define LOW_WORD(c) ((long)(c) & 0xFFFFFFFFL)
/* fake it on alpha32 */
typedef unsigned int lispobj;
#endif
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