ФУОЗ по дешману
на сайте:
ноя-08
нахождение:
Москва, Ясенево
|
|
26-11-20 18:13
|
|
Ребята на базе ардуино запилили фуоз, дешево и просто |
|
на сайте:
ноя-08
нахождение:
Москва, Ясенево
|
|
26-11-20 18:13
|
|
Ребята на базе ардуино запилили фуоз, дешево и просто |
|
Прикольная тема. Пойду закажу себе парочку платок у китайцев на эксперименты..
Уже заказал :) попробуем
Кто сделает отпишитесь , результат очень интересен.
Интересная тема, послежу. Давно подумывал про ФУОЗ на ардуинке, но пока знаний по написанию кода не хватает.
___________________________________________________________________
"Человека можно уничтожить, но его нельзя победить" (Э. Хемингуэй)
Интересная тема.
Удалось пока вроде разобраться с углами опережения, можно в самом скетче прописать более детальный диапазон, например с шагом в 500об/мин
Пока не понял, можно ли сделать второй сигнал через нужное время. Вроде выход Р4 можно использовать, но до конца не разобрался.
Второй сигнал зачем? На 4 горшка?
Кстати вопросик, в этом зажигании имеет значение разница в пропорциях шторка-окно, как оно обороты считает? На ютубе задал вопрос создателям сего, но они чего-то игнорируют...
Что я для себя вывел, т.к. зажигание выставляется уже в момент зажигания, надо углы прописывать с этим вычетом.
Обороты считает по сигналам от датчика (холла или опто) один сигнал - один оборот кв
nextIgnition = (500000 * (360 - ignitionDegree)) / (3 * rpm) + VMTtime;
Ниже задаётся для каких оборотов как угол использовать (но через формулу, в экселе подобрать удалось обратным методом)
Второй сигнал в целом можно использовать и для двух свечей в один цилиндр, и для v-моторов, и пр.
проще наверно вторую такую платку подвесить, со своим отдельным датчиком.
А вот сделать как в сарумановском несколько графиков, хотя-бы два, уже интереснее.
Тогда другую платку надо брать с большим объёмом памяти , либо несколько плат ардуино иметь и переключать их.
занято меньше половины памяти платы , так что думаю можно и второй вывод сделать со сдвигом, но интереснее сделать обработку ДАД.
(Скетч использует 2970 байт (49%) памяти устройства. Всего доступно 6012 байт.
Глобальные переменные используют 41 байт динамической памяти.)
вот цикл подсчета угла от оборотов и у меня большой вопрос возникает , график то получается не линейный..... с разрывами п... и плоской полкой после 4000 рпм
( if (rpm >= 700 && rpm <= 1000) { // 0 - 2.2
ignitionDegree = 0.007 * rpm + (-5.133);
}
if (rpm >= 1000 && rpm <= 2000) { // 2.2 - 15
ignitionDegree = 0.013 * rpm + (-10.600);
}
if (rpm >= 2000 && rpm <= 3000) { // 15 - 25.1
ignitionDegree = 0.013 * rpm + (-11.000);
}
if (rpm >= 3000 && rpm <= 4000) {// 25.1 - 33.7
ignitionDegree = 0.007 * rpm + (7.000);
}
if (rpm > 4000) {
ignitionDegree = 33.7;
})
Именно эту часть поправил, чтобы без разрывлв было, пример куска ниже., с чем удалось поиграться. Как прописать сдвиг например в формате + n градусов или + %
И свыше каких-то оборотов можно вывести на нужную полку как сделано у ребят. У меня скетч получился с учетом детализации на 60%, и пришлось коэффициент до 4го знака прописывать
if (rpm > 600 && rpm <= 800) { // 0 - 10.8
ignitionDegree = 0.0540 * rpm + (-32.400);
}
if (rpm > 800 && rpm <= 1000) { // 10.8 - 20.8
ignitionDegree = 0.0500 * rpm + (-29.200);
}
if (rpm > 1000 && rpm <= 1500) { // 20.8 - 18.6
ignitionDegree = 0.0044 * rpm + (25.200);
}
if (rpm > 1500 && rpm <= 2000) { // 18.6 - 17
ignitionDegree = 0.0032 * rpm + (-23.400);
}
....
if (rpm > 5500 && rpm <= 6000) { // 23.9 - 25
ignitionDegree = 0.0022 * rpm + (11.800);
}
if (rpm > 6000 && rpm <= 6500) { // 25 - 26.7
ignitionDegree = 0.0034 * rpm + (4.600);
}
if (rpm > 6500) {
ignitionDegree = 26.7;
}
ignitionDegree = 0.0044 * rpm + (25.200);
Знак забыл. У тебя тут получается 69,2 градуса угол. В космос улетит.
Рекомендовал бы оптимизировать расчёты, т.к. у ATMega/ATTiny нет блока для расчётов с плавающей точкой, и операции с дробными числами стоят дорого.
Текущий угол поворота можно перевести в uint16 / unsigned int (0...65535), а угол опережения - в uint8 / byte (0...255) - это освободит память и ускорит вычисления. Можно будет ещё каких свистелок-перделок напихать. :-)
Опять же, куча последовательных IF, когда может быть истинно только одно условие в один момент времени, не имеет смысла и будет тратить ресурсы, т.к. проверка не закончится на первом попавшемся истинном условии, а каждое будет проверяться на истинность. Лучше использовать CASE (как альтернатива - ELSE IF, но CASE красивее выглядит).
Но больше всего меня, конечно, беспокоит помехозащищённость. Я пока не победил наводки на Мегу от системы зажигания.
Peacedeath подкрался незаметно, но слышен был издалека
За знак спасибо, упустил при копипасте.
Я с программированием не очень знаком, если по переводу uint16 и uint8, а также IF ELSE в SWITCH CASE подскажешь, это очень поможет :)
Если дальше отодвинуть от системы зажигания?
как то так
if (rpm >= 700 && rpm <= 1000) { // 0 - 2.2
ignitionDegree = 0.007 * rpm + (-5.133);
}
else if (rpm > 1000 && rpm <= 2000) { // 2.2 - 15
ignitionDegree = 0.013 * rpm + (-10.600);
}
else if (rpm > 2000 && rpm <= 3000) { // 15 - 25.1
ignitionDegree = 0.013 * rpm + (-11.000);
}
else if (rpm > 3000 && rpm <= 4000) {// 25.1 - 33.7
ignitionDegree = 0.007 * rpm + (7.000);
}
else if (rpm > 4000) {
ignitionDegree = 33.7;
}
Ага. Только комменты всё равно сильно отличаются от истинных расчётных значений. Да и расчёт совсем не гибкий...
Я бы переписал чуть иначе.
Сначала надо придумать график и объявить его в самом начале кода в виде констант:
#define RPM_700 700 // Первая точка у нас на 700 об/мин
#define ANGLE_700 0
#define RPM_1000 1000
#define ANGLE_1000 22 // богомерзкий float умножаем на 10, пусть пока побудет целочисленным, а так это 2,2 градуса
#define RPM_2000 2000
#define ANGLE_2000 150
#define RPM_3000 3000
#define ANGLE_3000 251
#define RPM_4000 4000
#define ANGLE_4000 337
Вот мы получили график из 5 точек, соответствующий комментариям (не фактическим формулам!)
Так как графики между точками линейные, то вместо диких вычислений с плавающей точкой, волшебными коэффициентами и магическими слагаемыми можно взять более красивую функцию экстраполяции (map), а для наглядности и простоты добавления точек использовать switch case:
// расчёт угла по таблице из 5 точек с возможностью расширения до 60
float get_angle (unsigned int rpms) { // функция расчёта угла. Возвращает число с плавающей точкой, в качестве входного параметра принимает целочисленное значение оборотов в минуту
byte tempRPM = rpms / 100; // Делим обороты на 100, чтобы не расписывать варианты для каждого значения
switch (tempRPM) {
int tempDEG; // временная переменная, чтобы не трогать float
CASE 1:
CASE 2:
CASE 3:
CASE 4:
CASE 5:
CASE 6:
tempDEG = ANGLE_700; // вот мы поставили для первых 699 об/мин нулевой угол
break; // Не забываем ставить break там, где нужно прекратить проверку, если найдено сов падение
CASE 7:
CASE 8:
CASE 9:
tempDEG = map(rpm, RPM_700, RPM_1000, ANGLE_700, ANGLE_1000); // Вот пример использования функции. Приводим положение текущего значения оборотов в минуту в заданном диапазоне 700...1000 к соответствующей точке графика в диапазоне 0...22
break; // Не забываем ставить break!
CASE 10:
<...> // мне лень выписывать все строки от 10 до 19, да и пост слишком уж длинным получается, но они должны быть!
CASE 19:
tempDEG = map(rpm, RPM_1000, RPM_2000, ANGLE_1000, ANGLE_2000);
break;
CASE 20:
<...>
CASE 29:
tempDEG = map(rpm, RPM_2000, RPM_3000, ANGLE_2000, ANGLE_3000);
break;
CASE 30:
<...>
CASE 39:
tempDEG = map(rpm, RPM_3000, RPM_4000, ANGLE_3000, ANGLE_4000);
break;
CASE 40:
<...>
CASE 59:
tempDEG = ANGLE_4000; // А тут усреднение уже не нужно, тут полка угла.
break;
default:
tempDEG = 0; // По дефолту угол 0, если будет какое-то непредвиденное значение (например, 7000 RPM, или кто-то тоже поленится и не напишет CASE 25:, то при 2500 RPM тоже :-))
break;
}
return float(tempDEG) / 10; // и только сейчас переводим результат в число с плавающей точкой, делим на 10 и возвращаем в место вызова функции, хотя подозреваю, что оно нафиг не надо, т.к. в других местах тоже можно переписать под целые числа.
}
Этот кусок можешь вставить в конец кода.
А всю магию можно заменить на одну строчку:
ignitionDegree = get_angle(rpm);
Это можно написать ещё красивее, но мне лень. :-)
Peacedeath подкрался незаметно, но слышен был издалека
Подправил шрифт в комментариях к коду, для лучшей читабельности. BuffoG
вариант с map куда симпатичнее, но тут сразу возникает вопрос а не проще обойтись теми же 5 if else if меж кнтрольных точек, чем городить 40 кейсов ?
#define RPM_700 700 // Первая точка у нас на 700 об/мин
#define ANGLE_700 0
#define RPM_1000 1000
#define ANGLE_1000 22 // богомерзкий float умножаем на 10, пусть пока побудет целочисленным, а так это 2,2 градуса
#define RPM_2000 2000
#define ANGLE_2000 150
#define RPM_3000 3000
#define ANGLE_3000 251
#define RPM_4000 4000
#define ANGLE_4000 337
// это из тела программы в замен кривых расчетов .
if (rpm >= 0 && rpm <= 700) {
oldtime = micros();
ignitionFlag = true;
return;
}
else if (rpm >= 700 && rpm <= 1000) { // 0 - 2.2
ignitionDegree = (map(rpm, RPM_700, RPM_1000, ANGLE_700, ANGLE_1000))/10;
}
else if (rpm > 1000 && rpm <= 2000) { // 2.2 - 15
ignitionDegree = (map(rpm, RPM_1000, RPM_2000, ANGLE_1000, ANGLE_2000))/10;
}
else if (rpm > 2000 && rpm <= 3000) { // 15 - 25.1
ignitionDegree = (map(rpm, RPM_2000, RPM_3000, ANGLE_2000, ANGLE_3000))/10;
}
else if (rpm > 3000 && rpm <= 4000) {// 25.1 - 33.7
ignitionDegree = (map(rpm, RPM_3000, RPM_4000, ANGLE_3000, ANGLE_4000))/10;
}
else if (rpm > 4000) {
ignitionDegree = 33.7;
}
или в замен этого всего просто сделать такой
тут уж не надо констант и выборов .. а обработку ДАД сделать тем же мап .. допустим зашить ему изменение от 0 до -20 при изменении показания с датчика от 0 до 450мВ
if (rpm >= 0 && rpm <= 700) {
oldtime = micros();
ignitionFlag = true;
return;
}
else if (rpm >= 700 && rpm <= 5000) { // 0 - 2.2
rpm = rpm/100;
ignitionDegree = ((-0.02)*rpm*rpm)+1.96*rpm + (-15);
}
else if (rpm > 5000) {
ignitionDegree = 33.7;
Без полного кода править его куски - такое себе удовольствие. Ещё и в древовидной структуре, где ни фига не понятно.
В общем, если ты решил всерьёз заняться этим вопросом, то:
- Создай отдельную тему.
- Вынеси в её шапку ВЕСЬ код, а не отдельные куски.
- Обсудим в комментах к теме реализацию с участием других коллег-оппозитчиков
- Потом поправишь код в шапке исходя из того, что у нас наваяется.
Но вообще для совместной разработки принято использовать gitHub :-)
Peacedeath подкрался незаметно, но слышен был издалека
Скинь текст шестерёнкой, погляжу и покажу.
Увы, у меня несколько иная цель. Мне нужен в электронный тахометр сигнал системы зажигания, но гальванически развязанный от катушки, чтобы не спалить МК, и имеющий чёткие фронты без дребезга. Пока экспериментирую с оптопарой.
Peacedeath подкрался незаметно, но слышен был издалека
а если брать сигнал с датчика хола или оптики , который идет на комутатор ?
Отправил шестерней, потом можно сюда запостить итоговый вариант, чтобы при необходимости каждый сам мог просто углы свои проставить
метал корпус с заземлением?
а как график выглядет то есть формула в визуале его представить?
Дык Excel - наше всё.
Держи график по твоим формулам.
ignitionDegree = 0.007 * rpm + (-5.133);
}
if (rpm >= 1000 && rpm <= 2000) { // 2.2 - 15
ignitionDegree = 0.013 * rpm + (-10.600);
}
Истинны оба условия. На 1000 об/мин угол резко скакнёт с 1,87 до 2,4
И комменты неправильные.
1000 * 0,007 - 5,133 = 7 - 5,133 = 1,867, а никак не 2,2.
1000 * 0,013 - 10,6 = 13 - 10,6 = 2,4, а не 2,2
Peacedeath подкрался незаметно, но слышен был издалека
ох с таким графиком все должно вообще в одной строчке считаться линейно .. он почти прямой..
формулы не мои , это оригинал от разработчиков ))
почитал немного даташит на платку.. можно к ней прикрутить аналоговый датчик ДАД , например такой https://aliexpress.ru/item/4000274503044.html?spm=a2g0o.productlist.0.0....
и запилить в расчет от его показаний уменьшение оперяжения например от 0 до 25 градусов , по идеи это делается парой строчек
Ну не парой, не парой...
Тут уже получается трёхмерная карта, т.к. УОЗ начинает зависеть не только от оборотов, но и от разрежения.
Но если усреднить карту (сделать 5 точек по оборотам, 5 - по давлению, итого 25), то реально и в Tiny впихнуть.
Однако ДАД на нашем оппозите имеет смысл при монокарбе. Иначе нужно вешать либо два ДАД, либо смириться с некоторым несоответствием карты из-за разницы разрежения во впускных трактах разных цилиндров.
Peacedeath подкрался незаметно, но слышен был издалека
еще вопрос почему не считать все в милисекундах а не в микросекондах.. сорян за тупость с ардуино знаком я только вот пару часов сегодня.. или процессорное время единица в микроСек ?
Потому что при 6000 об/мин один оборот происходит за 1/6000 минуты, или 1/100 секунды, или 10 мс.
Таким образом, на одну миллисекунду приходится 36 градусов вращения.
Получается очень дискретное опережение - либо 0 градусов, либо 36...
Peacedeath подкрался незаметно, но слышен был издалека
А нельзя расчет кривой прямо в скетче сделать чтоб высчитывался?
Ну типа подставляем в нужные места значения желаемого опережения на нужном промежутке и дальше оно уже само компилируется.
?
Чтоб не воландаться каждый раз с формулами?
Я так-то начинающий ардуинщик, пока только автоматику на автоматические ворота себе написал, и то из кусков других скетчей..
Можно, конечно. Но чем больше точек, тем больше вес программы.
Чтобы составить таблицу, нужно определённое количество точек.
При самом оптимизированном размещении (3 байта на точку - 2 на об/мин, 1 - на угол опережения) на таблицу в 100 точек понадобится отвести 300 байт.
В 1000 точек - 3000 байт.
А то, что между точками, всё равно придётся высчитывать по формулам, ибо в диапазоне от 600 до 6000 об/мин - 5400 точек, и это уже почти 16 КБайт, что явно не влезет в Тини, это объём уже для Меги 32 и дальше.
Или я неправильно понял твою идею?
Если идея в том, чтобы задать пары "Обороты - угол" и ввести единую функцию для их расчёта, то тут примерно это и сделано. Только сделано коряво - объявлено "магическими числами" прямо в коде, а не вынесено в понятные человекочитаемые константы или переменные.
Peacedeath подкрался незаметно, но слышен был издалека
Да, я про второй вариант имел в виду. Чтоб не на сайте готовить скетч, а прямо перед прошивкой выставил нужные цифры прямо в тексте скетча и всё.
Чуть выше написал пример, как это можно написать более наглядно, масштабируемо и менее ресурсоёмко.
Peacedeath подкрался незаметно, но слышен был издалека
вывел формулу по которой изменяется график от 1000 до 4000 y=-0,0000011*x2+0,0162*x-12,8
если перед началом действий делить обороты на 100 по формула будет y=−0.02x2+1.96x−15 по трудозатратам хз как проще считать... но в это варианте получается перевернутая парабола с пиком на 4900 оборотов график начинается примерно с 850 оторотов
X = обороты, Y = угол, правильно понимаю?
Странные какие-то формулы, если честно. Но проверю. Откуда эти графики взял, если не секрет?
Вечером буду в жилище, нарисую график в Excel. Или сам скинь, полюбуюсь.
Оптимизировать будем потом, сначала надо добиться корректных расчётов. :-)
Peacedeath подкрался незаметно, но слышен был издалека
все верно, y- угол x - обороты.
сам график тупо брал по контрольным точкам от этого зажигания
вот на этом сайте подобрал формулу в онлайн расчетах
http://mathhelpplanet.com/static.php?p=onlayn-mnk-i-regressionniy-analiz
потом в экселе правил коэфиценты до приемлемых графиков.
файлик тут https://drive.google.com/file/d/1HN_ZuDV-9Lb1h3CIE2CUgWiGXlH9z2FA/view?u...
можно пользовать по ссылке его
Не лучше ли взять график типа Сарумана или Вуфера, и от них уже плясать? По крайней мере, под ними есть хоть какая-то исследовательская база и опыт использования.
Peacedeath подкрался незаметно, но слышен был издалека
докинул обработку MAP по спеки МАР выходное напряжение от 0 до 4.5В
но это если ардуино понимает сигнал с миливольтах
по спеки платы назначил аналоговый вход
pinMode(2, INPUT);
void countIgnitionTime() {
ignitionDegree =ignitionDegree + (map(analogRead(1), 450, 0, 0, -200) / 10);
nextIgnition = (500000 * (360 - ignitionDegree)) / (3 * rpm) + VMTtime;
ignitionFlagWithOffset = true;
}
Вот тут совсем не понял...
Сколько бит АЦП у платы? 10?
Диапазон АЦП - 0...5 вольт?
Тогда у тебя при 0 вольтах на аналоговом входе функция analogRead вернёт значение 0, а при 5 - 1023.
Какое напряжение на выходе датчика при атмосферном давлении и какое - при максимальном разрежении?
На какое значение ты хочешь корректировать УОЗ при атмосферном давлении, и на какое - при максимальном разрежении?
p.s. менять глобальные переменные внутри вызываемой функции (не loop) - моветон. При отладке придётся бегать по всем функциям и вспоминать, где какая переменная меняется. Глобальные переменные лучше менять только внутри основной (void loop() в случае Ардуино)
Peacedeath подкрался незаметно, но слышен был издалека
плата https://www.sgbotic.com/products/datasheets/sensors/02976-datasheet.pdf
предположительно надо брать от -100 до 0 модификация XGZP6847100KPGN
исходя из получается что берем значение от 0.5 до 4.5В изменяется при -100 до 0 кРа в реале подозреваю что значение будет меняться меньше .. это придется проверять опытным путем на моторе.
возможно надо просто записывать максимальное и минимальное значение в переменные во всем рабочем цикле и использовать уже их , тогда нам не важно какие именно будут значения на самом МАР
пришло вот такое в голову
long int LoadMax = 10;
long int LoadMin =9;
long int LoadD;
loop
if (ignitionDegree > 0) {
LoadD = analogRead(1);
if (LoadD > LoadMax) {
LoadMax = LoadD;
}
else if (LoadD < LoadMin) {
LoadMin = LoadD;
}
ignitionDegree =ignitionDegree + (map(LoadD, LoadMin, LoadMax, 0, -200) / 10);
countIgnitionTime();
}
П.С.
Понятно что придется делать ресивер и поместить под переднюю крышку , чтоб сгладить колебания , а подключать на место настроечных маномертор (которые подключаются меж головой и карбом) .
А почему ты берешь именно такой МАР? Этот МАР надо еще как-то вкорячить во впуск, почему не взять готовый МАР от авто?
Как вариант
https://www.avtoall.ru/datchik_absolyutnogo_davleniya_vozduha_gaz_uaz_um...
http://clubturbo.ru/market/elektronika/datchik_absolyutnogo_davleniya/da...
У последнего даже график работы есть
___________________________________________________________________
"Человека можно уничтожить, но его нельзя победить" (Э. Хемингуэй)
Что-то мы с тобой тему-то подзасрали, и начинаем лезть не в те дебри.
Давай сначала человечьим языком опишем, что мы хотим получить, прежде чем код трогать. Потому что сейчас я вижу:
// Объявили 3 глобальных переменных, зачем-то long, занимающий 4 байта, хотя двухбайтового беззнакового uint16 вполне хватило бы
long int LoadMax = 10;
long int LoadMin =9;
long int LoadD;
// циклически выполняющаяся функция
loop
if (ignitionDegree > 0) { // если УОЗ больше нуля, то
LoadD = analogRead(1); // читаем аналоговый вход (MAP)
if (LoadD > LoadMax) { // Если прочитанное значение больше текущего значения в переменной LoadMax
LoadMax = LoadD; // Устанавливаем значение LoadMax равное считанному значению.
}
else if (LoadD < LoadMin) { // иначе если прочитанное значение меньше LoadMin
LoadMin = LoadD; // Устанавливаем значение LoadMin равное считанному значению.
}
ignitionDegree =ignitionDegree + (map(LoadD, LoadMin, LoadMax, 0, -200) / 10); // прибавляем к переменной ignitionDegree значение (экстраполяция переменной LoadD в диапазоне от LoadMin до LoadMax на диапазон от 0 до -200 делённое на 10)
countIgnitionTime(); / вызываем некую функцию расчёта времени
}
В этом случае у тебя получится следующее:
При включении зажигания:
- На датчике атмосферное давление, на аналоговом входе 4,5V (analogRead(1) вернёт 920)
- ignitionDegree = 0
- Переменные LoadMin и LoadMax имеют значение 9 и 10 соответственно, т.к. ignitionDegree = 0
При запуске двигателя и ХХ 600 об/мин:
- На датчике появилось некое разрежение, условно -50 КПа, на аналоговом входе 2,5V (analogRead(1) вернёт 511)
- ignitionDegree = 0
- Переменные LoadMin и LoadMax имеют значение 9 и 10 соответственно, т.к. ignitionDegree = 0
При подъёме до 1000 об/мин:
- На датчике уменьшилось разрежение до -45 КПа, на аналоговом входе 2,7V
- Функция analogRead возвращает значение 552
- LoadD = 552
- ignitionDegree = 2,2
- Переменная LoadMin имеет значение 9, LoadMax принимает значение 552
- функция экстраполяции map(LoadD, LoadMin, LoadMax, 0, -200) возвращает значение -200, т.к. LoadD = LoadMax
- Переменная ignitionDegree принимает значение 2,2 + (- 200 / 10) = -17,8
- Мотор глохнет
Тебе точно нужен такой угол опережения?
Распиши сначала, какой именно алгоритм обработки тебе нужен. "Если - то - иначе". Сразу писать код тоже можно, конечно, но тогда хотя бы комментируй его, иначе через пару недель сам не вспомнишь, что и для чего.
Peacedeath подкрался незаметно, но слышен был издалека
первоначальные значения при назначении переменных пока стоят от балды , чисто для понимания,
по идеи можно прям со старта в setup присваивать loadMax значение AnalogRead(1) а LoadMin = LoadMax-10
тогда у нас максимальное разряжение будет писаться по мере работы двигателя, единственный момент что такая само установка покажет при сбросе газа например с 5000 оборотом и , не уплывет ли весь график после этого..
п.с.
и цифры например в -200 и 0 , их спокойно можно подвинуть например (100 , -200 )взята то же чисто для понимания алгоритма ,
возможно нам и не надо такой сложной системы и мы берем один раз в сетап присваиваем
loadMax = AnalogRead(1);
LoadMin = 0;
и может этого достаточно , так как атмосферного давления во впуске мы не получим, только приближение к нему при резко открытом газе.
почему беру именно этот дадчик , он дешев на али что то по 300р .. . можно и дадчик от газели прилепить... в этом то вроде проблем нет.
ссылка на скетч
как раз с этими правками
https://drive.google.com/file/d/1rRTP74p7kGGNRCdIZ0IxXFWP1vKnh5OF/view?u...
Выскажусь немного за МАР - при проектировании ФУОЗ надо отталкиваться от максимальной надежности, унифицированности и
доступности запасных частей в случае поломки (т.е. можно купить в любом автомаге). Датчик с Али хоть и дешев, но заказа с али еще надо дождаться, датчик выполнен в "бескорпусном" исполнении, нужно придумывать переходную плату под типовой водонепроницаемый разъем, корпус. Готовые автошные хоть и дороже, но уже лишены всех перечисленных недостатков.
___________________________________________________________________
"Человека можно уничтожить, но его нельзя победить" (Э. Хемингуэй)
Добавил скетч без обработки мар, с таблицей констант в которой можно выставлять точки графика в самом скече
https://drive.google.com/file/d/1-ncc-kpv4j7sMXa-U6K8jeBgD-EYJGkQ/view?u...
Вот этот же код, только разобранный по косточкам и с моими комментариями.
Работать будет даже с "магическими числами".
Но если ты собираешься его дорабатывать дальше - запихивать работу с MAP и вторым выходом, то его стоит рефакторить, ибо есть неиспользуемые переменные, переменные с непонятным принципом выбора типа данных и куски, где нет приведения данных к нужному типу, из-за чего, например, на 1200 RPM возникает погрешность - вместо расчётного угла 4,76 фактическое опережение будет от 4 до 5,1 градуса. Всё это затрудняет редактирование и увеличивает затраты времени и алкоголя на доработку, снижая прогнозируемость поведения.
Плюс если выключить зажигание на рабочем двигателе (щёлкнуть ДвигСтоп), а потом включить обратно, есть неиллюзорная вероятность пука в карбюраторы (см.строку 174). Но в общем и целом код работоспособен.
Peacedeath подкрался незаметно, но слышен был издалека
else if имеет смысл менять на case ? С твоими комментами перенес с использованием case (обновил файл по ссылке, первый был косячный)
https://drive.google.com/file/d/1pNQQIaCo9AkcKGHd8h8d4N3VcSqo8uAc/view?u...
Если правильно понял. По идее в самом начале достаточно только углы свои подставлять, больше ничего менять не надо.
Вот картинка, кстати, с таблицей про нагрузку, обороты и опережение:
https://drive.google.com/file/d/1huxCUYirpKRp0JddKR4rjXoWQLrNVisB/view?u...
Имеет смысл оценить размер скомпилированного кода в одном и в другом варианте,
Плюс в обоих вариантах стоит использовать временные переменные и однократный вызов функции map с передачей в неё этих переменных, чтобы не раздувать код - там вроде всего 8 кБайт в контроллере?
Плюс там есть зайчатки дебаггинга в виде вывода в serial значения оборотов в минуту.
Это дело хорошее, и его стоит продолжить, потому что можно, конечно, и мысленный эксперимент провести, как я сделал для трёх оборотов коленвала сферического двигателя в вакууме, но если прикручивать свистелки типа MAP-сенсора, то намного логичнее на стенде читать логи работы ФУОЗ в консоли, чем в сотый раз перечитывать в гараже прошивку и думать, почему мотоцикл начинает детонировать, стоит дать чуть нагрузки.
А вот таблица крайне спорная.
Не уверен, что её можно применить к нашим оппозитам. 20,7 градусов опережения на 600 об/мин???
Peacedeath подкрался незаметно, но слышен был издалека
Вот это Элиас огромное спасибо, да надо брать пиво и разбираться в коде и алгоритме по твоим комментариям .
В свое оправдание могу сказать что программировать для ардуино я не умею, ни синтаксиса, ни правил не знаю, правил скеч от блогеров опираясь на свои скудные знания паскаля и т.д. потому прошу не пинать. )) Пока время нет почитать методички по программированию на ардуино.... а мысли что возникают вечером , если не записать то забуду, и потом вспоминай какое изящное пришло решение с обработкой МАР сенсора например ))
П.С
почему ты пишешь : (map(rpm, RPM_700, RPM_1000, ANGLE_700, ANGLE_1000)) / 10; // устанавливаем float угол в пределах от 0 до 2 с шагом 1 градус (потому что оперируем не плавающей точкой, а целочисленными константами)
получается , что функция мар возвращает целочисленное число и её нельзя поделить с остатком?
тогда получается строка должна быть такой:
ignitionDegree = map(rpm, RPM_1000, RPM_2000, ANGLE_1000, ANGLE_2000);
ignitionDegree = ignitionDegree / 10;
?
так же в принципе все расчеты можно построить на значениях углов * 10 "как в объявлении констант" чтоб не пользовать запятых.
Да пожалуйста. Всё равно не спалось. :-)
Оправдания не нужно - я ж понимаю, что это левый код, написанный кем-то в Интернетах, и он почему-то работает, но хочется лучше.
Начало положено. Теперь он хотя бы понятный.
Да, функция map принимает на вход целые числа и возвращает целочисленное значение. Если она вернёт 47, то поделив это число на целочисленное 10, мы получим... Нет, не 4,7 и даже не 5. Мы получим 4. Дробная часть будет отброшена.
Поэтому целочисленное 47 сначала надо привести к типу с плавающей точкой, чтобы поделить его на 10 и получить дробное значение.
ignitionDegree = map(rpm, RPM_1000, RPM_2000, ANGLE_1000, ANGLE_2000);
ignitionDegree = ignitionDegree / 10;
?
Можно и так. Но здесь у тебя получается целых две операции, в которых участвует переменная с плавающей точкой.
Правильный путь - это
Запятые в этом коде не нужны, и если ты перепишешь код так, чтобы в нём остались только целые числа, ты ускоришь его выполнение и уменьшишь его размер.
Peacedeath подкрался незаметно, но слышен был издалека
Если мы считает угол так , угол*10
ignitionDegree = map(rpm, RPM_1000, RPM_2000, ANGLE_1000, ANGLE_2000);
то функция расчета времени искры будет такой:
void countIgnitionTime() { // Функция расчёта времени для следующего момента зажигания
nextIgnition = VMTtime + diffTime - (diffTime/360*ignitionDegree/10); // формула времявмт +время оборота- время оборота деленое на 360 градусов(нашли время одного градуса) умножили на необходимое количество градусов и разделили на 10 (так как градусы получаем в *10 состоянии)
ignitionFlagWithOffset = true;
}
немного причесал скеч с учетом правок и замечаний Элиоса , так же добавил условие первого запуска программы с бездействием до первого полного оборота по втм , так же в новый код сделал обработку МАР, расчеты угла сделал до 5000 оборотов , графики зашил пока для м72 лежит тут версия с МАР и без