#include #include #include #include #include #include #include //LSB static const u1_t PROGMEM DEVEUI[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //LSB static const u1_t PROGMEM APPEUI[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} ; //MSB static const u1_t PROGMEM APPKEY[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } ; int sleeptime = 35; // (sleeptime * 8s) - 20 s = Cycle-time // 35 -> 5 min // 110 ->15 min // 225 = 30 min // 450 -> 1h //Pindefinition für IOs #define ONE_WIRE_BUS A0 #define VCC_ADC A2 #define SOLAR_ADC A1 // Ausgabe von Spannung (bei 0 keine Ausgabe) int solarvoltagecountmax = 10; // Bei erreichen dieses Wertes wird die Variable Count zurück gesetzt. int battvoltagecountmax = 20; // Bei erreichen dieses Wertes wird die Variable Count zurück gesetzt. // Faktoren für Spannungsteiler an Analogeingängen const float solar_factor = 11 * 1.1 ; // Spannungsteiler 100K : 1M => Faktor 11 * 1,1 V Vref const float vcc_factor = 11 * 1.1 ; // Spannungsteiler 100K : 1M => Faktor 11 * 1,1 V Vref // Temperatursensor-Kalibrierung const float temp_calibration_offset = 0.0; const float temp_calibration_factor = 1.0; // Pin-Konfiguration RFM95 const lmic_pinmap lmic_pins = { .nss = 10, .rxtx = LMIC_UNUSED_PIN, .rst = 4, .dio = {3, 2, LMIC_UNUSED_PIN} }; const bool debug = false; // Debug-Meldungen aktivieren int battvoltagecount = 0 ; // Laufvariable für Spannungsmessung. Bei 1 werden Spannungswerte übertragen int solarvoltagecount = 0 ; // Laufvariable für Spannungsmessung. Bei 1 werden Spannungswerte übertragen bool sent = true; // nach Senden eines LoRa Packets wird die variable auf true gesetzt. Der Controller schläft erst wenn TX abgeschlossen und die variable false ist bool firststart = true; // Beim ersten Start wird nicht auf auf das Sendeintervall gewartet bool sensorerror = true; // Speicher für Fehlermeldung von Temperatursensor OneWire oneWire(ONE_WIRE_BUS); DallasTemperature sensors(&oneWire); DeviceAddress Thermometer; CayenneLPP lpp(20); #ifdef COMPILE_REGRESSION_TEST # define FILLMEIN 0 #else # warning "You must replace the values marked FILLMEIN with real values from the TTN control panel!" # define FILLMEIN (#dont edit this, edit the lines that use FILLMEIN) #endif void os_getArtEui (u1_t* buf) { memcpy_P(buf, APPEUI, 8); } void os_getDevEui (u1_t* buf) { memcpy_P(buf, DEVEUI, 8); } void os_getDevKey (u1_t* buf) { memcpy_P(buf, APPKEY, 16); } static osjob_t sendjob; void onEvent (ev_t ev) { switch (ev) { case EV_SCAN_TIMEOUT: if (debug) Serial.println(F("EV_SCAN_TIMEOUT")); break; case EV_BEACON_FOUND: if (debug) Serial.println(F("EV_BEACON_FOUND")); break; case EV_BEACON_MISSED: if (debug) Serial.println(F("EV_BEACON_MISSED")); break; case EV_BEACON_TRACKED: if (debug) Serial.println(F("EV_BEACON_TRACKED")); break; case EV_JOINING: if (debug) Serial.println(F("EV_JOINING")); break; case EV_JOINED: if (debug) Serial.println(F("EV_JOINED")); { u4_t netid = 0; devaddr_t devaddr = 0; u1_t nwkKey[16]; u1_t artKey[16]; LMIC_getSessionKeys(&netid, &devaddr, nwkKey, artKey); if (debug) { Serial.print("netid: "); Serial.println(netid, DEC); Serial.print("devaddr: "); Serial.println(devaddr, HEX); Serial.print("artKey: "); for (int i = 0; i < sizeof(artKey); ++i) { Serial.print(artKey[i], HEX); } Serial.println(""); Serial.print("nwkKey: "); for (int i = 0; i < sizeof(nwkKey); ++i) { Serial.print(nwkKey[i], HEX); } Serial.println(""); } } LMIC_setLinkCheckMode(0); break; case EV_JOIN_FAILED: if (debug) Serial.println(F("EV_JOIN_FAILED")); break; case EV_REJOIN_FAILED: if (debug) Serial.println(F("EV_REJOIN_FAILED")); break; case EV_TXCOMPLETE: if (debug) Serial.println(F("EV_TXCOMPLETE incl wait")); if (LMIC.txrxFlags & TXRX_ACK) if (debug) Serial.println(F("Received ack")); if (LMIC.dataLen) { if (debug) { Serial.print(F("Received ")); Serial.print(LMIC.dataLen); Serial.println(F(" bytes of payload")); Serial.print(F(" bytes of payload: 0x")); for (int i = 0; i < LMIC.dataLen; i++) { if (LMIC.frame[LMIC.dataBeg + i] < 0x10) { Serial.print(F("0")); } Serial.print(LMIC.frame[LMIC.dataBeg + i], HEX); } Serial.println(F("")); } if (LMIC.dataLen == 2) { byte command = LMIC.frame[LMIC.dataBeg ]; byte value = LMIC.frame[LMIC.dataBeg + 1]; setParameter(command, value); delay(1000); } } // Schedule next transmission os_setTimedCallback(&sendjob, os_getTime() + 5, do_send); // Fünf Tics nach der Übertragung wird do_send aufgerufen break; case EV_LOST_TSYNC: if (debug) Serial.println(F("EV_LOST_TSYNC")); break; case EV_RESET: if (debug) Serial.println(F("EV_RESET")); break; case EV_RXCOMPLETE: // data received in ping slot if (debug) Serial.println(F("EV_RXCOMPLETE")); break; case EV_LINK_DEAD: if (debug) Serial.println(F("EV_LINK_DEAD")); break; case EV_LINK_ALIVE: if (debug) Serial.println(F("EV_LINK_ALIVE")); break; /* || This event is defined but not used in the code. No || point in wasting codespace on it. || || case EV_SCAN_FOUND: || Serial.println(F("EV_SCAN_FOUND")); || break; */ case EV_TXSTART: if (debug) Serial.println(F("EV_TXSTART")); break; default: if (debug) { Serial.print(F("Unknown event: ")); Serial.println((unsigned) ev); } break; } } void do_send(osjob_t* j) { // Check if there is not a current TX/RX job running if (LMIC.opmode & OP_TXRXPEND) { Serial.println(F("OP_TXRXPEND, not sending")); } else { // Prepare upstream data transmission at the next possible time. if (debug) Serial.println(F("Start Deep-Sleep ")); if (!firststart) // Bei Neustart warten überspringen { for (int i = 0; i <= sleeptime; i++) // Für sleeptime*8s schlafen { LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); } if (debug) { Serial.println(" "); Serial.println("awake"); } } else { firststart = false; } sensors.requestTemperatures(); // Temperstursensor auslesen lpp.reset(); // Datenpacket leeren float temp = sensors.getTempCByIndex(0); //Temperatur aus erstem Sensor auslesen if (debug) { Serial.print("temp:"); Serial.println(temp); Serial.print("battvoltagecount:"); Serial.println(battvoltagecount); Serial.print("solarvoltagecount:"); Serial.println(solarvoltagecount); } if (temp > -120 && temp < 120 ) // bei Sensorfehler Temp < -120°C oder Temp > 120°C { temp += temp_calibration_offset; temp = temp * temp_calibration_factor; lpp.addTemperature(1, temp); // Temperatur ausgeben if (sensorerror) // wenn vorher ein Sensorfehler gelesen wurde ein "OK" senden { sensorerror = false; lpp.addDigitalInput(4, 0); // Nachricht für OK } } else { sensorerror = true; lpp.addDigitalInput(4, 1); // Fehlerhaften Sensor melden } if (battvoltagecount == 1) { float vcc = analogRead(VCC_ADC); // VCC auslesen vcc *= vcc_factor; // Spannungsteiler 10K : 100K => Faktor 11 * 1,1 V Vref vcc /= 1024; // von 10 Bit auf Spannung normieren if (debug) { Serial.print("vcc: "); Serial.print(vcc); Serial.println(" V"); } lpp.addAnalogInput(2, vcc); } if (solarvoltagecount == 1 ) { float solar = analogRead(SOLAR_ADC); // Solar Voltage solar *= solar_factor; // Spannungsteiler 10K : 100K => Faktor 11 * 1,1 V Vref solar /= 1024; // von 10 Bit auf Spannung normieren if (debug) { Serial.print("solar: "); Serial.print(solar); Serial.println(" V"); } lpp.addAnalogInput(3, solar); } battvoltagecount ++ ; if (battvoltagecount >= battvoltagecountmax) battvoltagecount = 0; solarvoltagecount ++ ; if (solarvoltagecount >= solarvoltagecountmax) solarvoltagecount = 0; LMIC_setTxData2(1, lpp.getBuffer(), lpp.getSize(), 0); if (debug) Serial.println(F("Packet queued")); } } void setup() { if (debug) { Serial.begin(9600); Serial.println(F("Starting")); } sensors.begin(); sensors.setResolution(10); analogReference(INTERNAL); #ifdef VCC_ENABLE // For Pinoccio Scout boards pinMode(VCC_ENABLE, OUTPUT); digitalWrite(VCC_ENABLE, HIGH); delay(1000); #endif os_init(); LMIC_reset(); LMIC_setClockError(MAX_CLOCK_ERROR * 1 / 100); do_send(&sendjob); // Start job (sending automatically starts OTAA too) } void loop() { os_runloop_once(); } void setParameter(byte command, byte value) { }