Closed mczakk closed 1 week ago
Do you think it makes sense to re-post an entire source file in order to let people (including me) search for any changes you might have made?
You got the display working in BresserWeatherSensorTTN. Why don't you apply the same changes to this project or go back one step and look into the display library's examples on how to use it? The general approach is:
You can place the include statement, the display object variable and the displayWeatherData() call in https://github.com/matthias-bs/BresserWeatherSensorLW/blob/main/src/PayloadBresser.cpp. If using separate header/source files for the displayWeatherData() implementation doesn't work for you, you can copy your code there as well.
The seems to be a bug in calling the rain gauge statistics (in my implementation).
The sensor battery flags have been moved into the AppLayer Status message: https://github.com/matthias-bs/BresserWeatherSensorLW/blob/main/README.md#application-layer--sensor-status-message
Do you think it makes sense to re-post an entire source file in order to let people (including me) search for any changes you might have made?
Anytime i try and ask for help with code, people always ask for the code so they can see what the problem is,so I was trying to eradicate that wasted message!
You got the display working in BresserWeatherSensorTTN. Why don't you apply the same changes to this project or go back one step and look into the display library's examples on how to use it? The general approach is:
I tried applying the same procedure as I had in BresserWeatherSensorTTN, but this failed as BresserWeatherSensorLW appears to have many more layers of code than the former. In that code the 'weatherSensor.sensor' values are accessible from the .ino, whereas they are not in BresserWeatherSensorLW. I apologise for not being an experienced programmer, i'm just a guy trying to make things work!
- Install the library in the IDE
Done
- Include the libraries header file provided as the interface in your code
done ( I think, as the screen does initialise)
- Create a an object by calling the class constructor
In BresserWeatherSensdorTTN i believe this is done here:
//displayWeatherData(ws);
// Copy index to weather station data from local variable into member variable for access by displayWeatherData()
wsIndex = ws;
within the
method, but i cannot see where (orhow to do this in BresserWeatherSensorLW.ino, so therefore cannot do this:-
- Execute the class methods (functions) as desired
You can place the include statement, the display object variable and the displayWeatherData() call in https://github.com/matthias-bs/BresserWeatherSensorLW/blob/main/src/PayloadBresser.cpp. If using separate header/source files for the displayWeatherData() implementation doesn't work for you, you can copy your code there as well.
does this mean i can put the
#ifdef SSD1306_Display
Wire.begin.....
parts from my .ino into PayloadBresser.cpp, and add a line that does the same as
wsIndex=ws
then do displayWeatherData(ws) from there?
The seems to be a bug in calling the rain gauge statistics (in my implementation).
are you looking into this?
The sensor battery flags have been moved into the AppLayer Status message: https://github.com/matthias-bs/BresserWeatherSensorLW/blob/main/README.md#application-layer--sensor-status-message
so how would i access this from within PayloadBresser.cpp, if thats where i';m doing the display?
I did see #98 ! Thanks to chatgpt, and a lot of swearing i now have the display working , i put the method in PayloadBresser.cpp and accessed it through appLayer. Interestingly, after the esp32 has been running for a while, it does report the correct rain current day, week, month and total values through my function to display on the screen, even though the sewrial monitor still reports rain statistics not valid?
The class PayloadBresser contains the weatherSensor object: https://github.com/matthias-bs/BresserWeatherSensorLW/blob/4962a3b68062829ccea5b70dbe65308c1029be99/src/PayloadBresser.h#L73 This is why we call the display function from there.
First I'd keep the display code separate from the rest as far as possible. To achieve this, I'd put displayWeatherData() in a file src/DisplayWeatherData.cpp:
#include <...> // include header files required for the display code here
#include "WeatherSensorCfg.h" // needed for interface description of sensor data structure
#include <WeatherSensor.h> // needed for interface description of sensor data structure
#include "RainGauge.h" // needed for interface description of rain gauge
#include "DisplayWeatherData.h"
// create instance of display class here
// ... display(...);
void displayWeatherData(sensor_t sensor) {
// implementation goes here
// ...
// e.g.
display.print(sensor.w.temp_c);
// ...
}
Now we create a header file which describes the interface of your display module in src/DisplayWeatherData.h, in this case a just a function prototype:
#if !defined(_DISPLAY_WEATHER_DATA_H)
#define _DISPLAY_WEATHER_DATA_H
void displayWeatherData(sensor_t sensor);
#endif
Now we use this module in PayloadBresser.cpp. In https://github.com/matthias-bs/growatt2lorawan-v2/blob/a57d3a8747d7e91b6233f2a8d9a8ed0eed96852e/growatt2lorawan_cfg.h#L82, we have all weather sensor data available, so we can place the display function call there.
// ...
#include "DisplayWeatherData.h"
// ...
void PayloadBresser::encodeWeatherSensor(int idx, uint8_t flags, LoraEncoder &encoder)
{
// ...
// weatherSensor.sensor[idx] gives a pointer, but we want the contents; therefore the dereferencing (star) operator
displayWeatherData(*weatherSensor.sensor[idx]);
if (weatherSensor.sensor[idx].w.temp_ok)
{
log_i("Air Temperature: %3.1f °C", weatherSensor.sensor[idx].w.temp_c);
encoder.writeTemperature(weatherSensor.sensor[idx].w.temp_c);
}
// ...
A more elegant solution to my mess i feel! I will try this tomorrow, as i'm now getting the most bizzare compile error i've ever seen:
/home/matt/.arduino15/packages/esp32/tools/esp-x32/2302/bin/../lib/gcc/xtensa-esp32-elf/12.2.0/../../../../xtensa-esp32-elf/bin/ld: sketch/src/PayloadBresser.cpp.o:(.literal._ZN14PayloadBresser18displayWeatherDataEi+0x70): undefined reference to `_ZN14PayloadBresser13printDateTimeEv'
/home/matt/.arduino15/packages/esp32/tools/esp-x32/2302/bin/../lib/gcc/xtensa-esp32-elf/12.2.0/../../../../xtensa-esp32-elf/bin/ld: sketch/src/PayloadBresser.cpp.o: in function `_ZN14PayloadBresser13encodeBresserEPhS0_R11LoraEncoder':
/home/matt/Arduino/libraries/BresserWeatherSensorLW-0.9.1/BresserWeatherSensorLW/src/PayloadBresser.cpp:307: undefined reference to `_ZN14PayloadBresser13printDateTimeEv'
where lines 301- 310 of PayloadBresser.cpp are this~:
{
encodeLeakageSensor(idx, encoder);
}
else if (type == SENSOR_TYPE_AIR_PM)
{
encodeAirPmSensor(idx, encoder);
}
else if (type == SENSOR_TYPE_CO2)
{
It has me beaten for tonight!
Thanks :)
Yes, the reported line number is strange. This is a linker error. The compiler can compile everything, but finally the linker fails to 'link' the parts compiled separately together. It seems a function printDateTime() called in that part cannot be found.
void printDateTime(void)
is located in the *.ino file.
A working (but rather unelegant solution) is to declare the function as extern in the *.cpp file where it is used (meaning: "Dear compiler, I assure you there is a function with this signature somewhere. Its currently not visible, but the linker will take care of it."
extern void printDateTime(void);
Yeah I'll restructure it all as per your instructions tomorrow, still need to get the battery status flag onto the display somehow, I can get it in ttn, although it seems to be the opposite of the BWSTTN mqtt message!
I've done as you suggested, but it won't compile, it doesn't like the DisplayWeatherData.h file, does that need any more than the four lines of code that you posted?
Yes, after my last modification it needs
i could not get it to compile unless i declared the method as
void displayWeatherData(WeatherSensor::sensor_t sensor)
but then i cant call the values this is an excerpt from my method inplementation:
void displayWeatherData(WeatherSensor::sensor_t sensor) {
printDateTime();
display.setCursor(0,0);
display.print("LORA WEATHER SENSOR ");
display.setCursor(0,10);
display.print("Getting Weather data.. ");
display.setCursor(0,20);
display.print("Time is:");
display.setCursor(0,30);
display.print(tbuf);
display.setCursor(0,40);
//get battery status flag
if (WeatherSensor.sensor[i].battery_ok == true){
display.print ("Battery OK");
}else if (WeatherSensor.sensor[i].battery_ok == false){
display.print("Change Battery");
}
//if flag is bad print "Change Battery"
//Serial.print(tbuf2);
display.display();
delay(10000);
display.clearDisplay();
//display.setTextColor(WHITE);
//display.setTextSize(1);
//display.setCursor(0, 0);
//display.print("LORA WEATHER SENDER ");
//display.display();
display.setCursor(0,0);
display.print("Rain Data:");
display.setCursor(0,10);
display.print("Hourly rain:");
display.setCursor(80, 10);
display.print(RainGauge.pastHour());display.print(" mm");
display.setCursor(0,20);
display.print("Weekly rain:");
display.setCursor(80,20);
display.print(RainGauge.currentWeek());display.print(" mm");
display.setCursor(0,30);
display.print("Monthly rain:");
display.setCursor(80,30);
display.print(RainGauge.currentMonth());display.print(" mm");
display.setCursor(0, 40);
display.print("Total Rain");
display.setCursor(0, 50);
display.print(WeatherSensor.sensor[idx].w.rain_mm);
if i just declare the method as you described i get the compile errors
n file included from /home/matt/Arduino/libraries/BresserWeatherSensorLW-0.9.1/BresserWeatherSensorLW/src/DisplayWeatherData.cpp:14:
/home/matt/Arduino/libraries/BresserWeatherSensorLW-0.9.1/BresserWeatherSensorLW/src/DisplayWeatherData.h:8:6: error: variable or field 'displayWeatherData' declared void
8 | void displayWeatherData(sensor_t sensor);
| ^~~~~~~~~~~~~~~~~~
/home/matt/Arduino/libraries/BresserWeatherSensorLW-0.9.1/BresserWeatherSensorLW/src/DisplayWeatherData.h:8:25: error: 'sensor_t' was not declared in this scope
8 | void displayWeatherData(sensor_t sensor);
| ^~~~~~~~
/home/matt/Arduino/libraries/BresserWeatherSensorLW-0.9.1/BresserWeatherSensorLW/src/DisplayWeatherData.cpp:45:6: error: variable or field 'displayWeatherData' declared void
45 | void displayWeatherData(sensor_t sensor) {
| ^~~~~~~~~~~~~~~~~~
The only efficient way to get this running is if you put your code on your GitHub account. Then I might pull it from there, try it and fix it if I find some time. Otherwise it's just tedious.
I've added the files that i have made changes in into the repository BresserOLED. I do appreciate your timer and energy, and apologise if I've butchered your code :) rest assured that you will get a mention in my PhD thesis!!
Here you are: https://github.com/matthias-bs/BresserWeatherSensorLW/tree/20240821-feat-oled
I've inserted a few comments marked with '@mczakk'.
Awesome, Many Thanks Matthias, they're both working (almost ) perfectly now.
Thankyou very much for those :)
There is one issue i am seeing, not sure if you can shed any light on it?
Occasionally the lorawan message si a bit bizzare, reporting humidity at 225% and temp at over 300 degrees!
it seems to be when the weather sensor failure flag has been raised.
these are screenshots of my ttn feed, the message received at 13:01:26 is the offending one, as you can see with the decoded message on the right:
this is the serial monitor from the same period, you caqn see that at 13:06:21.221 the debug reports Weather Sensor Failiure:, but still sends the message to ttn, is it possible to not send if this flag has been raised?
12:58:37.097 -> [ 14149][D][WeatherSensor.cpp:351] getMessage(): [SX1276] R [D4] RSSI: -31.0
12:58:37.097 -> [ 14156][D][WeatherSensorDecoders.cpp:449] decodeBresser6In1Payload(): Digest check failed - [5C04] != [C02A]
13:01:26.113 -> [183263][I][PayloadBresser.cpp:92] begin(): Receiving Weather Sensor Data failed
13:01:26.113 -> [183270][V][Preferences.cpp:399] getUShort(): nvs_get_u16 fail: sleep_int NOT_FOUND
13:01:26.113 -> [183278][D][BresserWeatherSensorLW.ino:571] setup(): Preferences: sleep_interval: 360 s
13:01:26.113 -> [183286][V][Preferences.cpp:399] getUShort(): nvs_get_u16 fail: sleep_int_long NOT_FOUND
13:01:26.214 -> [183294][D][BresserWeatherSensorLW.ino:573] setup(): Preferences: sleep_interval_long: 900 s
13:01:26.214 -> [183302][V][Preferences.cpp:375] getUChar(): nvs_get_u8 fail: lw_stat_int NOT_FOUND
13:01:26.214 -> [183310][D][BresserWeatherSensorLW.ino:575] setup(): Preferences: lw_stat_interval: 60 cycles
13:01:26.214 -> [183319][V][esp32-hal-periman.c:235] perimanSetBusDeinit(): Deinit function for type ADC_ONESHOT (7) successfully set to 0x400e6700
13:01:26.215 -> [183330][V][esp32-hal-periman.c:160] perimanSetPinBus(): Pin 35 successfully set to type ADC_ONESHOT (7) with bus 0x24
13:01:26.215 -> [183341][D][esp32-hal-adc.c:305] __analogReadMilliVolts(): Creating cali handle for ADC_0
13:01:26.215 -> [183349][D][adc.cpp:76] getVoltage(): Voltage = 4408mV
13:01:26.215 -> [183354][V][AppLayer.cpp:97] getPayloadStage1(): Port: 1
13:01:26.215 -> [183360][I][AppLayer.cpp:99] getPayloadStage1(): --- Uplink Data ---
13:01:26.221 -> [183366][I][PayloadBresser.cpp:309] encodeWeatherSensor(): -- Weather Sensor Failure
13:01:26.221 -> [183373][I][PayloadBresser.cpp:430] encodeWeatherSensor(): Rain past 60min: 0.0 mm
13:01:26.221 -> [183381][I][PayloadBresser.cpp:440] encodeWeatherSensor(): Rain curr. day: -1.0 mm
13:01:26.241 -> [183389][I][PayloadBresser.cpp:448] encodeWeatherSensor(): Rain curr. week: -1.0 mm
13:01:26.241 -> [183397][I][PayloadBresser.cpp:456] encodeWeatherSensor(): Rain curr. month: -1.0 mm
13:01:26.241 -> [183405][I][PayloadBresser.cpp:251] encodeBresser(): Thermo/Hygro Sensor Ch 1
13:01:26.241 -> [183411][I][PayloadBresser.cpp:255] encodeBresser(): -- Failure
13:01:26.241 -> [183417][I][PayloadBresser.cpp:251] encodeBresser(): Soil Sensor Ch 1
13:01:26.274 -> [183423][I][PayloadBresser.cpp:255] encodeBresser(): -- Failure
13:01:26.274 -> [183429][I][PayloadBresser.cpp:251] encodeBresser(): Lightning Sensor Ch 5
13:01:26.274 -> [183436][I][PayloadBresser.cpp:255] encodeBresser(): -- Failure
13:01:26.274 -> [183442][D][adc.cpp:76] getVoltage(): Voltage = 4408mV
13:01:26.274 -> [183447][I][PayloadAnalog.cpp:63] encodeAnalog(): ch 00: U_batt: 4408 mv
13:01:26.305 -> [183453][V][BresserWeatherSensorLW.ino:598] setup(): Initalise the radio
13:01:26.305 -> [183479][D][BresserWeatherSensorLW.ino:396] lwActivate(): Recalling LoRaWAN nonces & session
13:01:26.338 -> [183494][D][BresserWeatherSensorLW.ino:418] lwActivate(): Succesfully restored session - now activating
13:01:26.338 -> [183503][D][BresserWeatherSensorLW.ino:629] setup(): Battery level: 0
13:01:26.338 -> [183510][V][Preferences.cpp:375] getUChar(): nvs_get_u8 fail: app_stat_int NOT_FOUND
13:01:26.369 -> [183517][I][BresserWeatherSensorLW.ino:679] setup(): Sending uplink; port 1, size 38
13:01:32.650 -> [189804][D][BresserWeatherSensorLW.ino:800] setup(): FcntUp: 24
13:01:32.650 -> [189810][D][adc.cpp:76] getVoltage(): Voltage = 4136mV
13:01:32.650 -> [189815][I][BresserWeatherSensorLW.ino:320] gotoSleep(): Sleeping for 170 s
Please! Do me a favor and read the documentation! https://github.com/matthias-bs/BresserWeatherSensorLW/blob/main/README.md#encoding-of-unavailable-or-invalid-data
Seems to be solved.
Yes, all seems to be working well now thank you. Just that issue with the rain statistics now, interesting how the display correctly shows the hourly, daily, weekly and monthly values, but it doesn't send them to ttn correctly?
Which problem do you encounter with the rain statistics? No uplinks at all? Should be fixed with https://github.com/matthias-bs/BresserWeatherSensorLW/pull/100. If your modified SW does not work - did you try the official release?
Further to previous issue (which i have now closed), I am now connected to ttn with BresserWeatherSensorLW, but am having grest diffuculty accessing the sensor data to display it on the ESP32 board's OLED screen. I post my current .ino code below. I am aware that there is no ccall to the 'displayWeatherData' function, but I am unsure of where to put it, or how to phrase it. the code fails to compile as a result of the display.print (XX) lines in the function. If I comment out the entire function, the code will compile and upload, the screen comes on, but is filled with 'static', so i know that i am initialising the screen correctly, the issue is just trying to access the data. The raingauge statistics are not working either, though i'm not sure if this is the code, or the fact that there hzs been no rain since starting to use this code. I have another esp32 board which is running on the old code, and rain stats are working well on that one. It would also be very useful to be able to display the weather stations battery flag value on the display, but i cant see how to get that either. It was in the Status bit of the original code :)