Weather Station using ESP32 and Bosch BME688

Hello everyone,

I am new here and I have some questions.
So, I want to make a mini weather station using the ESP32 and BME688 sensor (using I2C protocol) which will upload data to a service like InfluxDB or something (I have not decided yet) via Wi-Fi or Bluetooth (I have not decided that either) but for now I just want to make everything work to make sure and my focus as of now is just that. So, as of right now my problem is the following:
I am really bad at coding so I decided to try Chat GPT and make it write a code for me. After many attempts, I dont seem to be able to verify the code and dont really know what is the problem or how to fix it. I have installed the ESP32 library for Arduino IDE which allows me to use the ESP in Arduino IDE, as well as installed the BME68x library by Bosch Sensortec. I tried looking everywhere in the latter (every header file, C file etc.) but I don`t seem to understand quite right how and what functions to use in order to understand what to do later. I am sharing the code, as well as the errors here but be aware that it is kind of a bad mess right now so I need someone to tell me where and what should I look for in the library and how exactly I should use it. I am really not good at programming, especially as it comes to embedded. Anyways, here is the code and the errors:

#include <bme68xLibrary.h>

#include <Wire.h>        // Include the Wire library for I2C communication


Bme68x mySensor;          // Create an instance of the BME68X sensor object


void setup() {
  Serial.begin(9600);     // Start serial communication at 9600 baud
  while (!Serial);        // Wait for the serial monitor to open

  void Bme68x::begin(uint8_t i2cAddr, TwoWire &i2c, bme68x_delay_us_fptr_t idleTask) //initialize the sensor based on the Wire library     //this gets coloured in red after verification
{
	comm.i2c.i2cAddr = i2cAddr;
	comm.i2c.wireobj = &i2c;
	bme6.intf = BME68X_I2C_INTF;
	bme6.read = bme68xI2cRead;
	bme6.write = bme68xI2cWrite;
	bme6.delay_us = idleTask;
	bme6.intf_ptr = &comm;
	bme6.amb_temp = 25;

	status = bme68x_init(&bme6);
}
  uint8_t Bme68x::getOpMode(void)    //this gets coloured in red after verification
{
	uint8_t opMode;
	status = bme68x_get_op_mode(&opMode, &bme6);
	return opMode;
}

}

void loop() {
  if (!mySensor.performReading()) {
    Serial.println("Failed to perform reading :(");
    return;
  }
  
  Serial.print("Temperature = ");
  Serial.print(mySensor.temperature);
  Serial.println(" *C");
  
  Serial.print("Pressure = ");
  Serial.print(mySensor.pressure / 100.0);
  Serial.println(" hPa");
  
  Serial.print("Humidity = ");
  Serial.print(mySensor.humidity);
  Serial.println(" %");

  Serial.print("Gas Resistance = ");
  Serial.print(mySensor.gas_resistance / 1000.0);
  Serial.println(" KOhms");

  Serial.println();
  
  delay(2000);    // Wait for 2 seconds before taking another reading
}

Errors:
D:\Mitko\University\4_kurs\8_Semester\Diplomna_rabota\TEST\bme688_test\bme688_test.ino: In function 'void setup()':
D:\Mitko\University\4_kurs\8_Semester\Diplomna_rabota\TEST\bme688_test\bme688_test.ino:13:21: error: qualified-id in declaration before '(' token
void Bme68x::begin(uint8_t i2cAddr, TwoWire &i2c, bme68x_delay_us_fptr_t idleTask) //initialize the sensor based on the Wire library
^
D:\Mitko\University\4_kurs\8_Semester\Diplomna_rabota\TEST\bme688_test\bme688_test.ino:26:28: error: qualified-id in declaration before '(' token
uint8_t Bme68x::getOpMode(void)
^
D:\Mitko\University\4_kurs\8_Semester\Diplomna_rabota\TEST\bme688_test\bme688_test.ino: In function 'void loop()':
D:\Mitko\University\4_kurs\8_Semester\Diplomna_rabota\TEST\bme688_test\bme688_test.ino:36:17: error: 'class Bme68x' has no member named 'performReading'
if (!mySensor.performReading()) {
^~~~~~~~~~~~~~
D:\Mitko\University\4_kurs\8_Semester\Diplomna_rabota\TEST\bme688_test\bme688_test.ino:42:25: error: 'class Bme68x' has no member named 'temperature'
Serial.print(mySensor.temperature);
^~~~~~~~~~~
D:\Mitko\University\4_kurs\8_Semester\Diplomna_rabota\TEST\bme688_test\bme688_test.ino:46:25: error: 'class Bme68x' has no member named 'pressure'
Serial.print(mySensor.pressure / 100.0);
^~~~~~~~
D:\Mitko\University\4_kurs\8_Semester\Diplomna_rabota\TEST\bme688_test\bme688_test.ino:50:25: error: 'class Bme68x' has no member named 'humidity'
Serial.print(mySensor.humidity);
^~~~~~~~
D:\Mitko\University\4_kurs\8_Semester\Diplomna_rabota\TEST\bme688_test\bme688_test.ino:54:25: error: 'class Bme68x' has no member named 'gas_resistance'
Serial.print(mySensor.gas_resistance / 1000.0);
^~~~~~~~~~~~~~

exit status 1

Compilation error: qualified-id in declaration before '(' token

Any help is appreciated! Thank you!

Did you notice how setup() is hosed?

void setup() {
  Serial.begin(9600);     // Start serial communication at 9600 baud
  while (!Serial);        // Wait for the serial monitor to open

  void Bme68x::begin(uint8_t i2cAddr, TwoWire & i2c, bme68x_delay_us_fptr_t idleTask) //initialize the sensor based on the Wire library     //this gets coloured in red after verification
  {

notice how setup() is not properly terminated with a } before a new function is declared?

  uint8_t Bme68x::getOpMode(void)    //this gets coloured in red after verification
  {
    uint8_t opMode;
    status = bme68x_get_op_mode(&opMode, &bme6);
    return opMode;
  }

notice how setup() is not properly terminated with a } before a new function is declared?

Problem is, despite what you might have heard, ChatGPT is also really bad at coding. Search this forum and you will find lots of examples!

Really, really bad idea if you want anything beyond a skeleton concept.

Yeah, I dont think Ill ever be using it for writing a code.

Yes, I know that now. Thank you!

Okay, here`s my code again. I think I fixed the '}' error:

#include <bme68xLibrary.h>

#include <Wire.h>        // Include the Wire library for I2C communication


Bme68x mySensor;          // Create an instance of the BME68X sensor object


void setup() {
  Serial.begin(9600);     // Start serial communication at 9600 baud
  while (!Serial);        // Wait for the serial monitor to open
}
  void Bme68x::begin(uint8_t i2cAddr, TwoWire &i2c, bme68x_delay_us_fptr_t idleTask) //initialize the sensor based on the Wire library
{
	comm.i2c.i2cAddr = i2cAddr;
	comm.i2c.wireobj = &i2c;
	bme6.intf = BME68X_I2C_INTF;
	bme6.read = bme68xI2cRead;
	bme6.write = bme68xI2cWrite;
	bme6.delay_us = idleTask;
	bme6.intf_ptr = &comm;
	bme6.amb_temp = 25;

	status = bme68x_init(&bme6);
}
  uint8_t Bme68x::getOpMode(void)
{
	uint8_t opMode;
	status = bme68x_get_op_mode(&opMode, &bme6);
	return opMode;
}



void loop() {
  if (!mySensor.performReading()) {   //gets coloured in red
    Serial.println("Failed to perform reading :(");
    return;
  }
  
  Serial.print("Temperature = ");
  Serial.print(mySensor.temperature);  //gets coloured in red
  Serial.println(" *C");
  
  Serial.print("Pressure = ");
  Serial.print(mySensor.pressure / 100.0);  //gets coloured in red
  Serial.println(" hPa");
  
  Serial.print("Humidity = ");
  Serial.print(mySensor.humidity);  //gets coloured in red
  Serial.println(" %");

  Serial.print("Gas Resistance = ");
  Serial.print(mySensor.gas_resistance / 1000.0);  //gets coloured in red
  Serial.println(" KOhms");

  Serial.println();
  
  delay(2000);    // Wait for 2 seconds before taking another reading
}

And here`s the error list now:

D:\Mitko\University\4_kurs\8_Semester\Diplomna_rabota\TEST\bme688_test\bme688_test.ino: In function 'void loop()':
D:\Mitko\University\4_kurs\8_Semester\Diplomna_rabota\TEST\bme688_test\bme688_test.ino:36:17: error: 'class Bme68x' has no member named 'performReading'
   if (!mySensor.performReading()) {
                 ^~~~~~~~~~~~~~
D:\Mitko\University\4_kurs\8_Semester\Diplomna_rabota\TEST\bme688_test\bme688_test.ino:42:25: error: 'class Bme68x' has no member named 'temperature'
   Serial.print(mySensor.temperature);
                         ^~~~~~~~~~~
D:\Mitko\University\4_kurs\8_Semester\Diplomna_rabota\TEST\bme688_test\bme688_test.ino:46:25: error: 'class Bme68x' has no member named 'pressure'
   Serial.print(mySensor.pressure / 100.0);
                         ^~~~~~~~
D:\Mitko\University\4_kurs\8_Semester\Diplomna_rabota\TEST\bme688_test\bme688_test.ino:50:25: error: 'class Bme68x' has no member named 'humidity'
   Serial.print(mySensor.humidity);
                         ^~~~~~~~
D:\Mitko\University\4_kurs\8_Semester\Diplomna_rabota\TEST\bme688_test\bme688_test.ino:54:25: error: 'class Bme68x' has no member named 'gas_resistance'
   Serial.print(mySensor.gas_resistance / 1000.0);
                         ^~~~~~~~~~~~~~

exit status 1

Compilation error: 'class Bme68x' has no member named 'performReading'

From this I understand that there is nothing in the bme68x library called with the names 'performReading', 'temperarure', 'pressure', 'humidity' and 'gas_resistance' so that I have to name them properly, but my problem is I don`t really know what they are called inside the library and should I only change their names or the entire structure of the whole function.

I suggest deleting that code. It's already taken up more of your time and the forum's time than it's worth.

I checked the library

but all the example sketches seem to use SPI rather than i²c, which is not a great job by the library author(s).

Let us begin with one of those and try to convert it to use i²c.

The "forced mode" example looks to be the simplest. Here is the first part of it:

/**
 * Copyright (C) 2021 Bosch Sensortec GmbH
 *
 * SPDX-License-Identifier: BSD-3-Clause
 * 
 */

#include "Arduino.h"
#include "bme68xLibrary.h"

#ifndef PIN_CS
#define PIN_CS SS
#endif

Bme68x bme;

/**
 * @brief Initializes the sensor and hardware settings
 */
void setup(void)
{
	SPI.begin();
	Serial.begin(115200);
	
	while (!Serial)
		delay(10);
		
	/* initializes the sensor based on SPI library */
	bme.begin(PIN_CS, SPI);

I suspect the rest of the sketch after that last line will work without alteration.

We won't need that part, it's related to SPI.

We can replace that with Wire.begin();

1 Like

We need to replace this line with the equivalent for i2c.

From the library's .h file, here is the begin() method for i²c:

void begin(uint8_t i2cAddr, TwoWire &i2c, bme68x_delay_us_fptr_t idleTask = bme68xDelayUs);

We need to provide the i²c address (a quick Google search revealed this as 0x76 or 0x77, we can try both).

So the replacement line should be, I think

bme.begin(0x76, Wire);
1 Like

Did you happen to look at the examples that were installed when the library was installed?

Was the Adafruit library for the devices tried?

Well, I did look at them, but they seem to be written using the SPI protocol. I want to use I2C and to be honest, I don`t really know how exactly to change the code to satisfy my needs.

Thank you very much for the detailed answer! As of now the code compiles without any errors but when I upload it to the ESP32 on my Windows 10 laptop it throws the following message:

Sketch uses 285953 bytes (21%) of program storage space. Maximum is 1310720 bytes.
Global variables use 22920 bytes (6%) of dynamic memory, leaving 304760 bytes for local variables. Maximum is 327680 bytes.
esptool.py v4.5.1
Serial port COM5
Connecting......................................

A fatal error occurred: Failed to connect to ESP32: No serial data received.
For troubleshooting steps visit: https://docs.espressif.com/projects/esptool/en/latest/troubleshooting.html
Failed uploading: uploading error: exit status 2

I searched on the Internet but I dont seem to find any of the solutions to work for me. The ESP is connected on the COM5 port (its the only one that becomes available after connecting the device to my laptop). I tried holding the BOOT button after uploading the sketch and releasing it when I see the "Connecting........" message but it does not work for me (tried several different ways of pressing, holding and releasing the button, as well). I think it seems that the ESP cannot enter in bootloader mode or something but Im not sure. Ive downloaded and installed the CP210x drivers for the port, as well so I dont think its a port or driver problem. The sensor is connected via I2C protocol the following:
ESP32 DevKit V1 ////////// BME688
3.3V ---------------------------> 2-6V (VCC)
GND -------------------------------> GND
D21 (GPIO21) -------------------> SDA
D23 (GPIO22) -------------------> SCL

And here`s the code for forced mode now:

/**
 * Copyright (C) 2021 Bosch Sensortec GmbH
 *
 * SPDX-License-Identifier: BSD-3-Clause
 * 
 */

#include "Arduino.h"
#include "bme68xLibrary.h"
#include "Wire.h"

//#ifndef PIN_CS
//#define PIN_CS SS
//#endif

Bme68x bme;

/**
 * @brief Initializes the sensor and hardware settings
 */
void setup(void)
{
	Wire.begin();
	Serial.begin(115200);
	
	while (!Serial)
		delay(10);
		
	/* initializes the sensor based on I2C library */
	bme.begin(0x76, Wire);

  void begin(uint8_t i2cAddr, TwoWire &i2c, bme68x_delay_us_fptr_t idleTask = bme68xDelayUs);

	if(bme.checkStatus())
	{
		if (bme.checkStatus() == BME68X_ERROR)
		{
			Serial.println("Sensor error:" + bme.statusString());
			return;
		}
		else if (bme.checkStatus() == BME68X_WARNING)
		{
			Serial.println("Sensor Warning:" + bme.statusString());
		}
	}
	
	/* Set the default configuration for temperature, pressure and humidity */
	bme.setTPH();

	/* Set the heater configuration to 300 deg C for 100ms for Forced mode */
	bme.setHeaterProf(300, 100);

	Serial.println("TimeStamp(ms), Temperature(deg C), Pressure(Pa), Humidity(%), Gas resistance(ohm), Status");
}

void loop(void)
{
	bme68xData data;

	bme.setOpMode(BME68X_FORCED_MODE);
	delayMicroseconds(bme.getMeasDur());

	if (bme.fetchData())
	{
		bme.getData(data);
		Serial.print(String(millis()) + ", ");
		Serial.print(String(data.temperature) + ", ");
		Serial.print(String(data.pressure) + ", ");
		Serial.print(String(data.humidity) + ", ");
		Serial.print(String(data.gas_resistance) + ", ");
		Serial.println(data.status, HEX);
	}
}

That's odd. At least one reply has disappeared from this topic. But I don't see a "topic deleted by author" message as I would expect to see ...

I started writing a response to it:

That line should not be in your sketch at all. It's a line from the sensor library that I referred to, to figure out how to replace the .begin() from the example sketch to work with i²c instead or SPI.

EDIT: yes, this is post #14. Where did post #13 go?

Yes, I received a message that the post is "temporarily hidden" and should appear shortly. I just edited it a little bit and this happened. As for the line you referred to, you mean it automatically gets called by my code and executes from the library?

EDIT: #post13 is visible now

Hi @sky_vortex. I apologize for the inconvenience.

The forum's automated spam filter sometimes produces false positives, which result in those topics temporarily being hidden unjustly. This is why a team of human moderators review every action taken by the automated system. Your missing post has now been restored as the result of such a review.

So I think in the end these false detections are always corrected, but there is an unfortunate delay between the time of the spam detection and when a moderator reviews the action.

Yes, your code line here:

calls a function/method in the library which is defined in the .h file as follows:

void begin(uint8_t i2cAddr, TwoWire &i2c, bme68x_delay_us_fptr_t idleTask = bme68xDelayUs);

You don't need the above line in your code, it's already in the library.

But this is academic at the moment, because you can't upload anything to the ESP board.

Yes, thank you! I am not sure what is the problem currently. I read that in order to upload a sketch on the ESP, I have to set the bootloader in LOW and that could be done by holding the BOOT button on the device (while the code is uploading), which through a high ohm resistor pulls it down but it does not seem to work (at least for me).

Unfortunately, I'm not very experienced with ESP32 boards. I have plenty of experience with their predecessors, ESP8266. With those boards, once you are in bootloader mode, you don't need to continue holding any buttons, it should just accept the new code upload. Maybe ESP32 is slightly different. There are plenty of forum members with ESP32 experience, maybe one of them can help you.

1 Like

Thank you very much, buddy! You helped me big time with my project and I am grateful for that! I hope now someone experienced in ESP32 sees my thread here. Until then, I will be trying to solve the problems.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.