Hello, I have been using the nRF24L01 Library to wirelessly transmit data from sensors to another Arduino and everything is working as intended. but recently I added another sensor the PM2.5 Air Quality Sensor by Adafruit which uses TX and RX connection and uses the Software Serial library. I can not get any reading from the sensor. I tried using the AltSoftware Serial but no luck.
Is this a known issue and is there a beginner-friendly way of receiving the data from Air Quality first and then transmit the data to another Arduino?
I can post code/pictures of the wiring diagram if need.
Shivam422:
I can post code/pictures of the wiring diagram if need.
Yes, we need to see your program and a wiring diagram - not photos of the actual wires, please.
There is also NeoSWSerial which may be worth trying.
My wild guess is that you may need better coordination between the reading of serial data and sending of nRF24 messages.
...R
//FLAME SENSOR
int analoog = A3; // define the flame sensor interface
//HUMIDITY & TEMPERATURE SENSOR
#include <Wire.h>
#include "Adafruit_HTU21DF.h"
Adafruit_HTU21DF htu = Adafruit_HTU21DF();
//PID-A12
int value = 0;
float voltage;
//CCS811 VOC SENSOR
#include "Adafruit_CCS811.h"
Adafruit_CCS811 ccs;
//PMS5003 Particle Sensor
#include <SoftwareSerial.h>
SoftwareSerial pmsSerial(0, 1);
//********************************************************************************
#include <nRF24L01.h>
#include <printf.h>
#include <RF24.h>
#include <RF24_config.h>
RF24 transmit (2,3); //create RF24 object called transmit
byte address [6] = "00001"; //set address to 00001
struct package //data package
{
float a0 = 0;
float a1 = 0;
float a3 = 0;
float a4 = 0;
float a5 = 0;
float CO2 = 0;
float TVOC = 0;
// Members for Particle Sensor
uint16_t framelen;
uint16_t pm10_standard, pm25_standard, pm100_standard;
uint16_t pm10_env, pm25_env, pm100_env;
uint16_t particles_03um, particles_05um, particles_10um, particles_25um, particles_50um, particles_100um;
uint16_t unused;
uint16_t checksum;
};
typedef struct package Package;
Package data;
//********************************************************************************
//*********************************SETUP******************************************
void setup() {
Serial.begin(115200);
Serial.println("hello");
transmit.begin();
transmit.openWritingPipe(address); //open writing pipe to address 00001
transmit.setPALevel(RF24_PA_MIN); //set RF power output to minimum
transmit.setDataRate(RF24_250KBPS); //set data rate to 250kbps
transmit.setChannel(100); //set frequency to channel 100
transmit.stopListening();
Wiring diagram for the PM2.5 particle sensor that uses software serial.
For software serial, I am using pins 0 and 1 b/c pins 2 and 3 being used.
I am not sure what the problem is. Thank you for your help!
You have not posted the complete program.
Have you been able to get data from the sensor with a simple program that just reads the sensor using SoftwareSerial? If not, that should be your starting point.
What microprocessor is on that Adafruit board?
...R
SoftwareSerial pmsSerial(0, 1);
Software serial on the hardware serial pins seems not very sensible to me.
struct package //data package
{
float a0 = 0;
float a1 = 0;
float a3 = 0;
float a4 = 0;
float a5 = 0;
float CO2 = 0;
float TVOC = 0;
// Members for Particle Sensor
uint16_t framelen;
uint16_t pm10_standard, pm25_standard, pm100_standard;
uint16_t pm10_env, pm25_env, pm100_env;
uint16_t particles_03um, particles_05um, particles_10um, particles_25um, particles_50um, particles_100um;
uint16_t unused;
uint16_t checksum;
};
Seems to long to be sent in one shot, but without code, who knows?
Whandall:
Software serial on the hardware serial pins seems not very sensible to me.
I had not noticed that.
The diagram shows a connection to Pin2.
...R
Robin2:
I had not noticed that.
So you overlooked the text (just as I did at first). ![]()
Shivam422:
For software serial, I am using pins 0 and 1 b/c pins 2 and 3 being used.
OP: that was a bad decision, like wasting the external IRQ pins to CS and CE.
Sorry about that, I thought I posted the full code. I have the full code below. *Note this is the transmission code.
I tested the particle sensor with pins 6-7 but it's still giving me zeros. I have attached the wiring diagram picture for other sensors that I am using.
//***********************SENSOR VARIABLE DECLARATIONS******************************
//FLAME SENSOR
int analoog = A3; // define the flame sensor interface
//HUMIDITY & TEMPERATURE SENSOR
#include <Wire.h>
#include "Adafruit_HTU21DF.h"
Adafruit_HTU21DF htu = Adafruit_HTU21DF();
//PID-A12
int value = 0;
float voltage;
//CCS811 VOC SENSOR
#include "Adafruit_CCS811.h"
Adafruit_CCS811 ccs;
//PMS5003 Particle Sensor
#include <SoftwareSerial.h>
SoftwareSerial pmsSerial(0, 1);
//********************************************************************************
#include <nRF24L01.h>
#include <printf.h>
#include <RF24.h>
#include <RF24_config.h>
RF24 transmit (2,3); //create RF24 object called transmit
byte address [6] = "00001"; //set address to 00001
struct package //data package
{
float a0 = 0;
float a1 = 0;
float a3 = 0;
float a4 = 0;
float a5 = 0;
float CO2 = 0;
float TVOC = 0;
// Members for Particle Sensor
uint16_t framelen;
uint16_t pm10_standard, pm25_standard, pm100_standard;
uint16_t pm10_env, pm25_env, pm100_env;
uint16_t particles_03um, particles_05um, particles_10um, particles_25um, particles_50um, particles_100um;
uint16_t unused;
uint16_t checksum;
};
typedef struct package Package;
Package data;
//********************************************************************************
//*********************************SETUP******************************************
void setup() {
Serial.begin(115200);
pmsSerial.begin(9600);
Serial.println("hello");
transmit.begin();
transmit.openWritingPipe(address); //open writing pipe to address 00001
transmit.setPALevel(RF24_PA_MIN); //set RF power output to minimum
transmit.setDataRate(RF24_250KBPS); //set data rate to 250kbps
transmit.setChannel(100); //set frequency to channel 100
transmit.stopListening();
//FLAME SENSOR
pinMode (analoog, INPUT) ;// output interface defines the flame sensor
//CCS811 VOC
if(!ccs.begin()){
Serial.println("Failed to start sensor! Please check your wiring.");
while(1);
}
Serial.println("Hello");
// Wait for the sensor to be ready
while(!ccs.available());
}
//********************************************************************************
//*************************************LOOP***************************************
void loop() {
Serial.println("Hello");
//FLAME SENSOR
data.a3 = analogRead(analoog);
//HUMIDITY & TEMPERATURE SENSOR
float temp = htu.readTemperature();
float rel_hum = htu.readHumidity();
data.a4 = temp;
data.a5 = rel_hum;
//PID-A12
value = analogRead(A0);
voltage = value * 5.0/1023;
data.a1 = voltage;
//CCS811 VOC Sensor
if(ccs.available()){
if(!ccs.readData()){
data.CO2 = ccs.geteCO2();
data.TVOC = ccs.getTVOC();
}
else{
data.CO2 = 0;
data.TVOC = 0;
}
}
Serial.print(data.a3);
Serial.println(data.a4);
Serial.println(data.a5);
Serial.println(data.a1);
Serial.println(data.CO2);
Serial.println(data.TVOC);
//Particle Sensor
if (readPMSdata(&pmsSerial)) {
// reading data was successful!
Serial.println();
Serial.println("---------------------------------------");
Serial.println("Concentration Units (standard)");
Serial.print("PM 1.0: "); Serial.print(data.pm10_standard);
Serial.print("\t\tPM 2.5: "); Serial.print(data.pm25_standard);
Serial.print("\t\tPM 10: "); Serial.println(data.pm100_standard);
Serial.println("---------------------------------------");
Serial.println("Concentration Units (environmental)");
Serial.print("PM 1.0: "); Serial.print(data.pm10_env);
Serial.print("\t\tPM 2.5: "); Serial.print(data.pm25_env);
Serial.print("\t\tPM 10: "); Serial.println(data.pm100_env);
Serial.println("---------------------------------------");
Serial.print("Particles > 0.3um / 0.1L air:"); Serial.println(data.particles_03um);
Serial.print("Particles > 0.5um / 0.1L air:"); Serial.println(data.particles_05um);
Serial.print("Particles > 1.0um / 0.1L air:"); Serial.println(data.particles_10um);
Serial.print("Particles > 2.5um / 0.1L air:"); Serial.println(data.particles_25um);
Serial.print("Particles > 5.0um / 0.1L air:"); Serial.println(data.particles_50um);
Serial.print("Particles > 10.0 um / 0.1L air:"); Serial.println(data.particles_100um);
Serial.println("---------------------------------------");
}
transmit.write(&data,sizeof(data)); //transmit the data
delay(1000);
}
// Particle Sensor Function
boolean readPMSdata(Stream *s) {
if (! s->available()) {
return false;
}
// Read a byte at a time until we get to the special '0x42' start-byte
if (s->peek() != 0x42) {
s->read();
return false;
}
// Now read all 32 bytes
if (s->available() < 32) {
return false;
}
uint8_t buffer[32];
uint16_t sum = 0;
s->readBytes(buffer, 32);
// get checksum ready
for (uint8_t i=0; i<30; i++) {
sum += buffer[i];
}
/* debugging
for (uint8_t i=2; i<32; i++) {
Serial.print("0x"); Serial.print(buffer[i], HEX); Serial.print(", ");
}
Serial.println();
*/
// The data comes in endian'd, this solves it so it works on all platforms
uint16_t buffer_u16[15];
for (uint8_t i=0; i<15; i++) {
buffer_u16[i] = buffer[2 + i*2 + 1];
buffer_u16[i] += (buffer[2 + i*2] << 8);
}
// put it into a nice struct :)
memcpy((void *)&data, (void *)buffer_u16, 30);
if (sum != data.checksum) {
Serial.println("Checksum failure");
return false;
}
// success!
return true;
}
Who frankensteined that horrible code?
It's so wrong in so many places.
SoftwareSerial pmsSerial(0, 1);
Serial.begin(115200);
pmsSerial.begin(9600);
:o
struct package //data package
{
float a0 = 0;
float a1 = 0;
float a3 = 0;
float a4 = 0;
float a5 = 0;
float CO2 = 0;
float TVOC = 0;
// Members for Particle Sensor
uint16_t framelen;
uint16_t pm10_standard, pm25_standard, pm100_standard;
uint16_t pm10_env, pm25_env, pm100_env;
uint16_t particles_03um, particles_05um, particles_10um, particles_25um, particles_50um, particles_100um;
uint16_t unused;
uint16_t checksum;
};
typedef struct package Package;
Package data;
Too long to be sent in one packet.
transmit.write(&data,sizeof(data)); //transmit the data
The typedef is not needed, here you could even write
struct Package {
...
} data;
voltage = value * 5.0/1023;
Correct is 1024, the 5.0 are rarely 5.0 but that does not matter for ratiometric stuff.
// put it into a nice struct :)
memcpy((void *)&data, (void *)buffer_u16, 30);
Correct would have been:
// put the generated values into the sensor float variables
// idea: don't bother reading the values in the first place
if (sum != data.checksum) {
As data.checksum is never set, this will nearly always be true.
delay(1000);
:o
Hello, I understand that my code is really bad but, it is my first time working with these libraries and sensors.
If possible can you elaborate on some of the code?
SoftwareSerial pmsSerial( 8, 9 ); <- what if I use AltSerialSoftware with pins 8 and 9? would that work?
Serial.begin(115200);
pmsSerial.begin(9600); <- would this have to be the same baud rate (115200).
Also If the data is too long to send in one package. can I have two different struct data and send them separately?
Code for the Particle Sensor was provided so I tried to just combine my code with what was provided seen below. I guess this was a bad idea!?
Thank you for all your help so far. I really want to learn from these mistakes.
// On Leonardo/Micro or others with hardware serial, use those!
// uncomment this line:
// #define pmsSerial Serial1
// For UNO and others without hardware serial, we must use software serial...
// pin #2 is IN from sensor (TX pin on sensor), leave pin #3 disconnected
// comment these two lines if using hardware serial
#include <SoftwareSerial.h>
SoftwareSerial pmsSerial(2, 3);
void setup() {
// our debugging output
Serial.begin(115200);
// sensor baud rate is 9600
pmsSerial.begin(9600);
}
struct pms5003data {
uint16_t framelen;
uint16_t pm10_standard, pm25_standard, pm100_standard;
uint16_t pm10_env, pm25_env, pm100_env;
uint16_t particles_03um, particles_05um, particles_10um, particles_25um, particles_50um, particles_100um;
uint16_t unused;
uint16_t checksum;
};
struct pms5003data data;
void loop() {
if (readPMSdata(&pmsSerial)) {
// reading data was successful!
Serial.println();
Serial.println("---------------------------------------");
Serial.println("Concentration Units (standard)");
Serial.print("PM 1.0: "); Serial.print(data.pm10_standard);
Serial.print("\t\tPM 2.5: "); Serial.print(data.pm25_standard);
Serial.print("\t\tPM 10: "); Serial.println(data.pm100_standard);
Serial.println("---------------------------------------");
Serial.println("Concentration Units (environmental)");
Serial.print("PM 1.0: "); Serial.print(data.pm10_env);
Serial.print("\t\tPM 2.5: "); Serial.print(data.pm25_env);
Serial.print("\t\tPM 10: "); Serial.println(data.pm100_env);
Serial.println("---------------------------------------");
Serial.print("Particles > 0.3um / 0.1L air:"); Serial.println(data.particles_03um);
Serial.print("Particles > 0.5um / 0.1L air:"); Serial.println(data.particles_05um);
Serial.print("Particles > 1.0um / 0.1L air:"); Serial.println(data.particles_10um);
Serial.print("Particles > 2.5um / 0.1L air:"); Serial.println(data.particles_25um);
Serial.print("Particles > 5.0um / 0.1L air:"); Serial.println(data.particles_50um);
Serial.print("Particles > 10.0 um / 0.1L air:"); Serial.println(data.particles_100um);
Serial.println("---------------------------------------");
}
}
boolean readPMSdata(Stream *s) {
if (! s->available()) {
return false;
}
// Read a byte at a time until we get to the special '0x42' start-byte
if (s->peek() != 0x42) {
s->read();
return false;
}
// Now read all 32 bytes
if (s->available() < 32) {
return false;
}
uint8_t buffer[32];
uint16_t sum = 0;
s->readBytes(buffer, 32);
// get checksum ready
for (uint8_t i=0; i<30; i++) {
sum += buffer[i];
}
/* debugging
for (uint8_t i=2; i<32; i++) {
Serial.print("0x"); Serial.print(buffer[i], HEX); Serial.print(", ");
}
Serial.println();
*/
// The data comes in endian'd, this solves it so it works on all platforms
uint16_t buffer_u16[15];
for (uint8_t i=0; i<15; i++) {
buffer_u16[i] = buffer[2 + i*2 + 1];
buffer_u16[i] += (buffer[2 + i*2] << 8);
}
// put it into a nice struct :)
memcpy((void *)&data, (void *)buffer_u16, 30);
if (sum != data.checksum) {
Serial.println("Checksum failure");
return false;
}
// success!
return true;
}

