Hello! I am currently working on code for a university project, and have been troubleshooting this code for quite a while, I want to see the data from the mod serial, then after from the _sensor serial. They both work independently, but as soon as I add the line _sensor.listen(), mod.available becomes false. I have no idea why this happens and I would love some help. Thank you!!Use code tags to format code for the forum
#include <SoftwareSerial.h>
#include <Wire.h>
#define RE 8
#define DE 7
const byte code[] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x03, 0x05, 0xCB};
byte values[11];
SoftwareSerial mod(2, 3);
SoftwareSerial _sensor(10, 11);
int waterReturn = -1;
float tempReturn = -1;
float humidityReturn = -1;
void setup()
{
Serial.begin(9600);
mod.begin(9600);
_sensor.begin(9600);
pinMode(RE, OUTPUT);
pinMode(DE, OUTPUT);
}
void loop() {
unsigned int nitrogen = 0;
unsigned int phosphorus = 0;
unsigned int potassium = 0;
byte val;
mod.listen();
digitalWrite(DE, HIGH);
digitalWrite(RE, HIGH);
delay(10);
if (mod.write(code, sizeof(code)) == 8)
{
digitalWrite(DE, LOW);
digitalWrite(RE, LOW);
for (byte i = 0; i < 11; i++)
{
//Serial.print(mod.read(),HEX);
values[i] = mod.read();
Serial.print(values[i],HEX);
}
Serial.println();
nitrogen = (((int)(values[3]))<<8) + ((int)(values[4]));
phosphorus = (((int)(values[5]))<<8) + ((int)(values[6]));
potassium = (((int)(values[7]))<<8) + ((int)(values[8]));
Serial.print("nitrogen =");
Serial.println(nitrogen);
Serial.print("phosphorus =");
Serial.println(phosphorus);
Serial.print("potassium =");
Serial.println(potassium);
mod.flush();
}
delay(1000);
_sensor.listen(); // the problem causing line
//_sensor.print("w");
mod.listen();
// while (!_sensor.read() == '=') {};
// waterReturn = _sensor.parseInt();
// Serial.print("Wetness: ");
// Serial.println(waterReturn);
}
J-M-L
June 3, 2024, 1:10pm
2
Using 2 software serial instances is just looking for troubles. it works in very specific cases where you control the incoming flows
I'd advise to get a better Arduino with more hardware Serial ports (Mega, ESP32, ...)
Thank you for the fast reply, is there anything that I can do that does not involve hardware changes?
blh64
June 3, 2024, 1:40pm
5
You can only listen to one port at a time and the other port will not be able to receive any data. Here is an example of using 2 instances of SoftwareSerial, but you need to swtich back and forth.
https://docs.arduino.cc/tutorials/communication/TwoPortReceive/
If you sensors are constantly sending data, you very likely will miss some. As @J-M-L pointed out, the proper solution is different hardware.
xfpd
June 4, 2024, 3:50am
6
Where did you get the program?
Don't use "_sensor" (it may be a keyword/macro), use "sensor"
If anyone else has this problem, here is how I solved it. Adding the mod.available==false and the delay worked
#include <SoftwareSerial.h>
#include <Wire.h>
#define RE 8
#define DE 7
const byte code[] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x03, 0x05, 0xCB};
byte values[11];
SoftwareSerial mod(2, 3);
SoftwareSerial _sensor(10, 11);
int waterReturn = -1;
float tempReturn = -1;
float humidityReturn = -1;
void setup()
{
Serial.begin(9600);
mod.begin(9600);
_sensor.begin(9600);
pinMode(RE, OUTPUT);
pinMode(DE, OUTPUT);
}
void loop() {
unsigned int nitrogen = 1000;
unsigned int phosphorus = 2000;
unsigned int potassium = 3000;
String Data("START");
byte val;
digitalWrite(DE, HIGH);
digitalWrite(RE, HIGH);
delay(10);
// if (mod.write(code, sizeof(code)) == 8)
if (mod.write(code, sizeof(code)) == 8)
{
mod.flush();
digitalWrite(DE, LOW);
digitalWrite(RE, LOW);
mod.listen();
// The next line waits until some data is available on mod
while(mod.available() == false);
// read 11 bytes from mod
for (byte i = 0; i < 11; i++)
{
//Serial.print(mod.read(),HEX);
if(mod.available()){
values[i] = mod.read();
Serial.print(values[i],HEX);
delay(10); ///////// I added this line, I think this is what made the difference - SG
}
}
Serial.println();
nitrogen = (((int)(values[3]))<<8) + ((int)(values[4]));
phosphorus = (((int)(values[5]))<<8) + ((int)(values[6]));
potassium = (((int)(values[7]))<<8) + ((int)(values[8]));
Serial.print("nitrogen =");
Serial.println(nitrogen);
Serial.print("phosphorus =");
Serial.println(phosphorus);
Serial.print("potassium =");
Serial.println(potassium);
mod.flush();
}
delay(1000);
_sensor.listen();
if (_sensor.isListening() == true)
{
_sensor.print("w");
while (!_sensor.read() == '=') {};
waterReturn = _sensor.parseInt();
Serial.print("Wetness: ");
Serial.println(waterReturn);
_sensor.print("t");
while (!_sensor.read() == '=') {};
tempReturn = _sensor.parseFloat();
Serial.print("Temperature: ");
Serial.println(tempReturn);
_sensor.print("h");
while (!_sensor.read() == '=') {};
humidityReturn = _sensor.parseFloat();
Serial.print("Humidity: ");
Serial.println(humidityReturn);
}
Data.concat('!');
Data.concat(nitrogen);
Data.concat('!');
Data.concat(phosphorus);
Data.concat("!");
Data.concat(potassium);
Data.concat("!");
Data.concat(waterReturn);
Data.concat("!");
Data.concat(tempReturn);
Data.concat("!");
Data.concat(humidityReturn);
Serial.println(Data);
Serial.println(" ");
delay(1000);
}
J-M-L
June 4, 2024, 12:32pm
8
at 9600 bauds you get 1 byte per ms roughly... if you pause for 10ms it's possible that you've accumulated 10 bytes in the buffer... if for some reason the buffer was next to full, you might have lost incoming bytes.
second guessing the timing of an asynchronous communication is never a good solution.
1 Like