Heltec WiFi LoRa 32V3 with RS485 Sensor

The issue has been resolved thanks to @nmcc. I have uploaded the code with comments and a wiring diagram to GitHub, see here.

Hello,

I am using an oxygen sensor which uses RS485 ModBus protocol (link to sensor) with a Heltec WiFi LoRa 32V3 MCU. For compatibility, I am using an active isolated RS485 to UART signal adapter module (link to converter).

My problem is, that with my current code, I receive a “??Time out” message (see Fig. 1 below).


Fig. 1: Serial monitor output showing “??Time out” for the setup with the Heltec MCU.

This is the code I'm using with the Heltec board:
HardwareSerial RS485(2); // define serial entity
float sal, ap; // define variables for Salinity and Atmospheric Pressure

// Define Com so that the error from it missing does not get thrown anymore.
uint8_t Com[8] = { 0x01, 0x03, 0x00, 0x00, 0x00, 0x06, 0xC5, 0xC8 };   
uint8_t Com1[8] = { 0x01, 0x03, 0x10, 0x22, 0x00, 0x01, 0x20, 0xC0 };  
uint8_t Com2[8] = { 0x01, 0x03, 0x10, 0x20, 0x00, 0x01, 0x81, 0x00 }; 

void setup() {
  // put your setup code here, to run once:
  
  // Power supply
  pinMode(Vext, OUTPUT);
  digitalWrite(Vext, LOW);

  Serial.begin(115200);
  RS485.begin(9600, SERIAL_8N1, 47, 48); // baud rate, bits, RX, TX
  Serial.println("[setup] WiFi LoRa 32 V3 RS485 Test");
}

void loop() {
  // put your main code here, to run repeatedly:
  // unchanged code from DFRobot
  readDO_DOS_TEM();
  Atmospheric_pressure();
  Serial.print("AP = ");
  Serial.print(ap, 2);
  Serial.print("Kpa  ");
  Salinity();
  Serial.print("Salinity = ");
  Serial.print(sal,0);
  Serial.println("%  ");
  Serial.println("   ");
  delay(1000);
}

void readDO_DOS_TEM(void) {
  uint32_t val = 0, val1 = 0, val2 = 0;
  uint8_t Data[18] = { 0 };
  uint8_t ch = 0;
  bool flag = 1;
  long timeStart = millis();
  long timeStart1 = 0;
  while (flag) {

    if ((millis() - timeStart1) > 100) {
      while (Serial.available() > 0) { // was mySerial
        Serial.read(); // was mySerial
      }
      Serial.write(Com, 8); // was mySerial // error due to Com being undefined, define before void setup()
      timeStart1 = millis();
    }

    if ((millis() - timeStart) > 1000) {
      Serial.println("Time out");
      //return -1;
    }

    if (readN(&ch, 1) == 1) {
      if (ch == 0x01) {
        Data[0] = ch;
        if (readN(&ch, 1) == 1) {
          if (ch == 0x03) {
            Data[1] = ch;
            if (readN(&ch, 1) == 1) {
              if (ch == 0x0C) {
                Data[2] = ch;
                if (readN(&Data[3], 14) == 14) {
                  if (CRC16_2(Data, 15) == (Data[15] * 256 + Data[16])) {
                    val = Data[3];
                    val = (val << 8) | Data[4];
                    val = (val << 8) | Data[5];
                    val = (val << 8) | Data[6];
                    float *dos = (float *)&val;
                    float Dos = *dos * 100.00;
                    Serial.print("DO Sat = ");
                    Serial.print(Dos, 1);
                    Serial.print("%  ");
                    val1 = Data[7];
                    val1 = (val1 << 8) | Data[8];
                    val1 = (val1 << 8) | Data[9];
                    val1 = (val1 << 8) | Data[10];
                    float *Do = (float *)&val1;
                    Serial.print("DO = ");
                    Serial.print(*Do, 2);
                    Serial.print(" mg/L  ");
                    val2 = Data[11];
                    val2 = (val2 << 8) | Data[12];
                    val2 = (val2 << 8) | Data[13];
                    val2 = (val2 << 8) | Data[14];
                    float *tem = (float *)&val2;
                    Serial.print("TEM = ");
                    Serial.print(*tem, 1);
                    Serial.println("°C");
                    flag = 0;
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

void Atmospheric_pressure(void) {
  uint8_t Data[12] = { 0 };
  uint8_t ch = 0;
  bool flag = 1;
  long timeStart = millis();
  long timeStart1 = 0;
  while (flag) {

    if ((millis() - timeStart1) > 100) {
      while (Serial.available() > 0) { // was mySerial
        Serial.read(); // was mySerial
      }
      Serial.write(Com1, 8); // error due to Com1 being undefined, define before void setup() // was mySerial
      timeStart1 = millis();
    }

    if ((millis() - timeStart) > 1000) {
      Serial.println("Time out2");
      //return -1;
    }

    if (readN(&ch, 1) == 1) {
      if (ch == 0x01) {
        Data[0] = ch;
        if (readN(&ch, 1) == 1) {
          if (ch == 0x03) {
            Data[1] = ch;
            if (readN(&ch, 1) == 1) {
              if (ch == 0x02) {
                Data[2] = ch;
                if (readN(&Data[3], 4) == 4) {
                  if (CRC16_2(Data, 5) == (Data[5] * 256 + Data[6])) {
                    ap = (Data[3] * 256 + Data[4]) / 100.0;
                    flag = 0;
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

void Salinity(void) {
  uint8_t Data[12] = { 0 };
  uint8_t ch = 0;
  bool flag = 1;
  long timeStart = millis();
  long timeStart1 = 0;
  while (flag) {

    if ((millis() - timeStart1) > 100) {
      while (Serial.available() > 0) { // was mySerial
        Serial.read(); // was mySerial
      }
      Serial.write(Com2, 8); // error due to Com2 being undefined, define before void setup() // was mySerial
      timeStart1 = millis();
    }

    if ((millis() - timeStart) > 1000) {
      Serial.println("Time out3");
      //return -1;
    }

    if (readN(&ch, 1) == 1) {
      if (ch == 0x01) {
        Data[0] = ch;
        if (readN(&ch, 1) == 1) {
          if (ch == 0x03) {
            Data[1] = ch;
            if (readN(&ch, 1) == 1) {
              if (ch == 0x02) {
                Data[2] = ch;
                if (readN(&Data[3], 4) == 4) {
                  if (CRC16_2(Data, 5) == (Data[5] * 256 + Data[6])) {
                    sal = Data[3] * 256 + Data[4];
                    flag = 0;
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

uint8_t readN(uint8_t *buf, size_t len) {
  size_t offset = 0, left = len;
  int16_t Tineout = 500;
  uint8_t *buffer = buf;
  long curr = millis();
  while (left) {
    if (Serial.available()) { // was mySerial
      buffer[offset] = Serial.read(); // was mySerial
      offset++;
      left--;
    }
    if (millis() - curr > Tineout) {
      break;
    }
  }
  return offset;
}

unsigned int CRC16_2(unsigned char *buf, int len) {
  unsigned int crc = 0xFFFF;
  for (int pos = 0; pos < len; pos++) {
    crc ^= (unsigned int)buf[pos];
    for (int i = 8; i != 0; i--) {
      if ((crc & 0x0001) != 0) {
        crc >>= 1;
        crc ^= 0xA001;
      } else {
        crc >>= 1;
      }
    }
  }

  crc = ((crc & 0x00ff) << 8) | ((crc & 0xff00) >> 8);
  return crc;
}

}

From the converter, I’m connecting to the board as follows: (-) -> GND, (+) -> Ve, R -> 47, T -> 48. Measuring voltages at the Heltec’s pins, I get Ve = 3.24 V, 47 = 3.23 V, 48 -> 3.23 V. Measuring voltages at the pins connecting converter to sensor, I get 12V = 12.75 V, A = 5.02 V, B = 0.05V.

In comparison, when I connect the same sensor and converter to an Arduino Minima R4, I receive plausible values (see Fig. 2 below) in the serial monitor.


Fig. 2: Serial monitor output showing desired output/values for the setup with the Arduino Minima R4.

With the Arduino Minima R4, I'm using the following code:
#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3);                                         //TX,RX
uint8_t Com[8] = { 0x01, 0x03, 0x00, 0x00, 0x00, 0x06, 0xC5, 0xC8 };   
uint8_t Com1[8] = { 0x01, 0x03, 0x10, 0x22, 0x00, 0x01, 0x20, 0xC0 };  
uint8_t Com2[8] = { 0x01, 0x03, 0x10, 0x20, 0x00, 0x01, 0x81, 0x00 };  
float sal, ap;

void setup() {
  Serial.begin(9600);
  mySerial.begin(4800);
}
void loop() {
  readDO_DOS_TEM();
  Atmospheric_pressure();
  Serial.print("AP = ");
  Serial.print(ap, 2);
  Serial.print("Kpa  ");
  Salinity();
  Serial.print("Salinityt = ");
  Serial.print(sal,0);
  Serial.println("%  ");
  Serial.println("   ");
  delay(1000);
}

void readDO_DOS_TEM(void) {
  uint32_t val = 0, val1 = 0, val2 = 0;
  uint8_t Data[18] = { 0 };
  uint8_t ch = 0;
  bool flag = 1;
  long timeStart = millis();
  long timeStart1 = 0;
  while (flag) {

    if ((millis() - timeStart1) > 100) {
      while (mySerial.available() > 0) {
        mySerial.read();
      }
      mySerial.write(Com, 8);
      timeStart1 = millis();
    }

    if ((millis() - timeStart) > 1000) {
      Serial.println("Time out");
      //return -1;
    }

    if (readN(&ch, 1) == 1) {
      if (ch == 0x01) {
        Data[0] = ch;
        if (readN(&ch, 1) == 1) {
          if (ch == 0x03) {
            Data[1] = ch;
            if (readN(&ch, 1) == 1) {
              if (ch == 0x0C) {
                Data[2] = ch;
                if (readN(&Data[3], 14) == 14) {
                  if (CRC16_2(Data, 15) == (Data[15] * 256 + Data[16])) {
                    val = Data[3];
                    val = (val << 8) | Data[4];
                    val = (val << 8) | Data[5];
                    val = (val << 8) | Data[6];
                    float *dos = (float *)&val;
                    float Dos = *dos * 100.00;
                    Serial.print("DO Sat = ");
                    Serial.print(Dos, 1);
                    Serial.print("%  ");
                    val1 = Data[7];
                    val1 = (val1 << 8) | Data[8];
                    val1 = (val1 << 8) | Data[9];
                    val1 = (val1 << 8) | Data[10];
                    float *Do = (float *)&val1;
                    Serial.print("DO = ");
                    Serial.print(*Do, 2);
                    Serial.print(" mg/L  ");
                    val2 = Data[11];
                    val2 = (val2 << 8) | Data[12];
                    val2 = (val2 << 8) | Data[13];
                    val2 = (val2 << 8) | Data[14];
                    float *tem = (float *)&val2;
                    Serial.print("TEM = ");
                    Serial.print(*tem, 1);
                    Serial.println("°C");
                    flag = 0;
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

void Atmospheric_pressure(void) {
  uint8_t Data[12] = { 0 };
  uint8_t ch = 0;
  bool flag = 1;
  long timeStart = millis();
  long timeStart1 = 0;
  while (flag) {

    if ((millis() - timeStart1) > 100) {
      while (mySerial.available() > 0) {
        mySerial.read();
      }
      mySerial.write(Com1, 8);
      timeStart1 = millis();
    }

    if ((millis() - timeStart) > 1000) {
      Serial.println("Time out2");
      //return -1;
    }

    if (readN(&ch, 1) == 1) {
      if (ch == 0x01) {
        Data[0] = ch;
        if (readN(&ch, 1) == 1) {
          if (ch == 0x03) {
            Data[1] = ch;
            if (readN(&ch, 1) == 1) {
              if (ch == 0x02) {
                Data[2] = ch;
                if (readN(&Data[3], 4) == 4) {
                  if (CRC16_2(Data, 5) == (Data[5] * 256 + Data[6])) {
                    ap = (Data[3] * 256 + Data[4]) / 100.0;
                    flag = 0;
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

void Salinity(void) {
  uint8_t Data[12] = { 0 };
  uint8_t ch = 0;
  bool flag = 1;
  long timeStart = millis();
  long timeStart1 = 0;
  while (flag) {

    if ((millis() - timeStart1) > 100) {
      while (mySerial.available() > 0) {
        mySerial.read();
      }
      mySerial.write(Com2, 8);
      timeStart1 = millis();
    }

    if ((millis() - timeStart) > 1000) {
      Serial.println("Time out3");
      //return -1;
    }

    if (readN(&ch, 1) == 1) {
      if (ch == 0x01) {
        Data[0] = ch;
        if (readN(&ch, 1) == 1) {
          if (ch == 0x03) {
            Data[1] = ch;
            if (readN(&ch, 1) == 1) {
              if (ch == 0x02) {
                Data[2] = ch;
                if (readN(&Data[3], 4) == 4) {
                  if (CRC16_2(Data, 5) == (Data[5] * 256 + Data[6])) {
                    sal = Data[3] * 256 + Data[4];
                    flag = 0;
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

uint8_t readN(uint8_t *buf, size_t len) {
  size_t offset = 0, left = len;
  int16_t Tineout = 500;
  uint8_t *buffer = buf;
  long curr = millis();
  while (left) {
    if (mySerial.available()) {
      buffer[offset] = mySerial.read();
      offset++;
      left--;
    }
    if (millis() - curr > Tineout) {
      break;
    }
  }
  return offset;
}

unsigned int CRC16_2(unsigned char *buf, int len) {
  unsigned int crc = 0xFFFF;
  for (int pos = 0; pos < len; pos++) {
    crc ^= (unsigned int)buf[pos];
    for (int i = 8; i != 0; i--) {
      if ((crc & 0x0001) != 0) {
        crc >>= 1;
        crc ^= 0xA001;
      } else {
        crc >>= 1;
      }
    }
  }

  crc = ((crc & 0x00ff) << 8) | ((crc & 0xff00) >> 8);
  return crc;
}

I assume that the time-out-error is being thrown due to sensor response not coming within the defined timeframe. Further, I assume that (1) the COM definitions at the top of the code made for the Heltec board are incorrect, which (2) blocks the B cable from getting enough voltage to produce a reply (hence having a voltage of 0.05 V). That’s where I then end up being stuck.

Any help, links, resources, ideas, suggestions etc. are very welcome and appreciated!

The first thing that strikes me is that you use a Serial baudrate of 4800 on the R4 but 9600 on the Heltec. Now have to get some haricot verts from the grocery.

Changed the baud rate from 9600 to 4800, the result in the Serial Monitor remains ��Time out, unfortunately. What do you plan on cooking? I’m seeing a plate with Salzkartoffeln, Tilapia or Pangasius, and the green beans, paired with some white wine for those who enjoy it…

Creamy chicken soup it is.
Reversing Tx/Rx doesn’t help with the modified baud rate? Looks like they are reversed currently (Rx to 47 which is then defined as Serial’s Rx)

Sounds delicious. Reversing Tx/Rx by setting T -> 47 and R -> 48 unfortunately does not help.

Right… So you’ve mixed Serial and mySerial and RS485.
You specifically call out in the Heltec code that it “was mySerial”. Those places should call out RS485, not Serial. Serial is what communicates with your PC, not the sensor.

Ah yes, I followed the compilation error message suggestions from the IDE. I now have the places calling for RS485, the change is the following: Previously, the error message was ��Time out, now it’s Time out.

What does the latest code look like, can you paste it again?

Sure, here you go:
HardwareSerial RS485(2); // define serial entity
float sal, ap; // define variables for Salinity and Atmospheric Pressure

// Define Com so that the error from it missing does not get thrown anymore.
uint8_t Com[8] = { 0x01, 0x03, 0x00, 0x00, 0x00, 0x06, 0xC5, 0xC8 };   
uint8_t Com1[8] = { 0x01, 0x03, 0x10, 0x22, 0x00, 0x01, 0x20, 0xC0 };  
uint8_t Com2[8] = { 0x01, 0x03, 0x10, 0x20, 0x00, 0x01, 0x81, 0x00 }; 

void setup() {
  // put your setup code here, to run once:
  
  // Power supply
  pinMode(Vext, OUTPUT);
  digitalWrite(Vext, LOW);

  Serial.begin(115200);
  RS485.begin(4800, SERIAL_8N1, 47, 48); // baud rate, bits, RX, TX // baud rate was 9600
  Serial.println("[setup] WiFi LoRa 32 V3 RS485 Test");
}

void loop() {
  // put your main code here, to run repeatedly:
  // unchanged code from DFRobot
  readDO_DOS_TEM();
  Atmospheric_pressure();
  Serial.print("AP = ");
  Serial.print(ap, 2);
  Serial.print("Kpa  ");
  Salinity();
  Serial.print("Salinity = ");
  Serial.print(sal,0);
  Serial.println("%  ");
  Serial.println("   ");
  delay(1000);
}

void readDO_DOS_TEM(void) {
  uint32_t val = 0, val1 = 0, val2 = 0;
  uint8_t Data[18] = { 0 };
  uint8_t ch = 0;
  bool flag = 1;
  long timeStart = millis();
  long timeStart1 = 0;
  while (flag) {

    if ((millis() - timeStart1) > 100) {
      while (RS485.available() > 0) { // was mySerial, now RS485
        RS485.read(); // was mySerial, now RS485
      }
      RS485.write(Com, 8); // was mySerial, now RS485 // error due to Com being undefined, define before void setup()
      timeStart1 = millis();
    }

    if ((millis() - timeStart) > 1000) {
      Serial.println("Time out");
      //return -1;
    }

    if (readN(&ch, 1) == 1) {
      if (ch == 0x01) {
        Data[0] = ch;
        if (readN(&ch, 1) == 1) {
          if (ch == 0x03) {
            Data[1] = ch;
            if (readN(&ch, 1) == 1) {
              if (ch == 0x0C) {
                Data[2] = ch;
                if (readN(&Data[3], 14) == 14) {
                  if (CRC16_2(Data, 15) == (Data[15] * 256 + Data[16])) {
                    val = Data[3];
                    val = (val << 8) | Data[4];
                    val = (val << 8) | Data[5];
                    val = (val << 8) | Data[6];
                    float *dos = (float *)&val;
                    float Dos = *dos * 100.00;
                    Serial.print("DO Sat = ");
                    Serial.print(Dos, 1);
                    Serial.print("%  ");
                    val1 = Data[7];
                    val1 = (val1 << 8) | Data[8];
                    val1 = (val1 << 8) | Data[9];
                    val1 = (val1 << 8) | Data[10];
                    float *Do = (float *)&val1;
                    Serial.print("DO = ");
                    Serial.print(*Do, 2);
                    Serial.print(" mg/L  ");
                    val2 = Data[11];
                    val2 = (val2 << 8) | Data[12];
                    val2 = (val2 << 8) | Data[13];
                    val2 = (val2 << 8) | Data[14];
                    float *tem = (float *)&val2;
                    Serial.print("TEM = ");
                    Serial.print(*tem, 1);
                    Serial.println("°C");
                    flag = 0;
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

void Atmospheric_pressure(void) {
  uint8_t Data[12] = { 0 };
  uint8_t ch = 0;
  bool flag = 1;
  long timeStart = millis();
  long timeStart1 = 0;
  while (flag) {

    if ((millis() - timeStart1) > 100) {
      while (RS485.available() > 0) { // was mySerial, now RS485
        RS485.read(); // was mySerial, now RS485
      }
      RS485.write(Com1, 8); // error due to Com1 being undefined, define before void setup() // was mySerial, now RS485
      timeStart1 = millis();
    }

    if ((millis() - timeStart) > 1000) {
      Serial.println("Time out2");
      //return -1;
    }

    if (readN(&ch, 1) == 1) {
      if (ch == 0x01) {
        Data[0] = ch;
        if (readN(&ch, 1) == 1) {
          if (ch == 0x03) {
            Data[1] = ch;
            if (readN(&ch, 1) == 1) {
              if (ch == 0x02) {
                Data[2] = ch;
                if (readN(&Data[3], 4) == 4) {
                  if (CRC16_2(Data, 5) == (Data[5] * 256 + Data[6])) {
                    ap = (Data[3] * 256 + Data[4]) / 100.0;
                    flag = 0;
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

void Salinity(void) {
  uint8_t Data[12] = { 0 };
  uint8_t ch = 0;
  bool flag = 1;
  long timeStart = millis();
  long timeStart1 = 0;
  while (flag) {

    if ((millis() - timeStart1) > 100) {
      while (RS485.available() > 0) { // was mySerial, now RS485
        RS485.read(); // was mySerial, now RS485
      }
      RS485.write(Com2, 8); // error due to Com2 being undefined, define before void setup() // was mySerial, now RS485
      timeStart1 = millis();
    }

    if ((millis() - timeStart) > 1000) {
      Serial.println("Time out3");
      //return -1;
    }

    if (readN(&ch, 1) == 1) {
      if (ch == 0x01) {
        Data[0] = ch;
        if (readN(&ch, 1) == 1) {
          if (ch == 0x03) {
            Data[1] = ch;
            if (readN(&ch, 1) == 1) {
              if (ch == 0x02) {
                Data[2] = ch;
                if (readN(&Data[3], 4) == 4) {
                  if (CRC16_2(Data, 5) == (Data[5] * 256 + Data[6])) {
                    sal = Data[3] * 256 + Data[4];
                    flag = 0;
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

uint8_t readN(uint8_t *buf, size_t len) {
  size_t offset = 0, left = len;
  int16_t Tineout = 500;
  uint8_t *buffer = buf;
  long curr = millis();
  while (left) {
    if (RS485.available()) { // was mySerial, now RS485
      buffer[offset] = RS485.read(); // was mySerial, now RS485
      offset++;
      left--;
    }
    if (millis() - curr > Tineout) {
      break;
    }
  }
  return offset;
}

unsigned int CRC16_2(unsigned char *buf, int len) {
  unsigned int crc = 0xFFFF;
  for (int pos = 0; pos < len; pos++) {
    crc ^= (unsigned int)buf[pos];
    for (int i = 8; i != 0; i--) {
      if ((crc & 0x0001) != 0) {
        crc >>= 1;
        crc ^= 0xA001;
      } else {
        crc >>= 1;
      }
    }
  }

  crc = ((crc & 0x00ff) << 8) | ((crc & 0xff00) >> 8);
  return crc;
}

It seems that I’m not missing a library, otherwise I’d probably get errors right away in the verification.

And what is Vext wired up to? You say ‘+’ but I don’t see a plus on the DFRobot converter board.

It’s actually wired to ‘+’, see the two figures below (I know that it’s strange to use ‘+’ and ‘-’ instead of VIN and GND):


Fig. 1: DFR0845 Gravity: Active Isolated RS485 to UART Signal Converter.


Fig. 2: Picture of the converter, the red cable (furthest on the right) is connected to Ve on the Heltec board.

Does the Tx or Rx LED blink on the converter when running the sketch?

It comes to mind that ESP32 is 3.3V while Arduino has 5V logic but I’ve had little problems with that in the past. You could try and make a voltage divider with a few resistors in the Rx line to drop it down to 3.3V. But that only makes sense if the LEDs are flashing in the first place.

It could be a better idea to connect + to 5V and try that.

No, there’s no blinking, unfortunately. The supply voltage of the converter is 3.3 ~ 5 V (see tech specs here) so technically, that should not be an issue. I can try the 5 V pin again but I’d have to build the voltage divider first to not fry the GPIOs. I will do that tomorrow morning and report back, good night! :zzz:

I don’t know if you’ve noticed, but if you follow through the relevant DFRobot documentation you ultimately get a link to this Hackster.io (AI-based Aquatic Ultrasonic Imaging & Chemical Water Testing) project that uses an Arduino Nano ESP32 and the subject DFRobot RS485-to-UART module. It is perhaps the most comprehensive project description that I’ve ever read (!) so there’s a lot to wade through to get to the essential details but what I have noticed so far is that the serial interface to the adaptor module is defined as:

Serial1.begin(19200, SERIAL_8N1, RX_1_PIN, TX_1_PIN);

So is the baud rate for the module fixed at 19200?

On the voltage front, I note from the schematic (from the DFRobot Wiki) that the module includes an MT3608 boost converter that would deal with the [3.3V] input voltage (as has just been noted as I was typing this).

1 Like

Nice resource, will read it in detail tomorrow. I don’t think the baud rate of the module is fixed at all. In the code example for the DO sensor, it gets assigned a baud rate = 4800. In the code example for the module itself, the assigned baud rate is now 9600. I could try the 19200 baud rate (and others) tomorrow as well. Trying certainly won’t/shouldn’t hurt.

There will, of course, be two applicable baud rates (and they will not necessarily be the same): one for RS485 communications with the sensor and the other for UART communications with the MCU, with the RS485-to-UART module sitting in between managing any difference between the two. There may be some auto-detect mechanism in play, but in my experience that’s not often the case.

Nonetheless, those weird characters you originally saw preceding the timeout message are the classic indicators of mismatched baud rates.

(EDITs are just clarification in wording)

I tested the different baud rates but there was no change, the output remained at Time out, and the speed of the output also did not change.

I tested the voltage divider, taking 5V down to 3V. The converter is now powered with 5V from the Heltec board. I used voltage dividers for both R and T.

  • Voltage divider on T only (R not connected):
    • Connected to 47: TX LED on converter continuous light, RX LED off.
    • Connected to 48: TX LED on converter continuous light, RX LED blinks rapidly.
  • Voltage divider on both:
    • T on 48, R on 47: Both LEDs blink incredibly fast (almost appearing to be continuous), the output in the Serial Monitor rushes through as if there was no delay at all.
    • T on 47, R on 48: Both LEDs still blink incredibly fast but the output is now at normal speed again.
  • Voltage divider on R only (T not connected): Received almost 5V on T which is why I did not connect to the Heltec board at all.

Interestingly, for all of these configurations, the output still only prints Time out, so there has to be another issue somewhere, perhaps in the code as the RX/TX LEDs are now blinking but the speed is overly fast and the output is still not the desired one.

You can’t divide the 3.3V logic up to 5V so the Heltec’s Tx to converter’s Rx must be wired straight. It could be that the converter doesn’t accept the 3.3V logic from ESP32.
If you divide the 3.3V equally to the 5V, you end up at roughly 2.5V which then likely floats around the threshold and that makes the LEDs flash continuously.

Okay, I removed the voltage divider on R (blue cable). Connecting that to 47, only the TX LED is on (seems to flash) and the output runs at normal speed, printing Time out. Connecting R to 48 instead, the TX LED is on (seemingly continuously) and RX’s LED blinks at normal speed but very faintly only; the output in the serial monitor runs at normal speed but still shows Time out.