|
@@ -7,6 +7,7 @@
|
|
|
#include "SD.h"
|
|
#include "SD.h"
|
|
|
#include "SPI.h"
|
|
#include "SPI.h"
|
|
|
#include "Arduino.h"
|
|
#include "Arduino.h"
|
|
|
|
|
+#include "math.h"
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
|
Uncomment and set up if you want to use custom pins for the SPI communication
|
|
Uncomment and set up if you want to use custom pins for the SPI communication
|
|
@@ -17,6 +18,7 @@ int mosi = -1;
|
|
|
int cs = -1;
|
|
int cs = -1;
|
|
|
*/
|
|
*/
|
|
|
|
|
|
|
|
|
|
+// Inicia I2C en pines default ESP32 (21 SDA, 22 SCL)
|
|
|
#define SCREEN_WIDTH 128 // Ancho píxeles
|
|
#define SCREEN_WIDTH 128 // Ancho píxeles
|
|
|
#define SCREEN_HEIGHT 64 // Alto píxeles
|
|
#define SCREEN_HEIGHT 64 // Alto píxeles
|
|
|
#define OLED_RESET -1 // Reset pin (no usado)
|
|
#define OLED_RESET -1 // Reset pin (no usado)
|
|
@@ -29,33 +31,36 @@ int cs = -1;
|
|
|
#define DHTPIN 4 // Digital pin connected to the DHT sensor
|
|
#define DHTPIN 4 // Digital pin connected to the DHT sensor
|
|
|
#define DHTTYPE DHT22
|
|
#define DHTTYPE DHT22
|
|
|
|
|
|
|
|
-// Objeto TinyGPS++
|
|
|
|
|
-TinyGPSPlus gps;
|
|
|
|
|
|
|
+#define BUTTON_PIN 27 // pin para pulsador
|
|
|
|
|
|
|
|
-// Serial para GPS
|
|
|
|
|
-HardwareSerial gpsSerial(2);
|
|
|
|
|
|
|
+//definicion de tiempos de pulsacion
|
|
|
|
|
+#define PULASCION_LARGA_MS 2000
|
|
|
|
|
+#define DURACION_WATCHDOG_MS 10000
|
|
|
|
|
|
|
|
-// Configuracion del DHT
|
|
|
|
|
-DHT dht(DHTPIN, DHTTYPE);
|
|
|
|
|
|
|
+#define MEASUREMENT_INTERVAL_S 1 //separación entre mediciones (s)
|
|
|
|
|
|
|
|
-//definición del objeto para la pantalla OLED
|
|
|
|
|
-Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
|
|
|
|
|
|
|
+#define DEG2RAD (M_PI/180.0)
|
|
|
|
|
|
|
|
-// pin para pulsador
|
|
|
|
|
|
|
|
|
|
-#define BUTTON_PIN 0
|
|
|
|
|
|
|
+// Objeto TinyGPS++
|
|
|
|
|
+TinyGPSPlus gps;
|
|
|
|
|
+HardwareSerial gpsSerial(2); // Usar UART2
|
|
|
|
|
+DHT dht(DHTPIN, DHTTYPE);
|
|
|
|
|
+Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
|
|
|
|
|
|
|
|
//valores de los sensores
|
|
//valores de los sensores
|
|
|
|
|
|
|
|
struct SensorData {
|
|
struct SensorData {
|
|
|
- double latitude;
|
|
|
|
|
- double longitude;
|
|
|
|
|
- float temperature;
|
|
|
|
|
- float humidity;
|
|
|
|
|
- float pressure;
|
|
|
|
|
|
|
+ double latitude = 0.0;
|
|
|
|
|
+ double longitude = 0.0;
|
|
|
|
|
+ float temperature = 0.0;
|
|
|
|
|
+ float humidity = 0.0;
|
|
|
|
|
+ float pressure = 0.0;
|
|
|
|
|
+ float altura = 0.0;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
SensorData latestData;
|
|
SensorData latestData;
|
|
|
|
|
+SensorData datosAntiguos;
|
|
|
|
|
|
|
|
SemaphoreHandle_t dataMutex; // Mutex para proteger el acceso a latestData
|
|
SemaphoreHandle_t dataMutex; // Mutex para proteger el acceso a latestData
|
|
|
SemaphoreHandle_t buttonSemaphore; // Semáforo para la tarea del botón
|
|
SemaphoreHandle_t buttonSemaphore; // Semáforo para la tarea del botón
|
|
@@ -63,17 +68,22 @@ SemaphoreHandle_t buttonSemaphore; // Semáforo para la tarea del botón
|
|
|
//flag para reducir las lecturas de DHT y presion
|
|
//flag para reducir las lecturas de DHT y presion
|
|
|
uint8_t readSensorsFlag = 0;
|
|
uint8_t readSensorsFlag = 0;
|
|
|
|
|
|
|
|
-//definicion de tiempos de pulsacion
|
|
|
|
|
-#define PULASCION_LARGA_MS 2000
|
|
|
|
|
-#define DURACION_WATCHDOG_MS 10000
|
|
|
|
|
-
|
|
|
|
|
-bool grabando = 0; //inicia apagado
|
|
|
|
|
|
|
+bool grabando = false; //inicia apagado
|
|
|
TaskHandle_t medicionesHandle = NULL; //para suspend/resume
|
|
TaskHandle_t medicionesHandle = NULL; //para suspend/resume
|
|
|
-#define X 1 //separación entre mediciones (s)
|
|
|
|
|
int pantallaEstado = 0; //maquina de estados
|
|
int pantallaEstado = 0; //maquina de estados
|
|
|
|
|
+float distancia_total = 0.0;
|
|
|
|
|
|
|
|
-float distancia_total = 0;
|
|
|
|
|
|
|
+char filename[13];
|
|
|
|
|
|
|
|
|
|
+void OLED_print(const String& line1, const String& line2) {
|
|
|
|
|
+ display.clearDisplay();
|
|
|
|
|
+ display.setTextSize(2);
|
|
|
|
|
+ display.setTextColor(SSD1306_WHITE);
|
|
|
|
|
+ display.setCursor(0, 0);
|
|
|
|
|
+ display.println(line1);
|
|
|
|
|
+ display.println(line2);
|
|
|
|
|
+ display.display();
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
void DHT_test() {
|
|
void DHT_test() {
|
|
|
dht.begin();
|
|
dht.begin();
|
|
@@ -82,13 +92,15 @@ void DHT_test() {
|
|
|
if (isnan(h) || isnan(t)) {
|
|
if (isnan(h) || isnan(t)) {
|
|
|
Serial.println("Failed to read from DHT sensor!");
|
|
Serial.println("Failed to read from DHT sensor!");
|
|
|
OLED_print("DHT22", "Error");
|
|
OLED_print("DHT22", "Error");
|
|
|
- while(1); // Detener si hay error
|
|
|
|
|
|
|
+ delay(5000);
|
|
|
|
|
+ DHT_test(); // Reintentar
|
|
|
}
|
|
}
|
|
|
else OLED_print("DHT22", "Correcto");
|
|
else OLED_print("DHT22", "Correcto");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void OLED_test() { //pantallazo a blanco y luego iniciando
|
|
void OLED_test() { //pantallazo a blanco y luego iniciando
|
|
|
// Inicia I2C en pines default ESP32 (21 SDA, 22 SCL)
|
|
// Inicia I2C en pines default ESP32 (21 SDA, 22 SCL)
|
|
|
|
|
+ Wire.begin();
|
|
|
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Dirección común: 0x3C
|
|
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Dirección común: 0x3C
|
|
|
Serial.println(F("Error: OLED no encontrado!"));
|
|
Serial.println(F("Error: OLED no encontrado!"));
|
|
|
for (;;); // Para siempre
|
|
for (;;); // Para siempre
|
|
@@ -106,39 +118,47 @@ void OLED_test() { //pantallazo a blanco y luego iniciando
|
|
|
delay(1000);
|
|
delay(1000);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void OLED_print(const char* line1, const char* line2) {
|
|
|
|
|
- display.clearDisplay();
|
|
|
|
|
- display.setTextSize(2);
|
|
|
|
|
- display.setTextColor(SSD1306_WHITE);
|
|
|
|
|
- display.setCursor(0, 0);
|
|
|
|
|
- display.println(line1);
|
|
|
|
|
- display.println(line2);
|
|
|
|
|
- display.display();
|
|
|
|
|
-}
|
|
|
|
|
|
|
|
|
|
-char* SD_test() {
|
|
|
|
|
- if (!SD.begin()) {
|
|
|
|
|
|
|
+void SD_test(){
|
|
|
|
|
+if (!SD.begin()) {
|
|
|
Serial.println("SD Card Mount Failed");
|
|
Serial.println("SD Card Mount Failed");
|
|
|
- OLED_print("SD Card", "Error\nInserte tarjeta");
|
|
|
|
|
- while(!SD.begin()); // Detener si hay error
|
|
|
|
|
|
|
+ OLED_print("SD Card", "Error\nInserte");
|
|
|
|
|
+ while (!SD.begin());
|
|
|
OLED_print("SD Card", "Insertada");
|
|
OLED_print("SD Card", "Insertada");
|
|
|
- }
|
|
|
|
|
- else OLED_print("SD Card", "Correcto");
|
|
|
|
|
|
|
+ } else {
|
|
|
|
|
+ OLED_print("SD Card", "Correcto");
|
|
|
|
|
+ Serial.println("SD Card initialized.");
|
|
|
|
|
+ }
|
|
|
|
|
+ uint8_t cardType = SD.cardType();
|
|
|
|
|
+ if (cardType == CARD_NONE) {
|
|
|
|
|
+ Serial.println("No SD card attached");
|
|
|
|
|
+ OLED_print("SD Card", "No detectada");
|
|
|
|
|
+ while (cardType == CARD_NONE) {
|
|
|
|
|
+ delay(1000);
|
|
|
|
|
+ cardType = SD.cardType();
|
|
|
|
|
+ }
|
|
|
|
|
+ OLED_print("SD Card", "Detectada");
|
|
|
|
|
+ }
|
|
|
|
|
+ uint8_t cardSize = SD.cardSize() / (1024 * 1024);
|
|
|
|
|
+ Serial.printf("SD Card Size: %uMB\n", cardSize);
|
|
|
|
|
|
|
|
- char filename[] = "data001.txt";
|
|
|
|
|
int num = 1;
|
|
int num = 1;
|
|
|
- // Buscar un nombre de archivo disponible
|
|
|
|
|
- while(SD.exists(filename)) {
|
|
|
|
|
|
|
+ sprintf(filename, "/data%03d.txt", num);
|
|
|
|
|
+ while (SD.exists(filename)) {
|
|
|
|
|
+ Serial.printf("File %s already exists. Trying next.\n", filename);
|
|
|
num++;
|
|
num++;
|
|
|
- sprintf(filename, "data%03d.txt", num);
|
|
|
|
|
|
|
+ sprintf(filename, "/data%03d.txt", num);
|
|
|
}
|
|
}
|
|
|
|
|
+ Serial.printf("Using file: %s\n", filename);
|
|
|
|
|
|
|
|
File file = SD.open(filename, FILE_WRITE);
|
|
File file = SD.open(filename, FILE_WRITE);
|
|
|
- file.Println("Latitud,Longitud,Temperatura,Humedad,Presión")
|
|
|
|
|
- file.close();
|
|
|
|
|
-
|
|
|
|
|
- return filename;
|
|
|
|
|
-
|
|
|
|
|
|
|
+ if (file) {
|
|
|
|
|
+ Serial.println("File created successfully");
|
|
|
|
|
+ file.println("Latitud,Longitud,Temperatura,Humedad,Presion");
|
|
|
|
|
+ file.close();
|
|
|
|
|
+ } else {
|
|
|
|
|
+ Serial.println("Error creando archivo");
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void GPS_test_wait() {
|
|
void GPS_test_wait() {
|
|
@@ -157,144 +177,156 @@ void GPS_test_wait() {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
float calcular_delta_dist(float lat1, float long1, float lat2, float long2){
|
|
float calcular_delta_dist(float lat1, float long1, float lat2, float long2){
|
|
|
- float R = 6371;
|
|
|
|
|
- float delta_lat = lat2 - lat1;
|
|
|
|
|
- float delta_long = long2 - long1;
|
|
|
|
|
- float a = sin(delta_lat/2)ˆ2+cos(lat1)*cos(lat2)*sin(delta_long/2)ˆ2;
|
|
|
|
|
|
|
+ float R = 6371.0; // Radio de la Tierra en km
|
|
|
|
|
+ float delta_lat = (lat2 - lat1) * DEG2RAD;
|
|
|
|
|
+ float delta_long = (long2 - long1) * DEG2RAD;
|
|
|
|
|
+ lat1 = lat1 * DEG2RAD;
|
|
|
|
|
+ lat2 = lat2 * DEG2RAD;
|
|
|
|
|
+ float a = sin(delta_lat/2)*sin(delta_lat/2)+cos(lat1)*cos(lat2)*sin(delta_long/2)*sin(delta_long/2);
|
|
|
float c = 2 * atan2(sqrt(a),sqrt(1-a));
|
|
float c = 2 * atan2(sqrt(a),sqrt(1-a));
|
|
|
- return float d = R * c;
|
|
|
|
|
|
|
+ return R * c; //En km
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void task_mediciones(void *pvParameters) {
|
|
void task_mediciones(void *pvParameters) {
|
|
|
TickType_t xLastWakeTime = xTaskGetTickCount();
|
|
TickType_t xLastWakeTime = xTaskGetTickCount();
|
|
|
- const char* filename = (const char*) pvParameters;
|
|
|
|
|
- SensorData datosAntiguos;
|
|
|
|
|
while(1) {
|
|
while(1) {
|
|
|
-
|
|
|
|
|
// se leen los valores antes de utilizar el semaphore
|
|
// se leen los valores antes de utilizar el semaphore
|
|
|
while (gpsSerial.available() > 0) {
|
|
while (gpsSerial.available() > 0) {
|
|
|
gps.encode(gpsSerial.read());
|
|
gps.encode(gpsSerial.read());
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
float new_latitude = gps.location.lat();
|
|
float new_latitude = gps.location.lat();
|
|
|
float new_longitude = gps.location.lng();
|
|
float new_longitude = gps.location.lng();
|
|
|
- if ((readSensorsFlag % 60) == 0) float new_temp = dht.readTemperature();
|
|
|
|
|
- if ((readSensorsFlag % 120) == 0) float new_hum = ddht.readHumidity();
|
|
|
|
|
|
|
+ float new_temp = (readSensorsFlag % 60 == 0) ? dht.readTemperature() : latestData.temperature;
|
|
|
|
|
+ float new_hum = (readSensorsFlag % 120 == 0) ? dht.readHumidity() : latestData.humidity;
|
|
|
float new_press = 0.0; // Placeholder, no hay sensor de presión
|
|
float new_press = 0.0; // Placeholder, no hay sensor de presión
|
|
|
|
|
|
|
|
|
|
+ if (gps.location.isValid() && datosAntiguos.latitude != 0.0) {
|
|
|
|
|
+ distancia_total += calcular_delta_dist(datosAntiguos.latitude, datosAntiguos.longitude, new_latitude, new_longitude);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- File file = SD.open(filename, FILE_WRITE);
|
|
|
|
|
- if (file) {
|
|
|
|
|
- // guardar datos en latestData
|
|
|
|
|
- if (xSemaphoreTake(dataMutex, portMAX_DELAY) == pdTRUE){
|
|
|
|
|
- latestData.latitude = new_latitude;
|
|
|
|
|
- latestData.longitude = new_longitude;
|
|
|
|
|
- latestData.temperature = new_temp;
|
|
|
|
|
- latestData.humidity = new_hum;
|
|
|
|
|
- latestData.pressure = new_press;
|
|
|
|
|
- }
|
|
|
|
|
- distancia_total += calcular_delta_dist(new_latitude, new_longitude, datosAntiguos.latitude, datosAntiguos.longitude);
|
|
|
|
|
|
|
+ if (xSemaphoreTake(dataMutex, portMAX_DELAY) == pdTRUE) {
|
|
|
|
|
+ latestData.latitude = new_latitude;
|
|
|
|
|
+ latestData.longitude = new_longitude;
|
|
|
|
|
+ latestData.temperature = new_temp;
|
|
|
|
|
+ latestData.humidity = new_hum;
|
|
|
|
|
+ latestData.pressure = new_press;
|
|
|
datosAntiguos = latestData;
|
|
datosAntiguos = latestData;
|
|
|
xSemaphoreGive(dataMutex);
|
|
xSemaphoreGive(dataMutex);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
-
|
|
|
|
|
|
|
+ File file = SD.open(filename, FILE_APPEND);
|
|
|
|
|
+ if (file) {
|
|
|
//Crear la string para escribir en el archivo
|
|
//Crear la string para escribir en el archivo
|
|
|
- char frase = String(datosAntiguos.latitude) + "," +
|
|
|
|
|
|
|
+ String frase = String(datosAntiguos.latitude) + "," +
|
|
|
String(datosAntiguos.longitude) + "," +
|
|
String(datosAntiguos.longitude) + "," +
|
|
|
String(datosAntiguos.temperature) + "," +
|
|
String(datosAntiguos.temperature) + "," +
|
|
|
String(datosAntiguos.humidity) + "," +
|
|
String(datosAntiguos.humidity) + "," +
|
|
|
String(datosAntiguos.pressure);
|
|
String(datosAntiguos.pressure);
|
|
|
|
|
|
|
|
-
|
|
|
|
|
// Escribir datos en el archivo
|
|
// Escribir datos en el archivo
|
|
|
file.println(frase);
|
|
file.println(frase);
|
|
|
-
|
|
|
|
|
file.close();
|
|
file.close();
|
|
|
- if (!(readSensorsFlag % 120)) readSensorsFlag = 0;
|
|
|
|
|
- readSensorsFlag++;
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(X*1000)); // Espera x*1000 milisegundos
|
|
|
|
|
|
|
+ if (!(readSensorsFlag % 120)) readSensorsFlag = 0;
|
|
|
|
|
+ readSensorsFlag++;
|
|
|
|
|
+
|
|
|
|
|
+ vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(MEASUREMENT_INTERVAL_S*1000)); // Espera x*1000 milisegundos
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void IRAM_ATTR isr_button() {
|
|
void IRAM_ATTR isr_button() {
|
|
|
static unsigned long lastInterrupt = 0;
|
|
static unsigned long lastInterrupt = 0;
|
|
|
if ((millis() - lastInterrupt) > 200 ){ // debounce de 200 ms
|
|
if ((millis() - lastInterrupt) > 200 ){ // debounce de 200 ms
|
|
|
|
|
+ BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
|
|
xSemaphoreGiveFromISR(buttonSemaphore, NULL);
|
|
xSemaphoreGiveFromISR(buttonSemaphore, NULL);
|
|
|
- lastInterrupt = mmillis();
|
|
|
|
|
|
|
+ lastInterrupt = millis();
|
|
|
|
|
+ if (xHigherPriorityTaskWoken) {
|
|
|
|
|
+ portYIELD_FROM_ISR();
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void task_ui(void *pvParameters){
|
|
void task_ui(void *pvParameters){
|
|
|
unsigned long pressTime = 0;
|
|
unsigned long pressTime = 0;
|
|
|
- unsigned long lastActivity = 0;
|
|
|
|
|
|
|
+ unsigned long lastActivity = millis();
|
|
|
bool pantallaOn = true; //comprobar el estado inicial, no se cual sera
|
|
bool pantallaOn = true; //comprobar el estado inicial, no se cual sera
|
|
|
|
|
|
|
|
while(1){
|
|
while(1){
|
|
|
- if (xSemaphoreTake(buttonSemaphore, portMAX_DELAY) == pdTRUE){ //button pressed
|
|
|
|
|
|
|
+ if (xSemaphoreTake(buttonSemaphore, pdMS_TO_TICKS(200)) == pdTRUE){ //button pressed
|
|
|
pressTime = millis();
|
|
pressTime = millis();
|
|
|
- lastActivity = millis();
|
|
|
|
|
|
|
|
|
|
if (!pantallaOn){
|
|
if (!pantallaOn){
|
|
|
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
|
|
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
|
|
|
pantallaOn = true;
|
|
pantallaOn = true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ bool timed_out = false;
|
|
|
while (digitalRead(BUTTON_PIN) == LOW){
|
|
while (digitalRead(BUTTON_PIN) == LOW){
|
|
|
vTaskDelay(pdMS_TO_TICKS(10));
|
|
vTaskDelay(pdMS_TO_TICKS(10));
|
|
|
- if ((millis() - lastActivity) > DURACION_WATCHDOG_MS){
|
|
|
|
|
- //WATCHDOG 'activo' solo funciona si se mantiene presionado el boton ese tiempo
|
|
|
|
|
|
|
+ if ((millis() - pressTime) > DURACION_WATCHDOG_MS){ //10s timeout para evitar bloqueos
|
|
|
|
|
+ timed_out = true;
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- unsigned long duration = millis() - pressTime;
|
|
|
|
|
-
|
|
|
|
|
- if (duration >= PULASCION_LARGA_MS){
|
|
|
|
|
- //pulsacion larga: cabia entre grabacion y no grabacion de datos
|
|
|
|
|
- grabando != grabando;
|
|
|
|
|
- if (grabando){
|
|
|
|
|
- vTaskResume(medicionesHandle);
|
|
|
|
|
- //Mostrar que empieza la grabación
|
|
|
|
|
- OLED_print("Ruta","iniciada");
|
|
|
|
|
- } else {
|
|
|
|
|
- vTaskSuspend(medicionesHandle);
|
|
|
|
|
- //Mostrar que se pausa/finaliza la grabación
|
|
|
|
|
- OLED_print("Ruta","pausada");
|
|
|
|
|
- }
|
|
|
|
|
|
|
+
|
|
|
|
|
+ if (timed_out){
|
|
|
|
|
+ OLED_print("Apagando","pantalla");
|
|
|
|
|
+ delay(1000);
|
|
|
|
|
+ display.ssd1306_command(SSD1306_DISPLAYOFF); //se apaga la
|
|
|
|
|
+ pantallaOn = false;
|
|
|
} else {
|
|
} else {
|
|
|
- //Pulsacion corta + grabando datos, cicla datos
|
|
|
|
|
- if (grabando) {
|
|
|
|
|
- pantallaEstado = (pantallaEstado + 1) % 3; //cicla entre 0-2
|
|
|
|
|
- SensorData currentData;
|
|
|
|
|
- if(xSemaphoreTake(dataMutex, portMAX_DELAY) == pdTRUE){
|
|
|
|
|
- currentData = latestData;
|
|
|
|
|
- xSemaphoreGive(dataMutex);
|
|
|
|
|
|
|
+
|
|
|
|
|
+ unsigned long duration = millis() - pressTime;
|
|
|
|
|
+
|
|
|
|
|
+ if (duration >= PULASCION_LARGA_MS){
|
|
|
|
|
+ //pulsacion larga: cabia entre grabacion y no grabacion de datos
|
|
|
|
|
+ grabando != grabando;
|
|
|
|
|
+ if (grabando){
|
|
|
|
|
+ vTaskResume(medicionesHandle);
|
|
|
|
|
+ //Mostrar que empieza la grabación
|
|
|
|
|
+ OLED_print("Ruta","iniciada");
|
|
|
|
|
+ } else {
|
|
|
|
|
+ vTaskSuspend(medicionesHandle);
|
|
|
|
|
+ //Mostrar que se pausa/finaliza la grabación
|
|
|
|
|
+ OLED_print("Ruta","pausada");
|
|
|
}
|
|
}
|
|
|
- switch (pantallaEstado){
|
|
|
|
|
- case 0:
|
|
|
|
|
- OLED_print("Posicion",String(currentData.longitude)+","+String(currentData.latitude));
|
|
|
|
|
- break;
|
|
|
|
|
- case 1:
|
|
|
|
|
- OLED_print("Distancia",String(distancia_total)+"km");
|
|
|
|
|
- break;
|
|
|
|
|
- case 2:
|
|
|
|
|
- OLED_print("Altitud",String(currentData.pressure)+"m");
|
|
|
|
|
- break;
|
|
|
|
|
|
|
+ } else {
|
|
|
|
|
+ //Pulsacion corta + grabando datos, cicla datos
|
|
|
|
|
+ if (grabando) {
|
|
|
|
|
+ pantallaEstado = (pantallaEstado + 1) % 3; //cicla entre 0-2
|
|
|
|
|
+ SensorData currentData;
|
|
|
|
|
+ if(xSemaphoreTake(dataMutex, portMAX_DELAY) == pdTRUE){
|
|
|
|
|
+ currentData = latestData;
|
|
|
|
|
+ xSemaphoreGive(dataMutex);
|
|
|
|
|
+ }
|
|
|
|
|
+ switch (pantallaEstado){
|
|
|
|
|
+ case 0:
|
|
|
|
|
+ OLED_print("Posicion",String(currentData.longitude) + "," + String(currentData.latitude));
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 1:
|
|
|
|
|
+ OLED_print("Distancia",String(distancia_total)+"km");
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 2:
|
|
|
|
|
+ OLED_print("Altitud",String(gps.altitude.meters(), 1)+"m");
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
} else {
|
|
} else {
|
|
|
- OLED_print("Grabación","pausada");
|
|
|
|
|
|
|
+ OLED_print("Grabacion","pausada");
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
}
|
|
}
|
|
|
- lastActivity = mmillis(); //reset watchdog
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- //check watchdog fuera del boton
|
|
|
|
|
- if (pantallaOn && ((millis() - lastActivity) > DURACION_WATCHDOG_MS)){
|
|
|
|
|
- display.ssd1306_command(SSD1306_DISPLAYOFF); //se apaga la pantalla
|
|
|
|
|
- pantallaOn = false;
|
|
|
|
|
|
|
+
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+ lastActivity = millis(); //reset watchdog
|
|
|
|
|
+ }
|
|
|
|
|
+ //check watchdog fuera del boton
|
|
|
|
|
+ if (pantallaOn && ((millis() - lastActivity) > DURACION_WATCHDOG_MS)){
|
|
|
|
|
+ display.ssd1306_command(SSD1306_DISPLAYOFF); //se apaga la pantalla
|
|
|
|
|
+ pantallaOn = false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
vTaskDelay(pdMS_TO_TICKS(100)); //pequeño delay para no busy waiting
|
|
vTaskDelay(pdMS_TO_TICKS(100)); //pequeño delay para no busy waiting
|
|
@@ -305,15 +337,21 @@ void task_ui(void *pvParameters){
|
|
|
void setup() {
|
|
void setup() {
|
|
|
Serial.begin(115200);
|
|
Serial.begin(115200);
|
|
|
|
|
|
|
|
|
|
+ pinMode(BUTTON_PIN, INPUT_PULLUP);
|
|
|
|
|
+ attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), isr_button, FALLING);
|
|
|
|
|
+
|
|
|
|
|
+ buttonSemaphore = xSemaphoreCreateBinary();
|
|
|
|
|
+ dataMutex = xSemaphoreCreateMutex();
|
|
|
|
|
+
|
|
|
// OLED check
|
|
// OLED check
|
|
|
OLED_test();
|
|
OLED_test();
|
|
|
- delay(500);
|
|
|
|
|
|
|
+ delay(1000);
|
|
|
// DHT check
|
|
// DHT check
|
|
|
DHT_test();
|
|
DHT_test();
|
|
|
- delay(500);
|
|
|
|
|
|
|
+ delay(1000);
|
|
|
// SD Card check
|
|
// SD Card check
|
|
|
- char *filename = SD_test();
|
|
|
|
|
- delay(500);
|
|
|
|
|
|
|
+ SD_test();
|
|
|
|
|
+ delay(1000);
|
|
|
// GPS check
|
|
// GPS check
|
|
|
GPS_test_wait();
|
|
GPS_test_wait();
|
|
|
delay(2000);
|
|
delay(2000);
|
|
@@ -323,7 +361,7 @@ void setup() {
|
|
|
task_mediciones, // Función de la tarea
|
|
task_mediciones, // Función de la tarea
|
|
|
"Mediciones", // Nombre de la tarea
|
|
"Mediciones", // Nombre de la tarea
|
|
|
2048, // Tamaño del stack
|
|
2048, // Tamaño del stack
|
|
|
- (void*)filename, // Parámetro de la tarea
|
|
|
|
|
|
|
+ NULL, // Parámetro de la tarea
|
|
|
10, // Prioridad de la tarea
|
|
10, // Prioridad de la tarea
|
|
|
&medicionesHandle, // Handle de la tarea
|
|
&medicionesHandle, // Handle de la tarea
|
|
|
0 // Núcleo donde se ejecuta
|
|
0 // Núcleo donde se ejecuta
|
|
@@ -339,6 +377,8 @@ void setup() {
|
|
|
1 // Núcleo donde se ejecuta
|
|
1 // Núcleo donde se ejecuta
|
|
|
);
|
|
);
|
|
|
|
|
|
|
|
|
|
+ vTaskSuspend(medicionesHandle); //inicia suspendida
|
|
|
|
|
+
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|