GY-39 modul sending weird data

Hello!
I'm working on a project, using GY-39. Here are usage information:
GY-39 Environmental Sensor Module (pressure, temperature, humidity, illuminance)
Detailed product description
Module GY-39 combines temperature, air pressure, relative humidity, and illumination measurements, and has a built-in controller (MCU) that processes the data and sends it via UART or I2C. Due to its 3-5 V power supply and TTL interface, it is suitable for Arduino, ESP32, and other development boards for electronics projects, DIY prototyping, and education. Typical uses include weather stations, microclimate control in greenhouses, smart lighting, and recording environmental parameters in IoT devices.
Note on sensors: GY-39 versions are usually based on bme280 (temp./humidity/pressure) and bh1750 or max44009 (light); check the version in the photo of your product.

Technical specifications

  • sensors: bme280 (temperature, humidity, pressure) + bh1750 or max44009 (light intensity)
  • Temperature measuring range: approx. −40 to +85 °C
  • Humidity measuring range: 0 to 100% RH
  • pressure measuring range: 300 to 1100 hPa
  • Illumination measurement range: from low lux to daylight (depending on version)
  • communication mode: uart (ttl) or i2c; “continuous” and “query” modes
  • typical uart speeds: 9600 or 115200 bps
  • i2c address: often 0x5b (7-bit) for mcu-i2c mode; direct chips have their own addresses (e.g. bme280 0x76/0x77, bh1750 0x23)
  • power supply: 3–5 V DC
  • refresh rate: up to approximately 10 Hz
  • typical pins: vcc, gnd, ct (uart_tx/i2c_scl), dr (uart_rx/i2c_sda), s0 (uart/i2c select), s1 (chip-only), int (interrupt for light sensor)

Communication with Arduino UNO (practical)

There are three modes; for UNO, the simplest is UART.

  1. UART mode (recommended for quick start)
  • setting: s0 = “high” (uart), s1 = “high” (mcu active)
  • links:
    • vcc → 5v (or 3.3v), gnd → gnd
    • tx module (ct) → uno d2, rx module (dr) → uno d3 (use SoftwareSerial; d0/d1 are occupied by usb)
    • if you are not sure about the 5 in input tolerance on the module, use a divider on the uno tx → module rx line (e.g. 1 kΩ + 2 kΩ)
  • speed: start with 9600 bps; if you get “strange” characters, switch to 115200 bps
  1. MCU-I2C mode (read module registers)
  • setting: s0 = “low” (i2c), s1 = “high” (mcu active)
  • connections: vcc → 5v, gnd → gnd, ct → scl (uno a5), dr → sda (uno a4)
  • notes: the default i2c address is 0x5b on most versions; you read the prepared values ​​from the module registers (the layout is usually described in the printed material or product sheet)
  1. “Chip-only” direct i2c to sensors (advanced use)
  • setting: s1 = “low” (mcu bypasses sensors), s0 = “low” (i2c)
  • connections: a4/a5 to sda/scl of sensors, vcc → 3.3v (recommended), add a level converter, as sensors are usually 3.3v logic
  • notes: addresses are typically bme280 0x76/0x77 and bh1750 0x23; use the appropriate arduino libraries

How to get reliable measurements

  • installation: mount the module away from heat and draft sources; point the light sensor towards the area you want to monitor
  • power supply: when powered from USB, consider noise; for more accurate measurements, you can use filtering or a separate power supply
  • communication: for longer i2c lines, reduce the speed (e.g. 50–100 kHz) and add appropriate pull-up resistors to sda/scl

Where is the module used in practice?

  • smart home: automatic dimmers, ventilation based on humidity and temperature
  • IoT prototypes: recording environmental parameters, warnings when exceeded
  • education: exercises in i2c/uart communication, calibration and data processing
  • environmental control: greenhouses, display cases, storage of sensitive materials

I decided to use the UART mode, because it says here, it is the easier to use with Aruino UNO, which I'm using for this project. The problem is, I'm getting weird data, like Temperature: 176.74 °C
Humidity: 24.83%
Pressure: 99095.19 hPa
Illumination: 327745723 lux

My code:


#include <SoftwareSerial.h>

SoftwareSerial gySerial(2, 3); // RX, TX on arduino
const int PACKET_SIZE = 33;
byte buffer[PACKET_SIZE];
int index = 0;
bool headerFound = false;

void setup() {
  Serial.begin(9600);
  gySerial.begin(9600);  
  Serial.println("starting gy39...");
}

void loop() {
  while (gySerial.available()) {
    byte incoming = gySerial.read();

    if (!headerFound) {
    
      if (index == 0 && incoming == 0x5A) {
        buffer[index++] = incoming;
      } else if (index == 1) {
        if (incoming == 0x5A) {
          buffer[index++] = incoming;
          headerFound = true;
        } else {
          // no header
          index = 0;
        }
      } else {
        index = 0;
      }
    } else {
  
      buffer[index++] = incoming;

      if (index == PACKET_SIZE) {
       
        parsePacket(buffer);

        // reset
        index = 0;
        headerFound = false;
      }
    }
  }
}

void parsePacket(byte* data) {
  // check header
  if (data[0] != 0x5A || data[1] != 0x5A) {
    Serial.println("Mistake, wrong header!");
    return;
  }

  // Temperature (2 bytes, int16_t)
  int16_t tempRaw = (data[2] << 8) | data[3];
  float temperatura = tempRaw / 100.0;

  //humidityt (2 bytes, int16_t)
  int16_t humRaw = (data[4] << 8) | data[5];
  float vlaga = humRaw / 100.0;

  //  pressure (4 bytes, uint32_t)
  uint32_t presRaw = ((uint32_t)data[6] << 24) |
                     ((uint32_t)data[7] << 16) |
                     ((uint32_t)data[8] << 8) |
                     data[9];
  float tlak = presRaw / 100.0;

  // light (4 bytes, uint32_t)
  uint32_t lightRaw = ((uint32_t)data[10] << 24) |
                      ((uint32_t)data[11] << 16) |
                      ((uint32_t)data[12] << 8) |
                      data[13];

 
  Serial.print("Temperature: "); Serial.print(temperature); Serial.println(" °C");
  Serial.print("Humidity: "); Serial.print(humidity); Serial.println(" %");
  Serial.print("Pressure: "); Serial.print(tpressure); Serial.println(" hPa");
  Serial.print("Light:  "); Serial.print(lightRaw); Serial.println(" lux");
  Serial.println("----------------------");
}

any idea, what could have possibly gone wrong?

on entry to function parsePacket() could you print the received values of data?
and post the output of the serial monitor (using code tags not a screen image)

also it is not a good idea to have the receiving baudrate and the serial monitor baudrate the same - make the serial monitor faster, e.g.

void setup() {
  Serial.begin(115200);
  gySerial.begin(9600);  

you should calculate the checksum of the received data and compare it with the received checksum

did you share the right code or was it localized in some way ? some variables you print like temperature , humidity , and tpressure do not exist.

your decoding is fragile, you should get the length of the payload after the header somewhere, I don't know this module, but looking at this doc, you have metadata available

➜ I would build a small state machine for the decoding.

That's your temperature, bytes 4 and 5 according to the docs.