Initial commit
This commit is contained in:
Executable
+4
@@ -0,0 +1,4 @@
|
||||
#Fichier de configuration du contrôleur du projet
|
||||
# Camétéo
|
||||
time_step=2000
|
||||
data_file=datalog3.csv
|
||||
@@ -0,0 +1,42 @@
|
||||
|
||||
#include "cameteo_teensy.h"
|
||||
|
||||
void stopRPI() {
|
||||
//Stop the Raspberry Pi via the MOSFET (grid connected to the RPI_PWR_PIN)
|
||||
|
||||
pinMode(RPI_PWR_PIN, INPUT); //Eteint via le MOSFET
|
||||
rpi_status = false;
|
||||
}
|
||||
|
||||
bool isStartedPI() {
|
||||
//Return true if the R-Pi respond to an simple request
|
||||
return rpi_status;
|
||||
}
|
||||
|
||||
void startRPI() {
|
||||
//Start the Raspberry Pi via the MOSFET (grid connected to the RPI_PWR_PIN)
|
||||
if (!isStartedPI()) {
|
||||
pinMode(RPI_PWR_PIN, OUTPUT);
|
||||
digitalWrite(RPI_PWR_PIN, LOW);
|
||||
rpi_status = true;
|
||||
}
|
||||
}
|
||||
|
||||
void sendDataToSerial(String data) {
|
||||
if (isStartedPI()) {
|
||||
char c[100]; // char buffer for conversion String->char
|
||||
data.toCharArray(c, sizeof(data)); //convert data string to char array
|
||||
|
||||
// //start serial comm. if needed
|
||||
// if(!SERIAL_PORT) {
|
||||
// SERIAL_PORT.begin(SERIAL_BAUD_RATE);
|
||||
// //while(!SERIAL_PORT);
|
||||
// }
|
||||
|
||||
SERIAL_PORT.print(c); // send data on serial port
|
||||
|
||||
}
|
||||
else {
|
||||
//error RPI is not started
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
|
||||
#include "cameteo_teensy.h"
|
||||
|
||||
void BootMessage(String s) {
|
||||
char c[13]; // char buffer for conversion String->char
|
||||
s.toCharArray(c, sizeof(s));
|
||||
SERIAL_PORT.printf("%-12s", c);
|
||||
}
|
||||
|
||||
void BootOK() {
|
||||
SERIAL_PORT.println("OK");
|
||||
}
|
||||
|
||||
void BootError() {
|
||||
SERIAL_PORT.println("EE");
|
||||
}
|
||||
|
||||
void sendDataOnSerial() {
|
||||
|
||||
//Print date & hour on serial port
|
||||
SERIAL_PORT.printf("%04d/%02d/%02d_%02d:%02d:%02d\n", year(), month(), day(), hour(), minute(), second());
|
||||
|
||||
// if (isnan(dht22_event_hum.relative_humidity) ||
|
||||
// isnan(dht22_event_temp.temperature)) {
|
||||
// SERIAL_PORT.printf("Failed to read from DHT sensor!\n");
|
||||
// }
|
||||
// else {
|
||||
// SERIAL_PORT.printf("Temperature:%8.2f %cC | Humidity:%8.0f %%\n",
|
||||
// dht22_event_temp.temperature, DEGREE, dht22_event_hum.relative_humidity);
|
||||
// }
|
||||
|
||||
// if (bme280_event.pressure) {
|
||||
SERIAL_PORT.printf("Temperature:%8.2f %cC | Humidity: %8.2f % | Pressure: %8.2f hPa | Altitude:%8.2f m\n",
|
||||
bme280_temp, DEGREE, bme280_press, bme280_alti);
|
||||
// }
|
||||
// else {
|
||||
// SERIAL_PORT.printf("BME280 Sensor error\n");
|
||||
// }
|
||||
|
||||
SERIAL_PORT.printf("Lightning strikes (from start) : %d | Perturb.: %d | Noise : %d | Unknown detect.: %d\n", lightning_nb_total,
|
||||
as3935_perturb_total,
|
||||
as3935_noise_total,
|
||||
as3935_unknown_total);
|
||||
|
||||
//SERIAL_PORT.printf("Temperature:%8.2f %cC\n", tcn75a_temp, DEGREE);
|
||||
|
||||
SERIAL_PORT.printf("GPS data: %04d/%02d/%02d_%02d:%02d:%02d (%d)\n", gps_year, gps_month, gps_day,
|
||||
gps_hour, gps_minutes, gps_second,
|
||||
gps_fix_age);
|
||||
SERIAL_PORT.printf(" Latitude: %11.8f | Longitude: %11.8f | Altitude: %5.2f m\n", gps_latitude, gps_longitude, gps_altitude);
|
||||
SERIAL_PORT.printf(" Speed: %4.1f km/h | Course : %4.1f %c\n", gps_speed, gps_course, DEGREE);
|
||||
SERIAL_PORT.printf(" Chars: %11d | Sentences: %11d | Failed cheksum: %4d\n", gps_chars, gps_sentences, gps_failed_checksum);
|
||||
|
||||
SERIAL_PORT.printf("Battery : %10d mV | Low Battery : %d\n", batt_voltage, low_battery_flag);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* CAMETEO project
|
||||
*
|
||||
* This is a personnal project of weather station with
|
||||
* automatic photo taking.
|
||||
* This code is the weather station part and is meant
|
||||
* to be run on a PJRC Teensy 3.2 board.
|
||||
*
|
||||
* Author : Arofarn
|
||||
*
|
||||
* Licence : GPL v3
|
||||
*
|
||||
*/
|
||||
|
||||
//Protocols
|
||||
#include <Wire.h> // library used with I2C protocol
|
||||
#include <SPI.h> // SPI protocol
|
||||
|
||||
//Teensy3.x Real Time Clock
|
||||
#include <TimeLib.h>
|
||||
|
||||
//SD card
|
||||
#include <SD.h>
|
||||
|
||||
// Sensors
|
||||
#include <Adafruit_Sensor.h> // Generic
|
||||
//#include <DHT.h> // DHT22
|
||||
//#include <DHT_U.h> // DHT22 unified
|
||||
//#include <Adafruit_BMP085_U.h> // BMP180
|
||||
#include <Adafruit_BME280.h> // BME280
|
||||
#include <PWFusion_AS3935.h>
|
||||
|
||||
//GPS
|
||||
//#include <Adafruit_GPS.h> // Adafruit Ultimate GPS
|
||||
#include <TinyGPS.h> //Builtin GPS lib
|
||||
|
||||
+399
@@ -0,0 +1,399 @@
|
||||
/*
|
||||
* CAMETEO project
|
||||
*
|
||||
* This is a personnal project of weather station with
|
||||
* automatic photo taking.
|
||||
* This code is the weather station part and is meant
|
||||
* to be run on a PJRC Teensy 3.2 board.
|
||||
*
|
||||
* Author : Arofarn
|
||||
*
|
||||
* Licence : GPL v3
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "cameteo_teensy.h"
|
||||
#include "SerialMessages.cpp"
|
||||
#include "RaspBerryPi_COM.cpp"
|
||||
|
||||
//sensors_event_t bme280_event;
|
||||
float seaLevelPressure = 1015.0;
|
||||
float bme280_press;
|
||||
float bme280_temp;
|
||||
float bme280_alti;
|
||||
float bme280_hum;
|
||||
|
||||
enum strike_sources { UNKNOWN_SRC, LIGHTNING, PERTURBATION, NOISE };
|
||||
volatile int8_t AS3935_ISR_Trig = 0; // Trigger for AS3935 lightning sensor
|
||||
|
||||
void AS3935_ISR() {
|
||||
AS3935_ISR_Trig = 1;
|
||||
}
|
||||
|
||||
PWF_AS3935 lightning(AS3935_CS_PIN, AS3935_IRQ_PIN, 33);
|
||||
|
||||
int as3935_src;
|
||||
int as3935_distance;
|
||||
long lightning_nb_total = 0;
|
||||
int lightning_nb_hour = 0;
|
||||
int lightning_nb_day = 0;
|
||||
int as3935_perturb_total = 0;
|
||||
int as3935_noise_total = 0;
|
||||
int as3935_unknown_total = 0;
|
||||
char lightning_log_file[12] = "lghtnng.log";
|
||||
|
||||
//GPS
|
||||
//Adafruit_GPS GPS(&GPS_SERIAL_PORT);
|
||||
TinyGPS GPS;
|
||||
float gps_latitude, gps_longitude, gps_altitude; // returns +- latitude/longitude in degrees
|
||||
float gps_speed, gps_course;
|
||||
unsigned long gps_time, gps_date, gps_fix_age;
|
||||
int gps_year;
|
||||
byte gps_month, gps_day, gps_hour, gps_minutes, gps_second, gps_hundreths;
|
||||
unsigned long gps_chars, gps_hdop;
|
||||
unsigned short gps_sentences, gps_failed_checksum, gps_satellites;
|
||||
|
||||
//Miscellaneous
|
||||
bool rpi_status;
|
||||
rpi_status = false;
|
||||
int batt_voltage;
|
||||
bool low_battery_flag = false;
|
||||
|
||||
// Tasks timers
|
||||
elapsedMillis since_bme280;
|
||||
//elapsedMillis since_dht;
|
||||
elapsedMillis since_gps;
|
||||
elapsedMillis since_display;
|
||||
elapsedMillis since_serial_send;
|
||||
elapsedMillis since_sd_log;
|
||||
elapsedMillis since_batt_chk;
|
||||
|
||||
//SD Card
|
||||
#define CONFIGFILE "config.txt"
|
||||
|
||||
//Configuration
|
||||
char data_file[13] = "datalog.csv";
|
||||
|
||||
//Delays
|
||||
|
||||
unsigned int bme280_delay = 500;
|
||||
//unsigned int dht_delay = 3000;
|
||||
unsigned int gps_delay = 100;
|
||||
unsigned int serial_send_delay = 5000;
|
||||
unsigned int sd_log_delay = 5000;
|
||||
unsigned int batt_chk_delay = 5000;
|
||||
|
||||
//Date and time
|
||||
int TZ = 1; //Time zone
|
||||
|
||||
/*
|
||||
* SETUP
|
||||
*/
|
||||
|
||||
void setup() {
|
||||
|
||||
//To be sure Raspberry-Pi won't be turned on unexpectedly
|
||||
stopRPI();
|
||||
|
||||
pinMode(LOW_BATT_PIN, INPUT_PULLUP);
|
||||
low_battery_flag = !digitalRead(LOW_BATT_PIN);
|
||||
|
||||
pinMode(GPS_BUT_PIN, INPUT_PULLUP);
|
||||
pinMode(GPS_EN_PIN, OUTPUT);
|
||||
gps_power();
|
||||
|
||||
SERIAL_PORT.begin(SERIAL_BAUD_RATE);
|
||||
delay(1000);
|
||||
//while (!SERIAL_PORT) { }; //Wait for serial port to start
|
||||
SERIAL_PORT.printf("Serial Comm. OK\nNow booting...\n");
|
||||
|
||||
BootMessage("SDcard");
|
||||
// see if the card is present and can be initialized:
|
||||
if (!SD.begin(SD_CS_PIN)) {
|
||||
BootError();
|
||||
while(1);
|
||||
}
|
||||
BootOK();
|
||||
|
||||
BootMessage("RT Clock");
|
||||
// set the Time library to use Teensy 3.0's RTC to keep time
|
||||
setSyncProvider(getTeensy3Time);
|
||||
if (timeStatus()!= timeSet) {
|
||||
BootError();
|
||||
while(1);
|
||||
}
|
||||
BootOK();
|
||||
|
||||
// BootMessage("AM2302/DHT22 (Humidity and Temperature)");
|
||||
// dht.begin();
|
||||
// //sensor_t sensor;
|
||||
// BootOK();
|
||||
|
||||
BootMessage("BME280 (Pressure and Temperature)");
|
||||
/* Initialise the sensor */
|
||||
if(!bme.begin())
|
||||
{
|
||||
/* There was a problem detecting the BMP085 ... check your connections */
|
||||
BootError();
|
||||
while(1);
|
||||
}
|
||||
BootOK();
|
||||
|
||||
BootMessage("AS3935 (Lightning)");
|
||||
SPI.begin();
|
||||
SPI.setClockDivider(SPI_CLOCK_DIV16); // SPI speed to SPI_CLOCK_DIV16/1MHz (max 2MHz, NEVER 500kHz!)
|
||||
SPI.setDataMode(SPI_MODE1); // MAX31855 is a Mode 1 device --> clock starts low, read on rising edge
|
||||
SPI.setBitOrder(MSBFIRST); // data sent to chip MSb first
|
||||
lightning.AS3935_DefInit(); // set registers to default
|
||||
// now update sensor cal for your application and power up chip
|
||||
lightning.AS3935_ManualCal(AS3935_CAPACITANCE, AS3935_INDOORS, AS3935_DIST_EN);
|
||||
// enable interrupt (hook IRQ pin to Arduino Uno/Mega interrupt input: 0 -> pin 2, 1 -> pin 3 )
|
||||
attachInterrupt(AS3935_IRQ_PIN, AS3935_ISR, RISING);
|
||||
BootOK();
|
||||
|
||||
BootMessage("GPS");
|
||||
GPS_SERIAL_PORT.begin(GPS_SERIAL_BAUD_RATE);
|
||||
while (!GPS_SERIAL_PORT) {} ;
|
||||
BootOK();
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* LOOP
|
||||
*/
|
||||
|
||||
void loop() {
|
||||
|
||||
//Power ON/OFF GPS
|
||||
gps_power();
|
||||
|
||||
//Lightning detection
|
||||
if (AS3935_ISR_Trig != 0) {
|
||||
AS3935_ISR_Trig = 0;
|
||||
time_t t = now();
|
||||
int distance = -9999;
|
||||
int energy = -9999;
|
||||
switch (as3935_src) {
|
||||
case UNKNOWN_SRC:
|
||||
//source inconnue
|
||||
as3935_unknown_total++;
|
||||
SERIAL_PORT.printf("Interruption (AS3935) : unkown source (not lightning)\n");
|
||||
break;
|
||||
case LIGHTNING:
|
||||
//Foudre !!!
|
||||
lightning_nb_total++;
|
||||
distance = lightning.AS3935_GetLightningDistKm();
|
||||
energy = lightning.AS3935_GetStrikeEnergyRaw();
|
||||
SERIAL_PORT.printf("Interruption (AS3935) : Lightningbolt !!!\n");
|
||||
SERIAL_PORT.printf("Distance : %4d km | Energy : %d \n", distance, energy);
|
||||
break;
|
||||
case PERTURBATION:
|
||||
//Perturbation
|
||||
as3935_perturb_total++;
|
||||
SERIAL_PORT.printf("Interruption (AS3935) : perturbation...\n");
|
||||
break;
|
||||
case NOISE:
|
||||
//Trop de bruit électromagnétique
|
||||
as3935_noise_total++;
|
||||
SERIAL_PORT.printf("Interruption (AS3935) : Too much electromagnetic noise!\n");
|
||||
break;
|
||||
}
|
||||
writeLightningToSD(as3935_src, t, distance, energy);
|
||||
}
|
||||
|
||||
if (since_batt_chk >= batt_chk_delay) {
|
||||
since_batt_chk -= batt_chk_delay;
|
||||
//Check battery status and voltage
|
||||
low_battery_flag = !digitalRead(LOW_BATT_PIN);
|
||||
batt_voltage = getBatteryVoltage();
|
||||
}
|
||||
|
||||
// if (since_dht >= dht_delay) {
|
||||
// since_dht = since_dht - dht_delay;
|
||||
// // Read temperature or humidity
|
||||
// dht.humidity().getEvent(&dht22_event_hum);
|
||||
// dht.temperature().getEvent(&dht22_event_temp);
|
||||
// }
|
||||
|
||||
if (since_bme280 >= bme280_delay) {
|
||||
since_bme280 = since_bme280 - bme280_delay;
|
||||
/* Get a new sensor event */
|
||||
bmp.getEvent(&bme280_event);
|
||||
|
||||
/* Get the values (barometric pressure is measure in hPa) */
|
||||
if (bme280_event.pressure)
|
||||
{
|
||||
bme280_press = bme280_event.pressure;
|
||||
bmp.getTemperature(&bme280_temp);
|
||||
bme280_alti = bmp.pressureToAltitude(seaLevelPressure, bme280_press);
|
||||
}
|
||||
}
|
||||
|
||||
if (since_gps >= gps_delay) {
|
||||
since_gps = since_gps - gps_delay;
|
||||
while (GPS_SERIAL_PORT.available()) {
|
||||
char c = GPS_SERIAL_PORT.read();
|
||||
if (GPS.encode(c)) {
|
||||
GPS.get_datetime(&gps_date, &gps_time, &gps_fix_age);
|
||||
GPS.crack_datetime(&gps_year, &gps_month, &gps_day,
|
||||
&gps_hour, &gps_minutes, &gps_second,
|
||||
&gps_hundreths, &gps_fix_age);
|
||||
GPS.f_get_position(&gps_latitude, &gps_longitude, &gps_fix_age);
|
||||
gps_altitude = GPS.f_altitude();
|
||||
gps_speed = GPS.f_speed_kmph();
|
||||
GPS.stats(&gps_chars, &gps_sentences, &gps_failed_checksum);
|
||||
gps_satellites = GPS.satellites();
|
||||
gps_hdop = GPS.hdop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (since_sd_log >= sd_log_delay) {
|
||||
since_sd_log = since_sd_log - sd_log_delay;
|
||||
writeDataToSD();
|
||||
}
|
||||
|
||||
if (since_serial_send >= serial_send_delay) {
|
||||
since_serial_send = since_serial_send - serial_send_delay;
|
||||
sendDataOnSerial();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* FUNCTIONS
|
||||
*/
|
||||
|
||||
time_t getTeensy3Time() {
|
||||
return Teensy3Clock.get();
|
||||
}
|
||||
|
||||
void gps_power() {
|
||||
if (digitalRead(GPS_BUT_PIN) == 0) { digitalWrite(GPS_EN_PIN, LOW); }
|
||||
else { digitalWrite(GPS_EN_PIN, HIGH); }
|
||||
}
|
||||
|
||||
int getBatteryVoltage() {
|
||||
long mean = 0;
|
||||
int U = 0;
|
||||
int n = 10;
|
||||
int res = 12;
|
||||
|
||||
analogReadResolution(res);
|
||||
|
||||
for (int i=0; i<n; i++) {
|
||||
mean += analogRead(BATT_VOLT_PIN);
|
||||
//delay(2);
|
||||
}
|
||||
mean /= n;
|
||||
|
||||
U = map(mean, 0, pow(2, res)-1, 0, 3300); // Convert data from ADC into input voltage in mV
|
||||
U *= 2; //Multiple by 2 for the voltage divider
|
||||
|
||||
return U;
|
||||
}
|
||||
|
||||
void writeDataToSD() {
|
||||
|
||||
char dir[20];
|
||||
char path[60];
|
||||
|
||||
String directory = dayDirectory();
|
||||
|
||||
directory.toCharArray(dir, sizeof(directory));
|
||||
sprintf(path, "%s/%s", dir, data_file);
|
||||
|
||||
// Test to know if the file exists before opening it, if it doesn't exist
|
||||
// we will write first an header
|
||||
bool no_header = SD.exists(path);
|
||||
|
||||
// open the file. note that only one file can be open at a time,
|
||||
// so you have to close this one before opening another.
|
||||
File dataFile = SD.open(path, FILE_WRITE);
|
||||
|
||||
// if the file is available, write to it:
|
||||
if (dataFile) {
|
||||
if (!no_header) {
|
||||
SERIAL_PORT.printf("Creating file with CSV header : %s\n", path);
|
||||
dataFile.printf("Date");
|
||||
dataFile.printf(";bme280_Pressure(hPa);BMP180_Temperature(degC);BMP180_Altitude(m)");
|
||||
// dataFile.printf(";DHT22_Humidity(%);DHT22_Temperature(degC)");
|
||||
dataFile.printf(";TotalLightningCount;TotalPerturbationEvents;TotalNoiseDetection;TotalUnknownDetection");
|
||||
dataFile.printf(";GPS_Latitude;GPS_Longitude;GPS_Altitude;GPS_Satellites;GPS_HDOP;GPS_Date");
|
||||
dataFile.printf(";Battery_voltage(mV);Low_Battery_Status");
|
||||
dataFile.printf("\n");
|
||||
}
|
||||
dataFile.printf("%04d/%02d/%02d_%02d:%02d:%02d", year(), month(), day(), hour(), minute(), second());
|
||||
dataFile.printf(";%.2f;%.2f;%.1f", bme280_press, bme280_temp, bme280_alti);
|
||||
// dataFile.printf(";%.0f;%.2f", dht22_event_hum.relative_humidity, dht22_event_temp.temperature);
|
||||
dataFile.printf(";%d;%d;%d;%d", lightning_nb_total, as3935_perturb_total, as3935_noise_total, as3935_unknown_total);
|
||||
dataFile.printf(";%.8f;%.8f;%.2f;%d;%d;%04d/%02d/%02d_%02d:%02d:%02d", gps_latitude, gps_longitude, gps_altitude,
|
||||
gps_satellites, gps_hdop,
|
||||
gps_year, gps_month, gps_day,
|
||||
gps_hour, gps_minutes, gps_second);
|
||||
dataFile.printf(";%d;%d", batt_voltage, low_battery_flag);
|
||||
dataFile.printf("\n");
|
||||
|
||||
dataFile.close();
|
||||
}
|
||||
SERIAL_PORT.printf("Data writen : %s\n", path);
|
||||
}
|
||||
|
||||
void writeLightningToSD(int type, time_t t, int dist, int energy) {
|
||||
|
||||
char dir[20];
|
||||
char path[60];
|
||||
|
||||
String directory = dayDirectory();
|
||||
|
||||
directory.toCharArray(dir, sizeof(directory));
|
||||
sprintf(path, "%s/%s", dir, lightning_log_file);
|
||||
|
||||
// Test to know if the file exists before opening it, if it doesn't exist
|
||||
// we will write first an header
|
||||
bool no_header = SD.exists(path);
|
||||
|
||||
// open the file. note that only one file can be open at a time,
|
||||
// so you have to close this one before opening another.
|
||||
File dataFile = SD.open(path, FILE_WRITE);
|
||||
|
||||
// if the file is available, write to it:
|
||||
if (dataFile) {
|
||||
if (!no_header) {
|
||||
SERIAL_PORT.printf("Creating file with CSV header : %s\n", path);
|
||||
dataFile.printf("Date");
|
||||
dataFile.printf(";distance(km);energie_raw");
|
||||
dataFile.printf(";TotalLightningCount;TotalPerturbationEvents;TotalNoiseDetection;TotalUnknownDetection");
|
||||
dataFile.printf(";BME280_Pressure(hPa);BME280_Temperature(degC);BME280_Altitude(m)");
|
||||
// dataFile.printf(";DHT22_Humidity(%);DHT22_Temperature(degC)");
|
||||
dataFile.printf("\n");
|
||||
}
|
||||
dataFile.printf("%04d/%02d/%02d_%02d:%02d:%02d", year(t), month(t), day(t), hour(t), minute(t), second(t));
|
||||
dataFile.printf(";%d;%d;%d", type, dist, energy);
|
||||
dataFile.printf(";%d;%d;%d;%d", lightning_nb_total, as3935_perturb_total, as3935_noise_total, as3935_unknown_total);
|
||||
dataFile.printf(";%.2f;%.2f;%.1f", bme280_press, bme280_temp, bme280_alti);
|
||||
// dataFile.printf(";%.0f;%.2f", dht22_event_hum.relative_humidity, dht22_event_temp.temperature);
|
||||
dataFile.printf("\n");
|
||||
|
||||
dataFile.close();
|
||||
}
|
||||
SERIAL_PORT.printf("Data writen : %s\n", path);
|
||||
}
|
||||
|
||||
String dayDirectory() {
|
||||
|
||||
char dir[20] ;
|
||||
|
||||
sprintf(dir, "data/%04d/%02d/%02d/", year(), month(), day());
|
||||
|
||||
if (!SD.exists(dir))
|
||||
{
|
||||
SERIAL_PORT.printf("Creating directory : %s ...", dir);
|
||||
SD.mkdir(dir);
|
||||
SERIAL_PORT.printf(" DONE!\n");
|
||||
}
|
||||
|
||||
return String(dir);
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* CAMETEO project
|
||||
*
|
||||
* This is a personnal project of weather station with
|
||||
* automatic photo taking.
|
||||
* This code is the weather station part and is meant
|
||||
* to be run on a PJRC Teensy 3.2 board.
|
||||
*
|
||||
* Author : Arofarn
|
||||
*
|
||||
* Licence : GPL v3
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* LIBRARIES
|
||||
*/
|
||||
|
||||
//Protocols
|
||||
#include <Wire.h> // library used with I2C protocol
|
||||
#include <SPI.h> // SPI protocol
|
||||
|
||||
//Teensy3.x Real Time Clock
|
||||
#include <TimeLib.h>
|
||||
|
||||
//SD card
|
||||
#include <SD.h>
|
||||
|
||||
// Sensors
|
||||
#include <Adafruit_Sensor.h> // Generic
|
||||
//#include <DHT.h> // DHT22
|
||||
//#include <DHT_U.h> // DHT22 unified
|
||||
//#include <Adafruit_BMP085_U.h> // BMP180
|
||||
#include <Adafruit_BME280.h> // BME280
|
||||
#include <PWFusion_AS3935.h>
|
||||
|
||||
//GPS
|
||||
//#include <Adafruit_GPS.h> // Adafruit Ultimate GPS
|
||||
#include <TinyGPS.h> //Builtin GPS lib
|
||||
|
||||
/*
|
||||
* DEFINE
|
||||
* &
|
||||
* DECLARE
|
||||
*/
|
||||
|
||||
//Special characteres
|
||||
#define DEGREE (char)176 //degree symbol in ISO 8859-1
|
||||
#define DEGREE_LCD (char)222 //degree symbol for lcd display
|
||||
|
||||
// Pins used
|
||||
#define RX1_PIN 0 // Raspberry Pi2 serial comm. - Hard wired
|
||||
#define TX1_PIN 1 // Raspberry Pi2 serial comm. - Hard wired
|
||||
#define RPI_PWR_PIN 2 // Raspberry Pi power control - Hard wired
|
||||
#define SD_CS_PIN 4 // SPI SD CS - Hard wired
|
||||
#define GPS_EN_PIN 6 // GPS ENable
|
||||
#define RX3_PIN 7 // GPS serial comm.
|
||||
#define TX3_PIN 8 // GPS serial comm.
|
||||
#define AS3935_IRQ_PIN 9 // Interrupts from AS3935 lightning sensor
|
||||
#define AS3935_CS_PIN 10 // SPI CS AS3935 lightning sensor
|
||||
#define SPI_DI_PIN 11 // SPI MOSI AS3935 lightning sensor
|
||||
#define SPI_DO_PIN 12 // SPI MISO AS3935 lightning sensor
|
||||
#define SPI_CK_PIN 13 // SPI clock SD + AS3935 lightning sensor + built-in LED
|
||||
//#define DHT_PIN 14 // Humidity sensor data
|
||||
#define GPS_BUT_PIN 16 // GPS switch power control
|
||||
|
||||
#define I2C_SDA_PIN 18 // I2C SDA
|
||||
#define I2C_SCL_PIN 19 // I2C SCL
|
||||
|
||||
#define BATT_VOLT_PIN 22 // Battery voltage monitoring (Analog Input)
|
||||
#define LOW_BATT_PIN 23 // Low Battery signal from charger (digital input)
|
||||
|
||||
//I2C addresses
|
||||
//#define TCN75A_ADDR 0x00 //Sensor I2C bus address
|
||||
#define BMP180_ADDR 0x77
|
||||
//#define BME280_ADDR 0x00 // ???
|
||||
|
||||
//Serial over USB communication
|
||||
#define SERIAL_PORT Serial
|
||||
#define SERIAL_BAUD_RATE 9600
|
||||
|
||||
//Raspberry Pi Serial Comm.
|
||||
#define RPI_SERIAL_PORT Serial1
|
||||
#define RPI_SERIAL_BAUD_RATE 115200
|
||||
|
||||
//GPS
|
||||
#define GPS_SERIAL_PORT Serial3
|
||||
#define GPS_SERIAL_BAUD_RATE 9600
|
||||
|
||||
// AS3935 Lightning sensor
|
||||
#define AS3935_INDOORS 0
|
||||
#define AS3935_OUTDOORS 1
|
||||
#define AS3935_DIST_DIS 0
|
||||
#define AS3935_DIST_EN 1
|
||||
#define AS3935_CAPACITANCE 72 // 72pF for THIS board (from seller)
|
||||
|
||||
|
||||
Executable
+553
@@ -0,0 +1,553 @@
|
||||
/*
|
||||
* CAMETEO project
|
||||
*
|
||||
* This is a personnal project of weather station with
|
||||
* automatic photo taking.
|
||||
* This code is the weather station part and is meant
|
||||
* to be run on a PJRC Teensy 3.2 board.
|
||||
*
|
||||
* Author : Arofarn
|
||||
*
|
||||
* Licence : GPL v3
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* LIBRARIES
|
||||
*/
|
||||
|
||||
//Protocols
|
||||
#include <Wire.h> // library used with I2C protocol
|
||||
#include <SPI.h> // SPI protocol
|
||||
|
||||
//Teensy3.x Real Time Clock
|
||||
#include <TimeLib.h>
|
||||
|
||||
//SD card
|
||||
#include <SD.h>
|
||||
|
||||
// Sensors
|
||||
#include <Adafruit_Sensor.h> // Generic
|
||||
#include <Adafruit_BME280.h> // BME280
|
||||
#include <PWFusion_AS3935.h>
|
||||
|
||||
//GPS
|
||||
//#include <Adafruit_GPS.h> // Adafruit Ultimate GPS
|
||||
#include <TinyGPS.h> //Builtin GPS lib
|
||||
|
||||
/*
|
||||
* DEFINE
|
||||
* &
|
||||
* DECLARE
|
||||
*/
|
||||
|
||||
//Special characteres
|
||||
#define DEGREE (char)176 //degree symbol in ISO 8859-1
|
||||
#define DEGREE_LCD (char)222 //degree symbol for lcd display
|
||||
|
||||
// Pins used
|
||||
#define RX1_PIN 0 // Raspberry Pi2 serial comm. - Hard wired
|
||||
#define TX1_PIN 1 // Raspberry Pi2 serial comm. - Hard wired
|
||||
#define RPI_PWR_PIN 2 // Raspberry Pi power control - Hard wired
|
||||
#define AS3935_CS_PIN 4 // SPI SD CS - Hard wired
|
||||
#define GPS_EN_PIN 6 // GPS ENable
|
||||
#define RX3_PIN 7 // GPS serial comm.
|
||||
#define TX3_PIN 8 // GPS serial comm.
|
||||
#define AS3935_IRQ_PIN 9 // Interrupts from AS3935 lightning sensor
|
||||
#define SD_CS_PIN 10 // SPI CS AS3935 lightning sensor
|
||||
#define SPI_DI_PIN 11 // SPI MOSI AS3935 lightning sensor
|
||||
#define SPI_DO_PIN 12 // SPI MISO AS3935 lightning sensor
|
||||
#define SPI_CK_PIN 13 // SPI clock SD + AS3935 lightning sensor + built-in LED
|
||||
#define BATT_VOLT_PIN 16 // Battery voltage monitoring (Analog Input)
|
||||
#define LOW_BATT_PIN 17 // Low Battery signal from charger (digital input)
|
||||
#define I2C_SDA_PIN 18 // I2C SDA BME280 sensor
|
||||
#define I2C_SCL_PIN 19 // I2C SCL BME280 sensor
|
||||
#define GPS_BUT_PIN 20 // GPS switch power control (unused)
|
||||
|
||||
//I2C addresses
|
||||
//#define TCN75A_ADDR 0x00 //Sensor I2C bus address
|
||||
//#define BMP180_ADDR 0x77
|
||||
|
||||
//Serial over USB communication
|
||||
#define SERIAL_PORT Serial
|
||||
#define SERIAL_BAUD_RATE 9600
|
||||
|
||||
//Raspberry Pi Serial Comm.
|
||||
#define RPI_SERIAL_PORT Serial1
|
||||
#define RPI_SERIAL_BAUD_RATE 9600
|
||||
|
||||
//GPS
|
||||
#define GPS_SERIAL_PORT Serial3
|
||||
#define GPS_SERIAL_BAUD_RATE 9600
|
||||
|
||||
//Sensors
|
||||
Adafruit_BME280 bme;
|
||||
float seaLevelPressure = SENSORS_PRESSURE_SEALEVELHPA;
|
||||
float bme280_press;
|
||||
float bme280_temp;
|
||||
float bme280_alti;
|
||||
float bme280_humi;
|
||||
|
||||
// AS3935 Lightning sensor
|
||||
#define AS3935_INDOORS 0
|
||||
#define AS3935_OUTDOORS 1
|
||||
#define AS3935_DIST_DIS 0
|
||||
#define AS3935_DIST_EN 1
|
||||
#define AS3935_CAPACITANCE 72 // 72pF for THIS board (from seller)
|
||||
enum strike_sources { UNKNOWN_SRC, LIGHTNING, PERTURBATION, NOISE };
|
||||
volatile int8_t AS3935_ISR_Trig = 0; // Trigger for AS3935 lightning sensor
|
||||
|
||||
void AS3935_ISR() {
|
||||
AS3935_ISR_Trig = 1;
|
||||
}
|
||||
|
||||
PWF_AS3935 lightning(AS3935_CS_PIN, AS3935_IRQ_PIN, 33);
|
||||
|
||||
int as3935_src;
|
||||
int as3935_distance;
|
||||
long lightning_nb_total = 0;
|
||||
int lightning_nb_hour = 0;
|
||||
int lightning_nb_day = 0;
|
||||
int as3935_perturb_total = 0;
|
||||
int as3935_noise_total = 0;
|
||||
int as3935_unknown_total = 0;
|
||||
char lightning_log_file[12] = "lghtnng.log";
|
||||
|
||||
//GPS
|
||||
//Adafruit_GPS GPS(&GPS_SERIAL_PORT);
|
||||
TinyGPS GPS;
|
||||
float gps_latitude, gps_longitude, gps_altitude; // returns +- latitude/longitude in degrees
|
||||
float gps_speed, gps_course;
|
||||
unsigned long gps_time, gps_date, gps_fix_age;
|
||||
int gps_year;
|
||||
byte gps_month, gps_day, gps_hour, gps_minutes, gps_second, gps_hundreths;
|
||||
unsigned long gps_chars, gps_hdop;
|
||||
unsigned short gps_sentences, gps_failed_checksum, gps_satellites;
|
||||
|
||||
//Miscellaneous
|
||||
bool rpi_status = true;
|
||||
int batt_voltage;
|
||||
bool low_battery_flag = false;
|
||||
|
||||
// Tasks timers
|
||||
elapsedMillis since_bme280;
|
||||
elapsedMillis since_gps;
|
||||
elapsedMillis since_display;
|
||||
elapsedMillis since_serial_send;
|
||||
elapsedMillis since_sd_log;
|
||||
elapsedMillis since_batt_chk;
|
||||
|
||||
|
||||
void BootMessage(String s) {
|
||||
char c[13]; // char buffer for conversion String->char
|
||||
s.toCharArray(c, sizeof(s));
|
||||
SERIAL_PORT.printf("%-12s", c);
|
||||
}
|
||||
|
||||
void BootOK() {
|
||||
SERIAL_PORT.println("OK");
|
||||
}
|
||||
|
||||
void BootError() {
|
||||
SERIAL_PORT.println("EE");
|
||||
}
|
||||
|
||||
void sendDataOnSerial() {
|
||||
|
||||
//Print date & hour on serial port
|
||||
SERIAL_PORT.printf("%04d/%02d/%02d_%02d:%02d:%02d\n", year(), month(), day(), hour(), minute(), second());
|
||||
|
||||
//if (bme280_event.pressure) {
|
||||
SERIAL_PORT.printf("Temperature:%8.2f %cC | Pressure: %8.2f hPa | Altitude:%8.2f m\n",
|
||||
bme280_temp, DEGREE, bme280_press, bme280_alti);
|
||||
// }
|
||||
// else {
|
||||
// SERIAL_PORT.printf("BMP180 Sensor error\n");
|
||||
// }
|
||||
|
||||
SERIAL_PORT.printf("Lightning strikes (from start) : %d | Perturb.: %d | Noise : %d | Unknown detect.: %d\n", lightning_nb_total,
|
||||
as3935_perturb_total,
|
||||
as3935_noise_total,
|
||||
as3935_unknown_total);
|
||||
|
||||
//SERIAL_PORT.printf("Temperature:%8.2f %cC\n", tcn75a_temp, DEGREE);
|
||||
|
||||
SERIAL_PORT.printf("GPS data: %04d/%02d/%02d_%02d:%02d:%02d (%d)\n", gps_year, gps_month, gps_day,
|
||||
gps_hour, gps_minutes, gps_second,
|
||||
gps_fix_age);
|
||||
SERIAL_PORT.printf(" Latitude: %11.8f | Longitude: %11.8f | Altitude: %5.2f m\n", gps_latitude, gps_longitude, gps_altitude);
|
||||
SERIAL_PORT.printf(" Speed: %4.1f km/h | Course : %4.1f %c\n", gps_speed, gps_course, DEGREE);
|
||||
SERIAL_PORT.printf(" Chars: %11d | Sentences: %11d | Failed cheksum: %4d\n", gps_chars, gps_sentences, gps_failed_checksum);
|
||||
|
||||
SERIAL_PORT.printf("Battery : %10d mV | Low Battery : %d\n", batt_voltage, low_battery_flag);
|
||||
}
|
||||
|
||||
|
||||
bool isStartedPI() {
|
||||
//Return true if the R-Pi respond to an simple request
|
||||
return rpi_status;
|
||||
}
|
||||
|
||||
void startRPI() {
|
||||
//Start the Raspberry Pi via the MOSFET (grid connected to the RPI_PWR_PIN)
|
||||
if (!isStartedPI()) {
|
||||
pinMode(RPI_PWR_PIN, OUTPUT);
|
||||
digitalWrite(RPI_PWR_PIN, LOW);
|
||||
rpi_status = true;
|
||||
}
|
||||
}
|
||||
|
||||
void stopRPI() {
|
||||
//Stop the Raspberry Pi via the MOSFET (grid connected to the RPI_PWR_PIN)
|
||||
|
||||
pinMode(RPI_PWR_PIN, INPUT); //Eteint via le MOSFET
|
||||
rpi_status = false;
|
||||
}
|
||||
|
||||
void sendDataToRPI() {
|
||||
//if (isStartedPI()) {
|
||||
//Print date & hour on serial port
|
||||
RPI_SERIAL_PORT.printf("%04d/%02d/%02d_%02d:%02d:%02d\n", year(), month(), day(), hour(), minute(), second());
|
||||
|
||||
//if (bme280_event.pressure) {
|
||||
RPI_SERIAL_PORT.printf("Temperature:%8.2f %cC | Pressure: %8.2f hPa | Altitude:%8.2f m\n",
|
||||
bme280_temp, DEGREE, bme280_press, bme280_alti);
|
||||
//}
|
||||
//else {
|
||||
// RPI_SERIAL_PORT.printf("BMP180 Sensor error\n");
|
||||
//}
|
||||
|
||||
RPI_SERIAL_PORT.printf("Lightning strikes (from start) : %d | Perturb.: %d | Noise : %d | Unknown detect.: %d\n", lightning_nb_total,
|
||||
as3935_perturb_total,
|
||||
as3935_noise_total,
|
||||
as3935_unknown_total);
|
||||
|
||||
RPI_SERIAL_PORT.printf("GPS data: %04d/%02d/%02d_%02d:%02d:%02d (%d)\n", gps_year, gps_month, gps_day,
|
||||
gps_hour, gps_minutes, gps_second,
|
||||
gps_fix_age);
|
||||
RPI_SERIAL_PORT.printf(" Latitude: %11.8f | Longitude: %11.8f | Altitude: %5.2f m\n", gps_latitude, gps_longitude, gps_altitude);
|
||||
RPI_SERIAL_PORT.printf(" Speed: %4.1f km/h | Course : %4.1f %c\n", gps_speed, gps_course, DEGREE);
|
||||
RPI_SERIAL_PORT.printf(" Chars: %11d | Sentences: %11d | Failed cheksum: %4d\n", gps_chars, gps_sentences, gps_failed_checksum);
|
||||
|
||||
RPI_SERIAL_PORT.printf("Battery : %10d mV | Low Battery : %d\n", batt_voltage, low_battery_flag);
|
||||
// }
|
||||
// else {
|
||||
// //error RPI is not started
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
//SD Card
|
||||
#define CONFIGFILE "config.txt"
|
||||
|
||||
//Configuration
|
||||
char data_file[13] = "datalog.csv";
|
||||
|
||||
//Delays
|
||||
|
||||
unsigned int bme280_delay = 500;
|
||||
//unsigned int dht_delay = 3000;
|
||||
unsigned int gps_delay = 100;
|
||||
unsigned int serial_send_delay = 5000;
|
||||
unsigned int sd_log_delay = 5000;
|
||||
unsigned int batt_chk_delay = 5000;
|
||||
|
||||
//Date and time
|
||||
int TZ = 1; //Time zone
|
||||
|
||||
/*
|
||||
* SETUP
|
||||
*/
|
||||
|
||||
void setup() {
|
||||
|
||||
//To be sure Raspberry-Pi won't be turned on unexpectedly
|
||||
stopRPI();
|
||||
|
||||
pinMode(LOW_BATT_PIN, INPUT_PULLUP);
|
||||
low_battery_flag = !digitalRead(LOW_BATT_PIN);
|
||||
|
||||
pinMode(GPS_BUT_PIN, INPUT_PULLUP);
|
||||
pinMode(GPS_EN_PIN, OUTPUT);
|
||||
gps_power();
|
||||
|
||||
SERIAL_PORT.begin(SERIAL_BAUD_RATE);
|
||||
delay(1000);
|
||||
//while (!SERIAL_PORT) { }; //Wait for serial port to start
|
||||
SERIAL_PORT.printf("Serial Comm. OK\nNow booting...\n");
|
||||
|
||||
RPI_SERIAL_PORT.begin(RPI_SERIAL_BAUD_RATE);
|
||||
delay(1000);
|
||||
//while (!RPI_SERIAL_PORT) { }; //Wait for serial port to start
|
||||
RPI_SERIAL_PORT.printf("Raspberry's Serial Comm. OK\nNow booting...\n");
|
||||
|
||||
BootMessage("SDcard");
|
||||
// see if the card is present and can be initialized:
|
||||
if (!SD.begin(SD_CS_PIN)) {
|
||||
BootError();
|
||||
while(1);
|
||||
}
|
||||
BootOK();
|
||||
|
||||
BootMessage("RT Clock");
|
||||
// set the Time library to use Teensy 3.0's RTC to keep time
|
||||
setSyncProvider(getTeensy3Time);
|
||||
if (timeStatus()!= timeSet) {
|
||||
BootError();
|
||||
while(1);
|
||||
}
|
||||
BootOK();
|
||||
|
||||
|
||||
BootMessage("BME280 (Pressure, Humidity and Temperature)");
|
||||
/* Initialise the sensor */
|
||||
// if(!bme.begin())
|
||||
// {
|
||||
// /* There was a problem detecting the BMP085 ... check your connections */
|
||||
// BootError();
|
||||
// while(1);
|
||||
// }
|
||||
BootOK();
|
||||
|
||||
BootMessage("AS3935 (Lightning)");
|
||||
SPI.begin();
|
||||
SPI.setClockDivider(SPI_CLOCK_DIV16); // SPI speed to SPI_CLOCK_DIV16/1MHz (max 2MHz, NEVER 500kHz!)
|
||||
SPI.setDataMode(SPI_MODE1); // MAX31855 is a Mode 1 device --> clock starts low, read on rising edge
|
||||
SPI.setBitOrder(MSBFIRST); // data sent to chip MSb first
|
||||
lightning.AS3935_DefInit(); // set registers to default
|
||||
// now update sensor cal for your application and power up chip
|
||||
lightning.AS3935_ManualCal(AS3935_CAPACITANCE, AS3935_OUTDOORS, AS3935_DIST_EN);
|
||||
// enable interrupt (hook IRQ pin to Arduino Uno/Mega interrupt input: 0 -> pin 2, 1 -> pin 3 )
|
||||
attachInterrupt(AS3935_IRQ_PIN, AS3935_ISR, RISING);
|
||||
BootOK();
|
||||
|
||||
BootMessage("GPS");
|
||||
GPS_SERIAL_PORT.begin(GPS_SERIAL_BAUD_RATE);
|
||||
while (!GPS_SERIAL_PORT) {} ;
|
||||
BootOK();
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* LOOP
|
||||
*/
|
||||
|
||||
void loop() {
|
||||
|
||||
//Power ON/OFF GPS
|
||||
gps_power();
|
||||
|
||||
//Lightning detection
|
||||
if (AS3935_ISR_Trig != 0) {
|
||||
AS3935_ISR_Trig = 0;
|
||||
time_t t = now();
|
||||
int distance = -9999;
|
||||
int energy = -9999;
|
||||
switch (as3935_src) {
|
||||
case UNKNOWN_SRC:
|
||||
//source inconnue
|
||||
as3935_unknown_total++;
|
||||
SERIAL_PORT.printf("Interruption (AS3935) : unkown source (not lightning)\n");
|
||||
break;
|
||||
case LIGHTNING:
|
||||
//Foudre !!!
|
||||
lightning_nb_total++;
|
||||
distance = lightning.AS3935_GetLightningDistKm();
|
||||
energy = lightning.AS3935_GetStrikeEnergyRaw();
|
||||
SERIAL_PORT.printf("Interruption (AS3935) : Lightningbolt !!!\n");
|
||||
SERIAL_PORT.printf("Distance : %4d km | Energy : %d \n", distance, energy);
|
||||
break;
|
||||
case PERTURBATION:
|
||||
//Perturbation
|
||||
as3935_perturb_total++;
|
||||
SERIAL_PORT.printf("Interruption (AS3935) : perturbation...\n");
|
||||
break;
|
||||
case NOISE:
|
||||
//Trop de bruit électromagnétique
|
||||
as3935_noise_total++;
|
||||
SERIAL_PORT.printf("Interruption (AS3935) : Too much electromagnetic noise!\n");
|
||||
break;
|
||||
}
|
||||
writeLightningToSD(as3935_src, t, distance, energy);
|
||||
}
|
||||
|
||||
if (since_batt_chk >= batt_chk_delay) {
|
||||
since_batt_chk -= batt_chk_delay;
|
||||
//Check battery status and voltage
|
||||
low_battery_flag = !digitalRead(LOW_BATT_PIN);
|
||||
batt_voltage = getBatteryVoltage();
|
||||
}
|
||||
|
||||
// if (since_bme280 >= bme280_delay) {
|
||||
// since_bme280 = since_bme280 - bme280_delay;
|
||||
//
|
||||
// bme280_press = bme.readPressure() / 100.0F;
|
||||
// bme280_alti = bme.readAltitude(seaLevelPressure);
|
||||
// bme280_temp = bme.readTemperature();
|
||||
// bme280_humi = bme.readHumidity();
|
||||
// }
|
||||
|
||||
if (since_gps >= gps_delay) {
|
||||
since_gps = since_gps - gps_delay;
|
||||
while (GPS_SERIAL_PORT.available()) {
|
||||
char c = GPS_SERIAL_PORT.read();
|
||||
if (GPS.encode(c)) {
|
||||
GPS.get_datetime(&gps_date, &gps_time, &gps_fix_age);
|
||||
GPS.crack_datetime(&gps_year, &gps_month, &gps_day,
|
||||
&gps_hour, &gps_minutes, &gps_second,
|
||||
&gps_hundreths, &gps_fix_age);
|
||||
GPS.f_get_position(&gps_latitude, &gps_longitude, &gps_fix_age);
|
||||
gps_altitude = GPS.f_altitude();
|
||||
gps_speed = GPS.f_speed_kmph();
|
||||
GPS.stats(&gps_chars, &gps_sentences, &gps_failed_checksum);
|
||||
gps_satellites = GPS.satellites();
|
||||
gps_hdop = GPS.hdop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (since_sd_log >= sd_log_delay) {
|
||||
since_sd_log = since_sd_log - sd_log_delay;
|
||||
writeDataToSD();
|
||||
}
|
||||
|
||||
if (since_serial_send >= serial_send_delay) {
|
||||
since_serial_send = since_serial_send - serial_send_delay;
|
||||
sendDataOnSerial();
|
||||
sendDataToRPI();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* FUNCTIONS
|
||||
*/
|
||||
|
||||
time_t getTeensy3Time() {
|
||||
return Teensy3Clock.get();
|
||||
}
|
||||
|
||||
void gps_power() {
|
||||
if (digitalRead(GPS_BUT_PIN) == 0) { digitalWrite(GPS_EN_PIN, LOW); }
|
||||
else { digitalWrite(GPS_EN_PIN, HIGH); }
|
||||
}
|
||||
|
||||
int getBatteryVoltage() {
|
||||
long mean = 0;
|
||||
int U = 0;
|
||||
int n = 10;
|
||||
int res = 12;
|
||||
|
||||
analogReadResolution(res);
|
||||
|
||||
for (int i=0; i<n; i++) {
|
||||
mean += analogRead(BATT_VOLT_PIN);
|
||||
//delay(2);
|
||||
}
|
||||
mean /= n;
|
||||
|
||||
U = map(mean, 0, pow(2, res)-1, 0, 3300); // Convert data from ADC into input voltage in mV
|
||||
U *= 2; //Multiple by 2 for the voltage divider
|
||||
|
||||
return U;
|
||||
}
|
||||
|
||||
void writeDataToSD() {
|
||||
|
||||
char dir[20];
|
||||
char path[60];
|
||||
|
||||
String directory = dayDirectory();
|
||||
|
||||
directory.toCharArray(dir, sizeof(directory));
|
||||
sprintf(path, "%s/%s", dir, data_file);
|
||||
|
||||
// Test to know if the file exists before opening it, if it doesn't exist
|
||||
// we will write first an header
|
||||
bool no_header = SD.exists(path);
|
||||
|
||||
// open the file. note that only one file can be open at a time,
|
||||
// so you have to close this one before opening another.
|
||||
File dataFile = SD.open(path, FILE_WRITE);
|
||||
|
||||
// if the file is available, write to it:
|
||||
if (dataFile) {
|
||||
if (!no_header) {
|
||||
SERIAL_PORT.printf("Creating file with CSV header : %s\n", path);
|
||||
dataFile.printf("Date");
|
||||
dataFile.printf(";BME280_Pressure(hPa);BME280_Temperature(degC);BME280_Humidity(%);BME280_Altitude(m)");
|
||||
dataFile.printf(";TotalLightningCount;TotalPerturbationEvents;TotalNoiseDetection;TotalUnknownDetection");
|
||||
dataFile.printf(";GPS_Latitude;GPS_Longitude;GPS_Altitude;GPS_Satellites;GPS_HDOP;GPS_Date");
|
||||
dataFile.printf(";Battery_voltage(mV);Low_Battery_Status");
|
||||
dataFile.printf("\n");
|
||||
}
|
||||
dataFile.printf("%04d/%02d/%02d_%02d:%02d:%02d", year(), month(), day(), hour(), minute(), second());
|
||||
dataFile.printf(";%.2f;%.2f;%.0f;%.1f", bme280_press, bme280_temp, bme280_humi, bme280_alti);
|
||||
dataFile.printf(";%d;%d;%d;%d", lightning_nb_total, as3935_perturb_total, as3935_noise_total, as3935_unknown_total);
|
||||
dataFile.printf(";%.8f;%.8f;%.2f;%d;%d;%04d/%02d/%02d_%02d:%02d:%02d", gps_latitude, gps_longitude, gps_altitude,
|
||||
gps_satellites, gps_hdop,
|
||||
gps_year, gps_month, gps_day,
|
||||
gps_hour, gps_minutes, gps_second);
|
||||
dataFile.printf(";%d;%d", batt_voltage, low_battery_flag);
|
||||
dataFile.printf("\n");
|
||||
|
||||
dataFile.close();
|
||||
}
|
||||
SERIAL_PORT.printf("Data writen : %s\n", path);
|
||||
}
|
||||
|
||||
void writeLightningToSD(int type, time_t t, int dist, int energy) {
|
||||
|
||||
char dir[20];
|
||||
char path[60];
|
||||
|
||||
String directory = dayDirectory();
|
||||
|
||||
directory.toCharArray(dir, sizeof(directory));
|
||||
sprintf(path, "%s/%s", dir, lightning_log_file);
|
||||
|
||||
// Test to know if the file exists before opening it, if it doesn't exist
|
||||
// we will write first an header
|
||||
bool no_header = SD.exists(path);
|
||||
|
||||
// open the file. note that only one file can be open at a time,
|
||||
// so you have to close this one before opening another.
|
||||
File dataFile = SD.open(path, FILE_WRITE);
|
||||
|
||||
// if the file is available, write to it:
|
||||
if (dataFile) {
|
||||
if (!no_header) {
|
||||
SERIAL_PORT.printf("Creating file with CSV header : %s\n", path);
|
||||
dataFile.printf("Date");
|
||||
dataFile.printf(";distance(km);energie_raw");
|
||||
dataFile.printf(";TotalLightningCount;TotalPerturbationEvents;TotalNoiseDetection;TotalUnknownDetection");
|
||||
dataFile.printf(";BME280_Pressure(hPa);BME280_Temperature(degC);BME280_Humidty(%);BME280_Altitude(m)");
|
||||
dataFile.printf("\n");
|
||||
}
|
||||
dataFile.printf("%04d/%02d/%02d_%02d:%02d:%02d", year(t), month(t), day(t), hour(t), minute(t), second(t));
|
||||
dataFile.printf(";%d;%d;%d", type, dist, energy);
|
||||
dataFile.printf(";%d;%d;%d;%d", lightning_nb_total, as3935_perturb_total, as3935_noise_total, as3935_unknown_total);
|
||||
dataFile.printf(";%.2f;%.2f;%.0f;%.1f", bme280_press, bme280_temp, bme280_humi, bme280_alti);
|
||||
dataFile.printf("\n");
|
||||
|
||||
dataFile.close();
|
||||
}
|
||||
SERIAL_PORT.printf("Data writen : %s\n", path);
|
||||
}
|
||||
|
||||
String dayDirectory() {
|
||||
|
||||
char dir[20] ;
|
||||
|
||||
sprintf(dir, "data/%04d/%02d/%02d/", year(), month(), day());
|
||||
|
||||
if (!SD.exists(dir))
|
||||
{
|
||||
SERIAL_PORT.printf("Creating directory : %s ...", dir);
|
||||
SD.mkdir(dir);
|
||||
SERIAL_PORT.printf(" DONE!\n");
|
||||
}
|
||||
|
||||
return String(dir);
|
||||
}
|
||||
|
||||
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Reference in New Issue
Block a user