@mario
Hi Mario,
nicht erschrecken das Programm ist noch im Experimtierstadium und ist eine Mischung von Pauls Programm „Mobiler Datenlogger für feinstaub“ und einem Programm zum Abspeichern auf SD-Karte.
Trotz intensiven Suchens ist mir sonst kein Beispielprojekt für GPS-Empfang mit der SenseBox aufgefallen.
/* Überarbeitete Version mit ersetztem smartDelay
* 8.5.2020
* erweitert mit den Zusätzen (noch auskommentiert)
* zur Speicherung aus SD-Karte
*/
//Einbinden der benötigten Libaries
#include <SD.h>
#include <senseBoxIO.h>
#include <TinyGPS++.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_HDC1000.h>
#include <SDS011-select-serial.h>
#include <LoraMessage.h>
#include <lmic.h>
#include <hal/hal.h>
#include <SPI.h>
// #define Statements für Globale Variablen
#define OLED_RESET 4
//#define ENABLE_DEBUG //diese Zeile entkommentieren für Ausgabe im Seriellen Monitor
#ifdef ENABLE_DEBUG
#define DEBUG(str) Serial.println(str)
#else
#define DEBUG(str)
#endif
//Globale Variablen
float pm10,pm25;
float temperature;
float humidity;
String fileName = "SenseBox.txt";
File myFile;
//Libary-Objekte
SDS011 SDS(Serial2);
Adafruit_SSD1306 display(OLED_RESET);
TinyGPSPlus gps;
Adafruit_HDC1000 hdc = Adafruit_HDC1000();
//Diese Funktion stellt sicher, dass das GPS-Modul weiterhin ausgelesen wird.
static void smartDelay(unsigned long ms)
{
unsigned long start = millis();
do
{
Wire.requestFrom(0x42,10);
while (Wire.available())
gps.encode(Wire.read());
} while (millis() - start < ms);
}
/* Ab hier folgen die Funktionen für den LoRaWAN und den TTN Support.
* An den Stellen, an denen Keys vom TTN-Device eingetragen werden müssen, steht dies klar beschrieben */
static const u1_t PROGMEM APPEUI[8]={ };//Hier muss die APPLICATION-EUI im lsb-Format eingetragen werden.
void os_getArtEui (u1_t* buf) { memcpy_P(buf, APPEUI, 8);}
static const u1_t PROGMEM DEVEUI[8]={ }; //Hier muss die DEVICE-EUI im lsb-Format eingetragen werden.
void os_getDevEui (u1_t* buf) { memcpy_P(buf, DEVEUI, 8);}
static const u1_t PROGMEM APPKEY[16] ={ };//Hier muss der APP-KEY im msb-Format eingetragen werden.
void os_getDevKey (u1_t* buf) { memcpy_P(buf, APPKEY, 16);}
static osjob_t sendjob;
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},
};
bool sending = false;
void onEvent (ev_t ev) {
sending=true;
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"));
display.print("joining...");
display.display();
break;
case EV_JOINED:
DEBUG(F("EV_JOINED"));
display.print("joined...");
display.display();
// 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"));
}
sending = false;
display.print("done");
display.display();
delay(2000);
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){
sending = true;
if (LMIC.opmode & OP_TXRXPEND) {
DEBUG(F("OP_TXRXPEND, not sending"));
} else {
LoraMessage message;
//-----Temperature-----//
//-----Humidity-----//
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);
//-----PM-----//
uint8_t attempt = 0;
while (attempt < 5) {
bool error = SDS.read(&pm25, &pm10);
if (!error) {
DEBUG(F("PM10: "));
DEBUG(pm10);
message.addUint16(pm10 * 10);
DEBUG(F("PM2.5: "));
DEBUG(pm25);
message.addUint16(pm25 * 10);
break;
}
attempt++;
}
message.addLatLng(gps.location.lat(),gps.location.lng());
LMIC_setTxData2(1, message.getBytes(), message.getLength(), 0);
DEBUG(F("Packet queued"));
// Abspeichern der Umweltdaten
myFile = SD.open("data.txt", FILE_WRITE);
// myFile.print(TEMP_ID);
//myFile.print(",");
myFile.print(hdc.readTemperature());
myFile.print(",");
// myFIle.println(timestamp)
// zweiter Messwert
//myFile.print(HUMI_ID);
myFile.print(",");
myFile.print(hdc.readHumidity());
myFile.print(",");
//myFIle.println(timestamp)
// Datei nachher schliessen
myFile.close();
}
}
/*
* Setup
*/
void setup() {
#ifdef ENABLE_DEBUG //Wenn Debug aktiviert ist, warten, bis eine Serielle Verbindung besteht
while(!Serial){}
Serial.println("Running in Debug Mode:");
#endif
Serial.begin(9600);
senseBoxIO.powerUART(true); //Den Strom einschalten
senseBoxIO.powerXB1(false); // Reset RFM9X
delay(250);
senseBoxIO.powerXB1(true); // PFM9X An
senseBoxIO.powerXB2(true);
senseBoxIO.powerI2C(true);
/* // Starten der SD-Bee
SD.begin(28);
// Öffnen der Datei auf der SD-Karte
myFile = SD.open(fileName, FILE_WRITE);
myFile.close();
*/
Serial1.begin(9600);//Serielle Schnittstellen starten
Serial2.begin(9600);
delay(2000);
display.begin(SSD1306_SWITCHCAPVCC, 0x3D); //Display starten
display.display();
delay(100);
display.clearDisplay();
display.setCursor(0,0);
display.setTextSize(1);
display.setTextColor(WHITE,BLACK);
hdc.begin(); //HDC starten
/*if(!Serial1.available()){ //Überprüfen, ob das GPS-Modul verbunden ist
Serial.println("ERR404: DEVICE ON Serial1 NOT FOUND");
display.println("NO MODULE CONNECTED!");
display.display();
while(true){
delay(100);
}
}
*/
//Den Nutzer über die Satellitensuche informieren
Serial.println("Beginning GPS Satellite Search:");
display.setCursor(0,0);
display.setTextSize(1);
display.setTextColor(WHITE,BLACK);
display.println("Searching Satellites");
display.display();
smartDelay(100);
//Warten, bis ein Satellit gefunden wird
int tries = 0;
while(gps.satellites.value() == 0){
smartDelay(100);
tries ++;
if (tries > 1200){
tries = 0;
goto ENDSETUP;
}
}
if(false){//Dieses Statement wird nur ausgeführt, wenn keine Satelliten gefunden werden
ENDSETUP:
display.clearDisplay();
display.setCursor(0,0);
display.println("No Satellites were found...");
display.println("To continue with the Loop, while still searching in the background, press the Button now");
display.display();
while(true){
if(digitalRead(0)==LOW){
while(digitalRead(0)==LOW){}
goto beginLoop;
}
}
}
//Wenn Satelliten gefunden sind:
display.clearDisplay();
while(!gps.location.isValid()){//Warten, bis das GPS-Signal gefunden wurde
Serial.print("Satellites found: ");
Serial.println(gps.satellites.value());
display.print("Found ");
display.print(gps.satellites.value());
display.println(" Satellites.");
display.display();
smartDelay(100);
display.clearDisplay();
display.setCursor(0,0);
}
if(gps.location.isValid()){//Position anzeigen, sobald gefunden.
display.clearDisplay();
display.setCursor(0,0);
display.setTextSize(2);
display.setTextColor(BLACK,WHITE);
display.println("GPS found, Location:");
display.print(gps.location.lat());
display.print(" ");
display.println(gps.location.lng());
display.display();
Serial.println("GPS Found!");
Serial.print("Time:");
Serial.print(gps.time.value());
smartDelay(5000);
}
//Goto Marker für den Loop
beginLoop:
//LoRa Schnittstelle starten
os_init();
LMIC_reset();
smartDelay(3000);
}
/*
* Loop
*/
void loop() {
//Die GPS-Informationen auf dem Display anzeigen
Serial.print(gps.location.lat());
Serial.print("N ");
Serial.print(gps.location.lng());
Serial.println("E");
display.clearDisplay();
display.setCursor(0,0);
display.setTextSize(2);
display.setTextColor(BLACK,WHITE);
display.println("Location: ");
display.print(gps.location.lat());
display.print(" ");
display.println(gps.location.lng());
display.setTextSize(1);
display.setTextColor(WHITE,BLACK);
display.print("Got ");
display.print(gps.satellites.value());
display.println(" Satellites");
display.print("Your Speed: ");
display.print(int(gps.speed.kmph()));
display.println("kmph");
display.print("HDOP: ");
display.println(gps.hdop.hdop());
display.print("Height ");
display.print(gps.altitude.meters());
display.println("m");
display.display();
if(digitalRead(0)==LOW){//Daten an OSeM senden, wenn der Button gedrückt wird.
while(digitalRead(0)==LOW){}//Diese while-Schleife stellt sicher, dass der Button losgelassen wird, bevor der Programmablauf fortgesetzt wird
display.clearDisplay();
display.setCursor(0,0);
display.print("Dumping to OSeM via LoRA and TTN...");
display.display();
do_send(&sendjob);
}
while(sending==true){//Diese Funktion stellt sicher, dass der Sendevorgang abgeschlossen wird, bevor ein neuer gestartet wird.
os_runloop_once();
}
smartDelay(100);//loop alle 100 Millisekunden
}