Hi @Felix
Hier das Listing:
/*
tigerlora_v1_4 senseBox mit Lora und CO2
und einem zweiten Displayjob frei nach Felix
Version 1.4 vom 05.09.2020
senseBox:home - Citizen Sensingplatform
Version: lorav2.0.0
Date: 2018-09-11
*/
#include <LoraMessage.h>
#include <lmic.h>
#include <hal/hal.h>
#include <SPI.h>
//#include <senseBoxIO.h>
#include <SenseBoxMCU.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_HDC1000.h>
#include <Adafruit_BMP280.h>
#include <Adafruit_BME680.h>
#include <Makerblog_TSL45315.h>
#include <VEML6070.h>
#include <SDS011-select-serial.h>
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
// Uncomment the next line to get debugging messages printed on the Serial port
// Do not leave this enabled for long time use
#define ENABLE_DEBUG
#ifdef ENABLE_DEBUG
#define DEBUG(str) Serial.println(str)
#else
#define DEBUG(str)
#endif
// Connected sensors
// Temperatur
#define HDC1080_CONNECTED
// rel. Luftfeuchte
#define HDC1080_CONNECTED
// Luftdruck
#define BMP280_CONNECTED
// Beleuchtungsstärke
#define TSL45315_CONNECTED
// UV-Intensität
#define VEML6070_CONNECTED
// PM10
#define SDS011_CONNECTED
// PM2.5
#define SDS011_CONNECTED
// CO2
#define MH-Z16_CONNECTED
//CO2 alternativ
#define GROVE_CO2 (Serial1)
// Number of serial port the SDS011 is connected to. Either Serial1 or Serial2
#ifdef SDS011_CONNECTED
#define SDS_UART_PORT (Serial2)
#endif
//Load sensors / instances
#ifdef HDC1080_CONNECTED
Adafruit_HDC1000 HDC = Adafruit_HDC1000();
float temperature = 0;
float humidity = 0;
#endif
#ifdef BMP280_CONNECTED
Adafruit_BMP280 BMP;
double pressure;
#endif
#ifdef TSL45315_CONNECTED
uint32_t lux;
Makerblog_TSL45315 TSL = Makerblog_TSL45315(TSL45315_TIME_M4);
#endif
#ifdef VEML6070_CONNECTED
VEML6070 VEML;
uint16_t uv;
#endif
#ifdef SDS011_CONNECTED
SDS011 SDS(SDS_UART_PORT);
float pm10 = 0;
float pm25 = 0;
#endif
#ifdef GROVE_CO2_CONNECTED
GROVE_CO2 GROVECO2;
float CO2;
#endif
#ifdef SMT50_CONNECTED
#define SOILTEMPPIN 0
#define SOILMOISPIN 1
#endif
#ifdef SOUNDLEVELMETER_CONNECTED
#define SOUNDMETERPIN 0
#endif
#ifdef BME680_CONNECTED
Adafruit_BME680 BME;
#endif
#ifdef WINDSPEED_CONNECTED
#define WINDSPEEDPIN 0
#endif
// This EUI must be in little-endian format, so least-significant-byte (lsb)
// first. When copying an EUI from ttnctl output, this means to reverse
// the bytes.
static const u1_t PROGMEM DEVEUI[8]= { 0x64, 0x0C, 0x5A, 0xC3, 0x2F, 0x52, 0x93, 0x00 };
void os_getDevEui (u1_t* buf) { memcpy_P(buf, DEVEUI, 8);}
// This EUI must be in little-endian format, so least-significant-byte (lsb)
// first. When copying an EUI from ttnctl output, this means to reverse
// the bytes. For TTN issued EUIs the last bytes should be 0xD5, 0xB3,
// 0x70.
static const u1_t PROGMEM APPEUI[8]= { 0xAB, 0x3F, 0x03, 0xD0, 0x7E, 0xD5, 0xB3, 0x70 };
void os_getArtEui (u1_t* buf) { memcpy_P(buf, APPEUI, 8);}
// This key should be in big endian format (msb) (or, since it is not really a
// number but a block of memory, endianness does not really apply). In
// practice, a key taken from ttnctl can be copied as-is.
// The key shown here is the semtech default key.
static const u1_t PROGMEM APPKEY[16] = { 0xDB, 0x57, 0x1E, 0x7F, 0xEE, 0x80, 0xC9, 0xAA, 0x9D, 0x2A, 0xD2, 0x59, 0xD5, 0xDA, 0x1D, 0x51 };
void os_getDevKey (u1_t* buf) { memcpy_P(buf, APPKEY, 16);}
const unsigned char cmd_get_sensor[] = {0xff, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79 }; // Code zum Auslesen des CO2 Sensors
unsigned char dataReviced[9];
int temperature_co2;
int CO2PPM;
uint8_t attempt = 0; //Versuchszählrt für PM und CO2
float CO2; // " CO2
int counter=0;
// Helper function for co2 sensor
int dataReceive(void)
{
byte data[9];
int i = 0;
//transmit command data
for(i=0; i<sizeof(cmd_get_sensor); i++)
{
GROVE_CO2.write(cmd_get_sensor[i]);
}
delay(10);
//begin receiving data
if(GROVE_CO2.available())
{
while(GROVE_CO2.available())
{
for(int i=0;i<9; i++)
{
data[i] = GROVE_CO2.read();
}
}
}
delay(100);
if((i != 9) || (1 + (0xFF ^ (byte)(data[1] + data[2] + data[3] + data[4] + data[5] + data[6] + data[7]))) != data[8])
{
return false;
}
CO2PPM = (int)data[2] * 256 + (int)data[3];
temperature_co2 = (int)data[4] - 40;
return CO2PPM;
}
static osjob_t sendjob;
static osjob_t displayjob;
// Schedule TX every this many seconds (might become longer due to duty
// cycle limitations).
const unsigned TX_INTERVAL = 60;
const unsigned DISPLAY_INTERVAL=1; //update Display each secnd
// Pin mapping
const lmic_pinmap lmic_pins = {
.nss = PIN_XB1_CS,
.rxtx = LMIC_UNUSED_PIN,
.rst = LMIC_UNUSED_PIN,
.dio = {PIN_XB1_INT, PIN_XB1_INT, LMIC_UNUSED_PIN},
};
void do_display(osjob_t* ) {
counter++;
//display.clearDisplay;
display.setCursor(0, 0);
display.setTextSize(2);
display.setTextColor(WHITE, BLACK);
display.print("Counter: ");
display.print(String(counter,DEC));
display.display();
//os_setTimedCallback(&displayjob, os_getTime() + sec2osticks(DISPLAY_IN
os_setTimedCallback(&displayjob, os_getTime() + sec2osticks(DISPLAY_INTERVAL), update_display);
}
void onEvent (ev_t ev) {
senseBoxIO.statusGreen();
DEBUG(os_getTime());
switch(ev) {
case EV_SCAN_TIMEOUT:
DEBUG(F("EV_SCAN_TIMEOUT"));
break;
case EV_BEACON_FOUND:
DEBUG(F("EV_BEACON_FOUND"));
break;
case EV_BEACON_MISSED:
DEBUG(F("EV_BEACON_MISSED"));
break;
case EV_BEACON_TRACKED:
DEBUG(F("EV_BEACON_TRACKED"));
break;
case EV_JOINING:
DEBUG(F("EV_JOINING"));
break;
case EV_JOINED:
DEBUG(F("EV_JOINED"));
// Disable link check validation (automatically enabled
// during join, but not supported by TTN at this time).
LMIC_setLinkCheckMode(0);
break;
case EV_RFU1:
DEBUG(F("EV_RFU1"));
break;
case EV_JOIN_FAILED:
DEBUG(F("EV_JOIN_FAILED"));
break;
case EV_REJOIN_FAILED:
DEBUG(F("EV_REJOIN_FAILED"));
break;
case EV_TXCOMPLETE:
DEBUG(F("EV_TXCOMPLETE (includes waiting for RX windows)"));
if (LMIC.txrxFlags & TXRX_ACK)
DEBUG(F("Received ack"));
if (LMIC.dataLen) {
DEBUG(F("Received "));
DEBUG(LMIC.dataLen);
DEBUG(F(" bytes of payload"));
}
// Schedule next transmission
os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(TX_INTERVAL), do_send);
os_setTimedCallback(&displayjob, os_getTime()+sec2osticks(TX_INTERVAL), do_display);
break;
case EV_LOST_TSYNC:
DEBUG(F("EV_LOST_TSYNC"));
break;
case EV_RESET:
DEBUG(F("EV_RESET"));
break;
case EV_RXCOMPLETE:
// data received in ping slot
DEBUG(F("EV_RXCOMPLETE"));
break;
case EV_LINK_DEAD:
DEBUG(F("EV_LINK_DEAD"));
break;
case EV_LINK_ALIVE:
DEBUG(F("EV_LINK_ALIVE"));
break;
default:
DEBUG(F("Unknown event"));
break;
}
}
void do_send(osjob_t* j){
// Check if there is not a current TX/RX job running
if (LMIC.opmode & OP_TXRXPEND) {
DEBUG(F("OP_TXRXPEND, not sending"));
} else {
LoraMessage message;
//-----Temperature-----//
//-----Humidity-----//
#ifdef HDC1080_CONNECTED
DEBUG(F("Temperature: "));
temperature = HDC.readTemperature();
DEBUG(temperature);
message.addUint16((temperature + 18) * 771);
delay(2000);
DEBUG(F("Humidity: "));
humidity = HDC.readHumidity();
DEBUG(humidity);
message.addHumidity(humidity);
delay(2000);
#endif
//-----Pressure-----//
#ifdef BMP280_CONNECTED
float altitude;
pressure = BMP.readPressure()/100;
altitude = BMP.readAltitude(1013.25); //1013.25 = sea level pressure
DEBUG(F("Pressure: "));
DEBUG(pressure);
message.addUint16((pressure - 300) * 81.9187);
delay(2000);
#endif
//-----Lux-----//
#ifdef TSL45315_CONNECTED
DEBUG(F("Illuminance: "));
lux = TSL.readLux();
DEBUG(lux);
message.addUint8(lux % 255);
message.addUint16(lux / 255);
delay(2000);
#endif
//-----UV intensity-----//
#ifdef VEML6070_CONNECTED
DEBUG(F("UV: "));
//uv = VEML.getUV();
DEBUG(uv);
message.addUint8(uv % 255);
message.addUint16(uv / 255);
delay(2000);
#endif
//-----PM-----//
#ifdef SDS011_CONNECTED
//uint8_t attempt = 0;
while (attempt < 5) {
//bool error = SDS.read(&pm25, &pm10); //wieder rückgängig
//if (!error) {
DEBUG(F("PM10: "));
DEBUG(pm10);
message.addUint16(pm10 * 10);
DEBUG(F("PM2.5: "));
DEBUG(pm25);
message.addUint16(pm25 * 10);
break;
}
attempt++;
}
#endif
//---------CO2--------//
while (attempt < 5) {
bool error_co2 = dataReceive();
if (error_co2 != 0) {
CO2PPM=dataReceive();
DEBUG(F("CO2 PPM: "));
DEBUG(CO2PPM);
Serial.print("CO2: ");
Serial.println(CO2PPM);
break;
}
CO2PPM=dataReceive();
Serial.print("CO2: ");
Serial.println(CO2PPM);
attempt++;
}
CO2=float (CO2PPM);
message.addUint16(CO2);
Serial.print(" CO2: ");Serial.println(CO2); //Kontrolle ob das Programm bis hirherkommt
//-----Soil Temperature & Moisture-----//
#ifdef SMT50_CONNECTED
float voltage = analogRead(SOILTEMPPIN) * (3.3 / 1024.0);
float soilTemperature = (voltage - 0.5) * 100;
message.addUint16((soilTemperature + 18) * 771);
voltage = analogRead(SOILMOISPIN) * (3.3 / 1024.0);
float soilMoisture = (voltage * 50) / 3;
message.addHumidity(soilMoisture);
#endif
//-----dB(A) Sound Level-----//
#ifdef SOUNDLEVELMETER_CONNECTED
float v = analogRead(SOUNDMETERPIN) * (3.3 / 1024.0);
float decibel = v * 50;
message.addUint16(decibel * 10);
#endif
//-----BME680-----//
#ifdef BME680_CONNECTED
BME.setGasHeater(0, 0);
if( BME.performReading()) {
message.addUint16((BME.temperature-1 + 18) * 771);
message.addHumidity(BME.humidity);
message.addUint16((BME.pressure/100 - 300) * 81.9187);
}
delay(100);
BME.setGasHeater(320, 150); // 320*C for 150 ms
if( BME.performReading()) {
uint16_t gasResistance = BME.gas_resistance / 1000.0;
message.addUint8(gasResistance % 255);
message.addUint16(gasResistance / 255);
}
#endif
//-----Wind speed-----//
#ifdef WINDSPEED_CONNECTED
float voltageWind = analogRead(WINDSPEEDPIN) * (3.3 / 1024.0);
float windspeed = 0.0;
if (voltageWind >= 0.018){
float poly1 = pow(voltageWind, 3);
poly1 = 17.0359801998299 * poly1;
float poly2 = pow(voltageWind, 2);
poly2 = 47.9908168343362 * poly2;
float poly3 = 122.899677524413 * voltageWind;
float poly4 = 0.657504127272728;
windspeed = poly1 - poly2 + poly3 - poly4;
windspeed = windspeed * 0.2777777777777778; //conversion in m/s
}
message.addUint16(windspeed * 10);
#endif
// Prepare upstream data transmission at the next possible time.
LMIC_setTxData2(1, message.getBytes(), message.getLength(), 0);
DEBUG(F("Packet queued"));
}
// Next TX is scheduled after TX_COMPLETE event.
}
void setup() {
#ifdef ENABLE_DEBUG
Serial.begin(9600);
#endif
delay(3000);
// RFM9X (LoRa-Bee) in XBEE1 Socket
senseBoxIO.powerXB1(false); // power off to reset RFM9X
delay(250);
senseBoxIO.powerXB1(true); // power on
// Sensor initialization
DEBUG(F("Initializing sensors..."));
#ifdef VEML6070_CONNECTED
VEML.begin();
delay(500);
#endif
#ifdef HDC1080_CONNECTED
HDC.begin();
#endif
#ifdef BMP280_CONNECTED
BMP.begin(0x76);
#endif
#ifdef TSL45315_CONNECTED
TSL.begin();
#endif
#ifdef SDS011_CONNECTED
SDS_UART_PORT.begin(9600);
#endif
#ifdef BME680_CONNECTED
BME.begin(0x76);
BME.setTemperatureOversampling(BME680_OS_8X);
BME.setHumidityOversampling(BME680_OS_2X);
BME.setPressureOversampling(BME680_OS_4X);
BME.setIIRFilterSize(BME680_FILTER_SIZE_3);
#endif
DEBUG(F("Sensor initializing done!"));
DEBUG(F("Starting loop in 3 seconds."));
delay(3000);
// LMIC init
os_init();
// Reset the MAC state. Session and pending data transfers will be discarded.
LMIC_reset();
// Start job (sending automatically starts OTAA too)
do_send(&sendjob);
update_display(&displayjob);
}
void loop() {
os_runloop_once();
}