|
|
@@ -7,7 +7,6 @@
|
|
|
#include "SD.h"
|
|
|
#include "SPI.h"
|
|
|
#include "Arduino.h"
|
|
|
-//#include "FreeRTOS.h"
|
|
|
|
|
|
/*
|
|
|
Uncomment and set up if you want to use custom pins for the SPI communication
|
|
|
@@ -64,6 +63,17 @@ SemaphoreHandle_t buttonSemaphore; // Semáforo para la tarea del botón
|
|
|
//flag para reducir las lecturas de DHT y presion
|
|
|
uint8_t readSensorsFlag = 0;
|
|
|
|
|
|
+//definicion de tiempos de pulsacion
|
|
|
+#define PULASCION_LARGA_MS 2000
|
|
|
+#define DURACION_WATCHDOG_MS 10000
|
|
|
+
|
|
|
+bool grabando = 0; //inicia apagado
|
|
|
+TaskHandle_t medicionesHandle = NULL; //para suspend/resume
|
|
|
+#define X 1 //separación entre mediciones (s)
|
|
|
+int pantallaEstado = 0; //maquina de estados
|
|
|
+
|
|
|
+float distancia_total = 0;
|
|
|
+
|
|
|
|
|
|
void DHT_test() {
|
|
|
dht.begin();
|
|
|
@@ -124,6 +134,7 @@ char* SD_test() {
|
|
|
}
|
|
|
|
|
|
File file = SD.open(filename, FILE_WRITE);
|
|
|
+ file.Println("Latitud,Longitud,Temperatura,Humedad,Presión")
|
|
|
file.close();
|
|
|
|
|
|
return filename;
|
|
|
@@ -145,61 +156,148 @@ void GPS_test_wait() {
|
|
|
OLED_print("GPS", "Encontrado");
|
|
|
}
|
|
|
|
|
|
+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 c = 2 * atan2(sqrt(a),sqrt(1-a));
|
|
|
+ return float d = R * c;
|
|
|
+}
|
|
|
|
|
|
void task_mediciones(void *pvParameters) {
|
|
|
TickType_t xLastWakeTime = xTaskGetTickCount();
|
|
|
const char* filename = (const char*) pvParameters;
|
|
|
+ SensorData datosAntiguos;
|
|
|
while(1) {
|
|
|
-
|
|
|
+
|
|
|
+ // se leen los valores antes de utilizar el semaphore
|
|
|
while (gpsSerial.available() > 0) {
|
|
|
gps.encode(gpsSerial.read());
|
|
|
}
|
|
|
+ float new_latitude = gps.location.lat();
|
|
|
+ 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_press = 0.0; // Placeholder, no hay sensor de presión
|
|
|
+
|
|
|
+
|
|
|
File file = SD.open(filename, FILE_WRITE);
|
|
|
if (file) {
|
|
|
// guardar datos en latestData
|
|
|
if (xSemaphoreTake(dataMutex, portMAX_DELAY) == pdTRUE){
|
|
|
- latestData.latitude = gps.location.lat();
|
|
|
- latestData.longitude = gps.location.lng();
|
|
|
- if ((readSensorsFlag % 60) == 0) latestData.temperature = dht.readTemperature();
|
|
|
- if ((readSensorsFlag % 120) == 0) latestData.humidity = dht.readHumidity();
|
|
|
- latestData.pressure = 0.0; // Placeholder, no hay sensor de presión
|
|
|
+ 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);
|
|
|
+ datosAntiguos = latestData;
|
|
|
+ xSemaphoreGive(dataMutex);
|
|
|
+
|
|
|
+
|
|
|
+ //Crear la string para escribir en el archivo
|
|
|
+ char frase = String(datosAntiguos.latitude) + "," +
|
|
|
+ String(datosAntiguos.longitude) + "," +
|
|
|
+ String(datosAntiguos.temperature) + "," +
|
|
|
+ String(datosAntiguos.humidity) + "," +
|
|
|
+ String(datosAntiguos.pressure);
|
|
|
|
|
|
+
|
|
|
// Escribir datos en el archivo
|
|
|
- file.println(String(latestData.latitude) + "," +
|
|
|
- String(latestData.longitude) + "," +
|
|
|
- String(latestData.temperature) + "," +
|
|
|
- String(latestData.humidity) + "," +
|
|
|
- String(latestData.pressure));
|
|
|
- xSemaphoreGive(dataMutex);
|
|
|
+ file.println(frase);
|
|
|
|
|
|
file.close();
|
|
|
if (!(readSensorsFlag % 120)) readSensorsFlag = 0;
|
|
|
readSensorsFlag++;
|
|
|
}
|
|
|
|
|
|
- vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(10000)); // Espera 1 segundo
|
|
|
+ vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(X*1000)); // Espera x*1000 milisegundos
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void IRAM_ATTR isr_button() {
|
|
|
- xSemaphoreGiveFromISR(buttonSemaphore, NULL);
|
|
|
+ static unsigned long lastInterrupt = 0;
|
|
|
+ if ((millis() - lastInterrupt) > 200 ){ // debounce de 200 ms
|
|
|
+ xSemaphoreGiveFromISR(buttonSemaphore, NULL);
|
|
|
+ lastInterrupt = mmillis();
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
|
|
|
void task_ui(void *pvParameters){
|
|
|
+ unsigned long pressTime = 0;
|
|
|
+ unsigned long lastActivity = 0;
|
|
|
+ bool pantallaOn = true; //comprobar el estado inicial, no se cual sera
|
|
|
+
|
|
|
while(1){
|
|
|
- if (xSemaphoreTake(buttonSemaphore, portMAX_DELAY) == pdTRUE){
|
|
|
-
|
|
|
- SensorData dataCopy;
|
|
|
- // Copiar datos protegidos por mutex
|
|
|
- if (xSemaphoreTake(dataMutex, portMAX_DELAY) == pdTRUE){
|
|
|
- dataCopy = latestData;
|
|
|
- xSemaphoreGive(dataMutex);
|
|
|
+ if (xSemaphoreTake(buttonSemaphore, portMAX_DELAY) == pdTRUE){ //button pressed
|
|
|
+ pressTime = millis();
|
|
|
+ lastActivity = millis();
|
|
|
+
|
|
|
+ if (!pantallaOn){
|
|
|
+ display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
|
|
|
+ pantallaOn = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ while (digitalRead(BUTTON_PIN) == LOW){
|
|
|
+ vTaskDelay(pdMS_TO_TICKS(10));
|
|
|
+ if ((millis() - lastActivity) > DURACION_WATCHDOG_MS){
|
|
|
+ //WATCHDOG 'activo' solo funciona si se mantiene presionado el boton ese tiempo
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- //Falta implementar la parte de UI con OLED
|
|
|
-
|
|
|
+ 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");
|
|
|
+ }
|
|
|
+ } 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(currentData.pressure)+"m");
|
|
|
+ break;
|
|
|
+ } else {
|
|
|
+ OLED_print("Grabación","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;
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
+
|
|
|
+ vTaskDelay(pdMS_TO_TICKS(100)); //pequeño delay para no busy waiting
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -226,17 +324,17 @@ void setup() {
|
|
|
"Mediciones", // Nombre de la tarea
|
|
|
2048, // Tamaño del stack
|
|
|
(void*)filename, // Parámetro de la tarea
|
|
|
- 1, // Prioridad de la tarea
|
|
|
- NULL, // Handle de la tarea
|
|
|
+ 10, // Prioridad de la tarea
|
|
|
+ &medicionesHandle, // Handle de la tarea
|
|
|
0 // Núcleo donde se ejecuta
|
|
|
);
|
|
|
|
|
|
xTaskCreatePinnedToCore(
|
|
|
task_ui, // Función de la tarea
|
|
|
"UI", // Nombre de la tarea
|
|
|
- 2048, // Tamaño del stack
|
|
|
+ 8192, // Tamaño del stack
|
|
|
NULL, // Parámetro de la tarea
|
|
|
- 1, // Prioridad de la tarea
|
|
|
+ 5, // Prioridad de la tarea
|
|
|
NULL, // Handle de la tarea
|
|
|
1 // Núcleo donde se ejecuta
|
|
|
);
|