Бортовой компьютер на авто с инжекторным двигателем (главное - расходомер топлива)

melvladimir
Offline
Зарегистрирован: 08.03.2013

Всем привет :)

Примерно в январе 2013 загорелся вникнуть в мир микроконтроллеров, предисторию писать не буду - длинно и мало кому надо :)

Цель - реализовать на инжекторном двигателе расходомер топлива по длительности впрыска форсунок.

Приобрел Arduino Mega2560. Начал потихоньку изучать. Подробности тоже опущу :)

Вчера провел первое боевое тестирование на авто, пути назад, можно сказать, нет - экран врезан в приборную панель :) (вместо указателей уровня топлива и температуры).

В наличии:
1) Ford Sierra MK3 2.0i DOHC N9E, MT75, тросиковый аналоговый спидометр;
2) 2х микроконтроллер Arduino Mega 2560 (далее МК);
3) дисплей к МК 2 строки по 16 символов латиницы (с подсветкой);
4) 2х преобразователь 12В - 5В 3А, для питания МК и дисплея;
5) 2х модуль дата/время TinyRTC v1.1 на DS1307Z;
6) акселерометр и 3D датчик наклона .

Желаемый функционал:
1) текущий (мгновенный) расход литры в час с обновлением каждые 3 секунды (удобно, видно расход и на холостых и по трассе) - реализовано.
2) общий расход за последний час, 24 часа, 7 дней, 30 дней, 365 дней, за все время - реализовано.
3) цифровой одометр/спидометр;
4) мгновенный расход на 100км;
5) средний расход за весь период и за "поездку" (кнопка обнуления);
6) разгон до 100км/ч (старт по кнопке);
7) включение аварийки при резком торможении;
8) включение зажигания (и пуск двигла) после введения пин-кода.
9) автоматическое переключение "ДХО - ближний" при достижении граничного порога освещенности;
10) функция диагностики двигателя и СУД (по аналогии со "светодиодным тестером").
11) выключение зажигания при высокой температуре (>113*C);
12) краткое включение сигнала поворота - автоматически 5 раз моргает;
13) кнопка "спасибо" - 3 раза блым аварийкой;
14) автозапирание ЦЗ (алгоритм будет обсуждаться позже);
15) индикатор уровня топлива;
16) индикатор температуры.

Код



#include 
// номинал форсунки 0.0032 мкл/мкс.
// предделитель таймера для максимальной точности берем 1, т.е. при каждом переполнении (256 циклов) будет проходить 16 мкс
// с учетом предделителя берем расход в 16 мкс, т.е. 0.0512мкл/16мкс. Точность (и кратность) замера расхода 0.0512мкл
// поскольку дробные вычисления занимают больше времение и памяти, то от дроби надо избавится
// Также на дисплей будут выводиться не литры в час и литры/100км, а мл/ч и мл/100км. Возможно позже переделаю.
// Нужно реализовать чтение из памяти и запись в память переменной dur, которая хранит кол-во сожженных литров всего (как одометр км).
// Также нужно реализовать фиксацию максимального и минимального мгновенного расхода на 100 км с фиксацией скоростей и оборотов двигателя.

LiquidCrystal lcd(12, 11, 5, 4, 3, 2); // параметры подключения дисплея, пины на ардуине

unsigned long dur; // предел = 21500 литров, хранит кол-во сожженного топлива с момента запуска проекта
unsigned long dur_t; // предел = 215 литров, считает от включения до выключения зажигания
unsigned long cur_ms; //кол-во мс с момента запуска микроконтроллера = мс с момента включения зажигания.
unsigned long prev_ms; // используется для определения интервалов времени, мс.
int ms; //количество прошедших мс
volatile long mks16; //сколько раз по 16 мкс форсунка впрыскивала топливо.
unsigned long m; //одометр
int interval; // интервал обновления экрана и период расчета мгновенного расхода, мс.
unsigned long aver; // переменная для расчета расхода за прошедший заданный интервал
unsigned long aver_temp; // еще одна вспомогательная
unsigned long aver_h; //прогнозируемый по последним 3 секундам расход мл/ч
unsigned long aver_100; //прогнозируемый по последним 3 секундам расход мл/100км
unsigned long brnd; //сожжено топлива с момента пуска двигателя
int temp; //температура двигателя

void setup()
{
lcd.begin(16, 2);
attachInterrupt(2, start, FALLING); //подключаем срабатывание прерывания по внещнему сигналу, при переходе с 1 в 0 будет срабатывать код команды start
attachInterrupt(3, odometer, CHANGE); //подключаем срабатывание прерывания по внещнему сигналу, при изменении с 0 в 1 и наоборот. будет срабатывать код команды odometer
dur_t = 0;
dur = 0; //вместо обнуления здесь должна быть процедура извлечения данных из памяти EEPROM, общий расход топлива.
mks16 = 0;
TCCR2A = 0; //режим работы таймера, выбран нормальный
TCCR2B = 1; //предделитель тиков таймера = частоте процессора, при каждом переполнении будет проходить 16мкс
TCNT2=0; // это и есть то "место", которое считает такты и будет переполняться по достижению 255+1 и генерировать прерывание.
//с помощью установки этого значения можно менять дробность, например, если постоянно ставить начальное значение 96, то за оставшиеся 160 тиков будет проходить 10мкс
aver = 0;
aver_temp = 0;
aver_h = 0;
aver_100 = 0;
}

//обработчик прерывания по переполнению таймера
ISR(TIMER2_OVF_vect) {
	mks16++;
}

//внешнее прерывание
void start() {
	TCNT2=0; //обнуление натикавшего таймера
	TIMSK2 |= (1 << TOIE2); //разрешаем прерывания по переполнению таймера
	attachInterrupt(2, stop, RISING); //переключение режима прерывания
}

//внешнее прерывание
void stop() {
	TIMSK2 &= ~(1< 10000000) {
		dur = (dur + dur_t) / 100; //загрубляем данные, хотя если разделить на 100 000, то точность будет 5мл :) т.е. данная точность - 5мкл
		dur_t = 0; //обнуляем переменную
	}
	attachInterrupt(2, start, FALLING); //переключение режима прерывания	
}

//внешнее прерывание
void odometer() {
	m++; //добавляем расчетное расстояние по каждому срабатыванию цифрового датчика
}
//основная программа
void loop() {
	cur_ms = millis(); //переменной присваиваем значение "натикавшего" таймера 1 в мс, который стартует с момента включения ардуины
	ms = cur_ms - prev_ms;
	if (ms > 3000) { //отбиваем заданный интервал 3с
		prev_ms = cur_ms; //первым делом записываем на каком значении таймера 1 мы начали
		interval++; // это для нечастого обновления данных с датчика температуры
		if (dur_t > 1000) { //проверка чтобы мы не сбрасывали показания на дисплее в ноль, можно убрать проверку совсем
			if (dur_t > aver_temp) { //еще одна проверка, чтобы при обнулении dur_t не получить в вычислении отрицательное значение
				aver = dur_t - aver_temp; //определяем суммарную длительность впрысков за прошедший интервал времени
				aver_temp = dur_t; //сохраняем показатель для расчета в следующем цикле
				aver_h = aver * 184 / ms / 1000 ; //переходим к миллилитрам, 184 - это расчетная величина по паспортному номинальному расходу форсунки
			} else {
			aver_temp = dur_t;
			}
		}
		ms=0;
		brnd = dur_t * 51 / 1000000; //переходим к миллилитрам сожженного топлива с момента пуска, 51 - это расчетная величина
		lcd.setCursor (0,0);
		lcd.print ("Avg:");
		lcd.print ("      ");
		lcd.setCursor (4,0);
		lcd.print (aver_h);
		lcd.setCursor (0,1);
		lcd.print ("Ovr:");
		lcd.print (brnd);
		if(interval == 3) { //обновляем показатель каждые 9 секунд
			temp = analogRead(6); //снимаем данные со штатного датчика
			lcd.setCursor (11,1);
			lcd.print ("T");
			lcd.print (temp);
			interval = 0; //обнуляем интервал для следующего обновления
		}
	}
});>

Текущая схема подключения:

схема

melvladimir
Offline
Зарегистрирован: 08.03.2013

Тестовый прогон результатом не впечатлил... то ли помеха, то ли код, то ли всё вместе. В общем - работает, что-то показывает, но далеко от правды. На холостых после прогрева показатель практически одинаковый (Aver:306)

Сегодня вникал в datasheet и Winterrupts.c, цель была - минимизировать потери на подключении внешнего прерывания, но в процессе изучения я так и не понял как вызывать разные функции (строки 51 и 58). Как изменить режим вроде понял :) И в результате решил сделать ход конем: вместо раздельных функций FALLING и RISING использовать CHANGE и при помощи прямого чтения порта 21 определять действие.

Код вижу таким (если посмотреть стартовый код, то изменена 30-я строка и изменено с 51 по 64):

attachInterrupt(2, fuel, CHANGE); //подключаем срабатывание прерывания по изменению внещнего сигнала

//внешнее прерывание
void fuel() {
	if (PIND!=1<<1) {
		TCNT2=0; //обнуление натикавшего таймера
		TIMSK2 |= (1 << TOIE2); //разрешаем прерывания по переполнению таймера
	}
	if (PIND=1<<1) {
		TIMSK2 &= ~(1<<TOIE2); //запрет прерывания по переполнению таймера
		dur_t = dur_t + mks16; //при каждой остановке полученный замер добавляем в переменную
		mks16 = 0; //обнуляем, чтобы не дублировать и не трогать эту переменную
		//каждые 10 000 000 "тиков" по 16мкс передаем показания для хранения и учета сожженного топлива, что соответствует сожженным 512мл
		if (dur_t > 10000000) {
			dur = (dur + dur_t) / 100; //загрубляем данные, хотя если разделить на 100 000, то точность будет 5мл :) т.е. данная точность - 5мкл
			dur_t = 0; //обнуляем переменную
		}
	}
}

Ну и в void setup() добавить:

pinMode(21, INPUT);
pinMode(20, INPUT);

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

melvladimir
Offline
Зарегистрирован: 08.03.2013

Упростил код, вроде больше нечего в коде оптимизировать...



#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

unsigned long dur;
unsigned long dur_t;
unsigned long cur_ms;
unsigned long prev_ms;
unsigned long brnd;
int ms;
volatile long mks16;
int interval;
unsigned long aver;
unsigned long aver_temp;
unsigned long aver_h;
unsigned long aver_100;
int temp;

void setup()
{
lcd.begin(16, 2);
pinMode(21, INPUT);
pinMode(20, INPUT);
dur_t = 0;
dur = 0;
mks16 = 0;
TCCR2A = 0;
TCCR2B = 1;
TCNT2=0;
aver = 0;
aver_temp = 0;
aver_h = 0;
aver_100 = 0;
prev_ms = 0;
attachInterrupt(2, fuel, CHANGE);
}
ISR(TIMER2_OVF_vect) {
	mks16++;
}
void fuel() {
	if (!(PIND & B00000001)) {
		TCNT2=0;
		TIMSK2 |= (1 << TOIE2);
	} else {
		TIMSK2 &= ~(1<<TOIE2);
		dur_t = dur_t + mks16;
		mks16 = 0;
	}
}
void loop() {
	cur_ms = millis();
	ms = cur_ms - prev_ms;
	if (ms > 3000) {
		prev_ms = cur_ms;
		aver = dur_t - aver_temp;
		aver_temp = dur_t;
		aver_h = aver * 184 / ms;
		brnd = dur_t * 51 / 1000000;
		ms=0;
		    lcd.setCursor (0,0);
		    lcd.print ("Avg:");
			lcd.print ("     ");
			lcd.setCursor (4,0);
			lcd.print (aver_h);
			lcd.setCursor (0,1);
			lcd.print ("mks:");
			lcd.print (dur_t);
			lcd.setCursor (10,0);
			lcd.print ("O:");
			lcd.print (brnd);
	}
}

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

На холостых оборотах по текущему заданному номиналу форсунок получилось 450мл/ч, а если на месте добавить обороты до 3000, то чуть меньше 1400мл/ч.

etaon
Offline
Зарегистрирован: 16.12.2011

О! тоже самое реализовать собираюсь. У форсунок производительность разная. Незначительно думаю.

Подключение к форсунке фонить не будет на ней же? На эбу никак попадать не будет? Диод тебе в помощь тут да?

Напряжение импульса какое? Делитель ваять не надо? Мало ли до 9 вольт будет прыгать импульс и попадать н аардуинку?

Производительность форсунки где взял? У меня дизельные форсунки. Замерять их производительность ломает как-то. Буду читать мануалы.

melvladimir
Offline
Зарегистрирован: 08.03.2013

У меня форсунки управляются минусом, следовательно делитель/преобразователь не нужен (в преобразователе 12В-5В, от которого питается МК, минус звонится насквозь).

Фонить вряд-ли будет. Сопротивление моих форсунок 15Ом. Диоды поставил для того, чтобы во-первых - отсечь +12 (которые присутствуют на форсунке пока она закрыта), а во-вторых - завести на один вход все форсунки.

Производительность вычитал в Интернете. Я думаю если пробить по каталожному номеру, то инфа всплывет. Впринципе можно и от фонаря поставить, а потом при тестовом прогоне на трассе посмотреть разницу и внести правки в прошивку. У меня на 90 км/ч должно быть около 6л/100 км или 5,4л/час.

etaon
Offline
Зарегистрирован: 16.12.2011

Достаточно же одну форсунку слушать. Тоже гляну что у меня на форсунку приходит.

melvladimir
Offline
Зарегистрирован: 08.03.2013

В общем - да, погрешность будет небольшая...

Жаль у меня нет осциллографа, глянуть насколько прямоугольный сигнал...

toc
Offline
Зарегистрирован: 09.02.2013

>> на трассе посмотреть разницу и внести правки в прошивку. 

Параметры лучше хранить в еепроме.

melvladimir
Offline
Зарегистрирован: 08.03.2013

Я пока не умею :) Почитал про страшную разбивку цифр на куски, перевод в биты и запись в EEPROM - не понял и забросил на потом :)

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

А вот писать в EEPROM 2 переменные unsigned long (одометр и литрометр) и еще наверное 3-5 int - хотелось бы.

renoshnik
Offline
Зарегистрирован: 11.04.2013
etaon
Offline
Зарегистрирован: 16.12.2011

 

планирую sd применить. туда и логи писать. там же и кгнфиги хранить.

ридер стоит 200р. к3ил уже этот шилд. каротнауалом. начну с 8 мегебайтной )

 

 

melvladimir
Offline
Зарегистрирован: 08.03.2013

Уже умеешь писать/читать данные с SD? (особенно писать логи, тоже хотел)

renoshnik пишет:

http://habrahabr.ru/post/135231/

Именно этот пост натолкнул меня на создание, но в том проекте я не увидел, чтобы код использовал прерывания... В общем - ссылкос не дает готового "продукта" для себя...

melvladimir
Offline
Зарегистрирован: 08.03.2013

Сегодня немножко тестировал. Изменил схему подключения, теперь "слушаю" только одну пару форсунок (у меня блок управления рулит форсунками попарно), поскольку подключение всех форсунок на один вход дает искажение данных, видимо из-за непрямоугольности сигнала. Таким образом 1 пара форсунок (любая, делал несколько замеров) дает показатель ~450 мл/час, а обе пары вместе - ~650 мл/час.

Если есть необходимость "слушать" все форсунки, то их надо подключать к разным портам (если разделенное управление, то можно нечетные сажать на один порт, а четные - на другой) и потом в коде объединять показатели. Я решил не заморачиваться.

Также из схемы убрал "подпорку" +5В, т.к. Ардуино само делает "подтяжку" сигнала HIGH (pullup).

Теперь схема подключения выглядит так:


 

dronsoft
Offline
Зарегистрирован: 02.06.2011

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

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

Так как у вас нет осциллографа добавьте компаратор на входе и проверьте. перед компаратором возможно нужен сглаживающий фильтр. да даже без компаратора лучше поставить. мое ИМХО

melvladimir
Offline
Зарегистрирован: 08.03.2013

Про компаратор не понял... Данные пока выдает подходящие, сегодня боевое тестирование. Единственный момент - забыл перед установкой добавить в код вычисление оборотов, а после сборки снимать БК было лень :)

dronsoft пишет:

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

Я чуть выше ж написал, что у меня управление идет парой форсунок :) В коде уже поправил.

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

Также добавлю в код подсчет оборотов по форсункам - это будет базовым показателем пропусков, также появилась мысль записывать и хранить количество сделанных оборотов и продолжительность работы двигателя... надо обдумать это :) была б новая машина - точно сделал бы, а так - уже особо нет смысла вычислять "пустой" износ (к примеру - 100 000км по трассам и по городу - совсем разные пробеги). Если и буду реализовывать, то в последнюю очередь.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

ну если все четко то конечно без компаратора

melvladimir
Offline
Зарегистрирован: 08.03.2013

Так а какой компаратор можно добавить? Я могу только с оборотами примерно сравнить с тахометром и по мгновенному расходу / общему по километражу сравнить с "реальными" цифрами (из расчета 9,5л/100км).

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

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

вот например что будет на 12В форсунке индуктивностью 100мкГ сопротивлением 15 Ом и емкостью 0,2 пФ (нашел параметры какой то форсунки. не говорю что у вас также)

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

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

melvladimir
Offline
Зарегистрирован: 08.03.2013

Сегодня провел тест - под нагрузкой лажа. Лучше, чем было, но всё равно врёт от 0 до нескольких литров...

Купил оптопары, буду пробовать подключиться через оптопару, может решится вопрос. Я в схемотехнике разбираюсь плохо :)

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

если в схемотехнике разбираетесь плохо то ни компараторов, ни быстрых операционников у вас нет

я показал что у вас приблизительно на входе. даже если набросаю схему вы сможете ее изготовить?

ishved
Offline
Зарегистрирован: 06.03.2013

http://compcar.ru/forum/showthread.php?t=4457 используя туже ардуину можно посмотреть сигнал с помощью осциллографа.
А вот схема по которой я подключался к форсункам
http://compcar.ru/forum/attachment.php?attachmentid=15962&stc=1&d=136085...

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

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

melvladimir
Offline
Зарегистрирован: 08.03.2013

Осцилограф еще не собрал, есть некоторые проблемки с примером... Добавил в код замер оборотов по тактам открытия форсунок - врет на +20..+30%

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

Сегодня набросал код меню, правда пока не знаю что в нем переключать :)

melvladimir
Offline
Зарегистрирован: 08.03.2013

Вчера переподключил дисплей - разжился 10-ти и 6-ти жильными проводами + коннектор, заодно изменил внешний вид, правда подсветку сильно притушил...

Также подключил форсунку через оптопару + добавил конденсатор 10нФ. Схема такая:

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

Теперь подбираю реальный номинал форсунки, а то сейчас показатели расхода врут примерно в 1,5 раза.

etaon
Offline
Зарегистрирован: 16.12.2011

 

подсветку ссделай автоматической. датчик света- фоторезистор. а подсветку экрана цепляй на ногу ардуины и ШИИом ее регулируй.

melvladimir
Offline
Зарегистрирован: 08.03.2013

Подсветка и так автоматом и без МК. Набор резисторов и фоторезистор. Просто тонировочная пленка много сожрала :) (хотел, чтобы выключенный экран не был виден вообще).

melvladimir
Offline
Зарегистрирован: 08.03.2013

Увеличил константы на 1,67, протестировал: после легкого прогрева 1,1л на холостых (835-865об/мин). Также переделал период обновления - сделал 2 секунды, так лучше.

Пару раз педалировал в пересчете до 25л/100км Максимальные цифры видел 13л/ч (при скорости около 65км/ч) на 3-й передаче.
В общем - доволен результатом. На днях добавлю запись/чтение данных в eeprom, чтобы сохранять кол-во сожженного топлива.

Сейчас пишу код обработки датчика скорости (его пока нет, делаю), расчет скорости и расход в пересчете на 100км.

xstramento
Offline
Зарегистрирован: 19.10.2013

melvladimir пишет:
Тестовый прогон результатом не впечатлил... то ли помеха, то ли код, то ли всё вместе. В общем - работает, что-то показывает, но далеко от правды. На холостых после прогрева показатель практически одинаковый 

На автомобиле очень высокий риск импульсных помех, особенно при отключении стартера. Рекомендую защитить все входные и питающие цепи TVS или варисторами.  Неиспользуемые выводы притянуть к GND. При длительной эксплуатации нужно учесть нестойкость к вибрации разъемных соединений печатной платы и образование конденсата.

Со вторым можно бороться помещая устройства в корпус IP56 c  герметичными вводами и пакетиком заранее осушенного силикагеля. Удачи Вам!

steel780
Offline
Зарегистрирован: 25.01.2013

к тому же время впрыска заметно зависит от напряжения сети (компенсация лага форсунки), и постоянно меняющееся давления в рейке (тойота от 2,5 на холостом до 3,3 при открытом дросселе для атмо моторов и гораздо больше для турбо) тоже не способствует точности измерений:)

xstramento
Offline
Зарегистрирован: 19.10.2013

steel780 пишет:
к тому же время впрыска заметно зависит от напряжения сети (компенсация лага форсунки), и постоянно меняющееся давления в рейке (тойота от 2,5 на холостом до 3,3 при открытом дросселе для атмо моторов и гораздо больше для турбо) тоже не способствует точности измерений:)

или усложнять систему и дублировать датчики МК инжектора двигателя :-((((  или по сети взять информацию о расходе топлива от МК

ishved
Offline
Зарегистрирован: 06.03.2013

steel780 пишет:

к тому же время впрыска заметно зависит от напряжения сети (компенсация лага форсунки), и постоянно меняющееся давления в рейке (тойота от 2,5 на холостом до 3,3 при открытом дросселе для атмо моторов и гораздо больше для турбо) тоже не способствует точности измерений:)


А откуда мозгам известно давление топлива? И наличие турбины на давление тоже не влияет, у меня точно такое же давление как и у вас. 2.2 литра + турбина.

melvladimir
Offline
Зарегистрирован: 08.03.2013

С учетом того, что производительность насоса около 100л/ч, а максимальная производительность форсунок при номинальном давлении 46л/ч, да еще и тот факт, что производительность не сильно прыгает в диапазоне 2,5-3,5атм, то этими всеми мегаточностями можно пренебречь.

Я вот щаз езжу по городу при 60-70км/ч на пятой - экономия 500мл/ч. Резко стараюсь не падалировать, а то расход может прыгать до 10л/ч, а скорость при этом - 30-40 км/ч :) Т.е. может доходить до 30л/100 км.

По поводу помех - хочу переподключить МК от преобразователя DC-DC от 10В, это снизит кол-во помех.

Корпус у МК сделан из оцинковки 0,5мм, на дне толстая пленка, МК прикреплен винтами к дну через пластиковые проставки. Провода в корпус введены через герметичные кабельные вводы (PG7). На пути к дисплею и датчикам один 14 пиновый разъем, чтобы исключить его рассоединение заклеиваю изолентой.

melvladimir
Offline
Зарегистрирован: 08.03.2013

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

Помогите, пожалуйста, разобраться!

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

unsigned long dur=0; //сделать запись и чтение из eeprom
unsigned long dur_t=0;
unsigned long prev_ms=0;
unsigned int brnd=0; //сделать запись и чтение из eeprom
char ms1=0;
volatile long mks16=0;
unsigned long aver=0;
unsigned long aver_temp=0;
unsigned int aver_h=0;
unsigned int aver_100=0;
unsigned long m=0; //сделать запись и чтение из eeprom
unsigned long m_temp=0;
unsigned int speed=0;
unsigned int speed_temp=0;
int T=0;
int F=0;
unsigned int tah = 0;
unsigned int tah_s = 0;

void setup()
{
lcd.begin(16, 2);
pinMode(21, INPUT);
digitalWrite(21, HIGH);
pinMode(20, INPUT);
digitalWrite(20, HIGH);
TCCR2A = 0;
TCCR2B = 1;
TCNT2=0;
attachInterrupt(2, fuel, CHANGE);
attachInterrupt(3, odom, FALLING);
}
ISR(TIMER2_OVF_vect)
{
	mks16++;
}
void fuel()
{
	if (!(PIND & B00000001)) {
		TCNT2=0;
		TIMSK2 |= (1 << TOIE2);
		tah++;
	} else {
		TIMSK2 &= ~(1<<TOIE2);
		dur_t += mks16;
		mks16 = 0;
	}
}
void odom()
{
	m++;
}
void loop()
{
	if ((millis() - prev_ms) >= 500) {
		prev_ms = millis();
		ms1++;
	}
	if (ms1 == 1 || ms1 == 5) {
		lcd.setCursor (0,0);
		lcd.print ("Avg:     ");
		lcd.setCursor (4,0);
		lcd.print (aver_h);
		lcd.setCursor (10,0);
		lcd.print ("Sp:   ");
		lcd.setCursor (13,0);
		lcd.print (speed);
		lcd.setCursor (10,1);
		speed_temp=m * 102/1000;
		lcd.print (speed_temp);
	}
	if (ms1 == 2 || ms1 == 6) {
		brnd = dur_t / 5847;
		lcd.setCursor (0,1);
		lcd.print ("Ovr:");
		lcd.print (brnd);
	}
	if (ms1 == 3) {
		T=analogRead(6);
	}
	if (ms1 == 4 || ms1 == 8) {
		aver = dur_t - aver_temp;
		aver_temp = dur_t;
		aver_h = aver * 308 / 1000;
		tah_s = tah * 30;
		speed = (m - m_temp) * 1836 / 10000;
        m_temp = m;
		tah=0;
		if (ms1 == 8) {ms1 = 0;}
	}
	if (ms1 == 7) {
		F=analogRead(7);
	}
	
}

 

steel780
Offline
Зарегистрирован: 25.01.2013

ishved пишет:
steel780 пишет:

к тому же время впрыска заметно зависит от напряжения сети (компенсация лага форсунки), и постоянно меняющееся давления в рейке (тойота от 2,5 на холостом до 3,3 при открытом дросселе для атмо моторов и гораздо больше для турбо) тоже не способствует точности измерений:)

А откуда мозгам известно давление топлива? И наличие турбины на давление тоже не влияет, у меня точно такое же давление как и у вас. 2.2 литра + турбина.

 

а для чего по вашему трубка идет от регулятора давления топлива к коллектору?  для компенсации давления топлива в зависимости от давления в коллекторе. иначе 2,5кг в рейке встретятся с 1,5 избытка в коллекторе и по итогу не хватит даже на распыл нормальный.

steel780
Offline
Зарегистрирован: 25.01.2013

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

melvladimir
Offline
Зарегистрирован: 08.03.2013

С кодом разобрался, просто натупил чуток :)

Скорость/метраж отображает точно (сравнивал с родным спидометром/одометром).

MikJagger
Offline
Зарегистрирован: 10.12.2013

Всем Добрый день! Я немного не понимаю, точнее не уверен, с повышением нагрузки или увеличением числа оборотов ДВС (когда вообщем давим на газульку), длительность впрыска форсунки увеличивается?! например, на холостых форсунка впрыскивает бенз с длительностью 2-3 мс, а с увеличением числа оборотов начинает впрыскивает с большей длительностью 4-5 мс?! Но, если на холостых это где-то 600 - 700 об мин + двигатель 4х тактный  = около 5 Гц период работы форсунки на холостых, и где-то 50-55 Гц   период форсунки на оборотах 6000 об/мин?! И за один период форсунка открывается 2-3 мс на холостых, и 6-7мс (например) на 6000об/мин, я правильно понимаю?!

MikJagger
Offline
Зарегистрирован: 10.12.2013

Всем Добрый день! Я немного не понимаю, точнее не уверен, с повышением нагрузки или увеличением числа оборотов ДВС (когда вообщем давим на газульку), длительность впрыска форсунки увеличивается?! например, на холостых форсунка впрыскивает бенз с длительностью 2-3 мс, а с увеличением числа оборотов начинает впрыскивает с большей длительностью 4-5 мс?! Но, если на холостых это где-то 600 - 700 об мин + двигатель 4х тактный  = около 5 Гц период работы форсунки на холостых, и где-то 50-55 Гц   период форсунки на оборотах 6000 об/мин?! И за один период форсунка открывается 2-3 мс на холостых, и 6-7мс (например) на 6000об/мин, я правильно понимаю?!

melvladimir
Offline
Зарегистрирован: 08.03.2013

В принципе - правильно. Обороты растут из-за большего кол-ва впрыскиваемого топлива в фазе впрыск, а кол-во растет за счет увеличения длительности открытия форсунки, а длительность открытия (у моего авто) зависит от положения дроссельной заслонки и поступающего объема воздуха :)

На холостых (1000) оборотах фаза впрыск длится 30мс, а форсунка при этом открывается всего на 0,8 миллисекунды. Для 4х цилиндрового двигателя фаза впрыск (равно как и другие фазы: "сжатие", "рабочий ход", "выпуск") происходят каждые пол оборота коленвала.

А вот на 2000 оборотах и скорости 75км/ч фаза впрыск длится 15мс, а каждая форсунка открывается на 1,5мс.

На 100км/ч и 2500 оборотов - 12мс фаза и 2мс форсунка льет в этой фазе.
На 6000 оборотов - не знаю какой будет расход, а кол-во впрысков - 12000 в минуту или 200Гц.

PS: эти данные зависят от номинального расхода форсунки и двигателя в целом

raptoridze
Offline
Зарегистрирован: 10.01.2014

можно перевыложить Текущая схема подключения ?

а то потерялась картинка((

melvladimir
Offline
Зарегистрирован: 08.03.2013

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

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

В код добавлено:
- чтение/запись в EEPROM данных.

raptoridze
Offline
Зарегистрирован: 10.01.2014

ну а старую схемку можно обновить?) 

melvladimir
Offline
Зарегистрирован: 08.03.2013

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

Нормальная схема подключения пары форсунок - сообщение №24.
Дисплей подключается по "типовой" схеме, я даже пины не менял, как во многих примерах в Инете.

С тех пор добавился спидометр, по-нормальному подключены датчики уровня топлива и температыра двигателя, МК подключен через DC-DC step-down преобразователь (на выходе держит 8В) и может еще что-то, уже всех блужданий в поисках истины не вспомню :)

raptoridze
Offline
Зарегистрирован: 10.01.2014

форсунку понял как подключить

хочу еще подключить тахометр и спидометр ... они не аналоговые ... на тахометре есть  три контакта : +, - , и управление ... 

на спидометре 4 контакта : +, -, одометр, спидометр

как их подключать?! по такой же схеме через оптопару?

Sergeyulianov
Offline
Зарегистрирован: 21.02.2015

Здравствуйте, тема еще жива?

выложите, пожалуйста скетч и новую схему подключения, заранее спасибо)

melvladimir
Offline
Зарегистрирован: 08.03.2013

Схему надо нарисовать... Насколько помню, последний скетч такой:

#include <EEPROMex.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

byte lch[8] =
{
  B10000,
  B10001,
  B11010,
  B00100,
  B01000,
  B10101,
  B00111,
  B00001,
};

byte lkm[8] =
{
  B10000,
  B10001,
  B11010,
  B00100,
  B01000,
  B10101,
  B00110,
  B00101,
};

byte azs[8] =
{
  B11100,
  B10100,
  B10100,
  B10111,
  B11110,
  B11100,
  B11100,
  B11100,
};
volatile unsigned long dur=0;
volatile unsigned long dur_t=0; //734л предел
volatile unsigned long m=0;
volatile int mks16=0;
unsigned long prev_ms=0;
unsigned long m_temp=0;
unsigned long aver=0;
unsigned long aver_temp=0;
unsigned int aver_h=0;
unsigned int aver_100=0;
unsigned int brnd=0;
unsigned int brnd2=0;
unsigned int speed=0;
unsigned int speed_temp=0;
unsigned int avg=0;
int T=0;
int F=0;
int ms=0;
int ms1=0;
int menu=0;

void setup()
{
dur=0;
dur_t=0;
m=0;
mks16=0;
prev_ms=0;
m_temp=0;
aver=0;
aver_temp=0;
aver_h=0;
aver_100=0;
brnd=0;
brnd2=0;
speed=0;
speed_temp=0;
avg=0;
T=0;
F=0;
ms=0;
ms1=0;
menu=0;

analogReference(EXTERNAL);
lcd.begin(16, 2);
pinMode(21, INPUT);
digitalWrite(21, HIGH);
pinMode(20, INPUT);
digitalWrite(20, HIGH);
pinMode(22, INPUT);
pinMode(23, INPUT);
pinMode(49, OUTPUT); //поддержание питания
digitalWrite(49, HIGH); //поддержание питания
TCCR2A = 0;
TCCR2B = 1;
TCNT2=0;
attachInterrupt(2, fuel, CHANGE);
attachInterrupt(3, odom, FALLING);

lcd.createChar(1, lch);
lcd.createChar(2, lkm);
lcd.createChar(3, azs);

dur=EEPROM.readLong(0);
dur_t=EEPROM.readLong(4);
m=EEPROM.readLong(8);
avg=EEPROM.readInt(12);
lcd.clear();
}
ISR(TIMER2_OVF_vect)
{
	mks16++;
}
void fuel() {
	if (!(PIND & B00000001)) {
		TCNT2=0;
		TIMSK2 |= (1 << TOIE2);
	} else {
		TIMSK2 &= ~(1<<TOIE2);
		dur += mks16;
		dur_t += mks16;
		mks16 = 0;
	}
}
void odom() {
	m++;
}
void loop() {
if (PINA & B00000001) { //замок зажигания в 1
	if (PINA & B00000011) { //замок зажигания в 2
		menu = 1;
	} else {
		if (menu == 1 || menu == 2) {
			menu = 2;
		} else {
		menu = 0;
		lcd.clear();
		lcd.setCursor (0,0);
		lcd.print ("  Start Engine  ");
		}
	}
} else {
	if (menu < 2) { menu = 2;}
	if ((millis() - prev_ms) >= 30000) {
		prev_ms = millis();
		menu++;
		if (menu == 4) {
			EEPROM.updateLong(0, dur);
			EEPROM.updateLong(4, dur_t);
			EEPROM.updateLong(8, m);
			EEPROM.updateInt(12, avg);
			lcd.clear();
			lcd.setCursor (0,0);
			lcd.print (" All Data Saved ");
			lcd.setCursor (0,1);
			lcd.print ("  Successfully  ");
		}
		if (menu == 5) {
			lcd.clear();
			lcd.setCursor (0,0);
			lcd.print ("   30 seconds   ");
			lcd.setCursor (0,1);
			lcd.print ("to switching off");
		}
		if (menu == 6) {
			digitalWrite(49, LOW); //выключение питания
		}
	}
}

if (menu == 1) {
	if ((millis() - prev_ms) >= 250) {
		ms += (millis() - prev_ms);
		prev_ms = millis();
		ms1++;
		if (ms1 == 1 || ms1 == 5) {
			if (speed < 15) {
				lcd.setCursor (0,0);
				lcd.write(1);
				lcd.print ("     ");
				lcd.setCursor (1,0);
				lcd.print (aver_h);
			} else {
				lcd.setCursor (0,0);
				lcd.write(2);
				lcd.print ("     ");
				lcd.setCursor (1,0);
				lcd.print (aver_100);
			}
			lcd.setCursor (6,0);
			lcd.print ("V     ");
			lcd.setCursor (7,0);
			lcd.print (speed);
			lcd.setCursor (6,1);
			lcd.print ("S      ");
			lcd.setCursor (7,1);
			speed_temp=m * 14/125;
			lcd.print (speed_temp);
			
		}
		if (ms1 == 2 || ms1 == 6) {
			brnd = dur_t / 5847;
			lcd.setCursor (0,1);
			lcd.print ("B");
			lcd.print (brnd);
			if (brnd < 10000) {lcd.print (" ");}
		}
		if (ms1 == 3) {
			T=analogRead(6);
			if (T>830) {
				lcd.setCursor (12,0);
				lcd.print ("STOP");
			} else {
				if (T<=830 && T>610) {
					lcd.setCursor (12,0);
					lcd.print ("COLD");
				} else {
					if (T<=610 && T>500) {
							lcd.setCursor (12,0);
							lcd.print ("norm");
						} else {
						if (T<=500 && T>390) {
							lcd.setCursor (12,0);
							lcd.print ("NORM");
						} else {
							if (T<=390 && T>310) {
								lcd.setCursor (12,0);
								lcd.print ("WARM");
							} else {
								lcd.setCursor (12,0);
								lcd.print ("HOT!");
						} } } }
			}
		}
		if (ms1 == 4 || ms1 == 8) {
			aver = dur_t - aver_temp;
			aver_temp = dur_t;
			aver_h = aver * 616 / ms;
			speed = (m - m_temp) * 403 / ms;
			ms = 0;
			aver_100 = aver * 153 / (m - m_temp);
			m_temp = m;
			if (ms1 == 8) {ms1 = 0;}
			if (aver < 777) { //включение стопов при торможении двигателем
				digitalWrite(48, HIGH);
			} else {
				digitalWrite(48, LOW);
			}
		}
		if (ms1 == 7) {
			F=analogRead(7);
			if (F<650 && F>=575) {F=0;}
			else if (F<575 && F>=553) {F=5;}
			else if (F<553 && F>=530) {F=10;}
			else if (F<530 && F>=508) {F=15;}
			else if (F<508 && F>=487) {F=20;}
			else if (F<487 && F>=465) {F=25;}
			else if (F<465 && F>=433) {F=30;}
			else if (F<433 && F>=401) {F=35;}
			else if (F<401 && F>=368) {F=40;}
			else if (F<368 && F>=324) {F=45;}
			else if (F<324 && F>=280) {F=50;}
			else if (F<280 && F>=235) {F=55;}
			else if (F<235) {F=60;}
			lcd.setCursor (13,1);
			lcd.write(3);
			lcd.print (F);
			lcd.print (" ");
		}
	}
}
}

 

alex26079
Offline
Зарегистрирован: 08.02.2016

Выложите пожалуйста схему подключения, заранее спасибо.

phbo
Offline
Зарегистрирован: 19.07.2016

Выложите пожалуйста схему подключения, заранее спасибо.