Бортовой компьютер, хотя скорее информационный дисплей
- Войдите на сайт для отправки комментариев
Тут уже много таких было. Но мне приспичело. Разбил дружище LCD щитка приборов ФордФокус2 дорестайл
было так
стало так , угол разбит и вверху ниче не показывает
LCD отдельно не продается. Вернее можно найти почти по стоимости панели, я нашел за 1500р. Дороговато. Но раз уж ардуиной увлекаюсь, хотел применить куда-нибудь и заодно научиться с ним работать, давно заказанный китайский LCD 2,4 mcufriend купленный за 200 руб. У штатного LCD функционал вообще никакой показывает положение селектора, когда зажигание включено. А когда выключено - надпись FordFOCUS и дату под чертой - всё! Хотелось бы конечно расширить функционал, раз уж заниматься этим.
Итак, дисплей MCUFriend 2.4. SD карта в него вставлена. На неё залить все эти файлы.
https://yadi.sk/d/lXuHZGff3NJk97
Пока задача просто вывести все моменты на дисплей. Тем более это всем подойдет не только к форду, например концевики дверей можно подключить к ардуино по аналогу и будет показывать конкретную дверь и т.д.
Мне же в последствии придётся извлекать информацию из кан-шины авто (наработки кое-какие есть уже) для управления элементами инф.дисплея.
Цель темы - если кого заинтересовало - помогайте, в одно лицо тяжеловато проект тащить.
Пока такие наработки https://yadi.sk/i/mfSIoE983NJjYD
Скетч
#include <SPI.h>
#include <SD.h>
#include <Adafruit_GFX.h>
#include <UTFTGLUE.h>
UTFTGLUE myGLCD(0x7783,A2,A1,A3,A4,A0); // у меня почему то ещё канает адрес LCD 0х0154
#define SD_CS 10
File bmpFile;
int bmpWidth, bmpHeight;
uint8_t bmpDepth, bmpImageoffset;
//#if !defined(GroteskBold16x32)
//extern uint8_t GroteskBold16x32[];
//#endif
void setup()
{
Serial.begin(9600);
pinMode(SD_CS, OUTPUT);
// пробуем обратиться к SD-карте памяти
Serial.print("Initializing SD card...");
if (!SD.begin(SD_CS)) {
Serial.println("failed!");
return;}
Serial.println("OK!");
randomSeed(analogRead(0));
pinMode(A0, OUTPUT);
digitalWrite(A0, HIGH);
myGLCD.InitLCD();
myGLCD.clrScr();
bmpDraw("car1.bmp", 113, 15);
// myGLCD.setTextSize(5);
myGLCD.setBackColor(0,0,0);
}
void loop()
{
for (int i=0; i<2; i++){
delay (1000);
FLdoorOPEN();
FRdoorOPEN();
RLdoorOPEN();
RRdoorOPEN();
delay (500);
FLdoorCLOSED();
delay (500);
FRdoorCLOSED();
delay (500);
RLdoorCLOSED();
delay (500);
RRdoorCLOSED();
delay (500);
myGLCD.setColor (0,255,0);
delay (500);
Drive();
delay (500);
Drive1();
delay (500);
Drive2();
delay (500);
Neutral();
delay (500);
Reverse();
delay (500);
Parking();}
myGLCD.clrScr(); // отобразим логотип форд, по задумке он будет появляться после выключения зажигания через 15 сек
Ford();
while (1); // тут пока тормозим скетч
}
void Drive() {myGLCD.setColor (0,0,0); myGLCD.fillRect (255,10,320,60); bmpDraw("D.bmp", 255, 10);}
void Neutral() {myGLCD.setColor (0,0,0); myGLCD.fillRect (255,10,320,60); bmpDraw("N.bmp", 255, 10);}
void Reverse() {myGLCD.setColor (0,0,0); myGLCD.fillRect (255,10,320,60); bmpDraw("R.bmp", 255, 10);}
void Parking() {myGLCD.setColor (0,0,0); myGLCD.fillRect (255,10,320,60); bmpDraw("P.bmp", 255, 10);}
void Drive1() {myGLCD.setColor (0,0,0); myGLCD.fillRect (255,10,320,60); bmpDraw("1.bmp", 255, 10);}
void Drive2() {myGLCD.setColor (0,0,0); myGLCD.fillRect (255,10,320,60); bmpDraw("2.bmp", 255, 10);}
void Drive3() {myGLCD.setColor (0,0,0); myGLCD.fillRect (255,10,320,60); bmpDraw("3.bmp", 255, 10);}
void Drive4() {myGLCD.setColor (0,0,0); myGLCD.fillRect (255,10,320,60); bmpDraw("4.bmp", 255, 10);}
void FLdoorOPEN() {bmpDraw("doorFL.bmp", 59, 63);}
void FRdoorOPEN() {bmpDraw("doorFR.bmp", 203, 68);}
void RLdoorOPEN() {bmpDraw("doorRL.bmp", 63, 128);}
void RRdoorOPEN() {bmpDraw("doorRR.bmp", 203, 128);}
void FLdoorCLOSED() {myGLCD.setColor (0,0,0); myGLCD.fillRect (59,68,114,118);}
void FRdoorCLOSED() {myGLCD.setColor (0,0,0); myGLCD.fillRect (203, 68,258,125);}
void RLdoorCLOSED() {myGLCD.setColor (0,0,0); myGLCD.fillRect (63, 128,114,166);}
void RRdoorCLOSED() {myGLCD.setColor (0,0,0); myGLCD.fillRect (203, 128,254,166);}
void Ford() {bmpDraw("ford.bmp",10, 64);}
Пока в скетче просто отображаются (не зависят не от чего, так для демонстрации) элементы инф.дисплея
Хотелось бы добавить:
1. Отображение времени и даты в момент отображения логотипа
2. Слева внизу может температуру двигателя показывать
3. Слева вверху напряжение АКБ
4. При перегреве ДВС на весь экран предупреждение
5. При отсутствии давления масла и наличии оборотов ДВС на весь экран предупреждение
ну и ещё ченить.



блин в скетче выше ошибка вот этот надо
#include <SPI.h> #include <SD.h> #include <Adafruit_GFX.h> #include <UTFTGLUE.h> UTFTGLUE myGLCD(0x7783,A2,A1,A3,A4,A0); // у меня почему то ещё канает адрес LCD 0х0154 #define SD_CS 10 File bmpFile; int bmpWidth, bmpHeight; uint8_t bmpDepth, bmpImageoffset; //#if !defined(GroteskBold16x32) //extern uint8_t GroteskBold16x32[]; //#endif //////////////// Ниже для считывания файла BMP с SD карты #define BUFFPIXEL 20 void bmpDraw(char *filename, uint8_t x, uint8_t y) { File bmpFile; int bmpWidth, bmpHeight; // W+H in pixels uint8_t bmpDepth; // Bit depth (currently must be 24) uint32_t bmpImageoffset; // Start of image data in file uint32_t rowSize; // Not always = bmpWidth; may have padding uint8_t sdbuffer[3*BUFFPIXEL]; // pixel buffer (R+G+B per pixel) uint8_t buffidx = sizeof(sdbuffer); // Current position in sdbuffer boolean goodBmp = false; // Set to true on valid header parse boolean flip = true; // BMP is stored bottom-to-top int w, h, row, col; uint8_t r, g, b; uint32_t pos = 0, startTime = millis(); if((x >= myGLCD.width()) || (y >= myGLCD.height())) return; Serial.println(); Serial.print("Loading image '"); Serial.print(filename); Serial.println('\''); // Open requested file on SD card if ((bmpFile = SD.open(filename)) == NULL) { Serial.print("File not found"); return; } // Parse BMP header if(read16(bmpFile) == 0x4D42) { // BMP signature Serial.print("File size: "); Serial.println(read32(bmpFile)); (void)read32(bmpFile); // Read & ignore creator bytes bmpImageoffset = read32(bmpFile); // Start of image data Serial.print("Image Offset: "); Serial.println(bmpImageoffset, DEC); // Read DIB header Serial.print("Header size: "); Serial.println(read32(bmpFile)); bmpWidth = read32(bmpFile); bmpHeight = read32(bmpFile); if(read16(bmpFile) == 1) { // # planes -- must be '1' bmpDepth = read16(bmpFile); // bits per pixel Serial.print("Bit Depth: "); Serial.println(bmpDepth); if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed goodBmp = true; // Supported BMP format -- proceed! Serial.print("Image size: "); Serial.print(bmpWidth); Serial.print('x'); Serial.println(bmpHeight); // BMP rows are padded (if needed) to 4-byte boundary rowSize = (bmpWidth * 3 + 3) & ~3; // If bmpHeight is negative, image is in top-down order. // This is not canon but has been observed in the wild. if(bmpHeight < 0) { bmpHeight = -bmpHeight; flip = false; } // Crop area to be loaded w = bmpWidth; h = bmpHeight; if((x+w-1) >= myGLCD.width()) w = myGLCD.width() - x; if((y+h-1) >= myGLCD.height()) h = myGLCD.height() - y; for (row=0; row<h; row++) { // For each scanline... myGLCD.setCursor(x, y+row); // Seek to start of scan line. It might seem labor- // intensive to be doing this on every line, but this // method covers a lot of gritty details like cropping // and scanline padding. Also, the seek only takes // place if the file position actually needs to change // (avoids a lot of cluster math in SD library). if(flip) // Bitmap is stored bottom-to-top order (normal BMP) pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize; else // Bitmap is stored top-to-bottom pos = bmpImageoffset + row * rowSize; if(bmpFile.position() != pos) { // Need seek? bmpFile.seek(pos); buffidx = sizeof(sdbuffer); // Force buffer reload } // optimize by setting pins now for (col=0; col<w; col++) { // For each pixel... // Time to read more pixel data? if (buffidx >= sizeof(sdbuffer)) { // Indeed bmpFile.read(sdbuffer, sizeof(sdbuffer)); buffidx = 0; // Set index to beginning } // Convert pixel from BMP to TFT format, push to display b = sdbuffer[buffidx++]; g = sdbuffer[buffidx++]; r = sdbuffer[buffidx++]; myGLCD.setColor(r,g,b); myGLCD.drawPixel(x+col, y+row); // optimized! //tft.pushColor(tft.Color565(r,g,b)); } // end pixel } // end scanline Serial.print("Loaded in "); Serial.print(millis() - startTime); Serial.println(" ms"); } // end goodBmp } } bmpFile.close(); if(!goodBmp) Serial.println("BMP format not recognized."); } // These read 16- and 32-bit types from the SD card file. // BMP data is stored little-endian, Arduino is little-endian too. // May need to reverse subscript order if porting elsewhere. uint16_t read16(File f) { uint16_t result; ((uint8_t *)&result)[0] = f.read(); // LSB ((uint8_t *)&result)[1] = f.read(); // MSB return result; } uint32_t read32(File f) { uint32_t result; ((uint8_t *)&result)[0] = f.read(); // LSB ((uint8_t *)&result)[1] = f.read(); ((uint8_t *)&result)[2] = f.read(); ((uint8_t *)&result)[3] = f.read(); // MSB return result; } ////////////////////// void setup() { Serial.begin(9600); pinMode(SD_CS, OUTPUT); // пробуем обратиться к SD-карте памяти Serial.print("Initializing SD card..."); if (!SD.begin(SD_CS)) { Serial.println("failed!"); return;} Serial.println("OK!"); randomSeed(analogRead(0)); pinMode(A0, OUTPUT); digitalWrite(A0, HIGH); myGLCD.InitLCD(); myGLCD.clrScr(); bmpDraw("car1.bmp", 113, 15); // myGLCD.setTextSize(5); myGLCD.setBackColor(0,0,0); } void loop() { for (int i=0; i<2; i++){ delay (1000); FLdoorOPEN(); FRdoorOPEN(); RLdoorOPEN(); RRdoorOPEN(); delay (500); FLdoorCLOSED(); delay (500); FRdoorCLOSED(); delay (500); RLdoorCLOSED(); delay (500); RRdoorCLOSED(); delay (500); myGLCD.setColor (0,255,0); delay (500); Drive(); delay (500); Drive1(); delay (500); Drive2(); delay (500); Neutral(); delay (500); Reverse(); delay (500); Parking();} myGLCD.clrScr(); // отобразим логотип форд, по задумке он будет появляться после выключения зажигания через 15 сек Ford(); while (1); // тут пока тормозим скетч } void Drive() {myGLCD.setColor (0,0,0); myGLCD.fillRect (255,10,320,60); bmpDraw("D.bmp", 255, 10);} void Neutral() {myGLCD.setColor (0,0,0); myGLCD.fillRect (255,10,320,60); bmpDraw("N.bmp", 255, 10);} void Reverse() {myGLCD.setColor (0,0,0); myGLCD.fillRect (255,10,320,60); bmpDraw("R.bmp", 255, 10);} void Parking() {myGLCD.setColor (0,0,0); myGLCD.fillRect (255,10,320,60); bmpDraw("P.bmp", 255, 10);} void Drive1() {myGLCD.setColor (0,0,0); myGLCD.fillRect (255,10,320,60); bmpDraw("1.bmp", 255, 10);} void Drive2() {myGLCD.setColor (0,0,0); myGLCD.fillRect (255,10,320,60); bmpDraw("2.bmp", 255, 10);} void Drive3() {myGLCD.setColor (0,0,0); myGLCD.fillRect (255,10,320,60); bmpDraw("3.bmp", 255, 10);} void Drive4() {myGLCD.setColor (0,0,0); myGLCD.fillRect (255,10,320,60); bmpDraw("4.bmp", 255, 10);} void FLdoorOPEN() {bmpDraw("doorFL.bmp", 59, 63);} void FRdoorOPEN() {bmpDraw("doorFR.bmp", 203, 68);} void RLdoorOPEN() {bmpDraw("doorRL.bmp", 63, 128);} void RRdoorOPEN() {bmpDraw("doorRR.bmp", 203, 128);} void FLdoorCLOSED() {myGLCD.setColor (0,0,0); myGLCD.fillRect (59,68,114,118);} void FRdoorCLOSED() {myGLCD.setColor (0,0,0); myGLCD.fillRect (203, 68,258,125);} void RLdoorCLOSED() {myGLCD.setColor (0,0,0); myGLCD.fillRect (63, 128,114,166);} void RRdoorCLOSED() {myGLCD.setColor (0,0,0); myGLCD.fillRect (203, 128,254,166);} void Ford() {bmpDraw("ford.bmp",10, 64);}Библиотеки для этого корявого LCD https://yadi.sk/d/U4wMuhG03NJsKj
И забыл скакзать LCD у меня 320х240
https://ru.aliexpress.com/item/LCD-module-TFT-2-4-inch-TFT-LCD-screen-for-Arduino-UNO-R3-Board-and-support/32552043575.html?spm=a2g0s.9042311.0.0.I42CYz
не знаю как работать с этой библиотекой со сторонними шрифтами, вроде все делаешь, один фиг SmallFont[] включается .
короче сделал время и дату встроенным шрифтом. Корявенько конечно.
#include <SPI.h> #include <SD.h> #include <Adafruit_GFX.h> #include <UTFTGLUE.h> UTFTGLUE myGLCD(0x7783,A2,A1,A3,A4,A0); // у меня почему то ещё канает адрес LCD 0х0154 #define SD_CS 10 File bmpFile; int bmpWidth, bmpHeight; uint8_t bmpDepth, bmpImageoffset; #if !defined(BigFont) extern uint8_t BigFont[]; #endif //////////////// Ниже для считывания файла BMP с SD карты #define BUFFPIXEL 20 void bmpDraw(char *filename, uint8_t x, uint8_t y) { File bmpFile; int bmpWidth, bmpHeight; // W+H in pixels uint8_t bmpDepth; // Bit depth (currently must be 24) uint32_t bmpImageoffset; // Start of image data in file uint32_t rowSize; // Not always = bmpWidth; may have padding uint8_t sdbuffer[3*BUFFPIXEL]; // pixel buffer (R+G+B per pixel) uint8_t buffidx = sizeof(sdbuffer); // Current position in sdbuffer boolean goodBmp = false; // Set to true on valid header parse boolean flip = true; // BMP is stored bottom-to-top int w, h, row, col; uint8_t r, g, b; uint32_t pos = 0, startTime = millis(); if((x >= myGLCD.width()) || (y >= myGLCD.height())) return; Serial.println(); Serial.print("Loading image '"); Serial.print(filename); Serial.println('\''); // Open requested file on SD card if ((bmpFile = SD.open(filename)) == NULL) { Serial.print("File not found"); return; } // Parse BMP header if(read16(bmpFile) == 0x4D42) { // BMP signature Serial.print("File size: "); Serial.println(read32(bmpFile)); (void)read32(bmpFile); // Read & ignore creator bytes bmpImageoffset = read32(bmpFile); // Start of image data Serial.print("Image Offset: "); Serial.println(bmpImageoffset, DEC); // Read DIB header Serial.print("Header size: "); Serial.println(read32(bmpFile)); bmpWidth = read32(bmpFile); bmpHeight = read32(bmpFile); if(read16(bmpFile) == 1) { // # planes -- must be '1' bmpDepth = read16(bmpFile); // bits per pixel Serial.print("Bit Depth: "); Serial.println(bmpDepth); if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed goodBmp = true; // Supported BMP format -- proceed! Serial.print("Image size: "); Serial.print(bmpWidth); Serial.print('x'); Serial.println(bmpHeight); // BMP rows are padded (if needed) to 4-byte boundary rowSize = (bmpWidth * 3 + 3) & ~3; // If bmpHeight is negative, image is in top-down order. // This is not canon but has been observed in the wild. if(bmpHeight < 0) { bmpHeight = -bmpHeight; flip = false; } // Crop area to be loaded w = bmpWidth; h = bmpHeight; if((x+w-1) >= myGLCD.width()) w = myGLCD.width() - x; if((y+h-1) >= myGLCD.height()) h = myGLCD.height() - y; for (row=0; row<h; row++) { // For each scanline... myGLCD.setCursor(x, y+row); // Seek to start of scan line. It might seem labor- // intensive to be doing this on every line, but this // method covers a lot of gritty details like cropping // and scanline padding. Also, the seek only takes // place if the file position actually needs to change // (avoids a lot of cluster math in SD library). if(flip) // Bitmap is stored bottom-to-top order (normal BMP) pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize; else // Bitmap is stored top-to-bottom pos = bmpImageoffset + row * rowSize; if(bmpFile.position() != pos) { // Need seek? bmpFile.seek(pos); buffidx = sizeof(sdbuffer); // Force buffer reload } // optimize by setting pins now for (col=0; col<w; col++) { // For each pixel... // Time to read more pixel data? if (buffidx >= sizeof(sdbuffer)) { // Indeed bmpFile.read(sdbuffer, sizeof(sdbuffer)); buffidx = 0; // Set index to beginning } // Convert pixel from BMP to TFT format, push to display b = sdbuffer[buffidx++]; g = sdbuffer[buffidx++]; r = sdbuffer[buffidx++]; myGLCD.setColor(r,g,b); myGLCD.drawPixel(x+col, y+row); // optimized! //tft.pushColor(tft.Color565(r,g,b)); } // end pixel } // end scanline Serial.print("Loaded in "); Serial.print(millis() - startTime); Serial.println(" ms"); } // end goodBmp } } bmpFile.close(); if(!goodBmp) Serial.println("BMP format not recognized."); } // These read 16- and 32-bit types from the SD card file. // BMP data is stored little-endian, Arduino is little-endian too. // May need to reverse subscript order if porting elsewhere. uint16_t read16(File f) { uint16_t result; ((uint8_t *)&result)[0] = f.read(); // LSB ((uint8_t *)&result)[1] = f.read(); // MSB return result; } uint32_t read32(File f) { uint32_t result; ((uint8_t *)&result)[0] = f.read(); // LSB ((uint8_t *)&result)[1] = f.read(); ((uint8_t *)&result)[2] = f.read(); ((uint8_t *)&result)[3] = f.read(); // MSB return result; } ////////////////////// void setup() { Serial.begin(9600); pinMode(SD_CS, OUTPUT); // пробуем обратиться к SD-карте памяти Serial.print("Initializing SD card..."); if (!SD.begin(SD_CS)) { Serial.println("failed!"); return;} Serial.println("OK!"); randomSeed(analogRead(0)); pinMode(A0, OUTPUT); digitalWrite(A0, HIGH); myGLCD.InitLCD(); myGLCD.setBackColor(0,0,0); } void loop() { myGLCD.clrScr(); bmpDraw("car1.bmp", 113, 15); delay (1000); FLdoorOPEN(); FRdoorOPEN(); RLdoorOPEN(); Drive(); delay (500); RRdoorOPEN(); delay (500); Neutral(); delay (500); FLdoorCLOSED(); delay (500); FRdoorCLOSED(); delay (500); RLdoorCLOSED(); delay (500); RRdoorCLOSED(); delay (500); Drive1(); delay (500); Drive2(); delay (500); Reverse(); delay (500); Parking(); delay (1000); myGLCD.clrScr(); // отобразим логотип форд, по задумке он будет появляться после выключения зажигания через 15 сек Ford(); myGLCD.setColor (255,255,255); myGLCD.setBackColor(0,0,0); myGLCD.setTextSize(4); myGLCD.print ("12:30",10,207); // время myGLCD.setTextSize(3); myGLCD.print ("29/09/2017",137,3); // дата delay (10000); } void Drive() {myGLCD.setColor (0,0,0); myGLCD.fillRect (255,10,320,60); bmpDraw("D.bmp", 255, 10);} void Neutral() {myGLCD.setColor (0,0,0); myGLCD.fillRect (255,10,320,60); bmpDraw("N.bmp", 255, 10);} void Reverse() {myGLCD.setColor (0,0,0); myGLCD.fillRect (255,10,320,60); bmpDraw("R.bmp", 255, 10);} void Parking() {myGLCD.setColor (0,0,0); myGLCD.fillRect (255,10,320,60); bmpDraw("P.bmp", 255, 10);} void Drive1() {myGLCD.setColor (0,0,0); myGLCD.fillRect (255,10,320,60); bmpDraw("1.bmp", 255, 10);} void Drive2() {myGLCD.setColor (0,0,0); myGLCD.fillRect (255,10,320,60); bmpDraw("2.bmp", 255, 10);} void Drive3() {myGLCD.setColor (0,0,0); myGLCD.fillRect (255,10,320,60); bmpDraw("3.bmp", 255, 10);} void Drive4() {myGLCD.setColor (0,0,0); myGLCD.fillRect (255,10,320,60); bmpDraw("4.bmp", 255, 10);} void FLdoorOPEN() {bmpDraw("doorFL.bmp", 59, 63);} void FRdoorOPEN() {bmpDraw("doorFR.bmp", 203, 68);} void RLdoorOPEN() {bmpDraw("doorRL.bmp", 63, 128);} void RRdoorOPEN() {bmpDraw("doorRR.bmp", 203, 128);} void FLdoorCLOSED() {myGLCD.setColor (0,0,0); myGLCD.fillRect (59,68,114,118);} void FRdoorCLOSED() {myGLCD.setColor (0,0,0); myGLCD.fillRect (203, 68,258,125);} void RLdoorCLOSED() {myGLCD.setColor (0,0,0); myGLCD.fillRect (63, 128,114,166);} void RRdoorCLOSED() {myGLCD.setColor (0,0,0); myGLCD.fillRect (203, 128,254,166);} void Ford() {bmpDraw("ford.bmp",10, 64);}