Посоветуйте по автомобильному спидометру.

Тарас Петрович
Offline
Зарегистрирован: 21.11.2015

Доброго времени суток! Делаю, с позволения сказать, бортовой компьютер для жигулей. Требуется измерять остаток бензина в баке, скорость, пробег. Пробег нужно скидывать в еепром. Делать это каждую секунду-минуту- не хочу, кончится ресурс перезаписи. Надо пробег писать, когда движок глушу. Не знаю, как отловить этот момент. Загвоздка в том, что хочу полностью отключать питание устройства при отключении зажигания. Видел где-то решение на тини 2313, там когда напруга пропадала, аналоговый компаратор прерывание вызывал, и скидывал инфу в память , пользуясь напругой, с разряжающегося конденсатора по питанию. В 328 меге комаратора нет, а АЦП к этой задаче не прикрутишь. Что бы придумать?

И ещё вопрос. По измерению уровня бензина. Напряжение бортсети (плюс) идёт через обмотку показометра на датчик (реостат). Второй хвост реостата сидит на массе. Напряжение в бортсети меняется, катушка не только нелинейна по импедансу, так ещё и на температуру реагирует (в части активного сопротивления, разумеется). Поплавок в баке прыгает. Так вот, с сопротивлением катушки я ничего не придумаю, а напряжение на эту цепь застабилизировать можно. Но нужен стабилизатор на 12 В и около 0,1А  с очень малым падением (чтоб не нарушать работу штатного прибора), 7812 тут не поможет, он чуть не полтора вольта теряет. Посоветуйте, какой взять из общедоступных! Параллельно датчику уровня топлива хочу повесить конденсатор, тысяч на 20 микрофарад, чтоб нивелировать плескание топлива и резкое изменение напряжения с поплавка. Думаю, АЦП Ардуины на конденсатор не обидится?

Спасибо кто дочитал!

Andy
Andy аватар
Offline
Зарегистрирован: 01.01.2016

Тарас Петрович пишет:
Что бы придумать?
Всё уже придумано до нас.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Тарас Петрович пишет:

В 328 меге комаратора нет, а АЦП к этой задаче не прикрутишь. Что бы придумать?

Как это компаратора нет? Загляните в  даташит, стр. 234 

Тарас Петрович
Offline
Зарегистрирован: 21.11.2015

To Dimax: Спасибо, и действительно есть. Конечно средствами IDE туда не добраться, но с прерыванием от WDT по вашим советам разобрался, может, и здесь чего найду.

To Andi: Интересная схема, буду изучать, устройство похоже на промышленное (многое предусмотрено), подскажите, пожалуйста, источник схемы, почитаю описание.

 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Тарас Петрович, я про работу с компаратором частенько писал, вот три ссылки из моих закладок: измеритель ёмкости  прерывание для кнопки  датчик вибрации  может поможет разобраться ..

Andy
Andy аватар
Offline
Зарегистрирован: 01.01.2016

Тарас Петрович пишет:
To Andi: Интересная схема, буду изучать, устройство похоже на промышленное (многое предусмотрено), подскажите, пожалуйста, источник схемы, почитаю описание.
Двое парней из Питера лет 15 назад разработали маршрутный компьютер для ВАЗ 2110, их сайт "приказал долго жить", вот все что удалось найти.

Тарас Петрович
Offline
Зарегистрирован: 21.11.2015

Andy, спасибо почитал. Там, конечно, серьёзные программисты работали (и с can шиной подружили контроллер, и с часами, и с кнопками, и с диплеем)-мне такое рановато.

Ещё уточняющий вопрос по стабилизатору: Прикупил я две микросхемы KA78R12 и LM2940-CT, обе обещают до 0,5В падение (опять ток бензодатчика не померил), ну до ампера должен быть. На выходе стабилизатора будет висеть немалая ёмкость (демпфирование колебаний датчика). Так вот, не обидится ли микросхема на потенциал на выходе после отключения входного напряжения (типа обратка получается, правда, полярность верная)? Тот же вопрос с питанием Ардуины. Мне ёмкости должно хватить на запись пробега в EEPROM (по прерыванию от компаратора, когда плюс после замка "закончился", а на конденсаторе фильтра ещё остался), а перед Ардуиной будет кренка на 5В стоять?

Andy
Andy аватар
Offline
Зарегистрирован: 01.01.2016

Тарас Петрович пишет:
На выходе стабилизатора будет висеть немалая ёмкость (демпфирование колебаний датчика). Так вот, не обидится ли микросхема на потенциал на выходе после отключения входного напряжения (типа обратка получается, правда, полярность верная)?
Так ведь на входе стабилизатора по определению тоже будет висеть емкость, и её нагрузкой будет являться стабилизатор, поэтому напряжение на входе будет уменьшаться вслед за напряжением на выходе. Но даже если взять и подать на выход стабилизатора напряжение извне, получим лишь обратносмещенный транзистор в стабилизаторе.

Тарас Петрович пишет:
Тот же вопрос с питанием Ардуины. Мне ёмкости должно хватить на запись пробега в EEPROM (по прерыванию от компаратора, когда плюс после замка "закончился", а на конденсаторе фильтра ещё остался), а перед Ардуиной будет кренка на 5В стоять?
Парни из Питера не стали гадать, хватит ёмкости или нет, а просто программно управляют питанием (через диод D8). Пока есть сигнал с контроллера, есть и питание на нем. Сняли сигнал - пропало питание. Т.е. идея такая: выключили зажигание, контроллер сделал свои дела и тоже отключился.

Тарас Петрович
Offline
Зарегистрирован: 21.11.2015

С питанием в общем определился, ардуине аккумулятор не съесть, пусть только проверяет, включено ли зажигание. Теперь возник вопрос с выводом цифр на дисплей 20х4. Нашёл на Ардуино.цц код из темы о выводе крупных цифр ( http://forum.arduino.cc/index.php/topic,44427.0.html ), код, как пишут, должен работать со стандартной библиотекой ЛиквидКристал, но не работает.

#include <LiquidCrystal.h>
LiquidCrystal lcd(2, 3, 4, 5, 6, 7, 8);

byte custchar[8][8] = {
 {
   B11111,
   B11111,
   B11111,
   B00000,
   B00000,
   B00000,
   B00000,
   B00000
 }, {
   B00000,
   B00000,
   B00000,
   B00000,
   B00000,
   B11111,
   B11111,
   B11111
 }, {
   B11111,
   B11111,
   B11111,
   B00000,
   B00000,
   B11111,
   B11111,
   B11111
 }, {
   B00000,
   B00000,
   B00000,
   B00000,
   B00000,
   B01110,
   B01110,
   B01110
 }, {
   B00000,
   B00000,
   B00000,
   B01110,
   B01110,
   B01110,
   B00000,
   B00000
 }, {
   B00000,
   B00000,
   B00000,
   B00000,
   B00000,
   B00000,
   B00000,
   B00000
 }, {
   B00000,
   B00000,
   B00000,
   B00000,
   B00000,
   B00000,
   B00000,
   B00000
 }, {
   B00000,
   B00000,
   B00000,
   B00000,
   B00000,
   B00000,
   B00000,
   B00000
 }
};

byte bignums[10][2][3] = {
 {
   {255, 0, 255},
   {255, 1, 255}
 },{
   {0, 255, 254},
   {1, 255, 1}
 },{
   {2, 2, 255},
   {255, 1, 1}
 },{
   {0, 2, 255},
   {1, 1, 255}
 },{
   {255, 1, 255},
   {254, 254, 255}
 },{
   {255, 2, 2},
   {1, 1, 255}
 },{
   {255, 2, 2},
   {255, 1, 255}
 },{
   {0, 0, 255},
   {254, 255, 254}
 },{
   {255, 2, 255},
   {255, 1, 255}
 },{
   {255, 2, 255},
   {254, 254, 255}
 }
};

void loadchars() {
 lcd.command(64);
 for (int i = 0; i < 8; i++)
   for (int j = 0; j < 8; j++)
     lcd.write(custchar[j]);
 lcd.home();
}

void printbigchar(byte digit, byte col, byte row, byte symbol = 0) {
 if (digit > 9) return;
 for (int i = 0; i < 2; i++) {
   lcd.setCursor(col, row + i);
   for (int j = 0; j < 3; j++) {
     lcd.write(bignums[digit][j]);
   }
   lcd.write(254);
 }
 if (symbol == 1) {
   lcd.setCursor(col + 3, row + 1);
   lcd.write(3);
 } else if (symbol == 2) {
   lcd.setCursor(col + 3, row);
   lcd.write(4);
   lcd.setCursor(col + 3, row + 1);
   lcd.write(4);
 }
 
 lcd.setCursor(col + 4, row);
}

void setup() {
 pinMode(13, OUTPUT);
 loadchars();
 digitalWrite(13, 1);
 
 printbigchar(0, 0, 0);
 printbigchar(1, 4, 0);
 printbigchar(2, 8, 0);
 printbigchar(3, 12, 0);
 printbigchar(4, 16, 0, 1);
 printbigchar(5, 0, 2);
 printbigchar(6, 4, 2);
 printbigchar(7, 8, 2);
 printbigchar(8, 12, 2);
 printbigchar(9, 16, 2, 2);
}

void loop() {}

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

C:\Users\user\Documents\Arduino\sketch_jun17a\sketch_jun17a.ino: In function 'void loadchars()':

sketch_jun17a:118: error: call of overloaded 'write(byte [8])' is ambiguous

      lcd.write(custchar[j]);

                           ^

C:\Users\user\Documents\Arduino\sketch_jun17a\sketch_jun17a.ino:118:27: note: candidates are:

In file included from C:\Users\user\Documents\Arduino\sketch_jun17a\sketch_jun17a.ino:1:0:

C:\Program Files\Arduino\libraries\LiquidCrystal\src/LiquidCrystal.h:83:18: note: virtual size_t LiquidCrystal::write(uint8_t) <near match>

   virtual size_t write(uint8_t);

                  ^

C:\Program Files\Arduino\libraries\LiquidCrystal\src/LiquidCrystal.h:83:18: note:   no known conversion for argument 1 from 'byte [8] {aka unsigned char [8]}' to 'uint8_t {aka unsigned char}'

In file included from C:\Program Files\Arduino\hardware\arduino\avr\cores\arduino/Stream.h:26:0,

                 from C:\Program Files\Arduino\hardware\arduino\avr\cores\arduino/HardwareSerial.h:29,

                 from C:\Program Files\Arduino\hardware\arduino\avr\cores\arduino/Arduino.h:224,

                 from sketch\sketch_jun17a.ino.cpp:1:

C:\Program Files\Arduino\hardware\arduino\avr\cores\arduino/Print.h:49:12: note: size_t Print::write(const char*) <near match>

     size_t write(const char *str) {

            ^

C:\Program Files\Arduino\hardware\arduino\avr\cores\arduino/Print.h:49:12: note:   no known conversion for argument 1 from 'byte [8] {aka unsigned char [8]}' to 'const char*'

C:\Users\user\Documents\Arduino\sketch_jun17a\sketch_jun17a.ino: In function 'void printbigchar(byte, byte, byte, byte)':

sketch_jun17a:127: error: call of overloaded 'write(byte [3])' is ambiguous

      lcd.write(bignums[digit][j]);

                                 ^

C:\Users\user\Documents\Arduino\sketch_jun17a\sketch_jun17a.ino:127:33: note: candidates are:

In file included from C:\Users\user\Documents\Arduino\sketch_jun17a\sketch_jun17a.ino:1:0:

C:\Program Files\Arduino\libraries\LiquidCrystal\src/LiquidCrystal.h:83:18: note: virtual size_t LiquidCrystal::write(uint8_t) <near match>

   virtual size_t write(uint8_t);

                  ^

C:\Program Files\Arduino\libraries\LiquidCrystal\src/LiquidCrystal.h:83:18: note:   no known conversion for argument 1 from 'byte [3] {aka unsigned char [3]}' to 'uint8_t {aka unsigned char}'

In file included from C:\Program Files\Arduino\hardware\arduino\avr\cores\arduino/Stream.h:26:0,

                 from C:\Program Files\Arduino\hardware\arduino\avr\cores\arduino/HardwareSerial.h:29,

                 from C:\Program Files\Arduino\hardware\arduino\avr\cores\arduino/Arduino.h:224,

                 from sketch\sketch_jun17a.ino.cpp:1:

C:\Program Files\Arduino\hardware\arduino\avr\cores\arduino/Print.h:49:12: note: size_t Print::write(const char*) <near match>

     size_t write(const char *str) {

            ^

C:\Program Files\Arduino\hardware\arduino\avr\cores\arduino/Print.h:49:12: note:   no known conversion for argument 1 from 'byte [3] {aka unsigned char [3]}' to 'const char*'

exit status 1
call of overloaded 'write(byte [8])' is ambiguous

В теме, из которой я взял этот код, люди пишут, что он рабочий, правда лет 7 назад пишут (может, среда программирования менялась или библиотеки?). Что следует из неоднозначности вызова переполенной переменной? На этом форуме я находил подобную проблему, там всё решилось добавлением знака & перед элементом массива (говорят, это непосредственное обращение к элементу по его адресу). Здесь, увы, тоже не понял.

 И ещё в коде присутствует строка: 

lcd.command(64);

 Компилятор её не подсвечивает в тексте (как, например, лсд.Райт), в инструкции к библиотеке такого тоже нет. Что эта строка может значить?

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

 Прошу совета по данной тематике!

Тарас Петрович
Offline
Зарегистрирован: 21.11.2015

Или графический дисплей проще взять, и к нему библиотеки с различными шрифтами поискать?

arduinec
Offline
Зарегистрирован: 01.09.2015

Тарас Петрович пишет:

 И ещё в коде присутствует строка: 

lcd.command(64);

 Компилятор её не подсвечивает в тексте (как, например, лсд.Райт), в инструкции к библиотеке такого тоже нет. Что эта строка может значить?

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

 Прошу совета по данной тематике!

Команда lcd.command(64); подаётся перед загрузкой символов в память дисплея. В библиотеке LiquidCrystal она обычно не требуется, так как вызывается внутри команды для загрузки символов lcd.createChar (есть в примерах к библиотеке).

Большие цифры есть здесь: http://arduino.ru/forum/programmirovanie/etyud-2-stroki-po-40-simvolov-na-lcd-1602

Тарас Петрович
Offline
Зарегистрирован: 21.11.2015

Arduinec, большое спасибо! В вашем примере всё просто и работает, пока собрал на макетке, вывел цифры на нужные знакоместа.

Тарас Петрович
Offline
Зарегистрирован: 21.11.2015

Аппаратную часть я благополучно спаял на макетке, теперь дело за окончательной программой. Что есть: Подключены 2 входа АЦП (на измерение бензина и напряжения), вход внешнего прерывания для общения с датчиком скорости, дисплей, ну и обвязка всякая (питание, стабилитроны, делители). Написал тестовый скетч.



#include <LiquidCrystal.h>

LiquidCrystal lcd(9, 8, 7, 6, 5, 4);

int sot;
int des;
int ed;
int w; //глобальная переменная счётчика
volatile int scor; //скорость в километрах в час
volatile int impuls = 0;//переменная для импульсов с датчика скорости
int q=0;
 
char number[10][2][4] = {
  "\1\2\1", "\1\3\1",
  "\2\1 ",  "\3\1\3",
  "\2\4\1", "\1\5\3",
  "\2\4\1", "\3\5\1",
  "\1 \1",  "\2\2\1",
  "\1\4\2", "\3\5\1",
  "\1\4\2", "\1\5\1",
  "\2\4\1", " \1 ",
  "\1\4\1", "\1\5\1",
  "\1\4\1", "\3\5\1"  };
byte i;

void setup()
{
  Serial.begin(9600);

    attachInterrupt(0, ImpulsCount, FALLING);// Прерывание для подсчёта импульсов с ДСА

  //Разрешаем прерывание от сторожевого таймера
  WDTCSR=B00011000; //установить биты WDCE WDE (что б разрешить запись в другие биты
  WDTCSR=B01000110; // разрешение прерывания + выдержка 1 секунда(55 страница даташита) можно выбрать от 16мс до 8 с

   
  //Забиваем спецсимволы для больших цифр
  byte pillar[8] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
  byte upper1[8] = { 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00 };
  byte lower1[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F };
  byte upper2[8] = { 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x1F };
  byte lower2[8] = { 0x1F, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F };

  lcd.begin(20, 4);
  lcd.noCursor();

  lcd.createChar(1, pillar);
  lcd.createChar(2, upper1);
  lcd.createChar(3, lower1);
  lcd.createChar(4, upper2);
  lcd.createChar(5, lower2);

  for (i=0; i<=9; i++) {
    numprint(i, 4*i);
  }
  delay(5000);
  lcd.clear();
}
 
void loop()
 {
   
 }
 


void numprint(byte num, byte poz) //функция вывода большой цифры
   {
  lcd.setCursor(poz, 0);
  lcd.print(number[num][0]);
  lcd.setCursor(poz, 1);
  lcd.print(number[num][1]);
   }
   

void speedprint()//функция вывода скорости на дисплей
  {

    lcd.setCursor(0, 0);      //Очистка дисплея от прошлых показаний
    lcd.print("           ");
    lcd.setCursor(0, 1);
    lcd.print("           ");
        
    int spd=scor;
    w=0;//переменная счётчика знакоместа
   if(spd>99)
     {
    sot=spd/100;
    spd=(spd-(sot*100));
    numprint(sot,w);
    w=w+4;
     }
    if((spd>9)||(sot>0))
     {
    sot=0;
    des=spd/10;
    spd=(spd-(des*10));
    numprint(des,w);
    w=w+4;
     }
    numprint(spd,w); 
   
   }


void BenzNaprCalcPrint() //Измерение, расчёт и вывод на дисплей напряжения бортсети и количества бензина
   {
    int benz = 0; 
    float napr = 0;     
       benz = analogRead(2);
       benz=benz/10;          
           lcd.setCursor(10, 3);
           lcd.print(benz);
           lcd.setCursor(12, 3);
           lcd.print("Litrov");  
       int rr = analogRead(3); 
           napr=(rr/40.43);  
           lcd.setCursor(0, 3);
           lcd.print(napr);
           lcd.setCursor(4, 3);
           lcd.print("Volt");

   }
   




void ImpulsCount() //Инкремент счётчика импульсов
  {
    impuls++;
    
  }


ISR (WDT_vect)
 {
  if(impuls>600)
  {impuls=600;} //Ограничение числа импульсов 360км/ч , выше- бесится функция вывода больших цифр
  scor=((impuls*6)/10); //Расчёт скорости в км/ч....Датчик 2110 (6 импульсов на метр)
  impuls=0; //Обнуляем посчитанные за секунду импульсы
 speedprint(); //Вызываем процедуру разбиения скорости по цифрам и её вывода на дисплей
 BenzNaprCalcPrint(); //Вызываем функцию измерения напряжения и уровня бензина и их вывода на дисплей
  
   
 }


 

 
 

         Здесь всё просто: есть функция для вывода больших цифр с поразрядной разбивкой, функция работы с АЦП и вывод.   Есть внешнее прерывание по спаду, оно считает импульсы с датчика. Есть прерывание от сторожевого таймера раз в секунду. Так-то всё работает, но чем выше скорость, тем больше ошибка. Имульсы я подаю с другой ардуино, написав на ней простенький генератор. Я думаю, что причина в долгом исполнении обработчика прерывания таймера. Поэтому, теряются импульсы.       

     

     Вопрос: правильно ли я строю алгоритм программы, может, есть идеи получше. И ещё, когда мы пишем функцию обработчика некого прерывания, нужно ли в конце указывать команду выхода из обработчика (восстановления флага I в SREG на вроде reti )?

 

Тарас Петрович
Offline
Зарегистрирован: 21.11.2015

Дорабатываю программу и выяснил, что  скорость выходит завышенная в 1,11 раза. Есть, конечно, выход- программно умножить скорость на 0,91 (что я пока и сделал), но хочется понять почему. Ещё наблюдение- при подключении генератора к устройству  "на ходу", первый раз выводится правильное значение скорости, а при всех последующих прерываниях- завышает. Если прерывание (его обработчик) от сторожевого таймера исполняется слишком долго, то дожны теряться прерывания от импульсов, то есть скорость должна быть ниже, а тут- наоборот. На периодичность следования прерываний от WDT, едва ли что-то может повлиять, там же счётчик аппаратный.  Может, для расчёта скорости ввести ещё прерывание от внутреннего таймера 1 (ШИМ мне не нужен), а по вачДогу заниматься всякой индикацией? Посему- если кто вникнет, а ещё и подскажет- буду очень благодарен!

ЗЫ Тему бы в программирование?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Тарас Петрович, вотч дог считает время неточно, лучше использовать таймер 1 для счёта секунд, если он не задействован.

Тарас Петрович
Offline
Зарегистрирован: 21.11.2015

Вот оно что! Спасибо. Тогда вачдог на индикацию задействую, и пойду искать мантру для вызова прерывания от таймера. Кстати, Dimax, благодарю за проект генератора с регулировкой частоты из сериал, его-то я и собраk как тестовый, осциллограф сказал, что частота соответствует выбранной.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Тарас Петрович, мантру можно тут взять :)

Тарас Петрович
Offline
Зарегистрирован: 21.11.2015

    Мантру нашёл))), работает. Ещё подладил программу. Теперь спидометр умеет правильно показывать скорость, напряжение питания устройства, бензин (пока без привязки к показаниям реального датчика) и пробег. Пробег хранится в энергонезависимой памяти, скидывается он туда в момент отключения питания прибора. После всех стабилизаторов, питания дисплея и т.п., я поставил диод Шоттки, а за ним-конденсатор на 1000,0. Питание от бортсети (плюс после замка зажигания), через делитель и стабилитрон, подан на вход внешнего прерывания. Когда прибор обесточивается, формируется прерывание  INT 1 по спаду, в этом прерывании происходит запись пробега в память. После- контроллер отключается ввиду разрядки конденсатора. Постоянного питания я не схему не завёл, пока конденсатор справляется.

    В планах прикрутить суточник пробега с кнопкой его сброса (жаль, прерывания внешние кончились((( и пищалку для подачи кратковременного звука при переходе через 77 км/ч.

   Ещё мысли вслух про уровень бензина: Жигулёвский датчик топлива имеет кривую характеристику, делать аппроксимацию я не хочу, поэтому думаю просто полуить (экспериментом) тарировочную карту, забить её в массив из 40 элементов и перебирать этот массив на ближайшее к АЦП значение.

 Скетч, вдруг кому интересно, или кто поправит:



#include <LiquidCrystal.h>

#include <EEPROM2.h>

LiquidCrystal lcd(9, 8, 7, 6, 5, 4);

int sot;
int des;
int ed;
int w; //глобальная переменная счётчика
volatile int scor; //скорость в километрах в час
volatile int impuls = 0;//переменная для импульсов с датчика скорости
unsigned long probeg;//Пробег в количестве импульсов, если разделить на 6000, будут километры

int q=0;
 
char number[10][2][4] = {
  "\1\2\1", "\1\3\1",
  "\2\1 ",  "\3\1\3",
  "\2\4\1", "\1\5\3",
  "\2\4\1", "\3\5\1",
  "\1 \1",  "\2\2\1",
  "\1\4\2", "\3\5\1",
  "\1\4\2", "\1\5\1",
  "\2\4\1", " \1 ",
  "\1\4\1", "\1\5\1",
  "\1\4\1", "\3\5\1"  };
byte i;

void setup()
{

   
 



  

   
  //Забиваем спецсимволы для больших цифр
  byte pillar[8] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
  byte upper1[8] = { 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00 };
  byte lower1[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F };
  byte upper2[8] = { 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x1F };
  byte lower2[8] = { 0x1F, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F };

  lcd.begin(20, 4);
  lcd.noCursor();

  lcd.createChar(1, pillar);
  lcd.createChar(2, upper1);
  lcd.createChar(3, lower1);
  lcd.createChar(4, upper2);
  lcd.createChar(5, lower2);

  for (i=0; i<=9; i++) {
    numprint(i, 4*i);
  }
  
  lcd.clear();
  delay(5000);

  ///probeg=0;
  ///EEPROM_write(0, probeg); 
  
  EEPROM_read(0, probeg);//Читаем пробег из энергонезависимой памяти
  
  Serial.begin(9600);

  attachInterrupt(0, ImpulsCount, FALLING);// Прерывание для подсчёта импульсов с ДСА

  attachInterrupt(1, Zapis, FALLING);// Прерывание при отключении питания

  //Разрешаем прерывание от сторожевого таймера
 // WDTCSR=B00011000; //установить биты WDCE WDE (что б разрешить запись в другие биты
 // WDTCSR=B01000110; // разрешение прерывания + выдержка 1 секунда(55 страница даташита) можно выбрать от 16мс до 8 с


  TCCR1A=(1<<WGM11); //режим14 FAST PWM 
  TCCR1B=(1<<CS12)|(1<<WGM13)|(1<<WGM12); //делить частоту CPU на 256
  ICR1=62499;  // (16000000MHz /div256) -1 = 1 раз в секунду
  TIMSK1=(1<<TOIE1); //разрешить прерывание

           lcd.setCursor(0,2);
           lcd.print("Total:");


  
}
 
void loop()
 {
   
 }
 


void numprint(byte num, byte poz) //функция вывода большой цифры
   {
  lcd.setCursor(poz, 0);
  lcd.print(number[num][0]);
  lcd.setCursor(poz, 1);
  lcd.print(number[num][1]);
   }
   

void speedprint()//функция вывода скорости на дисплей
  {

    int spd=scor;
    w=0;//переменная счётчика знакоместа
   if(spd>99)
     {
    sot=spd/100;
    spd=(spd-(sot*100));
    numprint(sot,w);
    w=w+4;
     }
    if((spd>9)||(sot>0))
     {
    sot=0;
    des=spd/10;
    spd=(spd-(des*10));
    numprint(des,w);
    w=w+4;
     }
    numprint(spd,w); 

  switch (w) {
        case 8:    // Ничего стирать не нужно
        break;
        case 4:    // Число было двузначным, стираем правый разряд 
    lcd.setCursor(8, 0);      
    lcd.print("    ");
    lcd.setCursor(8, 1);
    lcd.print("    ");
        break;
        case 0:    // Число было в один знак
    lcd.setCursor(4, 0);     
    lcd.print("       ");
    lcd.setCursor(4, 1);
    lcd.print("       ");
         break;
 
  } 
   
   }


void BenzNaprCalcPrint() //Измерение, расчёт и вывод на дисплей напряжения бортсети и количества бензина
   {
    int benz = 0; 
    float napr = 0;     
       benz = analogRead(2);
       benz=benz/10;          
           lcd.setCursor(11, 3);
           lcd.print(benz);
           if(benz<10){lcd.print(" ");}
           lcd.setCursor(13, 3);
           lcd.print(" Litrov");  
       int rr = analogRead(3); 
           napr=(rr/40.43);  
           lcd.setCursor(0, 3);
           lcd.print(napr);
           lcd.setCursor(4, 3);
           lcd.print(" Volt");

           unsigned long indProbeg=(probeg/60);
           lcd.setCursor(7,2);
           lcd.print((indProbeg/100));
           lcd.print(".");
           lcd.print((indProbeg%100));
           lcd.print(" Km");


   }
   




void ImpulsCount() //Инкремент счётчика импульсов
  {
    impuls++;
    
  }


ISR (WDT_vect)//Обработчик прерывания от сторожевого таймера, временно не используется
 {
  ///if(impuls>600)
 /// {impuls=600;} //Ограничение числа импульсов 360км/ч , выше- бесится функция вывода больших цифр
  ///scor=((impuls*6)/10); //Расчёт скорости в км/ч....Датчик 2110 (6 импульсов на метр)
  ///scor=((scor*9)/10);
 /// impuls=0; //Обнуляем посчитанные за секунду импульсы
// speedprint(); //Вызываем процедуру разбиения скорости по цифрам и её вывода на дисплей
// BenzNaprCalcPrint(); //Вызываем функцию измерения напряжения и уровня бензина и их вывода на дисплей
  
  //EEPROM_write(0, probeg); 
 }


ISR (TIMER1_OVF_vect) //Обработчик прерывания тот таймера Т1, 1 раз в секунду.
{ 

if(impuls>600)
  {impuls=600;} //Ограничение числа импульсов 360км/ч , выше- бесится функция вывода больших цифр
  probeg=probeg+impuls;
  scor=((impuls*6)/10);//Расчёт скорости в км/ч....Датчик 2110 (6 импульсов на метр)
  if(scor>40){scor++;}//Устраняем статистическую погрешность
  //scor=((scor*9)/10);
  impuls=0; //Обнуляем посчитанные за секунду импульсы
  speedprint(); //Вызываем процедуру разбиения скорости по цифрам и её вывода на дисплей
 BenzNaprCalcPrint(); //Вызываем функцию измерения напряжения и уровня бензина и их вывода на дисплей
}

void Zapis() //Обработчик прерывания при отключении внешнего питания
{
  //Serial.println ("pizdets");
  EEPROM_write(0, probeg); //Пишем пробег в EEPROM, используя энергию, накопленную в конденсаторе 1000,0 по питанию
}





  

 

uno
Offline
Зарегистрирован: 16.06.2016

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

Тарас Петрович
Offline
Зарегистрирован: 21.11.2015


       В записи пробега "каждый километр" неминуемо будут теряться данные. То есть вы проехали 15 км 900м и заглушили двигатель- 0,9 км потеряно, и не один раз в день. Так ни расход не подсчитать, да и пробег недостоверный. Схема записи, которую я применил- работает. Ёмкость я увеличил до 2000,0, два четырёхбайтных числа успевают записаться, надо туда ещё запись остатка топлива засунуть, что б при включении прибора, программа определяла факт заправки и подсчитывала "валовый" расход с момента заправки предыдущей.

       Ещё поменял в программе вывод пробега, слелал через float, так точнее. Остался вопрос с кнопкой. Сейчас она только сбрасывает пробег, а хочется ей же циклически (57/77/107) менять величину скорости, при которой зуммер подаёт однократный сигнал о превышении. Только пока не могу придумать реализацию. То ли по длительности удержания, то ли ещё как. Может Pulsein в loop засунуть, так дребезг кнопки замучает. Сейчас-то кнопка однократно опрашивается в каждом прерывании таймера и дребезг- побоку. Или конденсатор микрофарад на 10,0 на кнопку повесить?

      На днях подключал БК в машине, скорость разнится с навигатором в 1 км/ч, при работе стартера прибор не перезагружается, запись в память- действует, ошибка в измерении напряжения бортсети-не более 0,2В. Канал бензина пока не подключал, хлопотно приборку скидывать.

     Ну и вариант программы на данный момент:



#include <LiquidCrystal.h>

#include <EEPROM2.h>

LiquidCrystal lcd(9, 8, 7, 6, 5, 4);

int sot;
int des;
int ed;
int w; //глобальная переменная счётчика
volatile int scor; //скорость в километрах в час
volatile int impuls = 0;//переменная для импульсов с датчика скорости
unsigned long probeg;//Пробег в количестве импульсов, если разделить на 6000, будут километры
unsigned long sutki;//Обнуляемый счётчик суточного пробега
int q=0;
 
char number[10][2][4] = {
  "\1\2\1", "\1\3\1",
  "\2\1 ",  "\3\1\3",
  "\2\4\1", "\1\5\3",
  "\2\4\1", "\3\5\1",
  "\1 \1",  "\2\2\1",
  "\1\4\2", "\3\5\1",
  "\1\4\2", "\1\5\1",
  "\2\4\1", " \1 ",
  "\1\4\1", "\1\5\1",
  "\1\4\1", "\3\5\1"  };
byte i;

void setup()
{

 

  

   
  //Забиваем спецсимволы для больших цифр
  byte pillar[8] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
  byte upper1[8] = { 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00 };
  byte lower1[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F };
  byte upper2[8] = { 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x1F };
  byte lower2[8] = { 0x1F, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F };

  lcd.begin(20, 4);
  lcd.noCursor();

  lcd.createChar(1, pillar);
  lcd.createChar(2, upper1);
  lcd.createChar(3, lower1);
  lcd.createChar(4, upper2);
  lcd.createChar(5, lower2);

  //for (i=0; i<=9; i++)
  //{
  //  numprint(i, 4*i);
 // }


numprint(2, 2);
numprint(1, 6);
numprint(0, 10);
numprint(6, 14);

lcd.setCursor(3, 2);
lcd.print("Hello, Dimon!");
lcd.setCursor(2, 3);
lcd.print("Have a nice day!");


 pinMode(10, INPUT);//Кнопка
 
 pinMode(11, OUTPUT);//Зуммер
 digitalWrite(11, LOW);
 delay(200);
 digitalWrite(11,HIGH);  
 delay(200);
 digitalWrite(11, LOW);
 delay(200);
 digitalWrite(11,HIGH);  
 delay(200);
 digitalWrite(11, LOW);
 delay(200);
 digitalWrite(11,HIGH);  
 delay(200); 
  
  
  delay(2000);
  lcd.clear();
  //sutki=0;
  //EEPROM_write(50, sutki); 
  
  EEPROM_read(0, probeg);//Читаем пробег из энергонезависимой памяти
  EEPROM_read(50, sutki);//Читаем суточный пробег из энергонезависимой памяти
  
  Serial.begin(9600);

  attachInterrupt(0, ImpulsCount, FALLING);// Прерывание для подсчёта импульсов с ДСА

  attachInterrupt(1, Zapis, FALLING);// Прерывание при отключении питания

  //Разрешаем прерывание от сторожевого таймера
 // WDTCSR=B00011000; //установить биты WDCE WDE (что б разрешить запись в другие биты
 // WDTCSR=B01000110; // разрешение прерывания + выдержка 1 секунда(55 страница даташита) можно выбрать от 16мс до 8 с


  TCCR1A=(1<<WGM11); //режим14 FAST PWM 
  TCCR1B=(1<<CS12)|(1<<WGM13)|(1<<WGM12); //делить частоту CPU на 256
  ICR1=62499;  // (16000000MHz /div256) -1 = 1 раз в секунду
  TIMSK1=(1<<TOIE1); //разрешить прерывание

           lcd.setCursor(0,2);
           lcd.print("Total:");

           lcd.setCursor(12,0);
           lcd.print("Ttip A:");



// pinMode(11, INPUT);//Зуммер
  
}
 
void loop()
 {
   
 }
 


void numprint(byte num, byte poz) //функция вывода большой цифры
   {
  lcd.setCursor(poz, 0);
  lcd.print(number[num][0]);
  lcd.setCursor(poz, 1);
  lcd.print(number[num][1]);
   }
   

void speedprint()//функция вывода скорости на дисплей
  {

    int spd=scor;
    w=0;//переменная счётчика знакоместа
   if(spd>99)
     {
    sot=spd/100;
    spd=(spd-(sot*100));
    numprint(sot,w);
    w=w+4;
     }
    if((spd>9)||(sot>0))
     {
    sot=0;
    des=spd/10;
    spd=(spd-(des*10));
    numprint(des,w);
    w=w+4;
     }
    numprint(spd,w); 

  switch (w) {
        case 8:    // Ничего стирать не нужно
        break;
        case 4:    // Число было двузначным, стираем правый разряд 
    lcd.setCursor(8, 0);      
    lcd.print("    ");
    lcd.setCursor(8, 1);
    lcd.print("    ");
        break;
        case 0:    // Число было в один знак
    lcd.setCursor(4, 0);     
    lcd.print("       ");
    lcd.setCursor(4, 1);
    lcd.print("       ");
         break;
 
  } 
   
   }


void BenzNaprCalcPrint() //Измерение, расчёт и вывод на дисплей напряжения бортсети и количества бензина
   {
    int benz = 0; 
    float napr = 0;     
       benz = analogRead(2);
       benz=benz/10;          
           lcd.setCursor(11, 3);
           lcd.print(benz);
           if(benz<10){lcd.print(" ");}
           lcd.setCursor(13, 3);
           lcd.print(" Litrov");  
       int rr = analogRead(3); 
          napr=(rr/57.0);  
         // napr=rr;
           lcd.setCursor(0, 3);
           lcd.print(napr);
           lcd.setCursor(4, 3);
           lcd.print(" Volt");

           /*unsigned long indProbeg=(probeg/60);
           lcd.setCursor(7,2);
           lcd.print((indProbeg/100));
           lcd.print(".");
           lcd.print((indProbeg%100));
           lcd.print(" Km");

           unsigned long indSutki=(sutki/60);
           lcd.setCursor(12,1);
           lcd.print((indSutki/100));
           lcd.print(".");
           lcd.print((indSutki%100));
           lcd.print("Km");*/

           float indProbeg=probeg/6000.0;
           lcd.setCursor(7,2);
           lcd.print(indProbeg);
           //lcd.setCursor(12,1);
           lcd.print("Km");

           
           float indSutki=sutki/6000.0;
           lcd.setCursor(12,1);
           lcd.print(indSutki);
           lcd.print("Km");
   }
   




void ImpulsCount() //Инкремент счётчика импульсов
  {
    impuls++;
    
  }


/*ISR (WDT_vect)//Обработчик прерывания от сторожевого таймера, временно не используется
 {
  if(impuls>600)
 {impuls=600;} //Ограничение числа импульсов 360км/ч , выше- бесится функция вывода больших цифр
 scor=((impuls*6)/10); //Расчёт скорости в км/ч....Датчик 2110 (6 импульсов на метр)
 scor=((scor*9)/10);
 impuls=0; //Обнуляем посчитанные за секунду импульсы
 speedprint(); //Вызываем процедуру разбиения скорости по цифрам и её вывода на дисплей
 BenzNaprCalcPrint(); //Вызываем функцию измерения напряжения и уровня бензина и их вывода на дисплей
  
 EEPROM_write(0, probeg); 
 }*/


ISR (TIMER1_OVF_vect) //Обработчик прерывания тот таймера Т1, 1 раз в секунду.
{ 

digitalWrite(11, HIGH);
   
if(impuls>600)
  {impuls=600;} //Ограничение числа импульсов 360км/ч , выше- бесится функция вывода больших цифр
  probeg=probeg+impuls;
  sutki=sutki+impuls;
  scor=((impuls*6)/10);//Расчёт скорости в км/ч....Датчик 2110 (6 импульсов на метр)
  //if(scor>40){scor++;}//Устраняем статистическую погрешность
  //scor=((scor*9)/10);
  impuls=0; //Обнуляем посчитанные за секунду импульсы
  speedprint(); //Вызываем процедуру разбиения скорости по цифрам и её вывода на дисплей
 BenzNaprCalcPrint(); //Вызываем функцию измерения напряжения и уровня бензина и их вывода на дисплей
 if(digitalRead(10)==LOW)
     {
      sutki=0;
      digitalWrite(11, LOW);
      EEPROM_write(50, sutki);
      
 
     }





     
}

void Zapis() //Обработчик прерывания при отключении внешнего питания
{
  //Serial.println ("pizdets");
  EEPROM_write(0, probeg);  //Пишем пробег в EEPROM, используя энергию, накопленную в конденсаторе 1000,0 по питанию
  EEPROM_write(50, sutki);
}





  

 

uno
Offline
Зарегистрирован: 16.06.2016

Запись каждый километр в дополнение к вкл-выкл, а не вместо. Однократный зумер в какой нибуть тягнучке задалбливает меня на навигаторе.

Тарас Петрович
Offline
Зарегистрирован: 21.11.2015

Да, надо предусмотреть возможность отключения зуммера вообще, то есть подача сигнала при (57/77/107/никогда). 

 Только вот как сделать? Например- при включении прибора -77,  следующее-57, следующее-107, следующее- отключить. Удержание более 3 сек- сброс суточника....Или по-другому как... Счётчик какой завести в прерывании? 

Yarik.Yar
Offline
Зарегистрирован: 07.09.2014

В "Программирование"? Сказано - сделано)

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Про кнопочки тут, и удержание и дабл клик и ... в общем ТИТАНОВЫЙ ЛИСАПЕД ДЛЯ КНОПКИ.

Тарас Петрович
Offline
Зарегистрирован: 21.11.2015

     Всем привет! БК успешно используется, а вот до ума доводится медленно. Установил я новый датчик в бак и прокалибровал, заливая по 1 литру. Сопротивление не измерял, записывал сразу показания АЦП. Диапазон получился не очень- ну тут я с делителем просчитался.

     Поскольку ряд получился нелинейным, я думаю забить числа в массив, и ФОРом перебирать в поисках наиболее близкого значения. А номером элемента массива как раз и будет число литров.

     Теперь возник вопрос, как бороться с плесканием бензина и огромным (до 100 единиц)  разлётом данных ацп при резком перемещении машины, особенно когда бензина полбака? Усреднить- не получится (выборка может попасть на момент ускорения-торможения). Реже измерять- а если попадёт как раз на пик? Можно электролит повесить огромный на датчик, но тогда надо ток его заряда ограничивать, чтобы стабилизатор не сжечь, а ограничительный резистор погрешность внесёт. Есть у кого мысли, как правильно посчитать?

Тарас Петрович
Offline
Зарегистрирован: 21.11.2015

Изменил программу, как и планировал, перебрал ФОРом ряд калибровки. К моему удивлению, девиация показаний в литрах не превышает  одного-двух. Точность работы меня вполне устроила. Теперь хочу сделать, чтоб считал, сколько км осталось до запрвки при текущем расходе. Но тут надо расход мерить и колличество бензина знать точно. Как это математически реализовать- пока в раздумьях. Если кто чо думает по этому поводу- поделитесь! ЗЫ На морозе почему-то сдох зуммер((

Текущий вариант программы:



#include <LiquidCrystal.h>

#include <EEPROM2.h>

LiquidCrystal lcd(9, 8, 7, 6, 5, 4);
volatile int tur=0; //счётчик секунд нажатия кнопки сброса
int sot;
int des;
int ed;
int w; //глобальная переменная счётчика
volatile int scor; //скорость в километрах в час
volatile int impuls = 0;//переменная для импульсов с датчика скорости
unsigned long probeg;//Пробег в количестве импульсов, если разделить на 6000, будут километры
unsigned long sutki;//Обнуляемый счётчик суточного пробега
int q=0;
//int ffg=0;
 
char number[10][2][4] = {
  "\1\2\1", "\1\3\1",
  "\2\1 ",  "\3\1\3",
  "\2\4\1", "\1\5\3",
  "\2\4\1", "\3\5\1",
  "\1 \1",  "\2\2\1",
  "\1\4\2", "\3\5\1",
  "\1\4\2", "\1\5\1",
  "\2\4\1", " \1 ",
  "\1\4\1", "\1\5\1",
  "\1\4\1", "\3\5\1"  };
byte i;

void setup()
{

 

  

   
  //Забиваем спецсимволы для больших цифр
  byte pillar[8] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
  byte upper1[8] = { 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00 };
  byte lower1[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F };
  byte upper2[8] = { 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x1F };
  byte lower2[8] = { 0x1F, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F };

  lcd.begin(20, 4);
  lcd.noCursor();

  lcd.createChar(1, pillar);
  lcd.createChar(2, upper1);
  lcd.createChar(3, lower1);
  lcd.createChar(4, upper2);
  lcd.createChar(5, lower2);

  //for (i=0; i<=9; i++)
  //{
  //  numprint(i, 4*i);
 // }


numprint(2, 2);
numprint(1, 6);
numprint(0, 10);
numprint(6, 14);

lcd.setCursor(3, 2);
lcd.print("Hello, Dimon!");
lcd.setCursor(2, 3);
lcd.print("Have a nice day!");


 pinMode(10, INPUT);//Кнопка
 
 pinMode(11, OUTPUT);//Зуммер
 digitalWrite(11, LOW);
 delay(200);
 digitalWrite(11,HIGH);  
 delay(200);
 digitalWrite(11, LOW);
 delay(200);
 digitalWrite(11,HIGH);  
 delay(200);
 digitalWrite(11, LOW);
 delay(200);
 digitalWrite(11,HIGH);  
 delay(200); 
  
  
  delay(2000);
  lcd.clear();
  //sutki=46000;
  //EEPROM_write(50, sutki); 
  //probeg=319896000;
  //EEPROM_write(0, probeg); 
  
  EEPROM_read(0, probeg);//Читаем пробег из энергонезависимой памяти
  EEPROM_read(50, sutki);//Читаем суточный пробег из энергонезависимой памяти
  
  Serial.begin(9600);

  attachInterrupt(0, ImpulsCount, FALLING);// Прерывание для подсчёта импульсов с ДСА

  attachInterrupt(1, Zapis, FALLING);// Прерывание при отключении питания

  //Разрешаем прерывание от сторожевого таймера
 // WDTCSR=B00011000; //установить биты WDCE WDE (что б разрешить запись в другие биты
 // WDTCSR=B01000110; // разрешение прерывания + выдержка 1 секунда(55 страница даташита) можно выбрать от 16мс до 8 с


  TCCR1A=(1<<WGM11); //режим14 FAST PWM 
  TCCR1B=(1<<CS12)|(1<<WGM13)|(1<<WGM12); //делить частоту CPU на 256
  ICR1=62499;  // (16000000MHz /div256) -1 = 1 раз в секунду
  TIMSK1=(1<<TOIE1); //разрешить прерывание

           lcd.setCursor(0,2);
           lcd.print("Total:");

           lcd.setCursor(12,0);
           lcd.print("Ttip A:");



// pinMode(11, INPUT);//Зуммер
  
}
 
void loop()
 {
   
 }
 


void numprint(byte num, byte poz) //функция вывода большой цифры
   {
  lcd.setCursor(poz, 0);
  lcd.print(number[num][0]);
  lcd.setCursor(poz, 1);
  lcd.print(number[num][1]);
   }
   

void speedprint()//функция вывода скорости на дисплей
  {

    int spd=scor;
    w=0;//переменная счётчика знакоместа
   if(spd>99)
     {
    sot=spd/100;
    spd=(spd-(sot*100));
    numprint(sot,w);
    w=w+4;
     }
    if((spd>9)||(sot>0))
     {
    sot=0;
    des=spd/10;
    spd=(spd-(des*10));
    numprint(des,w);
    w=w+4;
     }
    numprint(spd,w); 

  switch (w) {
        case 8:    // Ничего стирать не нужно
        break;
        case 4:    // Число было двузначным, стираем правый разряд 
    lcd.setCursor(8, 0);      
    lcd.print("    ");
    lcd.setCursor(8, 1);
    lcd.print("    ");
        break;
        case 0:    // Число было в один знак
    lcd.setCursor(4, 0);     
    lcd.print("       ");
    lcd.setCursor(4, 1);
    lcd.print("       ");
         break;
 
  } 
   
   }


void BenzNaprCalcPrint() //Измерение, расчёт и вывод на дисплей напряжения бортсети и количества бензина
   {
    int benz = 0; 
    float napr = 0;     
       benz = analogRead(2);
      // Serial.println(benz);
       //benz=benz/10;          
           lcd.setCursor(11, 3);
           int fg = BenzConvertation(benz);
           lcd.print(fg);
           if(fg<10){lcd.print(" ");}
           lcd.setCursor(14, 3);
           lcd.print("Litrov");

                                 /* if(ffg != fg){
                   
                                             Serial.print ("ADC    ");
                                             Serial.print (benz);
                                             Serial.print (" POLUCHITSYA   ");
                                             Serial.println (fg);
                                             ffg=fg;
                                                   }*/

             
       int rr = analogRead(3);
       rr=rr+analogRead(3);
       rr=rr+analogRead(3); 
          napr=(rr/171.0);  
         // napr=rr;
           lcd.setCursor(0, 3);
           lcd.print(napr);
           lcd.setCursor(4, 3);
           lcd.print(" Volt");

           /*unsigned long indProbeg=(probeg/60);
           lcd.setCursor(7,2);
           lcd.print((indProbeg/100));
           lcd.print(".");
           lcd.print((indProbeg%100));
           lcd.print(" Km");

           unsigned long indSutki=(sutki/60);
           lcd.setCursor(12,1);
           lcd.print((indSutki/100));
           lcd.print(".");
           lcd.print((indSutki%100));
           lcd.print("Km");*/

           float indProbeg=probeg/6000.0;
           lcd.setCursor(7,2);
           lcd.print(indProbeg);
           //lcd.setCursor(12,1);
           lcd.print("Km");

           
           float indSutki=sutki/6000.0;
           lcd.setCursor(12,1);
           lcd.print(indSutki);
           lcd.print("Km");
   }
   




void ImpulsCount() //Инкремент счётчика импульсов
  {
    impuls++;
    
  }





ISR (TIMER1_OVF_vect) //Обработчик прерывания тот таймера Т1, 1 раз в секунду.
{ 

digitalWrite(11, HIGH);
   
if(impuls>600)
  {impuls=600;} //Ограничение числа импульсов 360км/ч , выше- бесится функция вывода больших цифр
  probeg=probeg+impuls;
  sutki=sutki+impuls;
  scor=((impuls*6)/10);//Расчёт скорости в км/ч....Датчик 2110 (6 импульсов на метр)
  //if(scor>40){scor++;}//Устраняем статистическую погрешность
  //scor=((scor*9)/10);
  impuls=0; //Обнуляем посчитанные за секунду импульсы
  speedprint(); //Вызываем процедуру разбиения скорости по цифрам и её вывода на дисплей
 BenzNaprCalcPrint(); //Вызываем функцию измерения напряжения и уровня бензина и их вывода на дисплей
 if(digitalRead(10)==LOW)
     { tur++;}

 else {tur=0;}

 if (tur==3)
    { 
      
      sutki=0;
      digitalWrite(11, LOW);
      EEPROM_write(50, sutki);
      tur=0;
     // Serial.println("hjk");// отладочный
     }





     
}

void Zapis() //Обработчик прерывания при отключении внешнего питания
{
  //Serial.println ("pizdets");
  EEPROM_write(0, probeg);  //Пишем пробег в EEPROM, используя энергию, накопленную в конденсаторе 1000,0 по питанию
  EEPROM_write(50, sutki);
}



int BenzConvertation(int AD)
{
  int Izmer[41]={435, 426, 420, 414, 403, 401, 392, 383, 381, 377, 371, 360, 348, 344, 340, 330, 322, 316, 314, 310, 312, 302, 295, 292, 287, 275, 269, 260, 255, 226, 208, 198, 178, 160, 140, 107, 72, 50, 45, 39, 34};
   if(AD<=34) {return 42;}
   if(AD>=435) {return 0;}
   for(int p=0; p<=39; p++)
     {if ((AD < Izmer[p]) && (AD>=Izmer[p+1]))
                     {
                      return p+1;
                      break;
                     }
     }
}

  


 

alexx_ee
Offline
Зарегистрирован: 18.05.2017

Добрый день!
Интересный проект. Хочу добавить сюда пару термодатчиков. 

Тарас Петрович, возможно выложить схему соединений из поста #19 с лучшим качеством? а то нечитабельно.