matthias-bs / BresserWeatherSensorTTN

Bresser 5-in-1/6-in-1/7-in-1 868 MHz Weather Sensor Radio Receiver based on ESP32 and RFM95W/SX1276 - sends data to a LoRaWAN Network (e.g. The Things Network)
MIT License
22 stars 9 forks source link

TTGO LoRa32-OLED V1 Configuration #38

Closed mczakk closed 1 year ago

mczakk commented 1 year ago

Hi Matthias - me again! I have complied and uploaded this code to my esp32 (TTGO LoRa32-OLED V1 with

// Enable debug mode (debug messages via serial port)
// Arduino IDE: Tools->Core Debug Level: "Debug|Verbose"
#define CORE_DEBUG_LEVEL ARDUHAL_LOG_LEVEL_DEBUG
//#define CORE_DEBUG_LEVEL ARDUHAL_LOG_LEVEL_VERBOSE

defined, but am not seeing anything in the serial monitor. how can i check that the board is recieving the data from the bresser?

Cheers Matt

matthias-bs commented 1 year ago

Here is something unexpected:

// Additional ADC pins (default: FireBeetle ESP32) 
//#define PIN_ADC0_IN         A0
//#define PIN_ADC1_IN         A1
//#define PIN_ADC2_IN         A2
#ifdef LORAWAN_NODE
  #define PIN_ADC3_IN         A3
#endif

// Additional ADC pins (default: FireBeetle ESP32) 
//#define PIN_ADC0_IN         A0
//#define PIN_ADC1_IN         A1
//#define PIN_ADC2_IN         A2
#define PIN_ADC3_IN         A3

I did not expect PIN_ADC3_IN to be defined, but this would give us only two extra bytes.

matthias-bs commented 1 year ago

hmmm, tried your .cfg change and bettery readings were very low (294mV) so it went to sleep immediately! changed the battery weak and battery low thresholds and trying again! (also added log_i line :)

Ah, o.k.:

#define BATTERY_LOW 0

We'll come back to this later.

mczakk commented 1 year ago

Here is something unexpected:

// Additional ADC pins (default: FireBeetle ESP32) 
//#define PIN_ADC0_IN         A0
//#define PIN_ADC1_IN         A1
//#define PIN_ADC2_IN         A2
#ifdef LORAWAN_NODE
  #define PIN_ADC3_IN         A3
#endif

// Additional ADC pins (default: FireBeetle ESP32) 
//#define PIN_ADC0_IN         A0
//#define PIN_ADC1_IN         A1
//#define PIN_ADC2_IN         A2
#define PIN_ADC3_IN         A3

I did not expect PIN_ADC3_IN to be defined, but this would give us only two extra bytes.

trying with

// Additional ADC pins (default: FireBeetle ESP32) 
//#define PIN_ADC0_IN         A0
//#define PIN_ADC1_IN         A1
//#define PIN_ADC2_IN         A2
#ifdef LORAWAN_NODE
  #define PIN_ADC3_IN         A3
#endif

// Additional ADC pins (default: FireBeetle ESP32) 
//#define PIN_ADC0_IN         A0
//#define PIN_ADC1_IN         A1
//#define PIN_ADC2_IN         A2
//#define PIN_ADC3_IN         A3

btw, got sensor_id :

14:55:12.551 -> [D][BresserWeatherSensorTTN.ino:1295] doUplink(): sensor_id: 939865349
matthias-bs commented 1 year ago

With both ADC voltages enabled:

    return decode(
      bytes,
      [uint32,        bitmap,          temperature,     uint8,       uint16fp1,             uint16fp1,            uint16fp1,
       rawfloat,      uint16,          uint16,          rawfloat,    rawfloat,              rawfloat,             rawfloat
      ],
      ['id',          'status',        'air_temp_c',    'humidity',  'wind_gust_meter_sec', 'wind_avg_meter_sec', 'wind_direction_deg',
       'rain_mm',     'supply_v',      'battery_v',     'rain_hr',   'rain_day',            'rain_week',          'rain_mon'
      ]
    );
matthias-bs commented 1 year ago

Your payload: >05350538< 0301C25008000800500A6766634427125B0100000000000000000000000000000000 Your sensor ID converted to hex: 0x38053505

So, you have the ID in your payload (bytes reversed).

Next byte: 05350538 >03< 01C25008000800500A6766634427125B0100000000000000000000000000000000 return ['res2', 'res1', 'res0', 'ble_ok', 's1_dec_ok', 's1_batt_ok', 'ws_dec_ok', 'ws_batt_ok'] Binary: 00000011 Weather Station decoding o.k. & battery o.k. - that's fine!

Next two bytes (temperature): 05350538 >01C2< 5008000800500A6766634427125B0100000000000000000000000000000000 (ignoring it for now)

Next byte (humidity): 05350538 01C2 >50< 08000800500A6766634427125B0100000000000000000000000000000000 0x50 = 80% rel. humidity (o.k.?)

wind gust (two bytes): 05350538 01C250>0800< 0800500A6766634427125B0100000000000000000000000000000000 0.8 m/s?

wind avg (two bytes): 05350538 01C2500800 >0800< 500A6766634427125B0100000000000000000000000000000000

wind direction (two bytes): 05350538 01C25008000800 >500A< 6766634427125B0100000000000000000000000000000000 0x0A50 = 264.0°?

rain gauge (4 bytes, floating point): 05350538 01C25008000800500A >67666344< 27125B0100000000000000000000000000000000 (ignoring it for now)

supply voltage (two bytes): 05350538 01C25008000800500A67666344 >2712< 5B0100000000000000000000000000000000 0x1227 = 4647 mV

battery voltage (two bytes): 05350538 01C25008000800500A676663442712 >5B01< 00000000000000000000000000000000 0x015B = 347 mV

remaining: rain statistics, 4x 4 bytes, all zero: 05350538 01C25008000800500A6766634427125B01 >00000000< >00000000< >00000000< >00000000<

So, I'd say there is nothing wrong with your payload.

mczakk commented 1 year ago

commenting out //#define PIN_ADC3_IN A3 resulten in ttn error changing to '36 at decode' from '38 at decode' as you suggested. trying with #define PIN_ADC3_IN A3 and change to 'decode.js' now

mczakk commented 1 year ago

both battery readings showing now, but message length in monitor output still 38 !! is it possible to see the message in serial monitor?

mczakk commented 1 year ago

I know there is probably an obvious answer to this, but this bit of 'decoder.js' concerns me? I dont have 'soil_sensor' or 'MiThermo' defined?

 var i = bytesToInt(byte);
    var bm = ('00000000' + Number(i).toString(2)).substr(-8).split('').map(Number).map(Boolean);
    // Only Weather Sensor
    //return ['res5', 'res4', 'res3', 'res2', 'res1', 'res0', 'dec_ok', 'batt_ok']
    // Weather Sensor + MiThermo (BLE) Sensor
    //return ['res4', 'res3', 'res2', 'res1', 'res0', 'ble_ok', 'dec_ok', 'batt_ok']
    // Weather Sensor, Soil Sensor and MiThermo (BLE) Sensor
    return ['res2', 'res1', 'res0', 'ble_ok', 's1_dec_ok', 's1_batt_ok', 'ws_dec_ok', 'ws_batt_ok']
        .reduce(function(obj, pos, index) {
        obj[pos] = bm[index];
        return obj;
        }, {});
matthias-bs commented 1 year ago

This function decodes the status byte, i.e. extracts all bit positions and assign their value to a named bit in the status object, e.g.:

"status": {
            "ble_ok": true,
            "long_sleep": false,
            "rtc_sync_req": false,
            "runtime_expired": true,
            "s1_batt_ok": true,
            "s1_dec_ok": true,
            "ws_batt_ok": true,
            "ws_dec_ok": true
          }

So in the worst case, some wrong values are interpreted here. In The best case, the default values are zero and the decoded values make sense.

(You see we have some undocumented features...)

mczakk commented 1 year ago

where is that function?

matthias-bs commented 1 year ago

In the Arduino sketch:

    // Status flags
    encoder.writeBitmap(longSleep,
                        rtcSyncReq, 
                        runtimeExpired,
                        mithermometer_valid,
                        (s1 > -1) ? weatherSensor.sensor[s1].valid : false,
                        (s1 > -1) ? weatherSensor.sensor[s1].battery_ok : false,
                        (ws > -1) ? weatherSensor.sensor[ws].valid : false,
                        (ws > -1) ? weatherSensor.sensor[ws].battery_ok : false);
mczakk commented 1 year ago

ok, hold the front page, i may have made a very noobie error.... I think i was updating the application payload formatter, not the end device one ! i now get this on ttn :) sucess

mczakk commented 1 year ago

I owe you a debt of gratitude Sir!!

matthias-bs commented 1 year ago

Congratulations!

The only this which needs improvement is the handling of supply voltage vs battery voltage. I'll set up a new issue as a reminder, but I think it's not urgent.

matthias-bs commented 1 year ago

My status decoder:

    var bitmap = function(byte) {
    if (byte.length !== bitmap.BYTES) {
        throw new Error('Bitmap must have exactly 1 byte');
    }
    var i = bytesToInt(byte);
    var bm = ('00000000' + Number(i).toString(2)).substr(-8).split('').map(Number).map(Boolean);
    return ['res', 'rtc_sync_req', 'runtime_expired', 'ble_ok', 's1_dec_ok', 's1_batt_ok', 'ws_dec_ok', 'ws_batt_ok']
        .reduce(function(obj, pos, index) {
        obj[pos] = bm[index];
        return obj;
        }, {});
    };
    bitmap.BYTES = 1;
matthias-bs commented 1 year ago

If you have a decent multimeter, it would be great to have a current measurement for this board in deep sleep mode. For this, we need the current drawn from the battery input, not the USB port. In fact, the USB may not be connected for this.

mczakk commented 1 year ago

aaaarg, i'm getting the mqtt out of ttn, but it doesn't show the wind!

matthias-bs commented 1 year ago

??? But it's in your decoded output according to the screenshot! If you mean an MQTT client: maybe the topic names are too long? You can change them in the decoder, of course.

mczakk commented 1 year ago

I've used the ttn mqtt integration to publish the mqtt message, and am subscribing with node-red. the mqtt i recieve is truncated at 's1_dec_ok' (see attached .txt) ttn-nodered-output.txt i tried taking out the bitmap and 'status' decoder, but this just threw the decode out!

matthias-bs commented 1 year ago

Maybe there is a way to increase a buffer size for MQTT messages in node-red? The JSON string from TTN is quite big!

mczakk commented 1 year ago

what are the topic names in the decoder, maybe i can just subscribe to the topics i need?

matthias-bs commented 1 year ago

Presumably, you only need "decoded_payload".

I'm always using https://mqtt-explorer.com/ for debugging.

mczakk commented 1 year ago

just trying mqtt decoder, can't get past the 'up' topic, and nodered mqtt in node wont accept v3/bresserttn@ttn/devices/bresseresp32/up or v3/bresserttn@ttn/devices/bresseresp32/up/# as a topic :( giving up for the day i think!

mczakk commented 1 year ago

D'oh, forgot to tell the Node-red mqtt in node to output parsed Jason! All is good now, just have to get the data into aws now 😱🤣😂🤣

matthias-bs commented 1 year ago

Cool! Mission completed!

matthias-bs commented 1 year ago

Some interesting information/discussion regarding the TTGO LoRa32 board: https://github.com/LilyGO/TTGO-LORA32/issues/3

mczakk commented 1 year ago

Cool! Mission completed!

For you, maybe! For which I and my PhD project are eternally grateful! 😁🙏😁.

matthias-bs commented 1 year ago

What is the subject of your project?

mczakk commented 1 year ago

What is the subject of your project?

I'm developing a model to predict how much rainfall gets through forest canopies to become groundwater (and later floodwater) so I have off grid weather stations and rainfall gauges connecting via iot. My weather station was connected to a pi and a gateway in an enclosure in a forest, but the enclosure leaked, and the pi was pulling to much current. That's why I've moved to the esp32. It should be going live next week, thanks in no small part to you!

matthias-bs commented 1 year ago

⁹Good luck!

From what I've read, the TTGO LoRa32 is not optimal regarding standby (deep sleep) current consumption and LoRaWAN range.

You might consider https://github.com/matthias-bs/LoRaWAN_Node if any of this proves to be a concern.

mczakk commented 1 year ago

We have developed our own lora node for the rain gauges, and hopefully the ttgo will work. It would be interesting if you could have a chat with myself and my network guy about the project. Can we connect via zoom? Do you have twitter to exchange contact details?

mczakk commented 1 year ago

Hi again, unfortunately it seems we have another issue :( the payload formatter seems to output the temperature, wind and rain values as strings, is it possible to output them as floats?

matthias-bs commented 1 year ago

That is easy: just replace return f.toFixed(1); by return f; (other variables accordingly)

The reason for this was that I cannot set the number of decimals in my MQTT panel and therefore converted it in the decoder to a string with one decimal. The MQTT panel does not care it it's a string or a float.

mczakk commented 1 year ago

that seems to have changed them to 'int' - no decimal places, can we make it a float?

matthias-bs commented 1 year ago

From the oldest version I kept:

    var uint16fp1 = function(bytes) {
    if (bytes.length !== uint16.BYTES) {
        throw new Error('int must have exactly 2 bytes');
    }
    return bytesToInt(bytes) * 0.1;
    };
    uint16fp1.BYTES = 2;

It seems I snipped the previous example from rawfloat.

mczakk commented 1 year ago

hmm, at line 37? has no effect!

matthias-bs commented 1 year ago

Please check this version: https://github.com/matthias-bs/BresserWeatherSensorTTN/blob/21a5de1b01874a554f31626768fac11cc6cd7853/decoder_basic.js

mczakk commented 1 year ago

copied that code into ttn. tested it and it gives :


  "bytes": {
    "air_temp_c": 4.8,
    "humidity": 87,
    "id": 939865349,
    "rain_day": 0,
    "rain_hr": 3.9796876386824805e-43,
    "rain_mm": 910,
    "rain_mon": 0,
    "rain_week": 0,
    "status": {
      "ble_ok": false,
"res0": false,
      "res1": false,
      "res2": false,
      "s1_batt_ok": false,
      "s1_dec_ok": false,
      "ws_batt_ok": true,
      "ws_dec_ok": true
    },
    "supply_v": 284,
    "wind_avg_meter_sec": 0,
    "wind_direction_deg": 186,
    "wind_gust_meter_sec": 0

so still no decimals for wind or rain, and a seemingly random value for rain_hr_mm!

matthias-bs commented 1 year ago

It's up to the application how to display floating point numbers. If the value is 0, it might well display it as 0 instead of 0.0. air_temp_c is now shown as 4.8 (no quotation marks, i.e. it's shown as floating point), but it could also be shown as 4.799999999 if the internal representation would lead to this result. Accordingly, rain_hr could be correct - a very small number, almost zero but not exactly zero.

https://stackoverflow.com/questions/19554972/json-standard-floating-point-numbers https://stackoverflow.com/questions/35709595/why-would-you-use-a-string-in-json-to-represent-a-decimal-number

So apparently, you can not have both a machine readable floating point value and a nice, human-friendly display.

mczakk commented 1 year ago

Unfortunately i think there is a bit of an issue with the decoder! I decided to test the device by adding a little water to the rain counter, I made it tip four times. the 'rain_mm' value went from 910.0mm to 910,7999 (perfectly normal), the others ...... air_temp_c: 2.5 humidity: 93 id: 939865349 rain_day: -33619248 rain_hr: -107481312 rain_mm: 910.7999877929688 rain_mon: -33619248 rain_week: -33619248 status: object supply_v: 284 wind_avg_meter_sec: 0 wind_direction_deg: 354 wind_gust_meter_sec: 0

not sure whats going on here!, maybe you can shed a little light?

matthias-bs commented 1 year ago

We have developed our own lora node for the rain gauges, and hopefully the ttgo will work. It would be interesting if you could have a chat with myself and my network guy about the project. Can we connect via zoom? Do you have twitter to exchange contact details?

I do not have Twitter, but chances are that you can find me on LinkedIn. Or is there a way to start a private conversation in GitHub? For sure I can join a zoom call if you set up one. Maybe on Friday?

mczakk commented 1 year ago

I don't think you can pm on github, I'll find you on linkedin. Friday might be difficult, hopefully I'll be installing the esp32 in the field!

matthias-bs commented 1 year ago

wire

Finally I found the purpose of this wire: Big ESP32 + SX127x topic part 2 has an excellent section about the different versions of the TTGO LoRa32 OLED boards. According to this, V2 lacks an on-board connection between the ESP and the LoRa radio chip!

In general, the version numbering/documentation of these boards is confusing and a schematic is not even available for most of them.