Arduino AltSoftSerial press enter to read/print altSerial? - serial-port

Don't know if there are any Arduino-wizards around here on StackOverflow, but I'm just gonna try and find one! I'm having issues understanding some code, and why I can't automate the process instead of pressing Enter.
I'm using an RFID reader to read some tags, and using the altSoftSerial library. However, in order to print the tagID to my serial, I need to press Enter. And for the love of God I can't figure out why that is. Isn't it possible to check the altSerial.read for a certain ID, and print it when it appears? Cause when I print the serial automatically I just get a lot of 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' noise...
#include <AltSoftSerial.h>
AltSoftSerial altSerial;
char txrxbuffer[255];
char get_readID[] = { 0xAA , 0x00, 0x03, 0x25, 0x26, 0x00, 0x00, 0xBB };
void setup()
{
Serial.begin(9600);
Serial.println("Hit Enter to read the RFID number");
altSerial.begin(9600);
}
void loop() // run over and over
{
int counter = 0;
if (Serial.available()){
Serial.read();
Serial.println("");
for (counter =0 ; counter < 8 ; counter++){
char tagID = get_readID[counter];
altSerial.write(tagID);
}
}
if (altSerial.available())
Serial.print(altSerial.read(),HEX);
}

seems like before reading a tag, you have to send a specific code to your rfod reader, code that you are sending in the first if; if at least one char is received on Serial (from pc), it read the char (but does not store it, it does so to clean the input buffer, so every char is a read, any char is good), and then send this code. The second if look for the answer and if present send it back to pc. So just send that code from setup() and then after every read, or look for an alternative commad that remain enabled

Related

How to wire a CO2 sensor to an arduino card and show / save its data

I'm trying for the first time to use Arduino for a school project, but I don't know much about it, so I hope you could help me.
I bought a CO2 sensor and I want to wire it to a "ELEGOO MEGA 2560 r3" (claimed to work as an Arduino Uno) to read the values of the sensor. More specifically I will have this kit:
° https://www.amazon.fr/ELEGOO-D%C3%A9marrage-dUtilisation-D%C3%A9butants-Professionnels/dp/B01JD043XC/ref=sr_1_1?__mk_fr_FR=%C3%85M%C3%85%C5%BD%C3%95%C3%91&dchild=1&keywords=ELEGOO+Mega+2560+R3+Kit+de+D%C3%A9marrage+Ultime+Le+Plus+Complet+avec+Manuel+d%27Utilisation+Fran%C3%A7ais+pour+D%C3%A9butants+et+Professionnels+DIY+Compatible+avec+Arduino+IDE&qid=1613500133&s=computers&sr=1-1
And this sensor:
° https://www.winsen-sensor.com/d/files/infrared-gas-sensor/mh-z14a_co2-manual-v1_01.pdf
(° https://wiki.dfrobot.com/Gravity__Analog_Infrared_CO2_Sensor_For_Arduino_SKU__SEN0219#target₆
° https://docs.rs-online.com/c20e/A700000006944474.pdf) → this is another sensor which seems the same but may not be the same.
I want to know if I have to purchase another component, or it will be okay to collect the data of the sensor. I saw it had 19 circle pads and 8 pads with a wire to connect them.
PIN Description
Pad1/Pad15/Pad17/Pad23 Vin Voltage Input
Pad2/Pad3/Pad12/Pad16/Pad22 GND
Pad4/Pad21 AnalogOutput(0.4~2V)
Pad6/Pad26 PWM
Pad8/Pad20 HD(Zerocalibration,lowlevelformorethan7secondsvalid)
Pad7/Pad9 NC
Pad11/Pad14/Pad18/Pad24 UART(RXD)TTLLevelinput
Pad10/Pad13/Pad19/Pad25 UART(TXD)TTLLeveloutput
The GND is the Ground, but I don't really know the others and how to wire them to my "ELEGOO MEGA 2560 r3" to take the data after.
If found this link with someone explaining how he did, but I don't have the same board. https://www.hackster.io/kritch83/getting-started-with-the-mh-z14a-co2-detector-e96234
" For the physical hookups we will use four wires: power, ground, RX, & TX and those are pads 19, 18, 17, & 16 but many are redundant. Connect as follows to your board:
5v DC -----> Pad 17
Ground ---> Pad 16
TX ----------> Pad 18
RX ----------> Pad 19"
I think I just have to use the same, but I don't know where to put them in my board.
For the code I want to print the value of CO2 in the air each x seconds and save the times and values in a file to create a graph after using python (I know how to code python but not Arduino). I saw this code on the tutorial I linked before.
#include <Arduino.h>
#include <ESP8266WiFi.h> // for OTA, Blynk, & restart command
#include <BlynkSimpleEsp8266.h> // for blynk
#include <ESP8266mDNS.h> // for OTA
#include <WiFiUdp.h> // for OTA
#include <ArduinoOTA.h> // for OTA
char auth[] = "token";
char ssid[] = "IoT";
char pass[] = "password";
byte cmd[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79}; // get gas command
byte cmdCal[9] = {0xFF, 0x01, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78}; // calibrate command
char response[9]; // holds the recieved data
int CO2ppm = 0;
unsigned long warmingTimer = 0;
unsigned long timer1 = 0;
void setup()
{
Serial.begin(9600); // Setup a serial connection with the sensor
Blynk.begin(auth, ssid, pass);
wifi_station_set_hostname("ESP-CO2 Monitor"); // network device hostname
ArduinoOTA.setHostname("ESP-CO2 Monitor"); // for OTA
ArduinoOTA.begin(); // for OTA
warmingTimer = millis(); // initilize warmup timer
}
void loop()
{
Blynk.run();
ArduinoOTA.handle(); // for OTA
while (millis() - warmingTimer < 310000)
{
Blynk.run();
ArduinoOTA.handle(); // for OTA
if (millis() - timer1 > 1000)
{
Blynk.virtualWrite(V2, (310000 - (millis() - warmingTimer)) / 1000); // counts down till the sensor is ready
timer1 = millis();
}
}
if (millis() - timer1 > 15000) // runs every 15 sec
{
getReadings();
maint();
timer1 = millis();
}
} // loop
void getReadings()
{
while (Serial.available()) // this clears out any garbage in the RX buffer
{
int garbage = Serial.read();
}
Serial.write(cmd, 9); // Sent out read command to the sensor
Serial.flush(); // this pauses the sketch and waits for the TX buffer to send all its data to the sensor
while (!Serial.available()) // this pauses the sketch and waiting for the sensor responce
{
delay(0);
}
Serial.readBytes(response, 9); // once data is avilable, it reads it to a variable
int responseHigh = (int)response[2];
int responseLow = (int)response[3];
CO2ppm = (256 * responseHigh) + responseLow;
Blynk.virtualWrite(V0, CO2ppm);
}
void calibrate()
{
Serial.write(cmdCal, 9);
delay(3000);
}
void maint()
{
int rssi = wifi_station_get_rssi();
Blynk.virtualWrite(V12, rssi);
}
BLYNK_WRITE(V10)
{
byte cali = param.asInt();
if (cali)
{
calibrate();
}
}
BLYNK_WRITE(V11) // restart chip
{
byte reset = param.asInt();
if (reset)
{
ESP.restart();
}
}
I don't understand it all, what means "AOT" ? Furthermore, I found that website https://arrayofthings.github.io/, but I don't really understand why I need this to read the value of a sensor? I have the same issue with "Blinks" or "ArduinoOTA" (https://blynk.io/ ?). I guess it is to have a cool app, but it's a bit too much I think, I just have to display (in the terminal or on a screen as there's a screen in the box, but I may not be able to use a screen while I even can't figure how to wire my sensor to my board) and save data and then have them in a text file for example to use it with Python and create a graph, I don't need an app or anything like that.
I also need to calibrate it and if I understand well I just have to ask the sensor to do it by himself by sending this weir command? "0xFF, 0x01, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78" like that "Serial.write(cmdCal, 9);"?
I don't really understand this code, as I never used Arduino it seems a little complicated to me, could someone help me to understand it or help me to simplify it to just have 2 commands, one that print the value each seconds (I may be able to save it by copy and paste it after in a text file but if the code do it that's better) and calibrate?
I'm sorry for all this questions, I'm a beginner in Arduino, so I hope someone will help me :)
Have a good day, hinzelin
Serial.begin(9600);
This command instructs Arduino Serial interface to setup communication with 9600bps baud rate. This is a prerequisite for the subsequent Serial commands Serial.Print. If you have connected your Arduino with a PC, you can see them on a terminal emulator.
This is the idea of calibration. Based on the graph that the manufacturer has provided, you can see that the output from the Sensor is 0.4v when there is no CO2. Even though it is the specified output this value can vary, as an example it can be 0.35v or 0.43v with 0 CO2. The manufacturer recommends to turn on the sensor in a 0 CO2 environment periodically, and adjust the voltage or the ADC value in your code in a way that it correctly represents the 0 value.

Reading char sent from wireless transmitter and creating switch case

I'm trying to transmit a char wirelessly and have the receiver read that char through serial in order to create a switch statement.
When trying to convert into int, I get the same int value no matter what char I type into the html text box. Serial.print(buffer); is displaying the right char. All help appreciated.
This is the char I'm inputting, and the result in the serial
Let's try this way. After convert "buffer" from "char"-->"int".You can check if h is digital or not before doing something.
//..Your code..//
//..Your code..//
//..Your code..//
int h = (int)buffer;
if (isDigit(h))
{
//Do something;
}

Write an array of bytes to EEPROM from PROGMEM

I'm trying to store an array of LED patterns to EEPROM, to later write to an external flash module. Below is my header file containing the patterns.
#ifndef DefaultPatterns_h
#define DefaultPatterns_h
#define DEFAULT_SIZE 147
const byte defaultData[DEFAULT_SIZE] PROGMEM ={225,112,111,};
#define RAINBOWPIXEL_SIZE 972
const byte rainbowpixelData[RAINBOWPIXEL_SIZE] PROGMEM ={255,0,0,0,0,0,0};
#endif
I've cut some bytes out from the above patterns as they are too long for this post.
Below is my sketch that is taken from ESP8266 EEPROM example library and I'm trying to use it as a starting point. I've commented out some things I've tried. Remember the patterns are in a header file.
#include "EEPROM.h"
#include "defaultPatterns.h"
int addr = 0;// address of EEPROM to write to
void setup() {
EEPROM.begin(512);
}
void loop() {
Serial.begin(9600);
//const byte defaultData[] = PROGMEM(defaultData,DEFAULT_SIZE );
// write the value to the appropriate byte of the EEPROM.
// these values will remain there when the board is
// turned off.
// EEPROM.write(addr, val);
//EEPROM.write(addr,byte (defaultData)) sizeof(defaultData));
//EEPROM.write ( 0, (byte *)defaultData), sizeof(defaultData)));
const char pattern = defaultData ;
EEPROM.write(addr, pattern);
// advance to the next address. There are 512 bytes in
// the EEPROM, so go back to 0 when we hit 512.
// save all changes to the flash.
addr = addr + 1;
if (addr == 512) {
addr = 0;
EEPROM.commit();
}
delay(100);
}
I've tried all sorts of different ways, but I'm getting errors and syntax errors.
I've tried to do this myself but I'll be at it forever. Any help that would be great.
I'm trying to build a LED controller that can store lots of patterns in the form of the patterns in the header file and play them back via a WS2812B strip of LEDs on button press. I've a long way to go.
Why use flash you ask? Space, I need lots of space. I know flash wears out faster, but I can replace it for a few bucks.
Look at the definition of EEPROM.write() - it only writes one byte. You need to use a for loop or EEPROM.put().

Raspi I2C communication with Arduino issues with wiringPi

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.

Docklight and Arduino serial communication (sending hex through RS232)

I have the following code (I'm using Arduino IDE and a NodeMCU with a MAX3232):
#include <SoftwareSerial.h>
SoftwareSerial RS232Serial(D1, D2); // RX | TX
void setup() {
Serial.begin(9600);
while (!Serial);
RS232Serial.begin(9600);
while (!RS232Serial);
}
void loop() {
Serial.println("Sending msg...");
char msg[] = {0x7E, 0x00, 0x78, 0xF0, 0x7E};
RS232Serial.write(msg, sizeof(msg));
Serial.println("Waiting incomming message:");
while(RS232Serial.available() <= 0) {
delay(1);
}
while(RS232Serial.available() > 0) {
Serial.print(RS232Serial.read(), HEX);
}
Serial.println("");
Serial.println("------------ END -----------");
}
I'm using Docklight to test the communication. So far I'm able to receive the HEX that the NodeMCU boards sends first char msg[] = {0x7E, 0x00, 0x78, 0xF0, 0x7E};. But I'm unable to receive the data properly from Docklight.
The HEX I'm trying to send from Docklight is 7E 00 00 70 15 7E. Debugging with serial monitor, sometimes I receive just 7E and sometimes 0FF, never the complete message. Baud rate, start/stop bits and parity are set to default.
What's wrong with my code?
One reason for not working as expected is:
You are processing the answer as soon as one byte has appeared in the receive buffer.
There is a related example in the Docklight Application Note Arduino Serial Communication - check the code listing on page 5. It makes use of the Arduino SerialEvent() function to collect the incoming telegram byte-per-byte. Only after receiving the end of telegram mark (here: a line feed "\n" character), it sets a flag that tells the code in the main loop() to do something with the accumulated data telegram.
The SerialEvent approach used in the Docklight exampleis not a must. You can solve this inside loop() alone, too. But you certainly need to change the
while(RS232Serial.available() <= 0) {
...
while(RS232Serial.available() > 0) {
parts to something that will wait until a full telegram has been received (or a timeout has occurred).
Now what irritates me still is that you write you sometimes receive "0FF" even though you never send it from Docklight. This could indicate still a second problem on the actual RS232 communication, but it's hard to guess without extra information.
But re-working the telegram receiving part as described above should already make things much clearer and then the source of the "0FF" is probably more obvious.
while(RS232Serial.available() <= 0) {
delay(1);
}
You are only waiting for the serial buffer to have at least 1 byte, but you are not guaranteed that your full message (6 bytes) will be present, when you call RS232Serial.available().
You should wait for the serial buffer to accumulate at least 6 bytes, before you try to read them.
while(RS232Serial.available() < 6) {
delay(1);
}
They you can read the full buffer with:
while(RS232Serial.available() > 0) {
Serial.print(RS232Serial.read(), HEX);
}
or only 6 bytes with:
for (int i=0; i<6; i++) {
Serial.print(RS232Serial.read(), HEX);
}
I don't know about your 0FF, but Serial.print(RS232Serial.read(), HEX) doesn't zero pad the hex string and this could actually be 00 0F 0F or 00 FF.
You should print out the bytes with:
byte b = RS232Serial.read();
if (b < 16) Serial.print('0'); // zero pad
Serial.print(b, HEX);
Serial.print(' '); // add space after each byte

Resources