mirror of
https://github.com/adrigongv23/G26---Telemetry-Software.git
synced 2026-08-25 11:33:17 +02:00
Telemetria WiFi+SD
This commit is contained in:
parent
7c069efa14
commit
4b58b1ec97
6 changed files with 181 additions and 152 deletions
|
|
@ -5,87 +5,101 @@
|
|||
DataProcessor dataProcessor;
|
||||
CAN canController;
|
||||
|
||||
// Objeto UDP para manejar la conexión UDP
|
||||
// SD
|
||||
SPIClass spiSD(HSPI);
|
||||
SdFat sd;
|
||||
SdFile logFile;
|
||||
|
||||
// UDP
|
||||
WiFiUDP udp;
|
||||
|
||||
//Envio de datos a través de UDP
|
||||
void TaskUdpSender(void *pvParameters){
|
||||
// --- Tarea UDP (Nucleo 0) ---
|
||||
void TaskUdpSender(void *pvParameters) {
|
||||
Serial.println("Iniciando tarea de envio UDP...");
|
||||
|
||||
Serial.println("Iniciando tarea de envío...");
|
||||
|
||||
while (true){
|
||||
if(WiFi.status() == WL_CONNECTED){
|
||||
|
||||
//Obtenemos los datos actuales
|
||||
while (true) {
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
int tempActual = dataProcessor.current_ect_value;
|
||||
int rpmActual = dataProcessor.current_rpm_value;
|
||||
float battActual = dataProcessor.current_vbatt_value;
|
||||
|
||||
float tpsActual = dataProcessor.current_tps_value;
|
||||
float frenoDelActual = dataProcessor.current_freno_del_value; // freno delantero (instalado)
|
||||
float frenoDelActual = dataProcessor.current_freno_del_value;
|
||||
float pcombActual = dataProcessor.current_pcomb_value;
|
||||
float taceiteActual = dataProcessor.current_taceite_value;
|
||||
float paceiteActual = dataProcessor.current_paceite_value;
|
||||
float mapActual = dataProcessor.current_map_value;
|
||||
float lambdaActual = dataProcessor.current_lambda_value;
|
||||
float lambdaObjActual = dataProcessor.current_lambda_obj_value;
|
||||
// Pendientes de montar/configurar en el coche. Cuando se instalen, descomentar aquí
|
||||
// y añadir su campo al snprintf; mientras no lleguen, el monitor los muestra como "--".
|
||||
//float velocidadActual = dataProcessor.current_velocidad_value;
|
||||
//float frenoTraActual = dataProcessor.current_freno_tra_value; // freno trasero
|
||||
|
||||
//Formato "clave=valor" separado por ';'
|
||||
char mensaje[256];
|
||||
snprintf(mensaje, sizeof(mensaje),
|
||||
"ect=%d;rpm=%d;vbatt=%.2f;tps=%.1f;freno_del=%.1f;"
|
||||
"pcomb=%.2f;taceite=%.1f;paceite=%.2f;map=%.1f;lambda=%.3f;lambda_obj=%.3f",
|
||||
tempActual, rpmActual, battActual, tpsActual, frenoDelActual,
|
||||
pcombActual, taceiteActual, paceiteActual, mapActual, lambdaActual, lambdaObjActual);
|
||||
// Al añadir los pendientes: sumar ";velocidad=%.0f;freno_tra=%.1f" al formato
|
||||
// y velocidadActual, frenoTraActual al final de los argumentos.
|
||||
|
||||
//Enviamos el paquete por broadcast a toda la red local (no hace falta conocer la IP del portátil)
|
||||
udp.beginPacket(IPAddress(255,255,255,255), UDP_PORT);
|
||||
udp.beginPacket(IPAddress(255, 255, 255, 255), UDP_PORT);
|
||||
udp.print(mensaje);
|
||||
udp.endPacket();
|
||||
|
||||
//Para comprobar que el paquete se está enviado correctamente podemos usar estos prints
|
||||
//Serial.print("UDP Enviado: ");
|
||||
//Serial.println(mensaje);
|
||||
}
|
||||
|
||||
else {
|
||||
//Si no hay Wifi o no se consigue conectar, lo intentamos reconectar
|
||||
} else {
|
||||
Serial.println("[WIFI] Desconectado...");
|
||||
WiFi.disconnect();
|
||||
WiFi.reconnect();
|
||||
}
|
||||
|
||||
//Ponemos de velocidad de envio 50ms, es ajustable
|
||||
vTaskDelay(50 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
delay(1000);
|
||||
Serial.println("\n--- G26 TELEMETRY: INICIO DE SISTEMA ---");
|
||||
|
||||
// 1. INICIAR CAN Y PANTALLA
|
||||
// Pasamos el puntero de dataProcessor al controlador CAN
|
||||
// 1. INICIALIZACION SD
|
||||
spiSD.begin(SD_SCK, SD_MISO, SD_MOSI, SD_CS);
|
||||
|
||||
if (!sd.begin(SdSpiConfig(SD_CS, DEDICATED_SPI, SD_SCK_MHZ(1), &spiSD))) {
|
||||
Serial.println("[FALLO] SD no detectada. El sistema continuara sin Datalogging.");
|
||||
} else {
|
||||
char filename[24];
|
||||
int session = 1;
|
||||
bool opened = false;
|
||||
|
||||
while (!opened && session < 100000) {
|
||||
snprintf(filename, sizeof(filename), "G26-%d.csv", session);
|
||||
if (logFile.open(filename, O_RDWR | O_CREAT | O_EXCL)) {
|
||||
opened = true;
|
||||
Serial.printf("[OK] Nueva sesion: %s\n", filename);
|
||||
} else {
|
||||
session++;
|
||||
}
|
||||
}
|
||||
|
||||
if (opened) {
|
||||
logFile.println("Time,ECT,RPM,TPS,VBATT,FRENO_DEL,PCOMB,TACEITE,PACEITE,MAP,LAMBDA,LAMBDA_OBJ");
|
||||
logFile.sync();
|
||||
} else {
|
||||
Serial.println("[ERROR] No se pudo abrir archivo de sesion");
|
||||
}
|
||||
}
|
||||
|
||||
dataProcessor.setLogSystem(&sd, &logFile);
|
||||
|
||||
// 2. INICIAR CAN
|
||||
canController.set_data_proccessor(&dataProcessor);
|
||||
canController.start();
|
||||
canController.start_listening_task();
|
||||
|
||||
// 2. INICIAR WIFI
|
||||
// 3. INICIAR WIFI
|
||||
Serial.println("--- CONECTANDO WIFI ---");
|
||||
|
||||
//IP estática dentro de la red del CPE (DHCP desactivado en el CPE)
|
||||
IPAddress local_IP(192, 168, 0, 50);
|
||||
IPAddress gateway(192, 168, 0, 254);
|
||||
IPAddress subnet(255, 255, 255, 0);
|
||||
|
||||
if (!WiFi.config(local_IP, gateway, subnet)) {
|
||||
Serial.println("[ERR] Fallo al configurar IP estática");
|
||||
Serial.println("[ERR] Fallo al configurar IP estatica");
|
||||
}
|
||||
|
||||
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
|
||||
|
|
@ -97,27 +111,26 @@ void setup() {
|
|||
intentos++;
|
||||
}
|
||||
|
||||
if(WiFi.status() == WL_CONNECTED){
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
Serial.println("\n[OK] WiFi Conectado.");
|
||||
} else {
|
||||
Serial.println("\n[ERR] No se pudo conectar WiFi (Continuando offline).");
|
||||
}
|
||||
|
||||
//Creamos la tarea UDP para el envio de datos
|
||||
//Usaremos el núcleo 1 o 0 ya que la ESP32 es Dual Core
|
||||
// 4. TAREA UDP
|
||||
xTaskCreatePinnedToCore(
|
||||
TaskUdpSender, // Función que debe de ejecutar
|
||||
"UdpSender", // Nombre de la tarea
|
||||
4096, // Stack size
|
||||
NULL, // Parámetros extras?
|
||||
1, // Prioridad (1 = Baja, 10 = Alta, la ponemos 1 ya que el CAN debe de tener más prioridad)
|
||||
NULL, // Handle
|
||||
0 // Núcleo
|
||||
TaskUdpSender,
|
||||
"UdpSender",
|
||||
4096,
|
||||
NULL,
|
||||
1,
|
||||
NULL,
|
||||
0
|
||||
);
|
||||
|
||||
Serial.println("OK CAN + UDP Sender ");
|
||||
Serial.println("[OK] Sistema ONLINE (CAN + SD + WiFi)");
|
||||
}
|
||||
|
||||
void loop(){
|
||||
void loop() {
|
||||
vTaskDelay(5 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
|
@ -6,15 +6,25 @@
|
|||
#include <ArduinoJson.h>
|
||||
#include <vector>
|
||||
|
||||
//Librerías WiFi y UDP ---
|
||||
// --- WiFi y UDP ---
|
||||
#include <WiFi.h>
|
||||
#include <WifiUdp.h>
|
||||
#include <WiFiUdp.h>
|
||||
|
||||
//CONFIGURACIÓN WIFI Y FIREBASE
|
||||
// --- SD ---
|
||||
#include <SPI.h>
|
||||
#include "SdFat.h"
|
||||
|
||||
// CONFIGURACION WIFI
|
||||
#define WIFI_SSID "FGades"
|
||||
#define WIFI_PASSWORD "GadesCPE"
|
||||
|
||||
//CONFIGURACIÓN WIFI Y FIREBASE
|
||||
// CONFIGURACION UDP
|
||||
#define UDP_PORT 4210
|
||||
|
||||
// CONFIGURACION SD (HSPI)
|
||||
#define SD_CS 25
|
||||
#define SD_MOSI 26
|
||||
#define SD_SCK 27
|
||||
#define SD_MISO 14
|
||||
|
||||
#endif
|
||||
|
|
@ -5,44 +5,53 @@
|
|||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
|
||||
class DataProcessor {
|
||||
public:
|
||||
DataProcessor() = default;
|
||||
|
||||
//Variables publicas para el CAN
|
||||
//Confirmadas: llegan en la trama 0
|
||||
// Variables CAN (actualizadas por los frames)
|
||||
volatile int current_ect_value = 0;
|
||||
volatile int current_rpm_value = 0;
|
||||
volatile float current_vbatt_value = 0.0;
|
||||
|
||||
volatile float current_tps_value = 0.0;
|
||||
volatile float current_freno_del_value = 0.0; // presion freno delantero, bar (instalado)
|
||||
volatile float current_pcomb_value = 0.0; // bar
|
||||
volatile float current_taceite_value = 0.0; // grados C
|
||||
volatile float current_paceite_value = 0.0; // bar
|
||||
volatile float current_map_value = 0.0; // kPa
|
||||
volatile float current_freno_del_value = 0.0;
|
||||
volatile float current_pcomb_value = 0.0;
|
||||
volatile float current_taceite_value = 0.0;
|
||||
volatile float current_paceite_value = 0.0;
|
||||
volatile float current_map_value = 0.0;
|
||||
volatile float current_lambda_value = 0.0;
|
||||
volatile float current_lambda_obj_value = 0.0;
|
||||
|
||||
// Pendientes de montar/configurar en el coche
|
||||
volatile float current_freno_tra_value = 0.0; // presion freno trasero, bar
|
||||
volatile float current_velocidad_value = 0.0; // km/h
|
||||
// Pendientes de instalar
|
||||
volatile float current_freno_tra_value = 0.0;
|
||||
volatile float current_velocidad_value = 0.0;
|
||||
|
||||
//Métodos de recepción de CAN
|
||||
// Configuracion SD
|
||||
void setLogSystem(SdFat* sd_inst, SdFile* file_inst) {
|
||||
_sd = sd_inst;
|
||||
_logFile = file_inst;
|
||||
}
|
||||
|
||||
// Metodos CAN
|
||||
void send_serial_frame_0(int rpmh, int rpml, int tpsh, int tpsl, int vbatth, int vbattl, int ect);
|
||||
void send_serial_frame_1(int lmbh, int lmbl, int lmbth, int lmbtl, int fuelh, int fuell, int gear);
|
||||
void send_serial_frame_2(int shut, int fan, int lmbch, int lmbcl, int brakeh, int brakel, int aux1);
|
||||
void send_serial_frame_3(int oilth, int oiltl, int oilph, int oilpl, int maph, int mapl, int dig1);
|
||||
void send_serial_frame_4(int dig3, int dig4, int dig5, int dig6, int dig7, int dig8, int dig9);
|
||||
|
||||
//Métodos extras
|
||||
void send_serial(byte type, unsigned int value);
|
||||
|
||||
char* process(std::vector<float> data);
|
||||
|
||||
private:
|
||||
SdFat* _sd = nullptr;
|
||||
SdFile* _logFile = nullptr;
|
||||
|
||||
uint32_t _last_sync_time = 0;
|
||||
const uint32_t _sync_interval_ms = 1000;
|
||||
|
||||
void flushToSD();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
* @file can.cpp
|
||||
* @author Raúl Arcos Herrera
|
||||
* @author Raul Arcos Herrera
|
||||
* @brief This file contains the implementation of the CAN Controller class for Link G4+ ECU.
|
||||
*/
|
||||
|
||||
|
|
@ -8,8 +8,7 @@
|
|||
|
||||
// Volcado en crudo de TODOS los mensajes del bus, a la velocidad a la que
|
||||
// llegan. Satura los 115200 baudios y frena la tarea de escucha, asi que solo
|
||||
// debe activarse para depurar el bus. Con esto a 1 no se leen las lineas
|
||||
// [TRAMA n] del data_processor, que son las utiles para localizar canales
|
||||
// debe activarse para depurar el bus.
|
||||
#define VOLCADO_CRUDO_CAN 0
|
||||
|
||||
static bool driver_installed = false;
|
||||
|
|
@ -47,7 +46,6 @@ void CAN::start() {
|
|||
return;
|
||||
}
|
||||
|
||||
// TWAI driver is now successfully installed and started
|
||||
driver_installed = true;
|
||||
}
|
||||
|
||||
|
|
@ -69,7 +67,7 @@ void CAN::start_listening_task() {
|
|||
"CAN_Listen_Task", // Task name
|
||||
4096, // Stack size (words)
|
||||
this, // Task parameter (this CAN instance)
|
||||
1, // Priority (lowered from 5 to 1)
|
||||
1, // Priority
|
||||
&_listen_task_handle // Task handle
|
||||
);
|
||||
|
||||
|
|
@ -88,7 +86,6 @@ void CAN::stop_listening_task() {
|
|||
if (_listen_task_handle != NULL) {
|
||||
_should_stop_listening = true;
|
||||
|
||||
// Wait for task to finish (max 1 second)
|
||||
for (int i = 0; i < 100; i++) {
|
||||
if (_listen_task_handle == NULL) {
|
||||
break;
|
||||
|
|
@ -96,7 +93,6 @@ void CAN::stop_listening_task() {
|
|||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
}
|
||||
|
||||
// Force delete if still running
|
||||
if (_listen_task_handle != NULL) {
|
||||
vTaskDelete(_listen_task_handle);
|
||||
_listen_task_handle = NULL;
|
||||
|
|
@ -128,21 +124,17 @@ twai_message_t CAN::createBoolMessage(bool b0, bool b1, bool b2, bool b3, bool b
|
|||
void CAN::listen() {
|
||||
Serial.println("CAN listening task started");
|
||||
|
||||
// Continuous loop for the thread
|
||||
while (!_should_stop_listening) {
|
||||
if (!driver_installed) {
|
||||
// Driver not installed
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if alert happened
|
||||
uint32_t alerts_triggered;
|
||||
twai_read_alerts(&alerts_triggered, 0); // Reduced timeout for more responsiveness
|
||||
twai_read_alerts(&alerts_triggered, 0);
|
||||
twai_status_info_t twaistatus;
|
||||
twai_get_status_info(&twaistatus);
|
||||
|
||||
// Handle alerts
|
||||
if (alerts_triggered & TWAI_ALERT_ERR_PASS) {
|
||||
Serial.println("Alert: TWAI controller has become error passive.");
|
||||
}
|
||||
|
|
@ -190,8 +182,6 @@ void CAN::listen() {
|
|||
Serial.println("");
|
||||
#endif
|
||||
if (!(message.rtr)) {
|
||||
|
||||
// Send to data processor based on first byte (maintaining original logic)
|
||||
switch (message.data[0]) {
|
||||
case 0:
|
||||
_data_processor->send_serial_frame_0(message.data[1], message.data[2], message.data[3], message.data[4], message.data[5], message.data[6], message.data[7]);
|
||||
|
|
@ -223,5 +213,5 @@ void CAN::listen() {
|
|||
|
||||
Serial.println("CAN listening task ending");
|
||||
_listen_task_handle = NULL;
|
||||
vTaskDelete(NULL); // Delete this task
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,76 +1,90 @@
|
|||
#include "../include/data_processor.hpp"
|
||||
|
||||
|
||||
char* DataProcessor::process(std::vector<float> data) {
|
||||
// Implementación del procesamiento de datos si es necesario
|
||||
return nullptr; // Placeholder
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void DataProcessor::send_serial(byte type, unsigned int value) { //Como parámetros se pasan el ID (type), que es el ID establecido al inicio del código para el dato que se quiera enviar. Ej: RPM_ID -> 0x51; y se envía el valor de dicho dato.
|
||||
byte dato[8] = { 0x5A, 0xA5, 0x05, 0x82, 0x00, 0x00, 0x00, 0x00 }; //Se establece un arreglo de bytes con los primeros datos necesarios para que la pantalla lo interprete como mensaje (En la Wiki hay tutoriales que lo explican a fondo), como ser la longitud y el tipo de mensaje.
|
||||
dato[4] = type; //Se configura en el mensaje el ID correspondiente al dato a enviar.
|
||||
dato[6] = (value >> 8) & 0xFF; //Se configura el dato en los últimos 2 bytes.
|
||||
void DataProcessor::send_serial(byte type, unsigned int value) {
|
||||
byte dato[8] = { 0x5A, 0xA5, 0x05, 0x82, 0x00, 0x00, 0x00, 0x00 };
|
||||
dato[4] = type;
|
||||
dato[6] = (value >> 8) & 0xFF;
|
||||
dato[7] = value & 0xFF;
|
||||
|
||||
Serial.write(dato, 8); //Se envía serialmente el mensaje, indicando su longituden bytes para ello.
|
||||
Serial.write(dato, 8);
|
||||
}
|
||||
|
||||
//RPM + TPS + vBatt + ECT
|
||||
void DataProcessor::send_serial_frame_0(int rpmh, int rpml, int tpsh, int tpsl, int vbatth, int vbattl, int ect){
|
||||
|
||||
//Calculos necesarios para obtener bien el formato de los valores necesarios
|
||||
// RPM + TPS + vBatt + ECT
|
||||
void DataProcessor::send_serial_frame_0(int rpmh, int rpml, int tpsh, int tpsl, int vbatth, int vbattl, int ect) {
|
||||
int rpm = (rpmh * 256) + rpml;
|
||||
double vbatt = ((vbatth * 256) + vbattl) / 100.0;
|
||||
int tps = (tpsh * 256) + tpsl;
|
||||
|
||||
//Serial.printf("TRAMA: 0\n");
|
||||
//Serial.printf("RPM: %d | VBATT: %f | TPS: %d | ECT: %d\n", rpm, vbatt, tps, ect);
|
||||
|
||||
// Actualizamos las variables globales para que puedan ser leidas por el protocolo UDP
|
||||
this->current_ect_value = ect;
|
||||
this->current_rpm_value = rpm;
|
||||
this->current_vbatt_value = vbatt;
|
||||
this->current_tps_value = tps;
|
||||
|
||||
flushToSD();
|
||||
}
|
||||
|
||||
|
||||
void DataProcessor::send_serial_frame_1(int lmbh, int lmbl, int lmbth, int lmbtl, int fuelh, int fuell, int gear){
|
||||
void DataProcessor::send_serial_frame_1(int lmbh, int lmbl, int lmbth, int lmbtl, int fuelh, int fuell, int gear) {
|
||||
float lambda = ((lmbh * 256) + lmbl) / 100.0;
|
||||
float lambdaTarget = ((lmbth * 256) + lmbtl) / 100.0;
|
||||
float presionComb = ((fuelh * 256) + fuell) / 100.0;
|
||||
|
||||
//Serial.printf("TRAMA: 1\n");
|
||||
//Serial.printf("LAMBDA: %f | LAMBDA TARGET: %f | PRESION COMBUSTIBLE: %f\n", lambda, lambdaTarget, presionComb);
|
||||
|
||||
this->current_lambda_value = lambda;
|
||||
this->current_lambda_obj_value = lambdaTarget;
|
||||
this->current_pcomb_value = presionComb;
|
||||
//this->current_marcha_value
|
||||
flushToSD();
|
||||
|
||||
}
|
||||
|
||||
void DataProcessor::send_serial_frame_2(int shut, int fan, int lmbch, int lmbcl, int brakeh, int brakel, int aux1){
|
||||
void DataProcessor::send_serial_frame_2(int shut, int fan, int lmbch, int lmbcl, int brakeh, int brakel, int aux1) {
|
||||
float freno = (brakeh * 256) + brakel;
|
||||
|
||||
//Serial.printf("TRAMA: 2\n");
|
||||
//Serial.printf("FRENO: %f\n", freno);
|
||||
|
||||
this->current_freno_del_value = freno;
|
||||
flushToSD();
|
||||
|
||||
}
|
||||
|
||||
void DataProcessor::send_serial_frame_3(int oilth, int oiltl, int oilph, int oilpl, int maph, int mapl, int dig1){
|
||||
void DataProcessor::send_serial_frame_3(int oilth, int oiltl, int oilph, int oilpl, int maph, int mapl, int dig1) {
|
||||
float tempOil = ((oilth * 256) + oiltl) / 100.0;
|
||||
float presionOil = ((oilph * 256) + oilpl) / 100.0;
|
||||
float map = ((maph * 256) + mapl) / 100.0;
|
||||
|
||||
//Serial.printf("TRAMA: 3\n");
|
||||
//Serial.printf("TEMP OIL: %f | PRESION OIL: %f | MAP: %f\n", tempOil, presionOil, map);
|
||||
|
||||
this->current_taceite_value = tempOil;
|
||||
this->current_paceite_value = presionOil;
|
||||
this->current_map_value = map;
|
||||
flushToSD();
|
||||
|
||||
}
|
||||
|
||||
void DataProcessor::send_serial_frame_4(int dig3, int dig4, int dig5, int dig6, int dig7, int dig8, int dig9){
|
||||
|
||||
void DataProcessor::send_serial_frame_4(int dig3, int dig4, int dig5, int dig6, int dig7, int dig8, int dig9) {
|
||||
}
|
||||
|
||||
// --- ESCRITURA SD ---
|
||||
|
||||
void DataProcessor::flushToSD() {
|
||||
if (_sd && _logFile && _logFile->isOpen()) {
|
||||
char buffer[256];
|
||||
int len = snprintf(buffer, sizeof(buffer),
|
||||
"%lu,%d,%d,%.1f,%.2f,%.1f,%.2f,%.1f,%.2f,%.1f,%.3f,%.3f\n",
|
||||
millis(),
|
||||
current_ect_value,
|
||||
current_rpm_value,
|
||||
current_tps_value,
|
||||
current_vbatt_value,
|
||||
current_freno_del_value,
|
||||
current_pcomb_value,
|
||||
current_taceite_value,
|
||||
current_paceite_value,
|
||||
current_map_value,
|
||||
current_lambda_value,
|
||||
current_lambda_obj_value);
|
||||
|
||||
_logFile->write(buffer, len);
|
||||
|
||||
if (millis() - _last_sync_time > _sync_interval_ms) {
|
||||
_logFile->sync();
|
||||
_last_sync_time = millis();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
# G26 Telemetria TFG
|
||||
|
||||
## Introducción del proyecto
|
||||
En este proyecto se desarollará para realizar mi TFG de Ingeniería Infórmatica, a la vez que lo usaremos para implementarlo en el equipo Formula Gades de la Universidad de Cádiz. El proyecto constará del desarrollo de una telemetría funcional, es decir, se recogerán datos en tiempo real que el monoplaza irá enviando para mostrarlos al equipo y a la vez se guardarán para posteriormente realizar un análisis exhaustivo.
|
||||
|
||||
|
||||
Además de la telemetría se desarrollará una página web para el equipo. Dicha página estará compuesta por un sistema de roles donde cada miembro tendrá unos accesos y restricciones especificadas. La web recogerá diferentes apartados básicos en el día a día del equipo, ya sea facturas, contabilidad, inventario... Además tendrá un apartado gráfico-visual para que los responsables puedan subir la telemetría mediante un archivo .csv y realizar el análisis post-test o post-competiciones que se realicen. git
|
||||
Loading…
Add table
Add a link
Reference in a new issue