2 SPI channels LoRa + BME

Hello, I have a heltec esp32 LoRa v3 that I use for a class project. I have 2 card and the goal is to have 1 with the webserver and the other one to have the sensors. Both have LoRa communication.

I use the heltec_unofficial library to have the LoRa interface that works well.

In this library I have :

 #include <SPI.h>
    SPIClass* hspi = new SPIClass(HSPI);
    SX1262 radio = new Module(SS, DIO1, RST_LoRa, BUSY_LoRa, *hspi);
  #else

That creates a hspi for the LoRa. This pins are not accessible by me.

I have a file to declare the BME functions and data :

#include <SPI.h>
#include <Adafruit_Sensor.h>
#include "Adafruit_BME680.h"
#define BME_SCK 36
#define BME_MISO 37
#define BME_MOSI 35
#define BME_CS 34
#define VSPI FSPI
#define SEALEVELPRESSURE_HPA (1013.25)

SPIClass* vspi = new SPIClass(VSPI);
Adafruit_BME680 bme(BME_CS, vspi);
//Adafruit_BME680 bme(BME_CS,BME_MOSI,BME_MISO, BME_SCK);
//static const int spiClk = 1000000;  // 1 MHz

void configurationBME(){
    if(!bme.begin()){
        Serial.println("Could not find the BME 680. Check the wiring or the address configuration");
        while(1);
    }
    bme.setTemperatureOversampling(BME680_OS_8X);
    bme.setHumidityOversampling(BME680_OS_2X);
    bme.setPressureOversampling(BME680_OS_4X);
    bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
    bme.setGasHeater(320,150); // 320 *C for 150 ms
}

void getDataBME(){
    if (! bme.performReading()) {
      Serial.println("Failed to perform reading :(");
      return;
    }
    Serial.print("Temperature = ");
    Serial.print(bme.temperature);
    Serial.println(" *C");

    Serial.print("Pressure =");
    Serial.print(bme.pressure/100.0);
    Serial.println(" hPa");
}

In my loop function I have this :

void setup(){
    heltec_setup();
    vspi->begin(BME_SCK, BME_MISO, BME_MOSI, BME_CS);
    //pinMode(vspi->pinSS(), OUTPUT);  //VSPI SS
    radio.sleep(true);
    display.setFont(ArialMT_Plain_10);
    configurationBME();
    display.drawString(0,0,"Hello, world!");
    configurationTMG3993();
    
    print_wakeup_reason();
    if (heltec_wakeup_was_timer()) {
    heltec_deep_sleep(2000);
    }
    esp_sleep_enable_ext0_wakeup(WAKEUP_GPIO, 1);
    while(!Serial);
    pinMode(ACTIVATION_PIN,INPUT);
    configurationLoRa();    // both the devices use LoRa communication method
    display.display();

}
void loop(){    
    hspi->endTransaction();
    digitalWrite(hspi->pinSS(),HIGH);
    vspi->begin();
    digitalWrite(vspi->pinSS(),LOW);
    getDataBME();
    getDataTMG3993();
    vspi->endTransaction();
    hspi->begin();
    data.temperature = bme.temperature;
    data.pressure = 15.0f;
    data.humidity = bme.humidity;
    uint16_t r, g, b, c;
    tmg3993.getRGBCRaw(&r,&g,&b,&c);
    data.light_intensity = tmg3993.getLux(r,g,b,c);

    //SendLoRa(data);
    delay(1000);
    esp_deep_sleep_start(); 
}

When I upload the code and I try to have the data of the BME send using the lora I have a message '“Failed to perform reading” but the LoRa works.
Does someone has an idea of why it is not working properly ?

Thanks in advance

have you managed to get the BME680 working in a separate program (e.g. without LoRa)
don't have a BME680 to try but have used a W5500 Ethernet on the Heltec LoRa V3 using HSPI
configured so

// Heltec LoRa V3  W5500 Ethernet test

/*
 * HelloServer example from the ESP32 WebServer library modified for Ethernet.
 */

#include <EthernetESP32.h>
#include <WebServer.h>
#include <ESPmDNS.h>

// define Heltec LoRa V3 W5500 SPI pins
#define W5500_SCK 40
#define W5500_MISO 42
#define W5500_MOSI 39
#define W5500_CS 41

W5500Driver driver(W5500_CS);  // SPI SS is GPIO34
//ENC28J60Driver driver;
//EMACDriver driver(ETH_PHY_LAN8720);

SPIClass hspi(HSPI);  // HSPI object used by W5500

WebServer server(80);

const int led = 13;

void handleRoot() {
  digitalWrite(led, 1);
  server.send(200, "text/plain", "hello from esp32!");
  digitalWrite(led, 0);
}

void handleNotFound() {
  digitalWrite(led, 1);
  String message = "File Not Found\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";
  for (uint8_t i = 0; i < server.args(); i++) {
    message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
  }
  server.send(404, "text/plain", message);
  digitalWrite(led, 0);
}

void setup(void) {
  pinMode(led, OUTPUT);
  digitalWrite(led, 0);
  Serial.begin(115200);
  delay(2000);
  // setup SPI pins
  hspi.begin(W5500_SCK, W5500_MISO, W5500_MOSI, W5500_CS);
  driver.setSPI(hspi);    // specify driver SPI interface
  Ethernet.init(driver);  // initialise driver
  Serial.println("Initialize Ethernet with DHCP:");
  if (Ethernet.begin()) {
    Serial.print("  DHCP assigned IP ");
    Serial.println(Ethernet.localIP());
  } else {
    Serial.println("Failed to configure Ethernet using DHCP");
    while (true) {
      delay(1);
    }
  }
  if (MDNS.begin("esp32")) {
    Serial.println("MDNS responder started");
  }
  server.on("/", handleRoot);
  server.on("/inline", []() {
    server.send(200, "text/plain", "this works as well");
  });
  server.onNotFound(handleNotFound);
  server.begin();
  Serial.println("HTTP server started");
}

void loop(void) {
  server.handleClient();
  delay(2);  //allow the cpu to switch to other tasks
}

consider using BME680 I2C interface?

It is mandatory to have the BME in SPI mode.

And are you sure that I can have the BME with SPI and then the LoRa onboard with the ethernet library and handle them together ?

Can I handle both without ethernet library ?

the ethernet was given as an example of using the Heltec LoRa V3 HSPI interface - you don't need ethernet

I would assume that LoRa uses VSPI so try the BME680 using HSPI?
will see if I can find a sensor with SPI interface to test with LoRa

BME680 sensor connected it to a Heltec 32 LoRa V3 using VSPI for LoRaWAN OTAA communication and HSPI for the BME680
file main.ino

// Heltec LoRa V3  SX1276  LoRaWAN OTAA test BME680 sensor test
//  displat BME680 data on OLED and transmit to LoRaWAN TTN V3 server

// using library https://github.com/jgromes/RadioLib/tree/master

// modified from File>Examples>RadioLib>LoRaWAN>LoRaWAN_Starter

/*
  RadioLib LoRaWAN Starter Example

  ! Please refer to the included notes to get started !

  This example joins a LoRaWAN network and will send
  uplink packets. Before you start, you will have to
  register your device at https://www.thethingsnetwork.org/
  After your device is registered, you can run this example.
  The device will join the network and start uploading data.

  Running this examples REQUIRES you to check "Resets DevNonces"
  on your LoRaWAN dashboard. Refer to the network's 
  documentation on how to do this.

  For default module settings, see the wiki page
  https://github.com/jgromes/RadioLib/wiki/Default-configuration

  For full API reference, see the GitHub Pages
  https://jgromes.github.io/RadioLib/

  For LoRaWAN details, see the wiki page
  https://github.com/jgromes/RadioLib/wiki/LoRaWAN

*/

#include "config.h"

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128  // OLED display1 width, in pixels
#define SCREEN_HEIGHT 64  // OLED display1 height, in pixels

// Declaration for an SSD1306 display1 connected to I2C (SDA, SCL pins)
#define SCREEN_ADDRESS 0x3C  //0x3D ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
// use Wire1 for OLED display as BMP280 is using Wire and would conflict (only one works)
Adafruit_SSD1306 display1(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire1, RST_OLED);

void setup() {
  Serial.begin(115200);
  delay(2000);
  // setup OLED display
  Wire1.begin(SDA_OLED, SCL_OLED);
  // SSD1306_SWITCHCAPVCC = generate display1 voltage from 3.3V internally
  if (!display1.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;)
      ;  // Don't proceed, loop forever
  }
  Serial.println(F("SSD1306 allocation OK"));
  delay(2000);  // Pause for 2 seconds
  display1.clearDisplay();
  display1.setTextSize(2);               // Normal 1:1 pixel scale
  display1.setTextColor(SSD1306_WHITE);  // Draw white text
  display1.setCursor(0, 0);              // Start at top-left corner
  display1.println(F("    EPAS\n  LoRaWAN\n    node"));
  display1.display();
  delay(2000);
  setupBME680();  // setup BME680 sensor
  Serial.println(F("\n\nHeltec LoRa V3  SX1262 Setup ... "));
  Serial.println(F("Initialise the radio"));    // setup LoRaWAN
  int16_t state = radio.begin();
  debug(state != RADIOLIB_ERR_NONE, F("Initialise radio failed"), state, true);

  // Setup the OTAA session information
  state = node.beginOTAA(joinEUI, devEUI, nwkKey, appKey);
  debug(state != RADIOLIB_ERR_NONE, F("Initialise node failed"), state, true);

  Serial.println(F("Join ('login') the LoRaWAN Network"));
  state = node.activateOTAA();
  debug(state != RADIOLIB_LORAWAN_NEW_SESSION, F("Join failed"), state, true);

  Serial.println(F("Ready!\n"));
}

extern float temperature, pressure, humidity, gas;  // BME680 sensor data

void loop() {
  Serial.print(F("Sending uplink "));
  loopBME680();             // read BME680 sensor data
  display1.clearDisplay();  // Dsiplay information
  display1.setTextSize(1);
  display1.setCursor(0, 0);
  display1.println("LoRaWAN BMP280\n");
  //display1.setCursor(0, 20);
  display1.printf("Temperature %.2f\n", temperature);
  //  display1.setCursor(0, 40);
  display1.printf("Pressure %.2f\n", pressure);
  display1.printf("Pressure %.2f\n", humidity);
  display1.printf("gas %.2f", gas);
  display1.display();

  // This is the place to gather the sensor inputs -  Build payload byte array 
  static uint8_t uplinkPayload[8] = { 0x61, 0x2f, 0xea, 0x03, 0xac, 0x12, 0x9d, 0x08 };
  Serial.printf("temp = %f, pressure = %f humidity = %f gas=%f\n", temperature, pressure, humidity, gas);
  int temp = (int)((temperature + 100) * 100.0), press = (int)(pressure), hum = humidity * 100, igas = (int)(gas * 100);
  uplinkPayload[0] = (temp & 0xff);
  uplinkPayload[1] = (temp >> 8) & 0xff;
  uplinkPayload[2] = press & 0xFF;
  uplinkPayload[3] = (press >> 8) & 0xff;
  uplinkPayload[4] = hum & 0xFF;
  uplinkPayload[5] = (hum >> 8) & 0xff;
  uplinkPayload[6] = igas & 0xFF;
  uplinkPayload[7] = (igas >> 8) & 0xff;
  Serial.print("LoRaWAN transmission ");
  for (int i = 0; i < 8; i++)  // ,,,, added print
    Serial.printf("%x ", uplinkPayload[i]);
  Serial.println();

  // Perform an uplink
  //int16_t state = node.sendReceive(uplinkPayload, sizeof(uplinkPayload));
  // perform uplink passing array for received data
  uint8_t dataDown[8] = { 0 };
  size_t lenDown = 0;
  int16_t state = node.sendReceive(uplinkPayload, sizeof(uplinkPayload), 1, dataDown, &lenDown);
  debug(state < RADIOLIB_ERR_NONE, F("Error in sendReceive"), state, false);

  // Check if a downlink was received
  // (state 0 = no downlink, state 1/2 = downlink in window Rx1/Rx2)
  if (state > 0) {
    Serial.print(F("Received a downlink "));
    Serial.printf("lenDown %d data ", lenDown);  // print downlink data
    for (int i = 0; i < lenDown; i++)
      Serial.printf("%x ", dataDown[i]);
    Serial.println();
  } else {
    Serial.println(F("No downlink received"));
  }

  Serial.print(F("Next uplink in "));
  Serial.print(uplinkIntervalSeconds);
  Serial.println(F(" seconds\n"));
  // Wait until next uplink - observing legal & TTN FUP constraints
  delay(uplinkIntervalSeconds * 1000UL);  // delay needs milli-seconds
}

file config.h (in same directory as above main.ino)

#ifndef _RADIOLIB_EX_LORAWAN_CONFIG_H
#define _RADIOLIB_EX_LORAWAN_CONFIG_H

#include <RadioLib.h>

// first you have to set your radio model and pin configuration
// this is provided just as a default example
//SX1276 radio = new Module(10, 2, 9, 3);

// Heltec LoRa V3  SX1262 has the following connections:
// NSS pin:   8
// DIO1 pin:  14
// NRST pin:  12
// BUSY pin:  13
SX1262 radio = new Module(8, 14, 12, 13);


// if you have RadioBoards (https://github.com/radiolib-org/RadioBoards)
// and are using one of the supported boards, you can do the following:
/*
#define RADIO_BOARD_AUTO
#include <RadioBoards.h>

Radio radio = new RadioModule();
*/

// how often to send an uplink - consider legal & FUP constraints - see notes
const uint32_t uplinkIntervalSeconds = 1UL * 60UL;    // minutes x seconds

// joinEUI - previous versions of LoRaWAN called this AppEUI
// for development purposes you can use all zeros - see wiki for details
#define RADIOLIB_LORAWAN_JOIN_EUI  0x0000000000000000

// the Device EUI & two keys can be generated on the TTN console 
#ifndef RADIOLIB_LORAWAN_DEV_EUI   // Replace with your Device EUI
#define RADIOLIB_LORAWAN_DEV_EUI   0xZZZZZZZZZZ
#endif
#ifndef RADIOLIB_LORAWAN_APP_KEY   // Replace with your App Key 
#define RADIOLIB_LORAWAN_APP_KEY 0x0E-------------------------------------
#endif
#ifndef RADIOLIB_LORAWAN_NWK_KEY   // Put your Nwk Key here
#define RADIOLIB_LORAWAN_NWK_KEY  0x86 ------------------------------------------
#endif

// for the curious, the #ifndef blocks allow for automated testing &/or you can
// put your EUI & keys in to your platformio.ini - see wiki for more tips

// regional choices: EU868, US915, AU915, AS923, AS923_2, AS923_3, AS923_4, IN865, KR920, CN470
const LoRaWANBand_t Region = EU868;

// subband choice: for US915/AU915 set to 2, for CN470 set to 1, otherwise leave on 0
const uint8_t subBand = 0;

// ============================================================================
// Below is to support the sketch - only make changes if the notes say so ...

// copy over the EUI's & keys in to the something that will not compile if incorrectly formatted
uint64_t joinEUI =   RADIOLIB_LORAWAN_JOIN_EUI;
uint64_t devEUI  =   RADIOLIB_LORAWAN_DEV_EUI;
uint8_t appKey[] = { RADIOLIB_LORAWAN_APP_KEY };
uint8_t nwkKey[] = { RADIOLIB_LORAWAN_NWK_KEY };

// create the LoRaWAN node
LoRaWANNode node(&radio, &Region, subBand);

// result code to text - these are error codes that can be raised when using LoRaWAN
// however, RadioLib has many more - see https://jgromes.github.io/RadioLib/group__status__codes.html for a complete list
String stateDecode(const int16_t result) {
  switch (result) {
  case RADIOLIB_ERR_NONE:
    return "ERR_NONE";
  case RADIOLIB_ERR_CHIP_NOT_FOUND:
    return "ERR_CHIP_NOT_FOUND";
  case RADIOLIB_ERR_PACKET_TOO_LONG:
    return "ERR_PACKET_TOO_LONG";
  case RADIOLIB_ERR_RX_TIMEOUT:
    return "ERR_RX_TIMEOUT";
  case RADIOLIB_ERR_MIC_MISMATCH:
    return "ERR_MIC_MISMATCH";
  case RADIOLIB_ERR_INVALID_BANDWIDTH:
    return "ERR_INVALID_BANDWIDTH";
  case RADIOLIB_ERR_INVALID_SPREADING_FACTOR:
    return "ERR_INVALID_SPREADING_FACTOR";
  case RADIOLIB_ERR_INVALID_CODING_RATE:
    return "ERR_INVALID_CODING_RATE";
  case RADIOLIB_ERR_INVALID_FREQUENCY:
    return "ERR_INVALID_FREQUENCY";
  case RADIOLIB_ERR_INVALID_OUTPUT_POWER:
    return "ERR_INVALID_OUTPUT_POWER";
  case RADIOLIB_ERR_NETWORK_NOT_JOINED:
	  return "RADIOLIB_ERR_NETWORK_NOT_JOINED";
  case RADIOLIB_ERR_DOWNLINK_MALFORMED:
    return "RADIOLIB_ERR_DOWNLINK_MALFORMED";
  case RADIOLIB_ERR_INVALID_REVISION:
    return "RADIOLIB_ERR_INVALID_REVISION";
  case RADIOLIB_ERR_INVALID_PORT:
    return "RADIOLIB_ERR_INVALID_PORT";
  case RADIOLIB_ERR_NO_RX_WINDOW:
    return "RADIOLIB_ERR_NO_RX_WINDOW";
  case RADIOLIB_ERR_INVALID_CID:
    return "RADIOLIB_ERR_INVALID_CID";
  case RADIOLIB_ERR_UPLINK_UNAVAILABLE:
    return "RADIOLIB_ERR_UPLINK_UNAVAILABLE";
  case RADIOLIB_ERR_COMMAND_QUEUE_FULL:
    return "RADIOLIB_ERR_COMMAND_QUEUE_FULL";
  case RADIOLIB_ERR_COMMAND_QUEUE_ITEM_NOT_FOUND:
    return "RADIOLIB_ERR_COMMAND_QUEUE_ITEM_NOT_FOUND";
  case RADIOLIB_ERR_JOIN_NONCE_INVALID:
    return "RADIOLIB_ERR_JOIN_NONCE_INVALID";
  case RADIOLIB_ERR_DWELL_TIME_EXCEEDED:
    return "RADIOLIB_ERR_DWELL_TIME_EXCEEDED";
  case RADIOLIB_ERR_CHECKSUM_MISMATCH:
    return "RADIOLIB_ERR_CHECKSUM_MISMATCH";
  case RADIOLIB_ERR_NO_JOIN_ACCEPT:
    return "RADIOLIB_ERR_NO_JOIN_ACCEPT";
  case RADIOLIB_LORAWAN_SESSION_RESTORED:
    return "RADIOLIB_LORAWAN_SESSION_RESTORED";
  case RADIOLIB_LORAWAN_NEW_SESSION:
    return "RADIOLIB_LORAWAN_NEW_SESSION";
  case RADIOLIB_ERR_NONCES_DISCARDED:
    return "RADIOLIB_ERR_NONCES_DISCARDED";
  case RADIOLIB_ERR_SESSION_DISCARDED:
    return "RADIOLIB_ERR_SESSION_DISCARDED";
  }
  return "See https://jgromes.github.io/RadioLib/group__status__codes.html";
}

// helper function to display any issues
void debug(bool failed, const __FlashStringHelper* message, int state, bool halt) {
  if(failed) {
    Serial.print(message);
    Serial.print(" - ");
    Serial.print(stateDecode(state));
    Serial.print(" (");
    Serial.print(state);
    Serial.println(")");
    while(halt) { delay(1); }
  }
}

// helper function to display a byte array
void arrayDump(uint8_t *buffer, uint16_t len) {
  for(uint16_t c = 0; c < len; c++) {
    char b = buffer[c];
    if(b < 0x10) { Serial.print('0'); }
    Serial.print(b, HEX);
  }
  Serial.println();
}

#endif

file bme680.ino (in same directory as above main.ino)

// Heltec 32 LoRa V3  BME280 test using HSPI

// modified si this can be called from another file
//   e.g. setup() become setupBME680() and loop() becomes loopBME680()

// using library https://github.com/adafruit/Adafruit_BME680

// File>Examples>Adafruit BME680 Library>bme680test

/***************************************************************************
  This is a library for the BME680 gas, humidity, temperature & pressure sensor

  Designed specifically to work with the Adafruit BME680 Breakout
  ----> http://www.adafruit.com/products/3660

  These sensors use I2C or SPI to communicate, 2 or 4 pins are required
  to interface.

  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing products
  from Adafruit!

  Written by Limor Fried & Kevin Townsend for Adafruit Industries.
  BSD license, all text above must be included in any redistribution
 ***************************************************************************/

//#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include "Adafruit_BME680.h"

SPIClass hspi(HSPI);  // HSPI object used by BME680

// Heltec 32 LoRa V3  HSPI 
#define BME_SCK 40
#define BME_MISO 42
#define BME_MOSI 39
#define BME_CS 41

#define SEALEVELPRESSURE_HPA (1013.25)

//Adafruit_BME680 bme(&Wire); // I2C
//Adafruit_BME680 bme(&Wire1); // example of I2C on another bus
Adafruit_BME680 bme(BME_CS, &hspi);  // hardware SPI
//Adafruit_BME680 bme(BME_CS, BME_MOSI, BME_MISO,  BME_SCK);

void setupBME680() {
  Serial.begin(115200);
  delay(2000);
  while (!Serial)
    ;
  Serial.println(F("BME680 test"));
  hspi.begin(BME_SCK, BME_MISO, BME_MOSI, BME_CS);
  if (!bme.begin()) {
    Serial.println("Could not find a valid BME680 sensor, check wiring!");
    while (1)
      ;
  }

  // Set up oversampling and filter initialization
  bme.setTemperatureOversampling(BME680_OS_8X);
  bme.setHumidityOversampling(BME680_OS_2X);
  bme.setPressureOversampling(BME680_OS_4X);
  bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
  bme.setGasHeater(320, 150);  // 320*C for 150 ms
}

// global variables enables extern access from other files
float temperature, pressure, humidity, gas;
void loopBME680() {
  if (!bme.performReading()) {
    Serial.println("Failed to perform reading :(");
    return;
  }
  Serial.print("Temperature = ");
  Serial.print(temperature=bme.temperature);
  Serial.print(" *C  ");

  Serial.print("Pressure = ");
  Serial.print(pressure=bme.pressure / 100.0);
  Serial.print(" hPa  ");
  Serial.print("Humidity = ");
  Serial.print(humidity=bme.humidity);
  Serial.println(" %");
  Serial.print("Gas = ");
  Serial.print(gas=bme.gas_resistance / 1000.0);
  Serial.print(" KOhms  ");
  Serial.print("Approx. Altitude = ");
  Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
  Serial.println(" m");
  Serial.println();
  delay(2000);
}

Heltec V3 reads BME680 sensor data, displays it on OLED and transmits it to TTN V3 server over LoRaWAN
serial monitor output

SSD1306 allocation OK
BME680 test


Heltec LoRa V3  SX1262 Setup ... 
Initialise the radio
Join ('login') the LoRaWAN Network
Ready!

Sending uplink Temperature = 21.67 *C  Pressure = 1001.47 hPa  Humidity = 46.31 %
Gas = 40.04 KOhms  Approx. Altitude = 98.37 m

temp = 21.670380, pressure = 1001.469971 humidity = 46.307465 gas=40.037998
LoRaWAN transmission 87 2f e9 3 16 12 a3 f 
Received a downlink lenDown 0 data 
Next uplink in 60 seconds

Sending uplink Temperature = 21.47 *C  Pressure = 1001.48 hPa  Humidity = 46.55 %
Gas = 28.70 KOhms  Approx. Altitude = 98.46 m

temp = 21.466648, pressure = 1001.479980 humidity = 46.551521 gas=28.701000
LoRaWAN transmission 72 2f e9 3 2f 12 36 b 
No downlink received
Next uplink in 60 seconds

Sending uplink Temperature = 21.36 *C  Pressure = 1001.48 hPa  Humidity = 46.49 %
Gas = 26.07 KOhms  Approx. Altitude = 98.54 m

temp = 21.360659, pressure = 1001.479980 humidity = 46.490311 gas=26.066999
LoRaWAN transmission 68 2f e9 3 29 12 2e a 
Received a downlink lenDown 5 data 99 88 77 66 55 
Next uplink in 60 seconds


TTNV3 payload formatter

function decodeUplink(input) {
  var data = {};
  data.temperature = ((input.bytes[1] <<8 | input.bytes[0])/100.0)-100.0; 
  data.pressure = (input.bytes[3] <<8 | input.bytes[2]);
  data.humidity = (input.bytes[5] <<8 | input.bytes[4])/100.0; 
  data.gas = (input.bytes[7] <<8 | input.bytes[6])/100.0; 
  return {
    data: data
  };
}

TTN V2 applications live data display

test setup