After performing what you said, yes, the LED of TXD in the auto switching unit flashes in sync with the TX LED on the Arduino Nano
That would seem to indicate that the pin labelled TXD on the RS485 module is actually the pin that receives data from the Nano.
I wonder if we can assume that the designer of that module used the TXD label as a "Transmit data goes in here" pin and that RXD equates to "Received data come out here" pin.
You should now be able to connect up your USB-RS485 dongle to the RS485 module (A->A, B->B & GND->GND) and see the test message transmitted by the Nano being displayed in Realterm. Make sure that Realterm is set for 4800 baud and is looking at the USB-RS485 dongle COM Port.
You may need to switch the Realterm display option back to Hex[space].
Hopefully you will see the packets of binary data being received by Realterm and displayed in hex.
These were the results that I had after doing the things that you asked me to do.
What does this mean? Is this a good sign and we can now identify how to return the correct values from the sensor?
Perfect! We're getting somewhere.
So what you are seeing in Realterm is the the contents of the msg array from the code we are using. The Nano has used the software serial port to send that data to the auto switching RS485 module, which in turn has successfully send it to the USB-RS485 dongle on your PC and Realterm has successfully displayed that data.
We can now try connecting up your sensor to the A, B and GND signals.
The message that is currently being transmitted was also one of the messages that got a response when you ran the PC test program. No code change needed for this next test!
I'm hoping that the sensor will respond and you will see the reply in Realterm. You can also put a wire from the RXD pin on the autoswitching RS485 module onto pin 8 of your Nano. If the sensor does respond, then your Nano should print out the response as well.
Fingers crossed - see what happens.
Hello these were the results after connecting the sensor to the auto switching module and run the sketch about the altsofserial. The baudrate that I used is 4800
I'm assuming that this is a good sign?
I have somewhat have a good new mark!! I tried running my code with altsoftwareserial as the library and I finally got to read the value for the nitrogen but the Phosporus and Potassium values are continuously zeroes.
This is the code that I used and I hope you can help me in adding the temperature, humidity, and ph measurements.
#include <AltSoftSerial.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// RO to pin 8 & DI to pin 9 when using AltSoftSerial
#define RE 6
#define DE 7
const byte nitro[] = {0x01, 0x03, 0x00, 0x1e, 0x00, 0x01, 0xe4, 0x0c};
const byte phos[] = {0x01, 0x03, 0x00, 0x1f, 0x00, 0x01, 0xb5, 0xcc};
const byte pota[] = {0x01, 0x03, 0x00, 0x20, 0x00, 0x01, 0x85, 0xc0};
byte values[11];
AltSoftSerial mod;
void setup() {
Serial.begin(9600);
mod.begin(4800);
pinMode(RE, OUTPUT);
pinMode(DE, OUTPUT);
// put RS-485 into receive mode
digitalWrite(DE, LOW);
digitalWrite(RE, LOW);
//Initializing and Configuring OLED display
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); //initialize with the I2C addr 0x3C (128x64)
delay(500);
display.clearDisplay();
display.setCursor(25, 15);
display.setTextSize(1);
display.setTextColor(WHITE);
display.println("Soil NPK Sensor");
display.setCursor(25, 35);
display.setTextSize(1);
display.print("Initializing");
display.display();
delay(3000);
}
void loop() {
byte val1, val2, val3;
Serial.print("Nitrogen: ");
val1 = nitrogen();
Serial.print(" = ");
Serial.print(val1);
Serial.println(" mg/kg");
delay(250);
Serial.print("Phosphorous: ");
val2 = phosphorous();
Serial.print(" = ");
Serial.print(val2);
Serial.println(" mg/kg");
delay(250);
Serial.print("Potassium: ");
val3 = potassium();
Serial.print(" = ");
Serial.print(val3);
Serial.println(" mg/kg");
Serial.println();
Serial.println();
display.clearDisplay();
display.setTextSize(2);
display.setCursor(0, 5);
display.print("N: ");
display.print(val1);
display.setTextSize(1);
display.print(" mg/kg");
display.setTextSize(2);
display.setCursor(0, 25);
display.print("P: ");
display.print(val2);
display.setTextSize(1);
display.print(" mg/kg");
display.setTextSize(2);
display.setCursor(0, 45);
display.print("K: ");
display.print(val3);
display.setTextSize(1);
display.print(" mg/kg");
display.display();
delay(3000);
}
byte nitrogen() {
// clear the receive buffer
mod.flushInput();
// switch RS-485 to transmit mode
digitalWrite(DE, HIGH);
digitalWrite(RE, HIGH);
delay(1);
// write out the message
for (uint8_t i = 0; i < sizeof(nitro); i++ ) mod.write( nitro[i] );
// wait for the transmission to complete
mod.flush();
// switching RS485 to receive mode
digitalWrite(DE, LOW);
digitalWrite(RE, LOW);
// delay to allow response bytes to be received!
delay(200);
// read in the received bytes
for (byte i = 0; i < 7; i++) {
values[i] = mod.read();
Serial.print(values[i], HEX);
Serial.print(' ');
}
return values[4];
}
byte phosphorous() {
mod.flushInput();
digitalWrite(DE, HIGH);
digitalWrite(RE, HIGH);
delay(1);
for (uint8_t i = 0; i < sizeof(phos); i++ ) mod.write( phos[i] );
mod.flush();
digitalWrite(DE, LOW);
digitalWrite(RE, LOW);
// delay to allow response bytes to be received!
delay(200);
for (byte i = 0; i < 7; i++) {
values[i] = mod.read();
Serial.print(values[i], HEX);
Serial.print(' ');
}
return values[4];
}
byte potassium() {
mod.flushInput();
digitalWrite(DE, HIGH);
digitalWrite(RE, HIGH);
delay(1);
for (uint8_t i = 0; i < sizeof(pota); i++ ) mod.write( pota[i] );
mod.flush();
digitalWrite(DE, LOW);
digitalWrite(RE, LOW);
// delay to allow response bytes to be received!
delay(200);
for (byte i = 0; i < 7; i++) {
values[i] = mod.read();
Serial.print(values[i], HEX);
Serial.print(' ');
}
return values[4];
}
after integrating the hex codes for temperature, moisture and pH. I was able to return their values. The only problem is that the Phosphorus and Potassium values are always in zero
Here is the code that I used:
#include <AltSoftSerial.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// RO to pin 8 & DI to pin 9 when using AltSoftSerial
#define RE 6
#define DE 7
const byte nitro[] = {0x01, 0x03, 0x00, 0x1e, 0x00, 0x01, 0xe4, 0x0c};
const byte phos[] = {0x01, 0x03, 0x00, 0x1f, 0x00, 0x01, 0xb5, 0xcc};
const byte pota[] = {0x01, 0x03, 0x00, 0x20, 0x00, 0x01, 0x85, 0xc0};
const byte ph[] = { 0x01, 0x03, 0x00, 0x06, 0x00, 0x01, 0x64, 0x0b }; // New
const byte mois[] = { 0x01, 0x03, 0x00, 0x12, 0x00, 0x01, 0x24, 0x0F };
const byte temp[] = { 0x01, 0x03, 0x00, 0x01, 0x00, 0x01, 0xD5, 0xCA };
byte values[11];
AltSoftSerial mod;
float soil_ph = 0.0, soil_moisture = 0.0, soil_temp = 0.0;
byte val1 = 0, val2 = 0, val3 = 0, val4 = 0, val5 = 0, val6 = 0;
void setup() {
Serial.begin(9600);
mod.begin(4800);
pinMode(RE, OUTPUT);
pinMode(DE, OUTPUT);
// put RS-485 into receive mode
digitalWrite(DE, LOW);
digitalWrite(RE, LOW);
//Initializing and Configuring OLED display
// display.begin(SSD1306_SWITCHCAPVCC, 0x3C); //initialize with the I2C addr 0x3C (128x64)
// delay(500);
// display.clearDisplay();
// display.setCursor(25, 15);
// display.setTextSize(1);
// display.setTextColor(WHITE);
// display.println("Soil NPK Sensor");
// display.setCursor(25, 35);
// display.setTextSize(1);
// display.print("Initializing");
// display.display();
// delay(3000);
}
void loop() {
byte val1, val2, val3, val4, val5, val6;
val1 = nitrogen();
delay(300);
val2 = phosphorous();
delay(300);
val3 = potassium();
delay(300);
val4 = phydrogen() / 10; // New
soil_ph = val4;
delay(300);
val5 = moisture();
soil_moisture = val5 / 10.0;
delay(300);
val6 = temperature();
soil_temp = temperature() / 10.0; // New
delay(300);
Serial.print("Nitrogen: ");
Serial.print(val1);
Serial.println(" mg/kg");
Serial.print("Phosphorous: ");
Serial.print(val2);
Serial.println(" mg/kg");
Serial.print("Potassium: ");
Serial.print(val3);
Serial.println(" mg/kg");
Serial.print("ph: "); // New
Serial.print(soil_ph);
Serial.println(" ph");
Serial.print("Moisture: ");
Serial.print(soil_moisture);
Serial.println(" %"); //
Serial.print("Temperature: ");
Serial.print(soil_temp);
Serial.println(" C");
Serial.println(); // New
delay(2000);
// display.clearDisplay();
//
// display.setTextSize(1);
// display.setCursor(0, 5);
// display.print("N: ");
// display.print(val1);
// display.setTextSize(1);
// display.print(" mg/kg");
//
// display.setTextSize(1);
// display.setCursor(0, 15);
// display.print("P: ");
// display.print(val2);
// display.setTextSize(1);
// display.print(" mg/kg");
//
// display.setTextSize(1);
// display.setCursor(0, 25);
// display.print("K: ");
// display.print(val3);
// display.setTextSize(1);
// display.print(" mg/kg");
//
// display.setTextSize(1); // New
// display.setCursor(0, 35);
// display.print("pH: ");
// display.print(soil_ph);
// display.setTextSize(1);
// display.print(" pH");
//
// display.setTextSize(1);
// display.setCursor(0, 45);
// display.print("Moisture: ");
// display.print(soil_mois);
// display.setTextSize(1);
// display.print(" %");
//
// display.setTextSize(1);
// display.setCursor(0, 55);
// display.print("Temperature: ");
// display.print(soil_temp);
// display.setTextSize(1);
// display.print(" C"); // New
//
// display.display();
}
byte nitrogen() {
// clear the receive buffer
mod.flushInput();
// switch RS-485 to transmit mode
digitalWrite(DE, HIGH);
digitalWrite(RE, HIGH);
delay(1);
// write out the message
for (uint8_t i = 0; i < sizeof(nitro); i++ ) mod.write( nitro[i] );
// wait for the transmission to complete
mod.flush();
// switching RS485 to receive mode
digitalWrite(DE, LOW);
digitalWrite(RE, LOW);
// delay to allow response bytes to be received!
delay(200);
// read in the received bytes
for (byte i = 0; i < 7; i++) {
values[i] = mod.read();
Serial.print(values[i], HEX);
Serial.print(' ');
}
return values[4];
}
byte phosphorous() {
mod.flushInput();
digitalWrite(DE, HIGH);
digitalWrite(RE, HIGH);
delay(1);
for (uint8_t i = 0; i < sizeof(phos); i++ ) mod.write( phos[i] );
mod.flush();
digitalWrite(DE, LOW);
digitalWrite(RE, LOW);
// delay to allow response bytes to be received!
delay(200);
for (byte i = 0; i < 7; i++) {
values[i] = mod.read();
Serial.print(values[i], HEX);
Serial.print(' ');
}
return values[4];
}
byte potassium() {
mod.flushInput();
digitalWrite(DE, HIGH);
digitalWrite(RE, HIGH);
delay(1);
for (uint8_t i = 0; i < sizeof(pota); i++ ) mod.write( pota[i] );
mod.flush();
digitalWrite(DE, LOW);
digitalWrite(RE, LOW);
// delay to allow response bytes to be received!
delay(200);
for (byte i = 0; i < 7; i++) {
values[i] = mod.read();
Serial.print(values[i], HEX);
Serial.print(' ');
}
return values[4];
}
byte phydrogen() {
// clear the receive buffer
mod.flush();
// switch RS-485 to transmit mode
digitalWrite(DE, HIGH);
digitalWrite(RE, HIGH);
delay(1);
// write out the message
for (uint8_t i = 0; i < sizeof(ph); i++) mod.write(ph[i]);
// wait for the transmission to complete
mod.flush();
// switching RS485 to receive mode
digitalWrite(DE, LOW);
digitalWrite(RE, LOW);
// delay to allow response bytes to be received!
delay(1000);
// read in the received bytes
for (byte i = 0; i < 7; i++) {
values[i] = mod.read();
Serial.print(values[i], HEX);
Serial.print(' ');
}
return values[4];
}
byte moisture() {
// clear the receive buffer
mod.flush();
// switch RS-485 to transmit mode
digitalWrite(DE, HIGH);
digitalWrite(RE, HIGH);
delay(1);
// write out the message
for (uint8_t i = 0; i < sizeof(mois); i++) mod.write(mois[i]);
// wait for the transmission to complete
mod.flush();
// switching RS485 to receive mode
digitalWrite(DE, LOW);
digitalWrite(RE, LOW);
// delay to allow response bytes to be received!
delay(1000);
// read in the received bytes
for (byte i = 0; i < 7; i++) {
values[i] = mod.read();
Serial.print(values[i], HEX);
Serial.print(' ');
}
return values[4];
}
byte temperature() {
// clear the receive buffer
mod.flush();
// switch RS-485 to transmit mode
digitalWrite(DE, HIGH);
digitalWrite(RE, HIGH);
delay(1);
// write out the message
for (uint8_t i = 0; i < sizeof(temp); i++) mod.write(temp[i]);
// wait for the transmission to complete
mod.flush();
// switching RS485 to receive mode
digitalWrite(DE, LOW);
digitalWrite(RE, LOW);
// delay to allow response bytes to be received!
delay(1000);
// read in the received bytes
for (byte i = 0; i < 7; i++) {
values[i] = mod.read();
Serial.print(values[i], HEX);
Serial.print(' ');
}
return values[3] << 8 | values[4];
}
Another problem that I encounter is when I'm using the display codes for the OLED. I get nothing from the Serial Monitor and the OLED is not lighting up.
Here is my updated code:
#include <AltSoftSerial.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// RO to pin 8 & DI to pin 9 when using AltSoftSerial
#define RE 6
#define DE 7
const byte nitro[] = {0x01, 0x03, 0x00, 0x1e, 0x00, 0x01, 0xe4, 0x0c};
const byte phos[] = {0x01, 0x03, 0x00, 0x1f, 0x00, 0x01, 0xb5, 0xcc};
const byte pota[] = {0x01, 0x03, 0x00, 0x20, 0x00, 0x01, 0x85, 0xc0};
const byte ph[] = { 0x01, 0x03, 0x00, 0x06, 0x00, 0x01, 0x64, 0x0b }; // New
const byte mois[] = { 0x01, 0x03, 0x00, 0x12, 0x00, 0x01, 0x24, 0x0F };
const byte temp[] = { 0x01, 0x03, 0x00, 0x01, 0x00, 0x01, 0xD5, 0xCA };
byte values[11];
AltSoftSerial mod;
float soil_ph = 0.0, soil_moisture = 0.0, soil_temp = 0.0;
byte val1 = 0, val2 = 0, val3 = 0, val4 = 0, val5 = 0, val6 = 0;
void setup() {
Serial.begin(9600);
mod.begin(4800);
pinMode(RE, OUTPUT);
pinMode(DE, OUTPUT);
// put RS-485 into receive mode
digitalWrite(DE, LOW);
digitalWrite(RE, LOW);
//Initializing and Configuring OLED display
// display.begin(SSD1306_SWITCHCAPVCC, 0x3C); //initialize with the I2C addr 0x3C (128x64)
// delay(500);
// display.clearDisplay();
// display.setCursor(25, 15);
// display.setTextSize(1);
// display.setTextColor(WHITE);
// display.println("Soil NPK Sensor");
// display.setCursor(25, 35);
// display.setTextSize(1);
// display.print("Initializing");
// display.display();
// delay(3000);
}
void loop() {
byte val1, val2, val3, val4, val5, val6;
val1 = nitrogen();
delay(300);
val2 = phosphorous();
delay(300);
val3 = potassium();
delay(300);
val4 = phydrogen() / 10; // New
soil_ph = val4;
delay(300);
val5 = moisture();
soil_moisture = val5 / 10.0;
delay(300);
val6 = temperature();
soil_temp = temperature() / 10.0; // New
delay(300);
Serial.print("Nitrogen: ");
Serial.print(val1);
Serial.println(" mg/kg");
Serial.print("Phosphorous: ");
Serial.print(val2);
Serial.println(" mg/kg");
Serial.print("Potassium: ");
Serial.print(val3);
Serial.println(" mg/kg");
Serial.print("ph: "); // New
Serial.print(soil_ph);
Serial.println(" ph");
Serial.print("Moisture: ");
Serial.print(soil_moisture);
Serial.println(" %"); //
Serial.print("Temperature: ");
Serial.print(soil_temp);
Serial.println(" C");
Serial.println(); // New
delay(2000);
// display.clearDisplay();
//
// display.setTextSize(1);
// display.setCursor(0, 5);
// display.print("N: ");
// display.print(val1);
// display.setTextSize(1);
// display.print(" mg/kg");
//
// display.setTextSize(1);
// display.setCursor(0, 15);
// display.print("P: ");
// display.print(val2);
// display.setTextSize(1);
// display.print(" mg/kg");
//
// display.setTextSize(1);
// display.setCursor(0, 25);
// display.print("K: ");
// display.print(val3);
// display.setTextSize(1);
// display.print(" mg/kg");
//
// display.setTextSize(1); // New
// display.setCursor(0, 35);
// display.print("pH: ");
// display.print(soil_ph);
// display.setTextSize(1);
// display.print(" pH");
//
// display.setTextSize(1);
// display.setCursor(0, 45);
// display.print("Moisture: ");
// display.print(soil_moisture);
// display.setTextSize(1);
// display.print(" %");
//
// display.setTextSize(1);
// display.setCursor(0, 55);
// display.print("Temperature: ");
// display.print(soil_temp);
// display.setTextSize(1);
// display.print(" C"); // New
//
// display.display();
}
byte nitrogen() {
// clear the receive buffer
mod.flushInput();
// switch RS-485 to transmit mode
digitalWrite(DE, HIGH);
digitalWrite(RE, HIGH);
delay(1);
// write out the message
for (uint8_t i = 0; i < sizeof(nitro); i++ ) mod.write( nitro[i] );
// wait for the transmission to complete
mod.flush();
// switching RS485 to receive mode
digitalWrite(DE, LOW);
digitalWrite(RE, LOW);
// delay to allow response bytes to be received!
delay(200);
// read in the received bytes
for (byte i = 0; i < 7; i++) {
values[i] = mod.read();
Serial.print(values[i], HEX);
Serial.print(' ');
}
return values[4];
}
byte phosphorous() {
mod.flushInput();
digitalWrite(DE, HIGH);
digitalWrite(RE, HIGH);
delay(1);
for (uint8_t i = 0; i < sizeof(phos); i++ ) mod.write( phos[i] );
mod.flush();
digitalWrite(DE, LOW);
digitalWrite(RE, LOW);
// delay to allow response bytes to be received!
delay(200);
for (byte i = 0; i < 7; i++) {
values[i] = mod.read();
Serial.print(values[i], HEX);
Serial.print(' ');
}
return values[4];
}
byte potassium() {
mod.flushInput();
digitalWrite(DE, HIGH);
digitalWrite(RE, HIGH);
delay(1);
for (uint8_t i = 0; i < sizeof(pota); i++ ) mod.write( pota[i] );
mod.flush();
digitalWrite(DE, LOW);
digitalWrite(RE, LOW);
// delay to allow response bytes to be received!
delay(200);
for (byte i = 0; i < 7; i++) {
values[i] = mod.read();
Serial.print(values[i], HEX);
Serial.print(' ');
}
return values[4];
}
byte phydrogen() {
// clear the receive buffer
mod.flush();
// switch RS-485 to transmit mode
digitalWrite(DE, HIGH);
digitalWrite(RE, HIGH);
delay(1);
// write out the message
for (uint8_t i = 0; i < sizeof(ph); i++) mod.write(ph[i]);
// wait for the transmission to complete
mod.flush();
// switching RS485 to receive mode
digitalWrite(DE, LOW);
digitalWrite(RE, LOW);
// delay to allow response bytes to be received!
delay(1000);
// read in the received bytes
for (byte i = 0; i < 7; i++) {
values[i] = mod.read();
Serial.print(values[i], HEX);
Serial.print(' ');
}
return values[4];
}
byte moisture() {
// clear the receive buffer
mod.flush();
// switch RS-485 to transmit mode
digitalWrite(DE, HIGH);
digitalWrite(RE, HIGH);
delay(1);
// write out the message
for (uint8_t i = 0; i < sizeof(mois); i++) mod.write(mois[i]);
// wait for the transmission to complete
mod.flush();
// switching RS485 to receive mode
digitalWrite(DE, LOW);
digitalWrite(RE, LOW);
// delay to allow response bytes to be received!
delay(1000);
// read in the received bytes
for (byte i = 0; i < 7; i++) {
values[i] = mod.read();
Serial.print(values[i], HEX);
Serial.print(' ');
}
return values[4];
}
byte temperature() {
// clear the receive buffer
mod.flush();
// switch RS-485 to transmit mode
digitalWrite(DE, HIGH);
digitalWrite(RE, HIGH);
delay(1);
// write out the message
for (uint8_t i = 0; i < sizeof(temp); i++) mod.write(temp[i]);
// wait for the transmission to complete
mod.flush();
// switching RS485 to receive mode
digitalWrite(DE, LOW);
digitalWrite(RE, LOW);
// delay to allow response bytes to be received!
delay(1000);
// read in the received bytes
for (byte i = 0; i < 7; i++) {
values[i] = mod.read();
Serial.print(values[i], HEX);
Serial.print(' ');
}
return values[3] << 8 | values[4];
}
As I said earlier, I suspect that the datasheet you were given may not correspond with the actual sensor you have.
I note that in your original image from post #1, that the sensor is presented with 3 probes. The datasheet from post #11 says on the front page that it is for a 5 pin 4 parameter sensor.
From what I have seen with Modbus type sensors, if you query an unsupported register, then you don't get a reply. In your case, you are getting responses from registers that don't appear in the datasheet you were given.
I don't know enough about a soil environment to know what figures to expect from this type of sensor. The more obvious readings such as pH and temperature can be guessed and compared to what the sensor is reporting. A pH of 5.0 sounds plausible as does a temperature of 23.7C.
From what I recall, that datasheet you provided didn't mention anything about N, P or K readings. In fact, section 4 of the datasheet says:
I guess it's a problem for another day. On the other hand can you help me figure out my problem in my post #69
I wouldn't expect any output on the OLED as most of the code is commented out. The OLED library can consume a lot of precious RAM on the micro when you only have 2K to begin with.
Looking at a previous photo you showed (post #44), it looks like a Nano clone. What does it say on the big chip on the board? I think I can make out the Atmel logo and the word MEGA. There should be a number next to the word MEGA - like MEGA328P or sometimes MEGA168P. Hopefully the number is 328.
If you are only displaying text on the OLED, then a much better library is the SSD1306ASCII library which I believe you can install via the IDE. If not here is the github page for it.
That library will consume a lot less RAM than the one from Adafruit.
With only 2K of RAM available, you can start to use it up quite quickly if you have a lot of Serial.print statements with string constants in them. You can get around this by forcing the string constants to stay in FLASH memory by using the F() macro.
For example, with this bit of code:
Serial.print("Nitrogen: ");
Serial.print(val1);
Serial.println(" mg/kg");
Serial.print("Phosphorous: ");
Serial.print(val2);
Serial.println(" mg/kg");
You can change it to this:
Serial.print(F("Nitrogen: "));
Serial.print(val1);
Serial.println(F(" mg/kg"));
Serial.print(F("Phosphorous: "));
Serial.print(val2);
Serial.println(F(" mg/kg"));
Notice the use of the F() macro. You should do this for all of your constant text strings.
Also see if the OLED library will accept the use of the F() macro like:
display.print(F(" mg/kg"));
As your code stands in post #69, when you compile it in the IDE, how much memory - FLASH and RAM - does the compilation process report has been used. It will be reported at the bottom of the screen in the IDE.
Hi Mark sorry for taking a while to reply. Yes, the Nano has a MEGA328P. After using the sensor again, I think that the values of pH, moisture, and temperature have been mixed up and there is still no P and K values.
After doing the macro in the display codes, I was finally able to have a display in my OLED.
This is my current code:
#include <AltSoftSerial.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// RO to pin 8 & DI to pin 9 when using AltSoftSerial
#define RE 6
#define DE 7
const byte nitro[] = {0x01, 0x03, 0x00, 0x1e, 0x00, 0x01, 0xe4, 0x0c};
const byte phos[] = {0x01, 0x03, 0x00, 0x1f, 0x00, 0x01, 0xb5, 0xcc};
const byte pota[] = {0x01, 0x03, 0x00, 0x20, 0x00, 0x01, 0x85, 0xc0};
const byte ph[] = { 0x01, 0x03, 0x00, 0x06, 0x00, 0x01, 0x64, 0x0b }; // New
const byte mois[] = { 0x01, 0x03, 0x00, 0x12, 0x00, 0x01, 0x24, 0x0F };
const byte temp[] = { 0x01, 0x03, 0x00, 0x01, 0x00, 0x01, 0xD5, 0xCA };
byte values[11];
AltSoftSerial mod;
float soil_ph = 0.0, soil_moisture = 0.0, soil_temp = 0.0;
byte val1 = 0, val2 = 0, val3 = 0, val4 = 0, val5 = 0, val6 = 0;
void setup() {
Serial.begin(9600);
mod.begin(4800);
pinMode(RE, OUTPUT);
pinMode(DE, OUTPUT);
// put RS-485 into receive mode
digitalWrite(DE, LOW);
digitalWrite(RE, LOW);
// Initializing and Configuring OLED display
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); //initialize with the I2C addr 0x3C (128x64)
delay(500);
display.clearDisplay();
display.setCursor(25, 15);
display.setTextSize(1);
display.setTextColor(WHITE);
display.println(F("Soil NPK Sensor"));
display.setCursor(25, 35);
display.setTextSize(1);
display.print(F("Initializing"));
display.display();
delay(3000);
}
void loop() {
byte val1, val2, val3, val4, val5, val6;
val1 = nitrogen();
delay(300);
val2 = phosphorous();
delay(300);
val3 = potassium();
delay(300);
val4 = phydrogen() / 10; // New
soil_ph = val4;
delay(300);
val5 = moisture();
soil_moisture = val5 / 10.0;
delay(300);
val6 = temperature();
soil_temp = temperature() / 10.0; // New
delay(300);
Serial.print(F("Nitrogen: "));
Serial.print(val1);
Serial.println(F(" mg/kg"));
Serial.print(F("Phosphorous: "));
Serial.print(val2);
Serial.println(F(" mg/kg"));
Serial.print(F("Potassium: "));
Serial.print(val3);
Serial.println(F(" mg/kg"));
Serial.print(F("ph: ")); // New
Serial.print(soil_ph);
Serial.println(F(" ph"));
Serial.print(F("Moisture: "));
Serial.print(soil_moisture);
Serial.println(F(" %")); //
Serial.print(F("Temperature: "));
Serial.print(soil_temp);
Serial.println(F(" C"));
Serial.println(); // New
delay(2000);
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0, 5);
display.print(F("N: "));
display.print(val1);
display.setTextSize(1);
display.print(F(" mg/kg"));
display.setTextSize(1);
display.setCursor(0, 15);
display.print(F("P: "));
display.print(val2);
display.setTextSize(1);
display.print(F(" mg/kg"));
display.setTextSize(1);
display.setCursor(0, 25);
display.print(F("K: "));
display.print(val3);
display.setTextSize(1);
display.print(F(" mg/kg"));
display.setTextSize(1); // New
display.setCursor(0, 35);
display.print(F("pH: "));
display.print(soil_ph);
display.setTextSize(1);
display.print(F(" pH"));
display.setTextSize(1);
display.setCursor(0, 45);
display.print(F("Moisture: "));
display.print(soil_moisture);
display.setTextSize(1);
display.print(F(" %"));
display.setTextSize(1);
display.setCursor(0, 55);
display.print(F("Temperature: "));
display.print(soil_temp);
display.setTextSize(1);
display.print(F(" C")); // New
display.display();
}
byte nitrogen() {
// clear the receive buffer
mod.flushInput();
// switch RS-485 to transmit mode
digitalWrite(DE, HIGH);
digitalWrite(RE, HIGH);
delay(1);
// write out the message
for (uint8_t i = 0; i < sizeof(nitro); i++ ) mod.write( nitro[i] );
// wait for the transmission to complete
mod.flush();
// switching RS485 to receive mode
digitalWrite(DE, LOW);
digitalWrite(RE, LOW);
// delay to allow response bytes to be received!
delay(200);
// read in the received bytes
for (byte i = 0; i < 7; i++) {
values[i] = mod.read();
Serial.print(values[i], HEX);
Serial.print(' ');
}
return values[4];
}
byte phosphorous() {
mod.flushInput();
digitalWrite(DE, HIGH);
digitalWrite(RE, HIGH);
delay(1);
for (uint8_t i = 0; i < sizeof(phos); i++ ) mod.write( phos[i] );
mod.flush();
digitalWrite(DE, LOW);
digitalWrite(RE, LOW);
// delay to allow response bytes to be received!
delay(200);
for (byte i = 0; i < 7; i++) {
values[i] = mod.read();
Serial.print(values[i], HEX);
Serial.print(' ');
}
return values[4];
}
byte potassium() {
mod.flushInput();
digitalWrite(DE, HIGH);
digitalWrite(RE, HIGH);
delay(1);
for (uint8_t i = 0; i < sizeof(pota); i++ ) mod.write( pota[i] );
mod.flush();
digitalWrite(DE, LOW);
digitalWrite(RE, LOW);
// delay to allow response bytes to be received!
delay(200);
for (byte i = 0; i < 7; i++) {
values[i] = mod.read();
Serial.print(values[i], HEX);
Serial.print(' ');
}
return values[4];
}
byte phydrogen() {
// clear the receive buffer
mod.flush();
// switch RS-485 to transmit mode
digitalWrite(DE, HIGH);
digitalWrite(RE, HIGH);
delay(1);
// write out the message
for (uint8_t i = 0; i < sizeof(ph); i++) mod.write(ph[i]);
// wait for the transmission to complete
mod.flush();
// switching RS485 to receive mode
digitalWrite(DE, LOW);
digitalWrite(RE, LOW);
// delay to allow response bytes to be received!
delay(1000);
// read in the received bytes
for (byte i = 0; i < 7; i++) {
values[i] = mod.read();
Serial.print(values[i], HEX);
Serial.print(' ');
}
return values[4];
}
byte moisture() {
// clear the receive buffer
mod.flush();
// switch RS-485 to transmit mode
digitalWrite(DE, HIGH);
digitalWrite(RE, HIGH);
delay(1);
// write out the message
for (uint8_t i = 0; i < sizeof(mois); i++) mod.write(mois[i]);
// wait for the transmission to complete
mod.flush();
// switching RS485 to receive mode
digitalWrite(DE, LOW);
digitalWrite(RE, LOW);
// delay to allow response bytes to be received!
delay(1000);
// read in the received bytes
for (byte i = 0; i < 7; i++) {
values[i] = mod.read();
Serial.print(values[i], HEX);
Serial.print(' ');
}
return values[4];
}
byte temperature() {
// clear the receive buffer
mod.flush();
// switch RS-485 to transmit mode
digitalWrite(DE, HIGH);
digitalWrite(RE, HIGH);
delay(1);
// write out the message
for (uint8_t i = 0; i < sizeof(temp); i++) mod.write(temp[i]);
// wait for the transmission to complete
mod.flush();
// switching RS485 to receive mode
digitalWrite(DE, LOW);
digitalWrite(RE, LOW);
// delay to allow response bytes to be received!
delay(1000);
// read in the received bytes
for (byte i = 0; i < 7; i++) {
values[i] = mod.read();
Serial.print(values[i], HEX);
Serial.print(' ');
}
return values[3] << 8 | values[4];
}
I hope that you can help me in displaying the correct values.
EDIT: These are the values that I'm getting when the sensor is not in the soil. It seems that the moisture and temperature are mixed up.
On the other hand, these are the measurements when I plug the sensor into the soil.
Possible Reason #1:
The mixed up values come mainly from the horrible code that can be found on many websites that claim to read an NPK sensor over RS485. There's a fundamental flaw in all their code and I suspect that either the individual authors have thought that they have got it working without checking the actual values being returned, or they simply copied from each other!
I've explained the reason why I believe that code to be flawed here:
However, in your case, because you have the delay(200) after switching to receive mode before reading back the values, you may have overcome the problem with that method of reading the data. You could increase this delay to 400 or 500ms and see if that changes anything.
The big clue if this is the issue is in the very first message that gets received when you reset your Nano. If the code thinks the very first message received back after a reset/power-on contains only 0xFF (or -1) values, then you have an issue with the serial handling.
If the first message you receive back is sensible, then it's not the serial handling issue that is a common theme on these NPK sensors.
Possible Reason #2:
Sorry to keep going on about this but I'm still not convinced that the datasheet you were provided matches the actual device you have.
- Your code is reading pH from address 0x006, but the datasheet you provided says it's at address 0x0003. The datasheet shows nothing at address 0x0006.
- Your code is reading moisture from address 0x0012, but the datasheet says that it's address 0x0000 (called water content). The datasheet shows nothing at address 0x0012.
The datasheet and your code both are using address 0x0001 for temperature.
The datasheet also makes no mention of N, P or K values either.
Is there a label on the side of your sensor that you could get some configuration information from that would tell you exactly which sensor you have?
Can you tell me which software you used? i have 7 in one soil sensors, im facing the same issue.
what software do you need? I used multiple software to troubleshoot the communication connections.
This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.