Chinese O2 Sensor

Hello all,

for a project I have bought this sensor:

https://de.aliexpress.com/item/Ultrasonic-oxygen-concentration-ultrasonic-flow-sensor-oxygen-sensor-oxygen-making-machine/32769505991.html?spm=a2g0s.9042311.0.0.8htq1p

It can measure the oxygen content of a gas - additionally it can measure the flow rate.

The sensor comes in two parts.

a) The actual sensor.

b) The display unit.

In the description of the sensor they say, that there is an RS232 interface, which in actual fact also exists.

There is an serial interface between the sensor and the display unit.

There was no data sheet, which explains the serial communication, so I thought I just try to use an Arduino to read the communication ....

Interestingly there was an RX and TX between the sensor and the display unit.

I did attach the RX of my Arduino to RX of the system and then to TX of the system.

Indeed I did receive data, but the data was goblygookish - trying all available baud rated did not help.

I assume they are sending the data in binary form or using Chinese characters!??!


My aim here is to get a hold in the oxygen value to insert the data to an IOT hub...

Any idea how to proceed in such an situation?

Thanks for your help.

Kr,

Andreas

By the was, this was the sketch I have used:

void setup() {
  Serial.begin(9600);
}

void loop() {

  while (Serial.available()) {
    char inChar = (char)Serial.read();
    Serial.print(inChar);
  }
}

There are some Images of the sensor

1 Like

I have even managed to get the data sheet of the sensor, however in chenese language...

超声波氧气流量浓度传感器说明书-阳光 V1.30 19200 9600 .pdf (573 KB)

I have used google translate to translate the part of the serial communication.


4, serial communication protocol

Mode 1:

RS-232 serial communication parameters:

Baud rate: 19200bps

Character length: 1 bit start bit, 8 bit data bit, 1 stop bit, no parity

Communication instructions

Features:

  1. Query the measurement results

send:

0x55 0xAA 0x7E 0x02 0x4F 0x43 0x94 0x0E 0x0D

answer:

0x55 0xAA 0x7E 0x04 0x4F 0x43 MSB LSB SUM XOR 0x0D

Function: Query the measurement result

Description:

For example: return 11 bytes, where the first 7 and 8 are directly oxygen concentration, the measurement result = (high byte * 256 + low byte) / (10).

Byte SUM is the cumulative value of bits 4, 5, 6, 7, 8 bytes, and the tenth byte XOR is the exclusive-OR value of bits 4, 5, 6, 7, 8 bits. E.g

The return data is:

0x55 0xAA 0x7E 0x04 0x4F 0x43 0x03 0xB4 0x4D 0xBF 0x0D

Results (O2) = 0x03B4 (hexadecimal) = 948, the concentration value was 94.8%

Mode 2:

RS-232 serial communication parameters:

Baud rate: 9600bps

Character length: 1 bit start bit, 8 bit data bit, 1 stop bit, no parity

Communication instructions

Features:

  1. Query the measurement results

Send: 11 01 01 ED

Response: [ACK] 09 01 (O2) (FLOW) [ST1] [ST2]

Function: Query the measurement result

Description:

(O2) (FLOW) as the measurement result, the measurement result = (high byte * 256 + low byte) / (10). (O2) (FLOW) (temperature) is one

A 16-bit signed integer. The most significant bit is the sign bit. In the use of the process, there may be "0xFF, 0xFF" (decimal: -1),

This is due to the use of the instrument in the process, there may be zero drift, which also appears negative drift. [ST] System status bit, used to indicate

(Q) + 09 + 01 + (O2) + (FLOW) + (temperature) + [ST1] + [ST2]) of the system,

For example: a measurement result for the flow: 5L / min, O2 concentration: 94.8%. Then the returned result (O2) = 94.8% = 0x03B4

(Hexadecimal), (FLOW) = 5.0 L / min = 0x0032 (hexadecimal), the returned data is "16 09 01 03 B4 00 32 00 D2 00 00 25"

Andreas1984:
Mode 1:

RS-232 serial communication parameters:

Baud rate: 19200bps

Character length: 1 bit start bit, 8 bit data bit, 1 stop bit, no parity

Communication instructions

Features:

  1. Query the measurement results

send:

0x55 0xAA 0x7E 0x02 0x4F 0x43 0x94 0x0E 0x0D

answer:

0x55 0xAA 0x7E 0x04 0x4F 0x43 MSB LSB SUM XOR 0x0D

Right, that explains why you got those garbage characters in the Serial terminal. It's not ASCII (no surprise), you get binary data down the line. Makes processing easier, though.

It looks pretty straightforward to read out that thing, now you have this data sheet translated. Pretty readable translation I have to add.

Yep, things how to interface with the sensor get more clear to me.

However currently I am still clueless in how to interpret the answer, in order to get an useable integer value out.

Thanks,

Andreas

Basiclly you have to send out the query sequence as they stated (using Serial.write()), then when the answer comes in read them into a byte array and start parsing that.

1 Like

To get your int value, take the two bytes (7 & 8) and combine them into a single int.

So:

byte reading[] // byte array where the Serial readings are stored.
int result // to store the reading.

result = reading[7] * 256 + reading[8]; // the readable version.

result = (int)(reading[7] << 8) | reading[8]; // the bitwise, super efficient version.

float O2concentration = result/10; // measured concentration in %

Of course you should also check the rest of the communication that it is as you expect, and validate the check sum.

Thanks a ton!

I dont even have the sensor at hand now, as I am not at home, but I have made up the following code now:

A bit a tricke part is also the section /*** Read data from sensor into byte array. ***/

I have this code from another thread where the person faced a simmilar issue: How to read an array of bytes through Serial.read( - Bugs & Suggestions - Arduino Forum

#include <SoftwareSerial.h>

SoftwareSerial mySerial(10, 11); // RX, TX

byte reading[10]; // byte array where the Serial readings are stored.
int result; 
boolean dataAvailable;
float O2concentration;

void setup() {
  Serial.begin(19200);    // Init serial to communicate with sensor.
  mySerial.begin(9600);   // Init softserial to communicate with other device.
}

void loop() {

  dataAvailable = false;

  /***  Send message to sensor, which make it send back data.***/
  
  byte message[] = { 0x55, 0xAA, 0x7E, 0x02, 0x4F, 0x43, 0x94, 0x0E, 0x0D };
  Serial.write(message, sizeof(message));

  /***  Read data from sensor into byte array. ***/
  
  int MAX_MILLIS_TO_WAIT = 100;
  unsigned long starttime;
  starttime = millis();
  
  while ( (Serial.available() <11 ) && ((millis() - starttime) < MAX_MILLIS_TO_WAIT) ) {      
    // not finished jet.
  }
  if(Serial.available() < 11) {
    // not finished jet.
  }
  else {
    for(int n=0; n < 10; n++) {
      reading[n] = Serial.read(); 
    }

    dataAvailable = true; 
  }

  /*** Interpreting the data. ***/

  if (dataAvailable == true) {

    result = reading[7] * 256 + reading[8]; // the readable version.

    result = (int)(reading[7] << 8) | reading[8]; // the bitwise, super efficient version.

    O2concentration = result/10; // measured concentration in %
  }

  /*** Send the extracted sensor value to other device over softserial. ***/
  mySerial.println("[" + String(O2concentration) + "]");

  delay(2000);
}