Projeto HUD Arduino Ago/25
HUD_T_U_Display_Led_AtMegaTacoTermoparV12_3
/*
========================================================================================================
Projeto: HUD Car - Display LED, AtMega, Termopar, AHT10 e Bússola
Wilson R. Bueno - 27/08/25
Base: Usina Info e WR Kits:Indicador de Nível de Bateria com Display OLED!https://www.makerguides.com/arduino-tachometer-a3144-hall-effect-sensor/
========================================================================================================
V0 Baseado na V1.3 * V1.0 - Incluído cartão SD-NOK ** V1.1 - Retirado cartão SD - ok ** V1.2 - Colocado Max6675 - termopar - nok
V1.3 - otimização - ok ** V2.0 - Inclusão de bara de progresso - ok ** V2.1 - progressivo - ok
V2.2 - inclusão de condicionais para temperatura * V3.0 - inclusão de tacômetro * V3.1 - reinclusão do termopar ok
V5.0 - troca por diplay 0,96" - duas cores * V7.0 - baseado na V5.0 - Ok * V7.1 - otimização Maya
V7.2 - otimização apresentação dos dados no display, mesmo sem rotação - NOK - o consumo da placa de SD é muito alto
V7.3 - Maya otimização apresentação dos dados no display, mesmo sem rotação - Ok * V8.0 - retirado condicional para temperatura e inclusão de seleção da tela - Ok
V8.1 - progressivo tela inicial - Ok * V8.2 - alteração para Km/h e resolver problema de início sem cabo USB //while (!Serial) {} //se habilitado, impede a inicialização até conectar o cabo USB
V9.0 - inclusão de encoder para seleção de menus * V9.1 - alteração menus pela Maya * V9.2 - nada * V9.3 - ajustes menu
V9.4 - ajustes menu - Ok * V9.5 - progressivo - Ok * V10.0 - inclusão bússola e acelerômetro - Ok
V10.1 - condicional para bússola - Ok * V10.2 - progressivo - Ok * V10.3 - progressivo com iclusão do acelerômetro - Ok * V10.4 - inclusão menu - NOk * V10.5 - inclusão menu, com Maya - Ok
V10.6 - progressivo - Ok * V10.7 - progressivo menu de abertura - Ok * V11.0 - inclusão temperatura da placa - Não disponível
V12.0 - progressivo - Ok * V12.1 - progressivo - Ok * V12.2 - mostrar o tempo desde início - Ok
V12.3 - inclusão de dias
*/
#include <Adafruit_SSD1306.h>
#include <Adafruit_AHT10.h>
#include <max6675.h>
#include <Encoder.h>
#include <Wire.h>
#include <LSM303.h>
// Constants for pins and display
#define thermoSCK 18
#define thermoCS 19
#define thermoSO 20
#define OLED_RESET 4
#define hallPin 7
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Encoder myEnc(5, 6);
MAX6675 thermocouple(thermoSCK, thermoCS, thermoSO);
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
Adafruit_AHT10 aht;
LSM303 compass; // Cria um objeto para o sensor
volatile int cnt = 0;
long oldPosition = -999;
//Mostrar a hora no menu
unsigned long previousMillis = 0; // Armazena o último momento em que o tempo foi atualizado
const long interval = 1000; // Intervalo para incrementar o relógio (1 segundo)
int seconds = 0;
int minutes = 0;
int hours = 0;
int days = 0;
void setup() {
Serial.begin(9600);
Wire.begin();
compass.init();
compass.enableDefault();
inicializaDisplay();
inicializaGeral();
}
void loop() {
sensors_event_t humidity, temp;
aht.getEvent(&humidity, &temp);
float tempC = thermocouple.readCelsius();
int rpm = calculateRPM();
displayData(temp.temperature, humidity.relative_humidity, tempC, rpm);
}
void displayData(float temp, float humidity, float thermoTemp, int rpm) {
display.clearDisplay();
display.drawRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, SSD1306_WHITE);
long newPosition = myEnc.read();
if (newPosition != oldPosition) {
oldPosition = newPosition;
Serial.println(newPosition);
}
switch (newPosition) {
case -4:
// display.display();
casedefault();
casemenostres();
break;
case -3:
// display.display();
caseContador();
break;
case -2:
mostrarBussola();
break;
case -1:
mostrarRPMMenor(temp, humidity, thermoTemp, rpm);
break;
case 0:
mostrarKmHGrande(temp, humidity, thermoTemp, rpm);
break;
case 1:
mostrarTEGrande(temp, humidity, thermoTemp, rpm);
break;
case 2:
mostrarBussola();
break;
case 3:
casedefault();
casetres();
break;
default:
casedefault();
break; // Adiciona break para garantir fluxo claro
}
display.display();
}
void caseContador() {
unsigned long currentMillis = millis();
// Verifica se um segundo se passou
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
seconds++; // Incrementa os segundos
if (seconds >= 60) {
seconds = 0;
minutes++;
}
if (minutes >= 60) {
minutes = 0;
hours++;
}
if (hours >= 24) {
hours = 0;
days++;
}
display.clearDisplay();
display.setTextSize(2);
display.setCursor(0, 0);
display.print("START TIME");
display.setCursor(12, 25);
//display.print(F("|"));
if (hours < 10) display.print('0');
display.print(hours);
display.print(F(":"));
if (minutes < 10) display.print('0');
display.print(minutes);
display.print(F(":"));
if (seconds < 10) display.print('0');
display.print(seconds);
display.setCursor(22, 45);
display.print(F("Day:"));
display.print(days);
display.display();
}
}
void casetres() {
display.setTextSize(2);
display.setCursor(8, 2);
display.print(F("======>>>"));
}
void casemenostres() {
display.setTextSize(2);
display.setCursor(8, 2);
display.print(F("<<<======"));
}
void casedefault() {
Serial.println(F("default"));
display.clearDisplay();
display.setTextSize(2);
display.setCursor(8, 20);
display.print(F("VOLTE UMA"));
display.setCursor(18, 40);
display.print(F("SELECAO"));
/* Invert and restore display, pausing in-between
display.invertDisplay(true);
delay(1000);
display.invertDisplay(false);
delay(1000);
*/
for (int16_t i = 0; i < max(display.width(), display.height()) / 2; i += 5) {
display.drawTriangle(
display.width() / 2, display.height() / 2 - i,
display.width() / 2 - i, display.height() / 2 + i,
display.width() / 2 + i, display.height() / 2 + i, SSD1306_WHITE);
display.display();
delay(1);
}
}
void mostrarBussola() {
compass.read();
float heading = atan2(compass.m.y, compass.m.x) * 180 / PI;
if (heading < 0) heading += 360;
String direction = calcularDirecao(heading);
Serial.print(F("Ponto Cardeal: "));
Serial.println(direction);
Serial.println(heading);
float ax = compass.a.x / 16384.0;
float ay = compass.a.y / 16384.0;
float az = compass.a.z / 16384.0;
Serial.print(F("Acelerômetro em g -> X: "));
Serial.print(ax, 4);
Serial.print(F(" Y: "));
Serial.print(ay, 4);
Serial.print(F(" Z: "));
Serial.println(az, 4);
display.setCursor(10, 2);
display.setTextSize(1);
display.print(F(":"));
display.print(ax, 2);
display.print(F(":"));
display.print(ay, 2);
display.print(F(":"));
display.print(az, 2);
display.print(F(":"));
display.setCursor(4, 30);
display.setTextSize(4);
display.print(direction);
display.setCursor(43, 30);
display.print(F(":"));
display.setCursor(60, 35);
display.setTextSize(3);
display.print(heading, 0);
}
String calcularDirecao(float heading) {
if (heading >= 337.5 || heading < 22.5) return "N";
if (heading >= 22.5 && heading < 67.5) return "NE";
if (heading >= 67.5 && heading < 112.5) return "L";
if (heading >= 112.5 && heading < 157.5) return "SE";
if (heading >= 157.5 && heading < 202.5) return "S";
if (heading >= 202.5 && heading < 247.5) return "SO";
if (heading >= 247.5 && heading < 292.5) return "O";
return "NO";
}
void mostrarRPMMenor(float temp, float humidity, float thermoTemp, int rpm) {
mostrarTemperaturas(temp, humidity, thermoTemp);
display.setTextSize(2);
display.setCursor(42, 20);
display.print(thermoTemp, 0);
display.setTextSize(2);
display.setCursor(92, 23);
display.print(F("oC"));
display.setTextSize(3);
display.setCursor(10, 40);
display.print(rpm * 60);
display.setTextSize(2);
display.setCursor(90, 42);
display.print(F("rpm"));
SerialOutput(temp, humidity, thermoTemp, rpm);
}
void mostrarKmHGrande(float temp, float humidity, float thermoTemp, int rpm) {
mostrarTemperaturas(temp, humidity, thermoTemp);
display.setTextSize(2);
display.setCursor(42, 20);
display.print(thermoTemp, 0);
display.setTextSize(2);
display.setCursor(92, 23);
display.print(F("oC"));
display.setTextSize(3);
display.setCursor(10, 40);
display.print(rpm);
display.setTextSize(2);
display.setCursor(75, 42);
display.print(F("km/h"));
SerialOutput(temp, humidity, thermoTemp, rpm);
}
void mostrarTEGrande(float temp, float humidity, float thermoTemp, int rpm) {
mostrarTemperaturas(temp, humidity, thermoTemp);
display.setTextSize(3);
display.setCursor(42, 20);
display.print(thermoTemp, 0);
display.setTextSize(2);
display.setCursor(92, 23);
display.print(F("oC"));
display.setTextSize(2);
display.setCursor(10, 45);
display.print(rpm);
display.setCursor(72, 46);
display.print(F("km/h"));
SerialOutput(temp, humidity, thermoTemp, rpm);
}
void mostrarTemperaturas(float temp, float humidity, float thermoTemp) {
display.setCursor(4, 2);
display.setTextSize(2);
display.print(temp, 0);
display.print(F("oC "));
display.setCursor(65, 2);
display.print(humidity, 0);
display.print(F("%HR"));
display.setCursor(4, 23);
display.print(F("TE:"));
}
void SerialOutput(float temp, float humidity, float thermoTemp, int rpm) {
Serial.print(rpm);
Serial.println(F(" km/h"));
Serial.print(temp, 1);
Serial.print(F(" oC <> "));
Serial.print(humidity, 1);
Serial.print(F(" %HR <> "));
Serial.print(thermoTemp, 1);
Serial.println(F(" oC"));
}
void inicializaDisplay() {
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 Fail"));
for (;;)
;
}
display.clearDisplay();
display.drawRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, SSD1306_WHITE);
testscrolltext(); // Draw scrolling text
}
void inicializaGeral() {
if (!aht.begin()) {
Serial.println(F("AHT Fail"));
while (1)
;
}
//Serial.println(F("---------------------"));
Serial.println(F("Marelli GTS Amparo"));
Serial.print(__TIME__);
Serial.print(" - ");
Serial.println(__DATE__);
//Serial.println(F("-------------------"));
Serial.println(F("Projeto HUD Car V12.3"));
//Serial.println(F("---------------------"));
pinMode(hallPin, INPUT);
attachInterrupt(digitalPinToInterrupt(hallPin), count, FALLING);
}
int calculateRPM() {
unsigned long start = millis();
cnt = 0;
while ((millis() - start) < 1000) {
// Waiting for 1 second
}
return cnt; // Reutilizar já como km/h
}
void count() {
cnt++;
}
void testscrolltext(void) {
display.clearDisplay();
display.setTextSize(2); // Draw 2X-scale text
display.setTextColor(SSD1306_WHITE);
display.setCursor(1, 0);
display.println(F("Marelli"));
display.setTextSize(1);
display.setCursor(18, 24);
display.println(F("Testing"));
display.setCursor(10, 34);
display.println(F("Engineering"));
display.setCursor(8, 44);
display.println(F("HUD Car V12.3"));
display.setCursor(1, 54);
display.println(F("IDE2.3.5-AGO/25"));
display.display(); // Show initial text
// Scroll in various directions, pausing in-between:
display.startscrollright(0x00, 0x07);
delay(2000);
display.stopscroll();
delay(1000);
display.startscrollleft(0x00, 0x07);
delay(2000);
display.stopscroll();
delay(1000);
}
Comentários
Postar um comentário