Бортовой компьютер для автомобиля с 3.5 TFT дисплеем
- Войдите на сайт для отправки комментариев
Сб, 05/06/2021 - 00:33
Здравствуйте, уважаемые спецы. В общем-то все работаем, но обновление информации происходит 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; }
Спасибо за информацию. Держите нас в курсе.
Это как выглядит в живую.
https://prnt.sc/142g3js
https://prnt.sc/142g9k8
В общем-то все работаем, но обновление информации происходит 1 раз в 3 секунды, а хотелось бы мгновенно.
"хотелось бы" - меняйте код.
В коде задержка 1 сек - измерение RPM, 1 секунда - замер расхода и еще 1 секунда - замер скорости. Вот и выходит, что быстрее трех секунд обновление инфы невозможно.
Да и весь код написан в абсолютно линейном последовательном стиле: - делаем первое... делаем второе... делаем третье... .... делаем тридцатое.... не код, а детский сад, пособие новичку "как не следует писать"
программы, требующие мгновенного отклика - так не пишут. Переписывайте все измерения, чтобы они выполнялись одновременно.
спс. буду изучать. Это первый серьезный проект. хоть толкнули в направлении.
ну вот например измерения оборотов, расхода и скорости в коде - три абсолютно одинаковых цикла длиной в 1 секунду, только величины разные. Самое простое - запихнуть измерение всех трех величин в один цикл, тогда хотя бы в сумме это будет занимать секунду, а не три
что это?
понял. опозорился походу спать пора
есть такая библиотека. мож через нее?
зачем? Вы без библиотеки не можете содержимое трех циклов перенести в один? Там ведь нет ОДНОВРЕМЕННЫХ процессов, для чего нужна сложная библиотека, просто у вас в цикле опрашивается пин. Сначала в первом цикле - один пин, потом во втором цикле - другой...
Что мешает прямо в первом цмкле опросить сразу три пина и посчитать все три величины? Думайте, задачка вообще элементарная...
так?
то есть использовать толь 1 const unsigned long sampleTime=1000;
Мда.
Видимо писал не сам.
ага, списывал
ага, списывал
Шурф, при таком уровне владения языком я не в состоянии вам помочь, извините
и на том спасибо. Это первый проект, не считая включения светодиодов, ну и часов с температурой и влажностью на лсд
а , если честно, я и так рад , что смог хоть так осилить этот БК и он работает! Есть недочеты, но для первого раза - сойдет
Тут у нас регулярно появляются "борцы за правду", обвиняющие форум в нетерпимости к новичкам. Где же вы теперь, покажите свою доброту, напишите человеку код... Эдик-создатель, ты так распинался в платном разделе на днях, твой выход!
а , если честно, я и так рад , что смог хоть так осилить этот БК и он работает! Есть недочеты, но для первого раза - сойдет
надо двигаться дальше
конечно, буду изучать. Вам спасибо, в один недочет кода носом ткнули.
конечно, желание форумом пользоваться, точнее писать в нем, в ближайшее время охота отпала(
так?