Бортовой компьютер для автомобиля с 3.5 TFT дисплеем

shurf83
Offline
Зарегистрирован: 10.07.2019

Здравствуйте, уважаемые спецы. В общем-то все работаем, но обновление информации происходит 1 раз в 3 секунды, а хотелось бы мгновенно. С расходом тоже беда. Показывает мгновенно, а хочется за час. 

Вот собственно код

#include <iarduino_RTC.h>
iarduino_RTC time(RTC_DS1307);

#include <DHT.h>
#include <DHT_U.h>
#define B 3950 // B-коэффициент
#define SERIAL_R 10000 // сопротивление последовательного резистора, 10 кОм
#define THERMISTOR_R 10000 // номинальное сопротивления термистора, 10 кОм
#define NOMINAL_T 25 // номинальная температура (при которой TR = 10 кОм)
 
const byte tempoPin = A12;




#define DHTTYPE DHT11
#define DHTPIN 41
DHT dht(DHTPIN, DHTTYPE);


#include <Adafruit_GFX.h>    // Core graphics library

#include <SPI.h>
#include <SD.h>
#include <MCUFRIEND_kbv.h>   // Hardware-specific library



#include <OneWire.h>
#include <Wire.h>
//const extern uint8_t FreeSans9pt7b
#include "Fonts/FreeSansBold24pt7b.h"    // когда вам нужны другие шрифты
    MCUFRIEND_kbv tft;

#define LCD_CS A3 // Chip Select goes to Analog 3
#define LCD_CD A2 // Command/Data goes to Analog 2
#define LCD_WR A1 // LCD Write goes to Analog 1
#define LCD_RD A0 // LCD Read goes to Analog 0



#define SD_CS 53     // Set the chip select line to whatever you use (10 doesnt conflict with the library)

const int tachPIN=18;// тахометр
const unsigned long sampleTime=1000;
const unsigned long sampleTime2=1000;
const unsigned long sampleTime3=1000;
const int speedPIN=19; //спидометр
////-------расход--------///
const int INJECTOR_PIN=A9;// форсунка


//------------------------------///


#define BLACK 0x0000
#define NAVY 0x000F
#define DARKGREEN 0x03E0
#define DARKCYAN 0x03EF
#define MAROON 0x7800
#define PURPLE 0x780F
#define OLIVE 0x7BE0
#define LIGHTGREY 0xC618
#define DARKGREY 0x7BEF
#define BLUE 0x001F
#define GREEN 0x07E0
#define CYAN 0x07FF
#define RED 0xF800
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
#define ORANGE 0xFD20
#define GREENYELLOW 0xAFE5
#define PINK 0xF81F


void setup()
{

  //tft.reset();
dht.begin();
time.begin(); 
  Serial.begin(9600);
  uint16_t ID = tft.readID();
  Serial.println("Example: Font_simple");
    Serial.print("found ID = 0x");
    Serial.println(ID, HEX);
    if (ID == 0xD3D3) ID = 0x9481; //force ID if write-only display
    tft.begin(ID);
    Wire.begin();
  //tft.setTextSize(2);
  //tft.fillScreen(0);
  tft.setRotation(1);
 
  if (!SD.begin(SD_CS )) {
    
    return;
  }
 
pinMode(tachPIN, INPUT);
digitalWrite(tachPIN, HIGH);// тахо
pinMode(speedPIN, INPUT);
digitalWrite(speedPIN, HIGH);
 pinMode( tempoPin, INPUT ); 
 //-------------расход------------//
pinMode(INJECTOR_PIN, INPUT);
digitalWrite(INJECTOR_PIN, HIGH);

//-----------------------------------//
  bmpDraw("OPEL3.bmp", 0, 0);
delay(5000);
//tft.reset();
//delay(1);
 tft.fillScreen( BLACK);

}


void loop()
{


   
//delay(2000);
float h = dht.readHumidity();   // считывание влажности
float t = dht.readTemperature();   // считывание температуры
tft.setTextColor(WHITE,BLACK);
 tft.setTextSize(3);
 tft.setCursor(5,270);
  tft.print(h);
  tft.setTextSize(3);
 tft.setCursor(5,230);
  tft.print(t);
  tft.setCursor(105,270);
  tft.print("%");
  tft.setCursor(105,230);
  tft.print("C");
  tft.setTextColor(BLUE,BLACK);
  tft.setCursor(10,185);
  tft.print(utf8rus("ВНУТРИ")); // ВНУТРИ
  
 tft.setCursor(85,52);
  tft.print(utf8rus("МГ"));   // РАСХОД
  tft.setCursor(3,140);
  //tft.print(utf8rus("Л/Ч"));
  tft.setCursor(380,50);
  tft.print(utf8rus("ТОСОЛ"));
  tft.setTextSize(2);
  tft.setCursor(380,245);
  tft.print(utf8rus("За окном"));

  
  // темп двиг (среднее от 100 замеров)
long valtemp = 0;
for (int kd=0; kd<100; ++kd) {
valtemp = valtemp + analogRead(A10);
}
valtemp = valtemp/100;
float voltemp = map(valtemp,750,0,0,1200);
voltemp = voltemp/10;
float temp3=voltemp;
int z = temp3;
tft.setTextColor(WHITE,BLACK);
  tft.setTextSize(5); 
tft.setCursor(375,100);
char d[5];
sprintf(d,"%3d",z);
tft.println(d);


  // напряжение (среднее от 100 замеров)
long valvolt = 0;
for (int k=0; k<100; ++k) {
valvolt = valvolt + analogRead(A8); // на панели припаян
}
valvolt = valvolt/100;
float voltage = map(valvolt, 0,1725,0,150);
voltage = voltage/5;


  tft.setTextColor(WHITE,BLACK);
  tft.setTextSize(3);
  tft.setCursor(380,215);
  tft.print(voltage);
  tft.setTextColor(BLUE,BLACK);
  tft.setCursor(380,185);
  tft.print(utf8rus("ЗАРЯД"));
  
  
  
  
  tft.drawFastHLine(365,240,115,0xFFFF);
   tft.drawFastHLine(0,170,480,0xFFFF);                                                 
   tft.drawFastHLine(0,40,480,0xFFFF);
tft.drawLine(130,170,170,210,0xFFFF);
tft.drawLine(365,170,325,210,0xFFFF);
tft.drawFastHLine(170,210,155,0xFFFF); 
tft.drawLine(130,40,130,380,0xFFFF);// верт полоска левая
tft.drawLine(365,40,365,380,0xFFFF);// верт полоска левая

float sped=getSPEED()/100;
int q = sped;
tft.setTextColor(RED,BLACK);
  tft.setTextSize(13); 
tft.setCursor(131,60);
char s[5];
sprintf(s,"%3d",q);
tft.println(s);




float rpm=getRPM(); 
  int n = rpm;
  tft.setTextColor(DARKGREY,BLACK);
  tft.setTextSize(8); 
tft.setCursor(155,225);
char o[6];
sprintf(o,"%4d",n);
tft.print(o);

// форсунки
  tft.setTextColor(WHITE,BLACK);
  //tft.setTextSize(5);
 float fors=getFORS();
 float racxod=rpm*fors/100000; 
//if (racxod < 10)
  //int f = fors;
  tft.setTextSize(3);
  tft.setCursor(0,52);
  //char y[5];
//sprintf(y,"%3d",f);
tft.println(racxod);
//if  (racxod >= 10)
//  tft.setCursor(20,85);
//tft.println(racxod);
tft.setTextSize(5);
  tft.setCursor(5,90);
tft.print("");


//tft.setCursor(20,95);
//sped = sped*100;
float sped1 = sped*sped;
float sped2 = sped*2;
float sped3 = sped1+sped2;
float rashod = (racxod/sped3)*10000;
if (rashod >= 100) rashod = 0;
float rashod2 = 0;
// расход (среднее от 10 замеров)
for (int is=0; is<100000; ++is) {
rashod2 = rashod2 + rashod; }
float rashod3 = rashod2/100000;
//if (rashod3 < 10 && sped > 5) //считаем если скорость более 5 км/ч

//  tft.setCursor(20,115);
//'tft.print(rashod3);
if (rashod3 >= 10 && sped > 5)
//tft.setTextSize(5);
  tft.setCursor(0,85);
tft.print(rashod3);


  //tft.print("6,7");
//  tft.print(fuelInHouR);


tft.setTextColor(WHITE,BLACK);                          
   tft.setTextSize(3);    // устанавливаем маленький шрифт                  
  
  tft.setCursor(180,300);
  tft.print("TAXOMETP");


tft.setTextColor(WHITE,BLACK);                          
   tft.setTextSize(3);    // устанавливаем маленький шрифт                  
  
  tft.setCursor(180,180);
  tft.print("CKOPOCTb");
  
  
  
  
  tft.setCursor(15,15);
  tft.print(time.gettime("d-m-Y"));  
  tft.setCursor(350,15);
  tft.print(time.gettime("H:i")); 

 // наружняя температура(среднее от 1000 замеров)
int t1 = analogRead( tempoPin );
    float tr = 1023.0 / t1 - 1;
    tr = SERIAL_R / tr;
   
    float steinhart;
    steinhart = tr / THERMISTOR_R; // (R/Ro)
    steinhart = log(steinhart); // ln(R/Ro)
    steinhart /= B; // 1/B * ln(R/Ro)
    steinhart += 1.0 / (NOMINAL_T + 273); // + (1/To)
    steinhart = 1.0 / steinhart; // Invert
    steinhart -= 273; 
       delay(100);
       tft.setTextColor(WHITE,BLACK);                          
   tft.setTextSize(3);    // устанавливаем маленький шрифт  
float tempsn;
tempsn=steinhart;
tft.setCursor(380, 280);
char m[6];
dtostrf(tempsn,5,1,m);
tft.println(m);
  

//tft.setCursor(380, 280);
//tft.print(steinhart-26);
  
 
  
  
  

}

// ----------- тахометр-------/////
int getRPM()
{
int kount=0;
boolean kflag=LOW;
unsigned long currentTime=0;
unsigned long startTime=millis();
while (currentTime<=sampleTime)
{
if (digitalRead(tachPIN)==HIGH)
{
kflag=HIGH;
}
if (digitalRead(tachPIN)==LOW && kflag==HIGH)
{
kount++;
kflag=LOW;
}

currentTime=millis()-startTime;
}
int kount2rpm = int(29400./float(sampleTime))*kount;
return kount2rpm;

}

  //----------------------------////  
   ////-------спидометр--------///
   int getSPEED()
{
int kount2=0;
boolean kflag2=LOW;
unsigned long currentTime2=0;
unsigned long startTime2=millis();
while (currentTime2<=sampleTime2)
{
if (digitalRead(speedPIN)==HIGH)
{
kflag2=HIGH;
}
if (digitalRead(speedPIN)==LOW && kflag2==HIGH)
{
kount2++;
kflag2=LOW;
}
currentTime2=millis()-startTime2;
}
int kount2racxod = int(25325./float(sampleTime2))*kount2;
return kount2racxod;
}
///---------------------------------------------------////
        ///-------форсунки------------////   

   int getFORS()
{
int kount3=0;
boolean kflag3=LOW;
unsigned long currentTime3=0;
unsigned long startTime3=millis();
while (currentTime3<=sampleTime3)
{
if (digitalRead(INJECTOR_PIN)==HIGH)
{
kflag3=HIGH;
}
if (digitalRead(INJECTOR_PIN)==LOW && kflag3==HIGH)
{
kount3++;
kflag3=LOW;
}
currentTime3=millis()-startTime3;
}
int kount3racxod = int(10000./float(sampleTime3))*kount3;
return kount3racxod;
}








// This function opens a Windows Bitmap (BMP) file and
// displays it at the given coordinates.  It's sped up
// by reading many pixels worth of data at a time
// (rather than pixel by pixel).  Increasing the buffer
// size takes more of the Arduino's precious RAM but
// makes loading a little faster.  20 pixels seems a
// good balance.

#define BUFFPIXEL 20

void bmpDraw(char *filename, int x, int 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 in buffer (R+G+B per pixel)
  uint16_t lcdbuffer[BUFFPIXEL];  // pixel out buffer (16-bit 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();
  uint8_t  lcdidx = 0;
  boolean  first = true;

  if((x >= tft.width()) || (y >= tft.height())) return;

#ifdef DEBUG
  tft.fillScreen(0);
  tft.setCursor(0,0);
  tft.print(F("Loading image '"));
  tft.print(filename);
  tft.println('\'');
#endif
  // Open requested file on SD card
  if ((bmpFile = SD.open(filename)) == NULL) {
    #ifdef DEBUG
    tft.println(F("File not found"));
    #endif
    return;
  }

  // Parse BMP header
  if(read16(bmpFile) == 0x4D42) {
      // BMP signature
    #ifdef DEBUG
    tft.println(F("File size: ")); tft.println(read32(bmpFile));
    #else
        read32(bmpFile);
    #endif
    (void)read32(bmpFile); // Read & ignore creator bytes
    bmpImageoffset = read32(bmpFile); // Start of image data
    #ifdef DEBUG
    tft.print(F("Image Offset: ")); tft.println(bmpImageoffset, DEC);
    // Read DIB header
    tft.print(F("Header size: ")); tft.println(read32(bmpFile));
    #else
    read32(bmpFile);
    #endif

    bmpWidth  = read32(bmpFile);
    bmpHeight = read32(bmpFile);
    if(read16(bmpFile) == 1) { // # planes -- must be '1'
      bmpDepth = read16(bmpFile); // bits per pixel
      #ifdef DEBUG
      Serial.print(F("Bit Depth: ")); Serial.println(bmpDepth);
      #endif
      if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed

        goodBmp = true; // Supported BMP format -- proceed!
        #ifdef DEBUG
        tft.print(F("Image size: "));
        tft.print(bmpWidth);
        tft.print('x');
        tft.println(bmpHeight);
        delay(3000);
        #endif
        // 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) >= tft.width())  w = tft.width()  - x;
        if((y+h-1) >= tft.height()) h = tft.height() - y;

        // Set TFT address window to clipped image bounds
        tft.setAddrWindow(x, y, x+w-1, y+h-1);

        for (row=0; row<h; row++) { // For each scanline...
          // 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
          }

          for (col=0; col<w; col++) { // For each column...
            // Time to read more pixel data?
            if (buffidx >= sizeof(sdbuffer)) { // Indeed
              // Push LCD buffer to the display first
              if(lcdidx > 0) {
                tft.pushColors(lcdbuffer, lcdidx, first);
                lcdidx = 0;
                first  = false;
              }
              bmpFile.read(sdbuffer, sizeof(sdbuffer));
              buffidx = 0; // Set index to beginning
            }

            // Convert pixel from BMP to TFT format
            b = sdbuffer[buffidx++];
            g = sdbuffer[buffidx++];
            r = sdbuffer[buffidx++];
            lcdbuffer[lcdidx++] = tft.color565(r,g,b);
          } // end pixel
        } // end scanline
        // Write any remaining data to LCD
        if(lcdidx > 0) {
          tft.pushColors(lcdbuffer, lcdidx, first);
        }

      } // end goodBmp
    }
  }

  bmpFile.close();
  if(!goodBmp) tft.println(F("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;
}






//Русские буквы
String utf8rus(String source)
{
  int i,k;
  String target;
  unsigned char n;
  char m[2] = { '0', '\0' };

  k = source.length(); i = 0;

  while (i < k) {
    n = source[i]; i++;

    if (n >= 0xC0) {
      switch (n) {
        case 0xD0: {
          n = source[i]; i++;
          if (n == 0x81) { n = 0xA8; break; }
          if (n >= 0x90 && n <= 0xBF) n = n-1 + 0x30;
          break;
        }
        case 0xD1: {
          n = source[i]; i++;
          if (n == 0x91) { n = 0xB8; break; }
          if (n >= 0x80 && n <= 0x8F) n = n -1 + 0x70;
          break;
        }
      }
    }
    m[0] = n; target = target + String(m);
  }
return target;
}

 

rkit
Offline
Зарегистрирован: 23.11.2016

Спасибо за информацию. Держите нас в курсе.

shurf83
Offline
Зарегистрирован: 10.07.2019

Это как выглядит в живую. 

https://prnt.sc/142g3js

https://prnt.sc/142g9k8

b707
Offline
Зарегистрирован: 26.05.2017

shurf83 пишет:

В общем-то все работаем, но обновление информации происходит 1 раз в 3 секунды, а хотелось бы мгновенно.

"хотелось бы" - меняйте код.

В коде задержка 1 сек - измерение RPM, 1 секунда - замер расхода и еще 1 секунда - замер скорости. Вот и выходит, что быстрее трех секунд обновление инфы невозможно.

Да и весь код написан в абсолютно линейном последовательном стиле: - делаем первое... делаем второе... делаем третье... .... делаем тридцатое....  не код, а детский сад, пособие новичку "как не следует писать"

программы, требующие мгновенного отклика - так не пишут. Переписывайте все измерения, чтобы они выполнялись одновременно.

shurf83
Offline
Зарегистрирован: 10.07.2019

спс. буду изучать. Это первый серьезный проект. хоть толкнули в направлении.

b707
Offline
Зарегистрирован: 26.05.2017

ну вот например измерения оборотов, расхода и скорости в коде - три абсолютно одинаковых цикла длиной в 1 секунду, только величины разные. Самое простое - запихнуть измерение всех трех величин в один цикл, тогда хотя бы в сумме это будет занимать секунду, а не три

shurf83
Offline
Зарегистрирован: 10.07.2019

 

b707
Offline
Зарегистрирован: 26.05.2017

что это?

shurf83
Offline
Зарегистрирован: 10.07.2019

понял. опозорился походу спать пора

есть такая библиотека. мож через нее?

#include <Thread.h>

 

b707
Offline
Зарегистрирован: 26.05.2017

зачем? Вы без библиотеки не можете содержимое трех циклов перенести в один? Там ведь нет ОДНОВРЕМЕННЫХ процессов, для чего нужна сложная библиотека, просто у вас в цикле опрашивается пин. Сначала в первом цикле - один пин, потом во втором цикле - другой...

Что мешает прямо в первом цмкле опросить сразу три пина и посчитать все три величины? Думайте, задачка вообще элементарная...

shurf83
Offline
Зарегистрирован: 10.07.2019
int getRPM()
{
int kount=0;
boolean kflag=LOW;
unsigned long currentTime=0;
unsigned long startTime=millis();
while (currentTime<=sampleTime)
{
if (digitalRead(tachPIN)==HIGH)
{
kflag=HIGH;
}
if (digitalRead(tachPIN)==LOW && kflag==HIGH)
{
kount++;
kflag=LOW;
}

currentTime=millis()-startTime;
}
int kount2rpm = int(29400./float(sampleTime))*kount;
return kount2rpm;

}

  //----------------------------////  
   ////-------спидометр--------///
int getSPEED()
{
int kount2=0;
boolean kflag2=LOW;
unsigned long currentTime=0;
unsigned long startTime=millis();
while (currentTime<=sampleTime)
{
if (digitalRead(speedPIN)==HIGH)
{
kflag2=HIGH;
}
if (digitalRead(speedPIN)==LOW && kflag2==HIGH)
{
kount2++;
kflag2=LOW;
}
currentTime=millis()-startTime;
}
int kount2racxod = int(25325./float(sampleTime))*kount2;
return kount2racxod;
}
///---------------------------------------------------////
        ///-------форсунки------------////   

int getFORS()
{
int kount3=0;
boolean kflag3=LOW;
unsigned long currentTime=0;
unsigned long startTime=millis();
while (currentTime<=sampleTime)
{
if (digitalRead(INJECTOR_PIN)==HIGH)
{
kflag3=HIGH;
}
if (digitalRead(INJECTOR_PIN)==LOW && kflag3==HIGH)
{
kount3++;
kflag3=LOW;
}
currentTime=millis()-startTime;
}
int kount3racxod = int(10000./float(sampleTime))*kount3;
return kount3racxod;
}

так?

то есть использовать толь 1 const unsigned long sampleTime=1000;

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Мда. 

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Видимо писал не сам.

shurf83
Offline
Зарегистрирован: 10.07.2019

ага, списывал

 

b707
Offline
Зарегистрирован: 26.05.2017

shurf83 пишет:

ага, списывал

 


Шурф, при таком уровне владения языком я не в состоянии вам помочь, извините

shurf83
Offline
Зарегистрирован: 10.07.2019

и на том спасибо. Это первый проект, не считая включения светодиодов, ну и часов с температурой и влажностью на лсд

 

 

а , если честно, я и так рад , что смог хоть так осилить  этот БК и он работает! Есть недочеты, но для первого раза - сойдет 

b707
Offline
Зарегистрирован: 26.05.2017

Тут у нас регулярно появляются "борцы за правду", обвиняющие форум в нетерпимости к новичкам. Где же вы теперь, покажите свою доброту, напишите человеку код... Эдик-создатель, ты так распинался в платном разделе на днях, твой выход!

b707
Offline
Зарегистрирован: 26.05.2017

shurf83 пишет:

а , если честно, я и так рад , что смог хоть так осилить  этот БК и он работает! Есть недочеты, но для первого раза - сойдет 


надо двигаться дальше

shurf83
Offline
Зарегистрирован: 10.07.2019

конечно, буду изучать. Вам спасибо, в один недочет кода носом ткнули.

 

 

конечно, желание форумом пользоваться, точнее писать в нем, в ближайшее время охота отпала(

shurf83
Offline
Зарегистрирован: 10.07.2019

#include <iarduino_RTC.h>
iarduino_RTC time(RTC_DS1307);

#include <DHT.h>
#include <DHT_U.h>
#define B 3950 // B-коэффициент
#define SERIAL_R 10000 // сопротивление последовательного резистора, 10 кОм
#define THERMISTOR_R 10000 // номинальное сопротивления термистора, 10 кОм
#define NOMINAL_T 25 // номинальная температура (при которой TR = 10 кОм)
 
const byte tempoPin = A12;




#define DHTTYPE DHT11
#define DHTPIN 41
DHT dht(DHTPIN, DHTTYPE);


#include <Adafruit_GFX.h>    // Core graphics library

#include <SPI.h>
#include <SD.h>
#include <MCUFRIEND_kbv.h>   // Hardware-specific library



#include <OneWire.h>
#include <Wire.h>
//const extern uint8_t FreeSans9pt7b
#include "Fonts/FreeSansBold24pt7b.h"    // когда вам нужны другие шрифты
    MCUFRIEND_kbv tft;

#define LCD_CS A3 // Chip Select goes to Analog 3
#define LCD_CD A2 // Command/Data goes to Analog 2
#define LCD_WR A1 // LCD Write goes to Analog 1
#define LCD_RD A0 // LCD Read goes to Analog 0



#define SD_CS 53     // Set the chip select line to whatever you use (10 doesnt conflict with the library)



//------------------------------///


#define BLACK 0x0000
#define NAVY 0x000F
#define DARKGREEN 0x03E0
#define DARKCYAN 0x03EF
#define MAROON 0x7800
#define PURPLE 0x780F
#define OLIVE 0x7BE0
#define LIGHTGREY 0xC618
#define DARKGREY 0x7BEF
#define BLUE 0x001F
#define GREEN 0x07E0
#define CYAN 0x07FF
#define RED 0xF800
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
#define ORANGE 0xFD20
#define GREENYELLOW 0xAFE5
#define PINK 0xF81F


void setup()
{

  //tft.reset();
dht.begin();
time.begin(); 
  Serial.begin(9600);
  uint16_t ID = tft.readID();
  Serial.println("Example: Font_simple");
    Serial.print("found ID = 0x");
    Serial.println(ID, HEX);
    if (ID == 0xD3D3) ID = 0x9481; //force ID if write-only display
    tft.begin(ID);
    Wire.begin();
  //tft.setTextSize(2);
  //tft.fillScreen(0);
  tft.setRotation(1);
 
  if (!SD.begin(SD_CS )) {
    
    return;
  }
 


//-----------------------------------//
  bmpDraw("OPEL3.bmp", 0, 0);
delay(5000);
//tft.reset();
//delay(1);
 tft.fillScreen( BLACK);

}


void loop()
{


   
//delay(2000);
float h = dht.readHumidity();   // считывание влажности
float t = dht.readTemperature();   // считывание температуры
tft.setTextColor(WHITE,BLACK);
 tft.setTextSize(3);
 tft.setCursor(5,270);
  tft.print(h);
  tft.setTextSize(3);
 tft.setCursor(5,230);
  tft.print(t);
  tft.setCursor(105,270);
  tft.print("%");
  tft.setCursor(105,230);
  tft.print("C");
  tft.setTextColor(BLUE,BLACK);
  tft.setCursor(10,185);
  tft.print(utf8rus("ВНУТРИ")); // ВНУТРИ
  
 tft.setCursor(85,52);
  tft.print(utf8rus("МГ"));   // РАСХОД
  tft.setCursor(3,140);
  //tft.print(utf8rus("Л/Ч"));
  tft.setCursor(380,50);
  tft.print(utf8rus("ТОСОЛ"));
  tft.setTextSize(2);
  tft.setCursor(380,245);
  tft.print(utf8rus("За окном"));

  
  // темп двиг (среднее от 100 замеров)
long valtemp = 0;
for (int kd=0; kd<100; ++kd) {
valtemp = valtemp + analogRead(A10);
}
valtemp = valtemp/100;
float voltemp = map(valtemp,750,0,0,1200);
voltemp = voltemp/10;
float temp3=voltemp;
int z = temp3;
tft.setTextColor(WHITE,BLACK);
  tft.setTextSize(5); 
tft.setCursor(375,100);
char d[5];
sprintf(d,"%3d",z);
tft.println(d);


  // напряжение (среднее от 100 замеров)
long valvolt = 0;
for (int k=0; k<100; ++k) {
valvolt = valvolt + analogRead(A8); // на панели припаян
}
valvolt = valvolt/100;
float voltage = map(valvolt, 0,1725,0,150);
voltage = voltage/5;


  tft.setTextColor(WHITE,BLACK);
  tft.setTextSize(3);
  tft.setCursor(380,215);
  tft.print(voltage);
  tft.setTextColor(BLUE,BLACK);
  tft.setCursor(380,185);
  tft.print(utf8rus("ЗАРЯД"));
  
  
  
  
  tft.drawFastHLine(365,240,115,0xFFFF);
   tft.drawFastHLine(0,170,480,0xFFFF);                                                 
   tft.drawFastHLine(0,40,480,0xFFFF);
tft.drawLine(130,170,170,210,0xFFFF);
tft.drawLine(365,170,325,210,0xFFFF);
tft.drawFastHLine(170,210,155,0xFFFF); 
tft.drawLine(130,40,130,380,0xFFFF);// верт полоска левая
tft.drawLine(365,40,365,380,0xFFFF);// верт полоска левая


//--------скорость--------//
long valsped = 0;
for (int kd=0; kd<100; ++kd) {
valsped = valsped + analogRead(19);
}
valsped = valsped/100;
float volsped = map(valsped,750,0,0,1200);
volsped = volsped/10;
float sped=volsped;
int q = sped;
tft.setTextColor(RED,BLACK);
  tft.setTextSize(13); 
tft.setCursor(131,60);
char s[5];
sprintf(s,"%3d",q);
tft.println(s);


//----------тахо---------//
long valrpm = 0;
for (int kd=0; kd<100; ++kd) {
valrpm = valrpm + analogRead(18);
}
valrpm = valrpm/100;
float volrpm = map(valrpm,750,0,0,1200);
volrpm = volrpm/10;
float rpm=volrpm;
  int n = rpm;
  tft.setTextColor(DARKGREY,BLACK);
  tft.setTextSize(8); 
tft.setCursor(155,225);
char o[6];
sprintf(o,"%4d",n);
tft.print(o);

// форсунки
  tft.setTextColor(WHITE,BLACK);
long valfors = 0;
for (int kd=0; kd<100; ++kd) {
valfors = valfors + analogRead(A9);
}
valfors = valfors/100;
float volfors = map(valfors,750,0,0,1200);
volfors = volfors/10;
float fors=volfors;
 float racxod=rpm*fors/100000; 
//if (racxod < 10)
  //int f = fors;
  tft.setTextSize(3);
  tft.setCursor(0,52);
  //char y[5];
//sprintf(y,"%3d",f);
tft.println(racxod);
//if  (racxod >= 10)
//  tft.setCursor(20,85);
//tft.println(racxod);
tft.setTextSize(5);
  tft.setCursor(5,90);
tft.print("");



  //tft.print("6,7");
//  tft.print(fuelInHouR);


tft.setTextColor(WHITE,BLACK);                          
   tft.setTextSize(3);    // устанавливаем маленький шрифт                  
  
  tft.setCursor(180,300);
  tft.print("TAXOMETP");


tft.setTextColor(WHITE,BLACK);                          
   tft.setTextSize(3);    // устанавливаем маленький шрифт                  
  
  tft.setCursor(180,180);
  tft.print("CKOPOCTb");
  
  
  
  
  tft.setCursor(15,15);
  tft.print(time.gettime("d-m-Y"));  
  tft.setCursor(350,15);
  tft.print(time.gettime("H:i")); 

 // наружняя температура(среднее от 1000 замеров)
int t1 = analogRead( tempoPin );
    float tr = 1023.0 / t1 - 1;
    tr = SERIAL_R / tr;
   
    float steinhart;
    steinhart = tr / THERMISTOR_R; // (R/Ro)
    steinhart = log(steinhart); // ln(R/Ro)
    steinhart /= B; // 1/B * ln(R/Ro)
    steinhart += 1.0 / (NOMINAL_T + 273); // + (1/To)
    steinhart = 1.0 / steinhart; // Invert
    steinhart -= 273; 
       delay(100);
       tft.setTextColor(WHITE,BLACK);                          
   tft.setTextSize(3);    // устанавливаем маленький шрифт  
float tempsn;
tempsn=steinhart;
tft.setCursor(380, 280);
char m[6];
dtostrf(tempsn,5,1,m);
tft.println(m);
  

//tft.setCursor(380, 280);
//tft.print(steinhart-26);
  
 
  
  
  

}








// This function opens a Windows Bitmap (BMP) file and
// displays it at the given coordinates.  It's sped up
// by reading many pixels worth of data at a time
// (rather than pixel by pixel).  Increasing the buffer
// size takes more of the Arduino's precious RAM but
// makes loading a little faster.  20 pixels seems a
// good balance.

#define BUFFPIXEL 20

void bmpDraw(char *filename, int x, int 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 in buffer (R+G+B per pixel)
  uint16_t lcdbuffer[BUFFPIXEL];  // pixel out buffer (16-bit 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();
  uint8_t  lcdidx = 0;
  boolean  first = true;

  if((x >= tft.width()) || (y >= tft.height())) return;

#ifdef DEBUG
  tft.fillScreen(0);
  tft.setCursor(0,0);
  tft.print(F("Loading image '"));
  tft.print(filename);
  tft.println('\'');
#endif
  // Open requested file on SD card
  if ((bmpFile = SD.open(filename)) == NULL) {
    #ifdef DEBUG
    tft.println(F("File not found"));
    #endif
    return;
  }

  // Parse BMP header
  if(read16(bmpFile) == 0x4D42) {
      // BMP signature
    #ifdef DEBUG
    tft.println(F("File size: ")); tft.println(read32(bmpFile));
    #else
        read32(bmpFile);
    #endif
    (void)read32(bmpFile); // Read & ignore creator bytes
    bmpImageoffset = read32(bmpFile); // Start of image data
    #ifdef DEBUG
    tft.print(F("Image Offset: ")); tft.println(bmpImageoffset, DEC);
    // Read DIB header
    tft.print(F("Header size: ")); tft.println(read32(bmpFile));
    #else
    read32(bmpFile);
    #endif

    bmpWidth  = read32(bmpFile);
    bmpHeight = read32(bmpFile);
    if(read16(bmpFile) == 1) { // # planes -- must be '1'
      bmpDepth = read16(bmpFile); // bits per pixel
      #ifdef DEBUG
      Serial.print(F("Bit Depth: ")); Serial.println(bmpDepth);
      #endif
      if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed

        goodBmp = true; // Supported BMP format -- proceed!
        #ifdef DEBUG
        tft.print(F("Image size: "));
        tft.print(bmpWidth);
        tft.print('x');
        tft.println(bmpHeight);
        delay(3000);
        #endif
        // 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) >= tft.width())  w = tft.width()  - x;
        if((y+h-1) >= tft.height()) h = tft.height() - y;

        // Set TFT address window to clipped image bounds
        tft.setAddrWindow(x, y, x+w-1, y+h-1);

        for (row=0; row<h; row++) { // For each scanline...
          // 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
          }

          for (col=0; col<w; col++) { // For each column...
            // Time to read more pixel data?
            if (buffidx >= sizeof(sdbuffer)) { // Indeed
              // Push LCD buffer to the display first
              if(lcdidx > 0) {
                tft.pushColors(lcdbuffer, lcdidx, first);
                lcdidx = 0;
                first  = false;
              }
              bmpFile.read(sdbuffer, sizeof(sdbuffer));
              buffidx = 0; // Set index to beginning
            }

            // Convert pixel from BMP to TFT format
            b = sdbuffer[buffidx++];
            g = sdbuffer[buffidx++];
            r = sdbuffer[buffidx++];
            lcdbuffer[lcdidx++] = tft.color565(r,g,b);
          } // end pixel
        } // end scanline
        // Write any remaining data to LCD
        if(lcdidx > 0) {
          tft.pushColors(lcdbuffer, lcdidx, first);
        }

      } // end goodBmp
    }
  }

  bmpFile.close();
  if(!goodBmp) tft.println(F("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;
}






//Русские буквы
String utf8rus(String source)
{
  int i,k;
  String target;
  unsigned char n;
  char m[2] = { '0', '\0' };

  k = source.length(); i = 0;

  while (i < k) {
    n = source[i]; i++;

    if (n >= 0xC0) {
      switch (n) {
        case 0xD0: {
          n = source[i]; i++;
          if (n == 0x81) { n = 0xA8; break; }
          if (n >= 0x90 && n <= 0xBF) n = n-1 + 0x30;
          break;
        }
        case 0xD1: {
          n = source[i]; i++;
          if (n == 0x91) { n = 0xB8; break; }
          if (n >= 0x80 && n <= 0x8F) n = n -1 + 0x70;
          break;
        }
      }
    }
    m[0] = n; target = target + String(m);
  }
return target;
}

 

 

так?