Example Code for Arduino-Read Dissolved Oxygen, Saturation, and Temperature

This project demonstrates how to use an Arduino board to read dissolved oxygen concentration, dissolved oxygen saturation, temperature, atmospheric pressure, and salinity from the RS485 Dissolved Oxygen Sensor using the ModBus-RTU protocol. Users will learn how to communicate with RS485 devices, parse ModBus-RTU data frames, and interpret the sensor's measurements.

Hardware Preparation

Software Preparation

Wiring Diagram

If the power of the RS485 device is small and the required current is less than 12V-160mA, the RS485 to UART signal conversion module does not require a 12V external power supply, making wiring more convenient.

Other Preparation Work

No additional preparation work is required beyond the hardware and software setup and wiring.

Sample 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;
}

Result

The serial port prints the dissolved oxygen concentration, dissolved oxygen saturation, temperature, atmospheric pressure, and salinity values ​​collected by the sensor.

Was this article helpful?

TOP