car/car.ino

411 lines
13 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include "button.h"
#include "variables.h"
#include <EEPROM.h>
#include "i18n.h"
// Для руссификации, нужно glcdfont.c поместить в C:\Users\USER\Documents\Arduino\libraries\Adafruit_GFX_Library. У вас путь до библиотеки может отличаться.
// Конвертор из UTF-8 в бинарную строку здесь: https://грибовы.рф/rusifikaciya-displeya-ssd1306/
i18n __lang(1); // 0 - английский язык, 1 - русский язык
Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &Wire);
#define ONE_WIRE_BUS 2
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
button btn1(4); // указываем пин кнопки 1
button btn2(5); // указываем пин кнопки 2
int piezoPin = 3; // пин бипера
int LightPin = A2; // пин подсветки кнопок
// Вольтметр
const int analogInput PROGMEM = A0; // Аналоговый порт куда подключается выход с делителя напряжения
const double inaccuracy PROGMEM = 0.5;
const float R1 PROGMEM= 10000.0; // Сопротивление R1 (10K) в ОМАХ
const float R2 PROGMEM = 2000.0; // Сопротивление R2 (2K)в ОМАХ
float vout = 0.0;
float vin = 0.0;
int value = 0;
// моточасы по умолчанию
struct SavedData {
byte beeper=0; // 1 - звук кнопок есть, 0 - нет
byte light=0; // 1 - подсветка кнопок есть, 0 - нет
int motoclock_motor=13200; // замена масла двигателя
int motoclock_kpp=26000; // замена масла МКПП
long motoclock_most=79200; // замена масла мосты
long motoclock_grm=79200; // замена ремня грм
};
SavedData ee_data; // данные с нестираемой памяти
SavedData etalon; // данные по умолчанию
long old_milis,old_milis_2;
byte layout=0; // текущий экран 0 - температура, 1 - моточасы
float celsius1,celsius2,celsius3;
extern int __bss_end;
extern void *__brkval;
void setup() {
Serial.begin(9600);
// инициализирую дисплей
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.cp437(true);
display.clearDisplay();
display.drawBitmap(0, 0, fxf, 128, 64, WHITE);
display.display();
// инициализация ног
pinMode(piezoPin, OUTPUT);
pinMode(analogInput, INPUT);
pinMode(LightPin, OUTPUT);
ee_data.beeper=1;
beep(ee_data.beeper,piezoPin);delay(1000);beep(ee_data.beeper,piezoPin); // два бипа - успешно включились
// читаем данные из энергонезависимой памяти
EEPROM.get(2,ee_data);
if (ee_data.beeper>0){ee_data.beeper=1;};
// если данных нет, то ставим их "по умолчанию"
if ((ee_data.motoclock_motor<0) or (ee_data.motoclock_kpp<0) or (ee_data.motoclock_most<0) or (ee_data.motoclock_grm<0)){
ee_data=etalon;
};
// включаем подсветку кнопок если нужно
if (ee_data.light==1){digitalWrite(LightPin, HIGH);} else {digitalWrite(LightPin, LOW);};
old_milis=millis(); // засекаем время начало работы адулины
old_milis_2=millis(); // засекаем время начало работы адулины
display.clearDisplay();
LayoutScreen(true,0); // Показываем основной экран
//ee_data.motoclock_motor=9;
}
int memoryFree(){
int freeValue;
if((int)__brkval == 0)
freeValue = ((int)&freeValue) - ((int)&__bss_end);
else
freeValue = ((int)&freeValue) - ((int)__brkval);
return freeValue;
}
// звуковой сигнал по нажатию кнопки
void beep(bool beeper,int piezoPin){
if (beeper==1) {
for (int i=0; i <= 100; i++){
digitalWrite(piezoPin, HIGH);
delay(1);
digitalWrite(piezoPin, LOW);
delay(1);
}
} else {
delay(500);
}
}
// отобразить текущий экран
// refresh true/false - стереть всё предварительно
// lay - экран. 0 - температура, 1 - моточасы
void LayoutScreen(boolean refresh,byte lay){
if (refresh==true){
display.clearDisplay();
display.drawBitmap(65, 32, fxf3, 59, 32, WHITE);
};
if (lay==0){
display.setTextColor(WHITE, BLACK);
// улица
display.setTextSize(2);
display.setCursor(50, 1);
//display.print(F("Street:"));
display.print(celsius1);display.print("c");
// салон
display.setTextSize(1);
display.setCursor(4, 1);
//display.print(F("Int:"));
display.print(celsius2);display.print("c");
// двигатель
display.drawBitmap(1, 22, ico_dvig, 16, 16, WHITE);
display.setCursor(20, 26);
display.print(celsius3);display.print("c");
// батарея
display.drawBitmap(1, 42, ico_bat, 16, 16, WHITE);
display.setCursor(20, 46);
display.print(vin);display.print("v");
display.display();
} else {
display.setTextColor(WHITE, BLACK);
display.setCursor(1, 1);
display.print(__lang.translate(F("Motoclock:")));display.print(ee_data.motoclock_motor/60);display.print(__lang.translate(F("h")));
display.setCursor(1, 10);
display.print(__lang.translate(F("Transmission:")));display.print(ee_data.motoclock_kpp/60);display.print(__lang.translate(F("h")));
display.setCursor(1, 20);
display.print(__lang.translate(F("Bridge:")));display.print(ee_data.motoclock_most/60);display.print(__lang.translate(F("h")));
display.setCursor(1, 30);
display.print(__lang.translate(F("GRM ribbon:")));display.print(ee_data.motoclock_grm/60);display.print(__lang.translate(F("h")));
display.display();
};
}
void PutStringMenu(int curpoz,int cursor,String myPointer){
if (curpoz==cursor){
display.print("> ");
};
display.println(myPointer);
};
void PutCharMenu(int curpoz,int cursor,char *myPointer, int length){
if (curpoz==cursor){
display.print("> ");
};
for (byte i = 0; i < length; i++) {
display.print(*(myPointer + i));
};
display.println();
};
void PutYouSure(int poz){
display.clearDisplay();
display.setCursor(1, 1);
display.println("You sure?");
display.setCursor(1, 15);
PutCharMenu(1,poz,"No",2); // Нет
PutCharMenu(2,poz,"Yes",3); // Да
display.display();
}
int AreYouSure(){
int poz=1;
PutYouSure(poz);
while(true){
if (btn1.click()) {
beep(ee_data.beeper,piezoPin);
poz=poz+1;
if (poz>=3){
poz=1;
};
PutYouSure(poz);
};
if (btn2.click()) {
return poz;
};
};
}
void ClearedTxt(){
display.clearDisplay();
display.setCursor(1, 20);
display.println(F("Cleared"));
display.display();
delay(1000);
};
void VerifyAllMoto(){
if ((ee_data.motoclock_motor<10) or (ee_data.motoclock_kpp<10) or (ee_data.motoclock_most<10) or (ee_data.motoclock_grm<10)){
display.clearDisplay();
display.setCursor(1, 0);
display.println(F("Its time to:"));
if (ee_data.motoclock_motor<10){
display.println(F("-Replace engine oil"));
};
if (ee_data.motoclock_kpp<10){
display.println(F("-Replace kpp oil"));
};
if (ee_data.motoclock_most<10){
display.println(F("-Replace brige oil"));
};
if (ee_data.motoclock_grm<10){
display.println(F("-Replace grm"));
};
display.display();
beep(ee_data.beeper,piezoPin);delay(1000);beep(ee_data.beeper,piezoPin);
beep(ee_data.beeper,piezoPin);delay(1000);beep(ee_data.beeper,piezoPin);
LayoutScreen(true,layout);
};
};
void PutMotoMenu(int poz){
display.clearDisplay();
display.setCursor(1, 1);
PutStringMenu(1,poz,F("Engine oil")); // Масло двигателя
PutStringMenu(2,poz,F("Gear oil")); // Масло в КПП
PutStringMenu(3,poz,F("Bridge oil")); // Масло в мостах
PutStringMenu(4,poz,F("Ribbon")); // ремень ГРМ
PutStringMenu(5,poz,F("Exit"));
display.display();
}
void SaveData(){
EEPROM.put(2,ee_data);
}
void MenuMoto(){
int poz=1;
PutMotoMenu(poz);
while(true){
if (btn1.click()) {
poz=poz+1;
if (poz>=6){
poz=1;
};
PutMotoMenu(poz);
beep(ee_data.beeper,piezoPin);
};
if (btn2.click()) {
// сброс моточасы масло двигателя
if (poz==1){
int sure=AreYouSure();
if (sure==2){
ee_data.motoclock_motor=etalon.motoclock_motor;
SaveData();
ClearedTxt();
};
};
// сброс моточасы масло кпп
if (poz==2){
int sure=AreYouSure();
if (sure==2){
ee_data.motoclock_kpp=etalon.motoclock_kpp;
SaveData();
ClearedTxt();
};
};
// сброс моточасы масло мосты
if (poz==3){
int sure=AreYouSure();
if (sure==2){
ee_data.motoclock_most=etalon.motoclock_most;
SaveData();
ClearedTxt();
};
};
// сброс моточасы ремень ГРМ
if (poz==4){
int sure=AreYouSure();
if (sure==2){
ee_data.motoclock_grm=etalon.motoclock_grm;
SaveData();
ClearedTxt();
};
};
if (poz==5){
return 0;
}
PutMotoMenu(poz);
beep(ee_data.beeper,piezoPin);
};
};
};
void PutMainMenu(int poz){
display.clearDisplay();
display.setCursor(1, 1);
PutStringMenu(1,poz,F("Motoclock"));
if (ee_data.beeper==1){
PutStringMenu(2,poz,F("Sound: Yes"));
} else {
PutStringMenu(2,poz,F("Sound: No"));
};
if (ee_data.light==1){
PutStringMenu(3,poz,F("Light: Yes"));
ee_data.light=1;
} else {
PutStringMenu(3,poz,F("Light: No"));
ee_data.light=0;
};
PutStringMenu(4,poz,F("Exit"));
display.display();
}
void MainMenu(){
int poz=1;
PutMainMenu(poz);
while(true){
if (btn1.click()) {
poz=poz+1;
if (poz>=5){
poz=1;
};
PutMainMenu(poz);
beep(ee_data.beeper,piezoPin);
};
if (btn2.click()) {
// сброс моточасов
if (poz==1){
MenuMoto();
PutMainMenu(poz);
};
// Звук кнопок
if (poz==2){
if (ee_data.beeper==1){
ee_data.beeper=0;
} else {
ee_data.beeper=1;
};
SaveData();
PutMainMenu(poz);
};
// подсветка кнопок
if (poz==3){
if (ee_data.light==1){
ee_data.light=0;
digitalWrite(LightPin, LOW);
} else {
ee_data.light=1;
digitalWrite(LightPin, HIGH);
};
SaveData();
PutMainMenu(poz);
};
if (poz==4){ // Exit
return 0;
};
beep(ee_data.beeper,piezoPin);
};
};
}
void GetDataSensors(){
// читаем показания датчиков температуры
sensors.requestTemperatures();
celsius1=sensors.getTempCByIndex(0); if (celsius1<-120){celsius1=0;};
celsius2=sensors.getTempCByIndex(1); if (celsius2<-120){celsius2=0;};
celsius3=sensors.getTempCByIndex(2); if (celsius3<-120){celsius3=0;};
// читаем показания вольтметра
value = analogRead(analogInput);
vout = (value * 5.0) / 1024.0;
vin = vout / (R2/(R1+R2))-inaccuracy;
old_milis_2=millis();
};
void loop() {
if (millis()-old_milis_2>1000){ // раз в секунду читаем показания
GetDataSensors();
LayoutScreen(false,layout);
Serial.println(memoryFree());
};
if (millis()-old_milis>60000){
old_milis=millis();
Serial.println(F("Timer! save to eerom"));
if (ee_data.motoclock_motor>0){ee_data.motoclock_motor=ee_data.motoclock_motor-1;};
if (ee_data.motoclock_kpp>0){ee_data.motoclock_kpp=ee_data.motoclock_kpp-1;};
if (ee_data.motoclock_most>0){ee_data.motoclock_most=ee_data.motoclock_most-1;};
if (ee_data.motoclock_grm>0){ee_data.motoclock_grm=ee_data.motoclock_grm-1;};
SaveData();
VerifyAllMoto();
}
if (btn1.click()) {
MainMenu();
LayoutScreen(true,layout);
};
if (btn2.click()) {
layout=layout+1;
if (layout>1){layout=0;};
LayoutScreen(true,layout);
beep(ee_data.beeper,piezoPin);
};
};