я имею ввиду просто колличество нажатий например на кнопку на за время а вообще просто нажатия например на кнопку но при этом если нет сигнала напрмер через 10 мс брос счетчика
В обработчике прерывания просто увеличиваете какой-то счетчик. И каждый раз запоминаете когда вы его увеличили. lastChangeTime=millis();
А в loop() все ремя поверяете сколько прошло времени с lastCHangeTime; Если больше какого-то промежутку - обнуляете счетчик. if(millis()-lastCHangeTime>10000) обнуляем.
Ну и, в том же loop(), аналогично время от времени "делаете расчеты, выводите счетчик в serial и т.п.)
По томуже принципу: сделали расчет, вывели, запомнили когда это сделали в lastReportTime=millis();, а потом проверяем if(millis()-lastReportTime>КАКОЕ-то время){повсторяем расчет, вывод, запоминание времени отчета}
Значит что то не так делаете или не так подключаете.
Да к 2 цифровому выводу. Если собрать схему из сообщения #16 и не подключать к катушке, то в сериал-монитор должны идти одни нули, у вас так?
Если же вы просто проверяете код без схемы, то так и должно быть - мусор.
а вот разберем такую ситуацию на катоде диода +5v, он ведь ничего не пропустит и на аноде нибудет ничего (или почти ничего),
Вы верно подметили "почти ничего". Но все-таки будет. В режиме "вход" через мегамный резистор пин, все-таки, подключен к питанию. По идее этого должно хватить что-бы analogRead намерял 1024.
Если не будет хватать - можно самому подтянуть ногу вверх (или включить внутрений подтягивающий резистор).
Приложился я, все-таки, по этому поводу "мордой об стол".
Как я сказал подключил по этой схеме без подтягивания ноги. Померял analogRead(A0). Вроде все хорошо. Все работает. Четко ловит и 0 и 1024. И чувствовал что "нужна", но "вроде работает и так" - сбило с толку.
Начал дальше скетч писать и в какой-то момент "поймал глюки". Чуть с ума не сошел почему вдруг, начало вместо 1024, что-то в районе 124 вовращать. Причем пускаю проверочный скетч упрощенный, на этом же пине как и положено 1024. Все логику излазил (может где-то включаю что-то не то) :(
А оказалось, что без подтяжки, если слишком часто ЧИТАТЬ (!!!!) СОСЕДНИЙ(!!!) пин (делать analogRead(A1)), то A0 - начинает "врать". Причем разница в "слишком часто" и "не слишком" - милисекунды (даже микро). Причем важно, даже, не "время между чтением A0 и A1", а именно "как часто A1" (разовое чтение - не портит картины).
Поэтому уловить это ошибку - очень трудно. На большом скетче найти это - взрыв мозга. Добавил пару строк в совершенно другое место - уменьшилась, оптимизировал логику - увеличилась.
Вообщем лучше сразу "делать подтяжку к питанию" что-бы потом не иметь сексуальных развлечений. Думаю и другие причину могут заставить "врать" A0. Без подтяжки "слишком не надежно" выходит.
Вопрос. Причем тут аналоговые пины? если код собирался для цифровых!
Вопрос причем тут аналоговость и цифровость пина? Ну у меня были аналоговые, у вас цифровые.
Или вы считаете, что цифровой на месте аналогово врать не будет? Он что, на 0.6V вместо ожидаемых 5v будет продолжать возвращать единицу?
Суть-то ошибки не в том что "аналоговый", а в том что, без подтяжки, на вход дуины (не важно какой) начинает поступать напряжение которое слишком легко "сбивается" любым внешним фактором, а не только тем сигналом который мы "хотим измерять".
Суть моего сообщения в том что предположение "По идее этого должно хватить" - не оправдалось. Иногда хватает, иногда нет. Мне понимание того что "не стоит полагатся на судьбу" - обшолось в три часа матюкания на морозе (ловить ее пришлось уже в "полевых условиях"). Решил поделиться этим, авось кому пригодится предупреждения о граблях(раз уж обсуждали эту схему измерения в чего-нибудь в автомобиле).
Считаете что к вашей схеме это не имеет отношения, и она не подвержена таким проблемам - ради бога. можете проигнорировать мой пост (у меня "на столе" тоже все работало хорошо ;).
leshak, по поводу аналога я такое наблюдал, достаточно использовать Firmata и посмотреть, как скачут входы при чтении.
Я думаю вы наблюдали просто "висящие в воздухе ноги". А тут засада в том, что они как-бы "подключены", но "не достаточно". Типичный "шум из эфира" - не наблюдается. Вход не "скачет", а как-бы "просаживается". Врет только при больших значениях. На малых продолжает возвращать правдоподобную картину. У меня проблема проявилась только при высокой частоте опроса. Включение подтяжки - решило проблему (или снижение частоты опроса, но IMHO это не надежное решение).
Может быть правильно предлагают неиспользуемые пины на OUTPUT программировать? Я не пробовал, правда, но такая рекомендация где то была. Для PICов тоже самое, вчера где то натыкался на статью.
А еще где то про АЦП было, что лучше перед чтением дать паузу, чтобы не было помех или что то в этом духе, хотя уже не вспомню где читал.
Может быть правильно предлагают неиспользуемые пины на OUTPUT программировать? Я не пробовал, правда, но такая рекомендация где то была. Для PICов тоже самое, вчера где то натыкался на статью.
Не знаю как для пиков, для AVR это КРАЙНЕ плохая идея. Когда он на INPUT то он хоть как-то защищен. Если вы на него дадите случайно 5v от питания - с ним ничего не случится. А вот если он на OUTPUT - тут ему карачун и настанет. Или будет заземлен, а вы случайно digitalWrite(..,HIGH) сделаете.
Не зря, все-таки, разработчики камня сделали, по умолчанию, все пины "на вход" и Z-состояние.
Да банально начинать любой скетч с переключения ВСЕХ пинов (у меги их 54-ре), кроме парочки, на OUTPUT будет выглядеть как.... вообщем не очень красиво :)
Честно говоря сложно сказать откуда такие глюки лезут, но включение подтяжки это не выход, потому как получается "пертягивание" вывода внутренней подтяжкой к +5V, а внешним резистором(при отсутствии 12 вольт) к земле. И тут уже получается кто кого перетянет. Можно попробовать уменьшить номиналы резисторов.
Честно говоря сложно сказать откуда такие глюки лезут, но включение подтяжки это не выход, потому как получается "пертягивание" вывода внутренней подтяжкой к +5V, а внешним резистором(при отсутствии 12 вольт) к земле. И тут уже получается кто кого перетянет. Можно попробовать уменьшить номиналы резисторов.
Ну, собственно "а почему-бы и нет"? В этом же принцип работы подтяжки и состоит. Разрешать себя "перетянуть" :) Естественно в делителе нижние плечо должно быть существенно меньше чем внутреняя подтяжка (или сделать внешнюю резистором поболее).
В моем случае "повезло" уже стоящие номиналы справились с подтяжкой. Ну разве что analogRead начал не чистый 0 возвращать. Сузилась точность измерения. Но в моей задаче это не критично было.
P.S. Хе-хе, думаю давно Максиму никто не объяснял что как работает подтяжка ;) ;)
Так в том то и дело что нуля не будет, так и какая разница, что показания при отсутствии внешнего сигнала скачут от 0 до 124 или висят постоянно в районе 200. Для цифрового входа лучше не включать подтяжку.
Вам ввиду какойто не стандартной задачи помогло включение внутренней подтяжки.
так и какая разница,что показания при отсутствии внешнего сигнала скачут от 0 до 124
Не скачут!!! Без подтяжки, без внешнего сигнала - ноль (или очень близко). При наличии внешнего сигнала - 124 максимум выходило. Вместо ожидаемых 1024. То есть диапазон возвращаем analogRead сузился от 0 (без внешнего сигнала) до 124 (при полном внешнем сигнале) . Причем еще и не линейно (поэтому фиг в вольты пересчитаешь). Плюс зависит от частоты чтения соседнего пина.
Разве такое лучше, чем с подтяжкой небольшой "подъем нуля" из-за подтяжки? Зато линейно, не зависит от фазы луны и проч. Imho написать map(200,1024,....) вместо map(0,1024) - не такая уж и большая расплата за предсказуемость. А, в случае цифрогого 200 - это 0.9 вольта, что, вообщем-то должно четко как ноль ловится.
А если поигратся с номиналами резисторов и взять диод шотки, то и еще ниже "ноль опустить" можно.
А у делителя номиналы какие и какое напряжение подаете?
Да не важно :) Уже все работает. Все равно я ничего не могу их поменять. Клиент самостоятельно заказал/изготовил плату, поставил ее в машину, а потом начали код писать :)
Оба резистора по 100K. Вольтаж - 12V, естественно. Диод - 1N4004. Ну и нижний резистор запаралелен с еще с 22p кондером (оппа! а вот на это я как-то не обратил внимание).
Так что возможно дело в кондере или... Тут на днях видел упомоминания что у атмеги всего один АЦП. Хоть аналоговых входов и много, но работают все через один АЦП с помощью мультиплексера. Так что возможно при быстром чтении сам АЦП не успевает "перезаряжятся" (я же так понимаю у него тоже какой-то кондер для измерения используется). Но...
А у делителя номиналы какие и какое напряжение подаете?
Му-ха-ха. Как выяснилось PCB дизайн вы же и делали :) Так что "какие резисторы" - скорее у вас спрашивать нужно было :) Вот так "заочно" нас женили :) Участвовали в одном проекте - не зная об этом. Ну, как я говорил уже, не важно. Все заработало, владелец авто счастлив :)
Да я тоже это понял, толко зачем вы пытались считать с делителя предназначенного для цифрового сигнала аналоговый для меня загадка. Или ТЗ поменялось когда плата уже была готова? Аналоговый делитель был только один, который измерял напряжение питания, все остальные делители предназначались для цифровых входов.
Да я тоже это понял, толко зачем вы пытались считать с делителя предназначенного для цифрового сигнала аналоговый для меня это загадка. Или ТЗ поменялось когда плата уже была готова? Аналоговый делитель был только один, который измерял напряжение питания, все остальные делители предназначались для цифровых входов.
Я не знаю. Может и поменялось. Мне же не ведомо в каком виде задача ставилась перед вами. Ко мне оно попало уже в виде "GENERATOR IN (A0) и GLOW IN (A1) достигают определеного уровня (и не обязательно это "цифровой уровень"). То есть должны использоватся как "аналоговые" (плюс еще в ТЗ ошибочно было ошибочное указание что ни должны "падать"). И, сейчас точно не помню, но через какое-то время (не сразу, видимо от погоды или еще чего), но и A4 (напряжение питания) тоже начал подобным образом подключивать.
Простейший код
loop(){
Serial.println(analogRead(A0));
delay(5); // без этого могут врать
Serial.println(analogRead(A1));
}
давал неверный значения. А если читать только A0 или только A1 - все хорошо. Либо "не слишком часто", либо "подтяжку" включать.
Здравствуйте. Я тоже загорелся сделать тахометр, но столкнулся с несколькими проблемами.
Во первых когда я беру питание с замка зажигания (ведь работающая ардуина не нужна на незаведенной машине), не подключенная к катушке ардуина на средних оборотах двигателя захватывает наводки и считает обороты (в пределах 150 при 2000-3000 об). Этот баг пропадает при запитке от аккумулятора и подкуривателя. Как с этим бороться? Ардуина запитана через стабилизатор, с двух сторон которой стоят кандеры
Во вторых собственно ардуина не хочет правильно считывать обороты. Показания скачут от -18000(я вообще не понимаю как тут может быть минус) и до 10000. Подключал по такой схеме:
Сразу несколько обьяснений. Второй диод поставил, т.к. тестировал на автомобильной зарядке. В общем по стандартной схеме мультиметр фиксировал отрицательное напряжение. И схема не работала. На всякий пожарный так и оставил. Стягивающий резистор я поставил, т.к. схема была чувствительна к малейшим наводкам (буквально палец на пару см к проводу подносил и уже фиксировало). В домашних условиях при банальном замыкании провода "к катушке" на 12В автомобильной зарядки счетчик моментально реагировал. А вот проверка на авто показала, что схема работать не хочет. Правда раз показала адекватный результат, когда я случайно пропустил сигнал не напрямую, а через свой палец. Дальшейшие экперименты с пальцем успеха не принесли( Код использовал такой:
if(time > 0)
{
//5 Sample Moving Average To Smooth Out The Data
rpm_array[0] = rpm_array[1];
rpm_array[1] = rpm_array[2];
rpm_array[2] = rpm_array[3];
rpm_array[3] = rpm_array[4];
rpm_array[4] = 60*(1000000/(time*2));
//Last 5 Average RPM Counts Eqauls....
rpm = (rpm_array[0] + rpm_array[1] + rpm_array[2] + rpm_array[3] + rpm_array[4]) / 5;
}
}
}
void fan_interrupt()
{
time = (micros() - time_last);
time_last = micros();
}
Код не мой. Взят из этой статьи http://cxem.net/arduino/arduino66.php. Мне этот фильтр то жене нравится, но я в них профан начинающий. Сейчас главная проблема в железе. Притом хочется собрать из подручных средств т.к. радиодетали брать негде...
По теме. Ставил сигнальный провод к дуине на аналоговый вход, чтоб глянуть, что там творится. На входе показало где-то 50 из 1024. Этого вполне хватает(как оказалось) для срабатывания прерывания. Веше описанный код попробую, как только разберусь со своей ЛСД-шкой. Здается мне она сдохла(три четверти символов светятся сплошными кубиками, а остальные вообще молчат даже при отключении всех сигнальных проводов. Тость на самом питании). Нужно прозвонить каждый контакт мультиметром, который появится у меня только завтра.
Отрабатывал два варианта кода тахометра, обоим нужны усреднения параметром, так как в переменной Taho проскакивают завышенные значения
Как бы это реализовать? Да и вообще может я не оптимальные решения нашел самих кодов?
Вариант 1 (с прерыванием)
pinMode(TahometrPin, INPUT); // Контакт для тахометра !!!!!!!!!ПРЕРЫВАНИЕ 5
digitalWrite(TahometrPin, HIGH); //внутренняя подтяжка входа тахометра
attachInterrupt(5, TahometrImpulse_on, FALLING); //RISING);// настройка прерывания и функции на него
...
void TahometrImpulse_on()
{
Tahometr_impulse_count++; //увеличить счетчик импульсов
if (Tahometr_impulse_count >=4) //2имп=1 оборот коленвала
{
Taho_ImpulseTime = micros()-Taho_time; //время прихода между импульсами
Taho_time = micros(); //обнулить
Taho=((Tahometr_impulse_count*60*1000000)/(2*Taho_ImpulseTime)); // перевод в об/мин
Tahometr_impulse_count = 0;
}
}
Вариант 2 (с прерыванием и таймером)
#include <TimerThree.h>
long Timer_Time=500000; //mcsec
Timer3.initialize(Timer_Time);//(Timer_Time*1000); // initialize timer3, and set a 1/2 second period
Timer3.pwm(2, 512);
Timer3.pwm(3, 512);
Timer3.pwm(5, 512);
Timer3.attachInterrupt(Timer3_Timer);
...
pinMode(TahometrPin, INPUT); // Контакт для тахометра !!!!!!!!!ПРЕРЫВАНИЕ 5
digitalWrite(TahometrPin, HIGH); //внутренняя подтяжка входа тахометра
attachInterrupt(5, TahometrImpulse_on, FALLING); //RISING);// настройка прерывания и функции на него
...
void TahometrImpulse_on()
{
Tahometr_impulse_count++; //увеличить счетчик импульсов
}
void Timer3_Timer() //обработка событий в таймере
{
Taho=(Tahometr_impulse_count*1000000*60)/(2*Timer_Time); // - 2 импульса на 1 оборот
Tahometr_impulse_count = 0;
}
Недостаток первого кода - при 0 об/мин в переменной Taho сидит последнее значение оборотов, а не 0.
в переменной Taho проскакивают завышенные значения
Что значит "проскакивают"? Сравнивайте с предыдущим, и если оно отличается больше, чем на N - считайте его "завышенным" и заменяйте на предыдущее+N (или N/2) и наоборот, если меньше... http://arduino.ru/forum/apparatnye-voprosy/izmeryaem-tok#comment-31149 - вот тут кусочек моего кода для усреднения измерения тока, который изменяется медленнее, чем обороты, так что есть время проверить...
Это если вам понадобится где-то в коде количество секунд в сутках.. вы бедную мегу, каждый раз напрягать будите умножением 60*60*24? :))
Ну, во первых, лучше уже "напрячь" и получить более читабельный код. Вот будете вы читать чей-то чужой код, и увидите какое-то "магическое число" 86400. И что оно значит - фиг его пойми. Так что с точки зрения сопровождения - лучше все-таки 60*60*24. Все таки эти цифры средний человек "узнает" гораздо легче.
Лично я бы - с легкостью пожертвую парой тактов, в угоду читабельности. Хотя, конечно, лучше вообще это заменить константами/директивами препроцессора с говорящими именами. "Магические числа" в коде - это вообще не сдорово.
Это к вопросу "нафига вы такие конструкции".
Во вторых, к вопросу "о напряжности". А вы проверяли что это действительно "напряжно?" Практически уверен, что что никакой "расплаты" за читабильность нет вовсе. И ваше выражение "*60*60*24" для меги ни на йоту не менее напряжно чем "*86400". Так как любой современный компилятор применяет оптимизации. И то что это выражение можно упростить - заметит не хуже вас. И самостоятельно сделает эту подмену. Так что итог - будет тот же самый. А потом, возможно, пойдет еще дальше. Где возможно - заменит деление на операции сдвига, как менее "напряжные" (вот как раз там где у нас было умножение деление на двойку, он имел шанс это сделать, а "свернув" это - вы лишили его возможность сделать это).
Так что желание "оптимизации", особено на микроконтоллерах - оно вполне понятно. Но не нужно впадать в ересь "преждевременной оптимизации" и жесткой безапеляционности. Тонкое это дело, замеров требует, эксперементов. Иначе, вместо оптимизации, можно получить просто несопровождаемый код, да еще менее эффективный.
Ну так сами и проводите, нам это зачем? Вы считаете что с математекой у людей плохо и рекомендуете отказаться от читабельных конструкций в пользу нечитабельных, вот сами и докладывайте.
А то получается:
- Господа, вы не правы!
- Почему? - Так сами и проверяйте почему.
заметил если умножаешь какие то числа которовые можно записать одним числом компилятор за это "не берёт" байты он их хам перемнодит и в контроллер пропишет уже готовое число вот пример два примера откомпилированы с одним размером... как говорится найдите десять отличий....
Вы серьезно? Вы решили занятся оптимизацией там где не нужно, а я должен это проверять и докладывать? Вы часом не бывший военый? Они дурную работу любят. Давать другим.
Vad пишет:
на компилятор полагайся но сам не плошай))
"Компьютер должен работать, а человек - думать". Поэтому все что возможно - должно быть автоматизированно. Тем более где "оплошать" - очень вероятно (что вы и сделали).
Vad пишет:
ленивое поколение)))
Так кто тут поленился проверить собственные предположения, а сразу выдал их за истину? Да еще с диким апломбом?
Вообщем ход вашей оптимизационной мысли - понятен. Я бы даже сказал - естественен и логичен. Но из-за нехватки знаний - у вас получился "вредный совет". Это тоже нормально. Собственно для того и форум, что-бы подобными "тонкостями" делится и совместно искать действительно лучшие решение.
Но то что вы свой совет "приправили" поучениями про школу, поколения и т.п. - это "ты, Зин, на грубость нарываешься..". Хотели выступить в качестве "гуру математики", а получился банальный Шариков: "...позволяете себе с развязностью совершенно невыносимой подавать какие-то советы космического масштаба и космической же глупости ...." (C)
он их хам перемнодит и в контроллер пропишет уже готовое число
Ну я это и имел ввиду, когда говорил что "компилятор сам сделает замену".
А "Хам ПеремНодит" - это здорово :). Конечно, не мне (с моей безграмотностью) смеятся над опечатками, но юмор в том что эта опечатка, в принципе, отражает то как именно парсер-компилятор выполняет эту работу.
При анализе кода он выстраивает AST-дерево. У которого узлы называются Ноды (Node). И если у ноды типа "умножение", оба дочерних узла "константы", он заменяет ее на ноду типа "константа". И уж только потом отправит это на компиляцию. Думаю вполне можно обозвать эту операцию ПеремНодиванием ;) , а за то что он "вмешался в авторский замысел" - можно и Хамом обозвать ;)
P.S. Сдорово, что вы не поленились проверить наш спор. В данном случае одинаковый размер, действительно, вышел именно потому что в итоге получается одинаковый результат. Но в общем виде - одинаковый размер не говорит о том, что мы в контроллер загрузится одинаковые скетчи и использовать они будут одинаковое количество памяти. 100% подтверждением, идентичности обоих вариантов будет только бинарное сравнение сгенерированных HEX-сов (или дизасемблироваи и просмотр в какие же именно команды скомпилировался наш исходник).
P.S.S. Я не говорю что "нужно было еще и HEX-сы проверять". Ваша проверка, в данном случае, вполне достаточно-показательна.
А "Хам ПеремНодит" - это здорово :). Конечно, не мне (с моей безграмотностью) смеятся над опечатками, но юмор в том что эта опечатка, в принципе, отражает то как именно парсер-компилятор выполняет эту работу.
По любому оптимизировать код я буду, но не сейчас, а когда "релиз" так сказать заливать буду, и то в комментах распишу откуда цифра взялась полученная в результате умножения.
Как правило обычно извиняются перед людьми которых уважают. Вы же своим "стартом", про вида "математики не знаете" (ага, конечн. только вы в школе учились), "ленивые" - явно таких чувств не вызвали.
Во вторых, как я вам уже говорил "к оптимизации нужно подходить осторожно, тестируя и проверя", а не "из житейской логики". Из ваших двух советов, как показали замеры - в одном случае выигрыша вообще небыло, в другом - пару байт. То есть, как миниум в 50% случаев - вы пролетели мимо кассы.
Зато в 100% случаев - ухудшили код. Зато в 100% случаев, учитывая размер скетча - это нафиг было не нужно. И если вы считаете что это "фиг с ним, главное как процессору", а читабельность "дело десятое" - то это говорит только о том, что вы никогда не учавствовали в серьезных проектах. А если учавтсвовали - я сочуствую вашим колегами и жалею того кто, в итоге, оплачивал возросшую, по вашей вине, стоимость сопровождения.
При этом вы еще и новичков пытаетесь учить "нечитабельности". Вы еще ждете извинений?
2kadushkin:
По сути, хоть и не хочется, но вынужден признать что " как только ты написал "attachInterrupt" - обязан делать все, чтоб экономить время" - таки имеет смысл.
Поэтому, в первом варианте, можно пересчет времени между импульсами вынести из функции обработки прерывания. Что-бы уж наверняка было не важно, сколько тактов занимает то деление/умножение :)
Делать пересчет в обороты - где-то в loop(), уже тогда когда реально потребовалось знать именно обороты.
Эффект "при 0 об/мин в переменной Taho сидит последнее значение оборотов" можно победить банальным "если Taho_ImpulseTime сликом большое" - все обнулять.
Кстати Tahometr_impulse_count >=4 - это уже некое "усреднение", можно попробовать увеличить эту цифру.
Или вообще решить "а зачем"? Будем между каждым импульсом засекатьв ремя (просто в формуле Taho=((Tahometr_impulse_count*60*1000000)/(2*Taho_ImpulseTime));
учитывать, что без Tahometr_impulse_count >=4 переменная Tahometr_impulse_count будет расти в четыре раза быстрее. Тогда и не только в комментариям можно будет понять, что у нас два импульса на оборот, но и просто глядя на формулу Taho=(2*Tahometr_impulse_count*1000000*60)/Timer_Time;
"Магическая" двойка в знаменателе исчезнет.
По поводу "иногда проскакивают слишком большие значения". А вы осцилом не смотрели? Может реально есть какие-то наводки, и действительнго пробегают лишние импульсы?
А еще, к сожалению не видно, как вы объявляли переменные Tahometr_impulse_count, Timer_Time . Про необходимость volatile не забыли? Иногда это тоже может довать трудно-ловимые глюки.
P.S. Ну не могу удержаться. "Для Vad" - формула (2*Tahometr_impulse_count*1000000*60)/Timer_Time; компилится в те же самый 726 байт, что и ваш "оптимизированный вариант". А учитывая что при ее использовании можно будет выбросить Tahometr_impulse_count и один If - ваши оптимизации вообще выглядить очень бледно. А требования "извинений" - подавно.
При таких жестких условиях экономии времени у меня основной код отвалится.
А с чего ему отваливатся?
Смотрите. В обработке прерывания мы просто делаем "минимально необходимое". Регистриуем факт события (увеличили каунтер) или "когда это произошло". Вообщем пишем туда только то, что может быть "только в обработчике".
А уж все вычисления/расчеты/конвертации - делаем в основом коде, когда потребовалось. Там где пара миллисекунд уже роли не играет и можно не торопится.
kadushkin пишет:
Придется скорость и обороты из OBD-II читать, хотя не вариант.
На скажу что "пробовал", но думаю это еще медленее будет.
kadushkin пишет:
Возможно есть еще способы определения скорости и оборотов? ну не ставить же еще один контроллер...
Погуглите книгу Arduino Cookbook автора Michael Margolis . Вроде видел там пример использования аппаратных счетчиков и пульсо-измерителей. (Chapter 18, разделы "Counting Pulses" и "Measuring Pulses More Accurately"). Возможно это на какие-то идеи натолкнет.
А на функции PulseIn может забазироваться? или неточно будет?
Можете попробовать. Но IMHO область ее применения - скетчик на 5-ть строк. Просто посмотреть "какие импульсы там идут". В реальный скетч - лучше ее не использовать.
У нее та же история с "нежелательностью в приличном обществе" что и у delay().
Она блокирует скетч. То есть, пока она ждет импульс - скетч стоит. Ни кнопки не обработать, ни на экран вывести.
Плюс, она "слышит" только те импульсы которые произошли именно в момент ее исполнения. Все что происходило пока скетч выполнял какую-то другую работу - для нее не существует.
Вообщем, может это мои предубеждения, но лично я бы не смотрел в ее сторону.
А еще такая мысль пришла в голову.
Откуда вы берете тестовый сигнал? На чем вы скетчи проверяете? Может вам "неточность" дает не "тахометр", а "подопытный"?
Подопытный - мое авто. Беру сигнал непосредственно с комбинации приборов. Результаты работы скетча проверяю на мониторе магнитолы тут же в машине - вывожу информацию через библиотеку TVout.
я имею ввиду просто колличество нажатий например на кнопку на за время а вообще просто нажатия например на кнопку но при этом если нет сигнала напрмер через 10 мс брос счетчика
В обработчике прерывания просто увеличиваете какой-то счетчик. И каждый раз запоминаете когда вы его увеличили. lastChangeTime=millis();
А в loop() все ремя поверяете сколько прошло времени с lastCHangeTime; Если больше какого-то промежутку - обнуляете счетчик. if(millis()-lastCHangeTime>10000) обнуляем.
Ну и, в том же loop(), аналогично время от времени "делаете расчеты, выводите счетчик в serial и т.п.)
По томуже принципу: сделали расчет, вывели, запомнили когда это сделали в lastReportTime=millis();, а потом проверяем if(millis()-lastReportTime>КАКОЕ-то время){повсторяем расчет, вывод, запоминание времени отчета}
Maksim , попробовал код на мониторе но там идет мусор если я правильно понял то цеплять надо на 2пин
Значит что то не так делаете или не так подключаете.
Да к 2 цифровому выводу. Если собрать схему из сообщения #16 и не подключать к катушке, то в сериал-монитор должны идти одни нули, у вас так?
Если же вы просто проверяете код без схемы, то так и должно быть - мусор.
Да я именно без схемы проверял.
а вот разберем такую ситуацию на катоде диода +5v, он ведь ничего не пропустит и на аноде нибудет ничего (или почти ничего),
Вы верно подметили "почти ничего". Но все-таки будет. В режиме "вход" через мегамный резистор пин, все-таки, подключен к питанию. По идее этого должно хватить что-бы analogRead намерял 1024.
Если не будет хватать - можно самому подтянуть ногу вверх (или включить внутрений подтягивающий резистор).
Приложился я, все-таки, по этому поводу "мордой об стол".
Как я сказал подключил по этой схеме без подтягивания ноги. Померял analogRead(A0). Вроде все хорошо. Все работает. Четко ловит и 0 и 1024. И чувствовал что "нужна", но "вроде работает и так" - сбило с толку.
Начал дальше скетч писать и в какой-то момент "поймал глюки". Чуть с ума не сошел почему вдруг, начало вместо 1024, что-то в районе 124 вовращать. Причем пускаю проверочный скетч упрощенный, на этом же пине как и положено 1024. Все логику излазил (может где-то включаю что-то не то) :(
А оказалось, что без подтяжки, если слишком часто ЧИТАТЬ (!!!!) СОСЕДНИЙ(!!!) пин (делать analogRead(A1)), то A0 - начинает "врать". Причем разница в "слишком часто" и "не слишком" - милисекунды (даже микро). Причем важно, даже, не "время между чтением A0 и A1", а именно "как часто A1" (разовое чтение - не портит картины).
Поэтому уловить это ошибку - очень трудно. На большом скетче найти это - взрыв мозга. Добавил пару строк в совершенно другое место - уменьшилась, оптимизировал логику - увеличилась.
Вообщем лучше сразу "делать подтяжку к питанию" что-бы потом не иметь сексуальных развлечений. Думаю и другие причину могут заставить "врать" A0. Без подтяжки "слишком не надежно" выходит.
Вопрос. Причем тут аналоговые пины? если код собирался для цифровых!
leshak, по поводу аналога я такое наблюдал, достаточно использовать Firmata и посмотреть, как скачут входы при чтении.
Вопрос. Причем тут аналоговые пины? если код собирался для цифровых!
Вопрос причем тут аналоговость и цифровость пина? Ну у меня были аналоговые, у вас цифровые.
Или вы считаете, что цифровой на месте аналогово врать не будет? Он что, на 0.6V вместо ожидаемых 5v будет продолжать возвращать единицу?
Суть-то ошибки не в том что "аналоговый", а в том что, без подтяжки, на вход дуины (не важно какой) начинает поступать напряжение которое слишком легко "сбивается" любым внешним фактором, а не только тем сигналом который мы "хотим измерять".
Суть моего сообщения в том что предположение "По идее этого должно хватить" - не оправдалось. Иногда хватает, иногда нет. Мне понимание того что "не стоит полагатся на судьбу" - обшолось в три часа матюкания на морозе (ловить ее пришлось уже в "полевых условиях"). Решил поделиться этим, авось кому пригодится предупреждения о граблях(раз уж обсуждали эту схему измерения в чего-нибудь в автомобиле).
Считаете что к вашей схеме это не имеет отношения, и она не подвержена таким проблемам - ради бога. можете проигнорировать мой пост (у меня "на столе" тоже все работало хорошо ;).
leshak, по поводу аналога я такое наблюдал, достаточно использовать Firmata и посмотреть, как скачут входы при чтении.
Я думаю вы наблюдали просто "висящие в воздухе ноги". А тут засада в том, что они как-бы "подключены", но "не достаточно". Типичный "шум из эфира" - не наблюдается. Вход не "скачет", а как-бы "просаживается". Врет только при больших значениях. На малых продолжает возвращать правдоподобную картину. У меня проблема проявилась только при высокой частоте опроса. Включение подтяжки - решило проблему (или снижение частоты опроса, но IMHO это не надежное решение).
Может быть правильно предлагают неиспользуемые пины на OUTPUT программировать? Я не пробовал, правда, но такая рекомендация где то была. Для PICов тоже самое, вчера где то натыкался на статью.
А еще где то про АЦП было, что лучше перед чтением дать паузу, чтобы не было помех или что то в этом духе, хотя уже не вспомню где читал.
UPD: можно на ты, если что
Может быть правильно предлагают неиспользуемые пины на OUTPUT программировать? Я не пробовал, правда, но такая рекомендация где то была. Для PICов тоже самое, вчера где то натыкался на статью.
Не знаю как для пиков, для AVR это КРАЙНЕ плохая идея. Когда он на INPUT то он хоть как-то защищен. Если вы на него дадите случайно 5v от питания - с ним ничего не случится. А вот если он на OUTPUT - тут ему карачун и настанет. Или будет заземлен, а вы случайно digitalWrite(..,HIGH) сделаете.
Не зря, все-таки, разработчики камня сделали, по умолчанию, все пины "на вход" и Z-состояние.
Да банально начинать любой скетч с переключения ВСЕХ пинов (у меги их 54-ре), кроме парочки, на OUTPUT будет выглядеть как.... вообщем не очень красиво :)
Честно говоря сложно сказать откуда такие глюки лезут, но включение подтяжки это не выход, потому как получается "пертягивание" вывода внутренней подтяжкой к +5V, а внешним резистором(при отсутствии 12 вольт) к земле. И тут уже получается кто кого перетянет. Можно попробовать уменьшить номиналы резисторов.
Честно говоря сложно сказать откуда такие глюки лезут, но включение подтяжки это не выход, потому как получается "пертягивание" вывода внутренней подтяжкой к +5V, а внешним резистором(при отсутствии 12 вольт) к земле. И тут уже получается кто кого перетянет. Можно попробовать уменьшить номиналы резисторов.
Ну, собственно "а почему-бы и нет"? В этом же принцип работы подтяжки и состоит. Разрешать себя "перетянуть" :) Естественно в делителе нижние плечо должно быть существенно меньше чем внутреняя подтяжка (или сделать внешнюю резистором поболее).
В моем случае "повезло" уже стоящие номиналы справились с подтяжкой. Ну разве что analogRead начал не чистый 0 возвращать. Сузилась точность измерения. Но в моей задаче это не критично было.
P.S. Хе-хе, думаю давно Максиму никто не объяснял что как работает подтяжка ;) ;)
Так в том то и дело что нуля не будет, так и какая разница, что показания при отсутствии внешнего сигнала скачут от 0 до 124 или висят постоянно в районе 200. Для цифрового входа лучше не включать подтяжку.
Вам ввиду какойто не стандартной задачи помогло включение внутренней подтяжки.
так и какая разница,что показания при отсутствии внешнего сигнала скачут от 0 до 124
Не скачут!!! Без подтяжки, без внешнего сигнала - ноль (или очень близко). При наличии внешнего сигнала - 124 максимум выходило. Вместо ожидаемых 1024. То есть диапазон возвращаем analogRead сузился от 0 (без внешнего сигнала) до 124 (при полном внешнем сигнале) . Причем еще и не линейно (поэтому фиг в вольты пересчитаешь). Плюс зависит от частоты чтения соседнего пина.
Разве такое лучше, чем с подтяжкой небольшой "подъем нуля" из-за подтяжки? Зато линейно, не зависит от фазы луны и проч. Imho написать map(200,1024,....) вместо map(0,1024) - не такая уж и большая расплата за предсказуемость. А, в случае цифрогого 200 - это 0.9 вольта, что, вообщем-то должно четко как ноль ловится.
А если поигратся с номиналами резисторов и взять диод шотки, то и еще ниже "ноль опустить" можно.
А у делителя номиналы какие и какое напряжение подаете?
А у делителя номиналы какие и какое напряжение подаете?
Да не важно :) Уже все работает. Все равно я ничего не могу их поменять. Клиент самостоятельно заказал/изготовил плату, поставил ее в машину, а потом начали код писать :)
Оба резистора по 100K. Вольтаж - 12V, естественно. Диод - 1N4004. Ну и нижний резистор запаралелен с еще с 22p кондером (оппа! а вот на это я как-то не обратил внимание).
Так что возможно дело в кондере или... Тут на днях видел упомоминания что у атмеги всего один АЦП. Хоть аналоговых входов и много, но работают все через один АЦП с помощью мультиплексера. Так что возможно при быстром чтении сам АЦП не успевает "перезаряжятся" (я же так понимаю у него тоже какой-то кондер для измерения используется). Но...
все равно. Внутреняя подтяжка решила вопрос. :)
А у делителя номиналы какие и какое напряжение подаете?
Му-ха-ха. Как выяснилось PCB дизайн вы же и делали :) Так что "какие резисторы" - скорее у вас спрашивать нужно было :) Вот так "заочно" нас женили :) Участвовали в одном проекте - не зная об этом. Ну, как я говорил уже, не важно. Все заработало, владелец авто счастлив :)
Да я тоже это понял, толко зачем вы пытались считать с делителя предназначенного для цифрового сигнала аналоговый для меня загадка. Или ТЗ поменялось когда плата уже была готова? Аналоговый делитель был только один, который измерял напряжение питания, все остальные делители предназначались для цифровых входов.
Да я тоже это понял, толко зачем вы пытались считать с делителя предназначенного для цифрового сигнала аналоговый для меня это загадка. Или ТЗ поменялось когда плата уже была готова? Аналоговый делитель был только один, который измерял напряжение питания, все остальные делители предназначались для цифровых входов.
Я не знаю. Может и поменялось. Мне же не ведомо в каком виде задача ставилась перед вами. Ко мне оно попало уже в виде "GENERATOR IN (A0) и GLOW IN (A1) достигают определеного уровня (и не обязательно это "цифровой уровень"). То есть должны использоватся как "аналоговые" (плюс еще в ТЗ ошибочно было ошибочное указание что ни должны "падать"). И, сейчас точно не помню, но через какое-то время (не сразу, видимо от погоды или еще чего), но и A4 (напряжение питания) тоже начал подобным образом подключивать.
Простейший код
давал неверный значения. А если читать только A0 или только A1 - все хорошо. Либо "не слишком часто", либо "подтяжку" включать.
Странно конечно, но расчет был на то что эти выводы будут использоваться так:
Но не знаю может там небыло 12 вольт. В общем сейчас уже не важно.
Здравствуйте. Я тоже загорелся сделать тахометр, но столкнулся с несколькими проблемами.
Во первых когда я беру питание с замка зажигания (ведь работающая ардуина не нужна на незаведенной машине), не подключенная к катушке ардуина на средних оборотах двигателя захватывает наводки и считает обороты (в пределах 150 при 2000-3000 об). Этот баг пропадает при запитке от аккумулятора и подкуривателя. Как с этим бороться? Ардуина запитана через стабилизатор, с двух сторон которой стоят кандеры
Во вторых собственно ардуина не хочет правильно считывать обороты. Показания скачут от -18000(я вообще не понимаю как тут может быть минус) и до 10000. Подключал по такой схеме:
Сразу несколько обьяснений. Второй диод поставил, т.к. тестировал на автомобильной зарядке. В общем по стандартной схеме мультиметр фиксировал отрицательное напряжение. И схема не работала. На всякий пожарный так и оставил. Стягивающий резистор я поставил, т.к. схема была чувствительна к малейшим наводкам (буквально палец на пару см к проводу подносил и уже фиксировало). В домашних условиях при банальном замыкании провода "к катушке" на 12В автомобильной зарядки счетчик моментально реагировал. А вот проверка на авто показала, что схема работать не хочет. Правда раз показала адекватный результат, когда я случайно пропустил сигнал не напрямую, а через свой палец. Дальшейшие экперименты с пальцем успеха не принесли( Код использовал такой:
Я вот только что подумал, а стягавающий резистор ведь нужно поставить как можно ближе к дуине?
Да, способ усреднения жесткий вы выбрали... но не суть. Попробуйте более простой способ измерения оборотов:
По поводу считывания сигнала с катушки, думаю, стоит поставить оптрон.
Код не мой. Взят из этой статьи http://cxem.net/arduino/arduino66.php. Мне этот фильтр то жене нравится, но я в них профан начинающий. Сейчас главная проблема в железе. Притом хочется собрать из подручных средств т.к. радиодетали брать негде...
По теме. Ставил сигнальный провод к дуине на аналоговый вход, чтоб глянуть, что там творится. На входе показало где-то 50 из 1024. Этого вполне хватает(как оказалось) для срабатывания прерывания. Веше описанный код попробую, как только разберусь со своей ЛСД-шкой. Здается мне она сдохла(три четверти символов светятся сплошными кубиками, а остальные вообще молчат даже при отключении всех сигнальных проводов. Тость на самом питании). Нужно прозвонить каждый контакт мультиметром, который появится у меня только завтра.
Отрабатывал два варианта кода тахометра, обоим нужны усреднения параметром, так как в переменной Taho проскакивают завышенные значения
Как бы это реализовать? Да и вообще может я не оптимальные решения нашел самих кодов?
Недостаток первого кода - при 0 об/мин в переменной Taho сидит последнее значение оборотов, а не 0.
Даже зарегистрироваться не поленился ;)
Господа, я понимаю.. писать вы только учитесь.. но что у вас с математикой?
ну нафига такие конструкции?
вполне заменимо на
тоже самое и сдесь
укорачивается до
Это если вам понадобится где-то в коде количество секунд в сутках.. вы бедную мегу, каждый раз напрягать будите умножением 60*60*24? :))
Оптимизация кода отдельная песня....
Меня вопрос усреднения волнует.
в переменной Taho проскакивают завышенные значения
Что значит "проскакивают"? Сравнивайте с предыдущим, и если оно отличается больше, чем на N - считайте его "завышенным" и заменяйте на предыдущее+N (или N/2) и наоборот, если меньше... http://arduino.ru/forum/apparatnye-voprosy/izmeryaem-tok#comment-31149 - вот тут кусочек моего кода для усреднения измерения тока, который изменяется медленнее, чем обороты, так что есть время проверить...
это не оптимизация .. как только ты написал "attachInterrupt" - обязан делать все, чтоб экономить время...
к этому нужно привыкать, что бы потом не "проскакивало"..
усреднение для тахометра красиво делается по принципу "скользящего окна"
данных много.. девать все равно некуда.. отображать каждую итерацию изменения - бессмысленно.
Спасибо за науку.
А как же быть если замеры скорости и оборотов это только часть программы, причем не основная?
Это если вам понадобится где-то в коде количество секунд в сутках.. вы бедную мегу, каждый раз напрягать будите умножением 60*60*24? :))
Ну, во первых, лучше уже "напрячь" и получить более читабельный код. Вот будете вы читать чей-то чужой код, и увидите какое-то "магическое число" 86400. И что оно значит - фиг его пойми. Так что с точки зрения сопровождения - лучше все-таки 60*60*24. Все таки эти цифры средний человек "узнает" гораздо легче.
Лично я бы - с легкостью пожертвую парой тактов, в угоду читабельности. Хотя, конечно, лучше вообще это заменить константами/директивами препроцессора с говорящими именами. "Магические числа" в коде - это вообще не сдорово.
Это к вопросу "нафига вы такие конструкции".
Во вторых, к вопросу "о напряжности". А вы проверяли что это действительно "напряжно?" Практически уверен, что что никакой "расплаты" за читабильность нет вовсе. И ваше выражение "*60*60*24" для меги ни на йоту не менее напряжно чем "*86400". Так как любой современный компилятор применяет оптимизации. И то что это выражение можно упростить - заметит не хуже вас. И самостоятельно сделает эту подмену. Так что итог - будет тот же самый. А потом, возможно, пойдет еще дальше. Где возможно - заменит деление на операции сдвига, как менее "напряжные" (вот как раз там где у нас было умножение деление на двойку, он имел шанс это сделать, а "свернув" это - вы лишили его возможность сделать это).
Так что желание "оптимизации", особено на микроконтоллерах - оно вполне понятно. Но не нужно впадать в ересь "преждевременной оптимизации" и жесткой безапеляционности. Тонкое это дело, замеров требует, эксперементов. Иначе, вместо оптимизации, можно получить просто несопровождаемый код, да еще менее эффективный.
ну так.. проведите эксперимент.. )) измерьте.. доложите тут..
на компилятор полагайся но сам не плошай))
ленивое поколение)))
Ну так сами и проводите, нам это зачем? Вы считаете что с математекой у людей плохо и рекомендуете отказаться от читабельных конструкций в пользу нечитабельных, вот сами и докладывайте.
А то получается:
- Господа, вы не правы!
- Почему?
- Так сами и проверяйте почему.
:)
к чему полемика?
- Господа, вы не правы! потому что ТАК будет лучще!
- Почему?
- потому, что будет ЛУЧШЕ.
- Нет не будет, потому что я думаю, что все равно.. или не все равно. Даже скажу больше, но сказать нечего потому что я не знаю.
-так проверьте и расскажите раз не знаете
- Так сами и проверяйте.
Да ради бога.. делайте как хотите..
да спор ни о чём....
заметил если умножаешь какие то числа которовые можно записать одним числом компилятор за это "не берёт" байты он их хам перемнодит и в контроллер пропишет уже готовое число вот пример два примера откомпилированы с одним размером... как говорится найдите десять отличий....
ну так.. проведите эксперимент.. )) измерьте.. доложите тут..
Вы серьезно? Вы решили занятся оптимизацией там где не нужно, а я должен это проверять и докладывать? Вы часом не бывший военый? Они дурную работу любят. Давать другим.
на компилятор полагайся но сам не плошай))
"Компьютер должен работать, а человек - думать". Поэтому все что возможно - должно быть автоматизированно. Тем более где "оплошать" - очень вероятно (что вы и сделали).
ленивое поколение)))
Так кто тут поленился проверить собственные предположения, а сразу выдал их за истину? Да еще с диким апломбом?
Вообщем ход вашей оптимизационной мысли - понятен. Я бы даже сказал - естественен и логичен. Но из-за нехватки знаний - у вас получился "вредный совет". Это тоже нормально. Собственно для того и форум, что-бы подобными "тонкостями" делится и совместно искать действительно лучшие решение.
Но то что вы свой совет "приправили" поучениями про школу, поколения и т.п. - это "ты, Зин, на грубость нарываешься..". Хотели выступить в качестве "гуру математики", а получился банальный Шариков: "...позволяете себе с развязностью совершенно невыносимой подавать какие-то советы космического масштаба и космической же глупости ...." (C)
он их хам перемнодит и в контроллер пропишет уже готовое число
Ну я это и имел ввиду, когда говорил что "компилятор сам сделает замену".
А "Хам ПеремНодит" - это здорово :). Конечно, не мне (с моей безграмотностью) смеятся над опечатками, но юмор в том что эта опечатка, в принципе, отражает то как именно парсер-компилятор выполняет эту работу.
При анализе кода он выстраивает AST-дерево. У которого узлы называются Ноды (Node). И если у ноды типа "умножение", оба дочерних узла "константы", он заменяет ее на ноду типа "константа". И уж только потом отправит это на компиляцию. Думаю вполне можно обозвать эту операцию ПеремНодиванием ;) , а за то что он "вмешался в авторский замысел" - можно и Хамом обозвать ;)
P.S. Сдорово, что вы не поленились проверить наш спор. В данном случае одинаковый размер, действительно, вышел именно потому что в итоге получается одинаковый результат. Но в общем виде - одинаковый размер не говорит о том, что мы в контроллер загрузится одинаковые скетчи и использовать они будут одинаковое количество памяти. 100% подтверждением, идентичности обоих вариантов будет только бинарное сравнение сгенерированных HEX-сов (или дизасемблироваи и просмотр в какие же именно команды скомпилировался наш исходник).
P.S.S. Я не говорю что "нужно было еще и HEX-сы проверять". Ваша проверка, в данном случае, вполне достаточно-показательна.
А "Хам ПеремНодит" - это здорово :). Конечно, не мне (с моей безграмотностью) смеятся над опечатками, но юмор в том что эта опечатка, в принципе, отражает то как именно парсер-компилятор выполняет эту работу.
очепятка зачОтная ))) я не хотел))))
человек должен думать.. но... не хочет
вы определитесь.. вы пишете чтоб контроллер работал с вашей писаниной или чтоб читать приятно было.
И хватит спорить "ниочем"...
По существу вопроса давайте.
По любому оптимизировать код я буду, но не сейчас, а когда "релиз" так сказать заливать буду, и то в комментах распишу откуда цифра взялась полученная в результате умножения.
по существу вопроса - жду извинений ))
по существу вопроса - жду извинений ))
Ню-ню.... ждите.
Как правило обычно извиняются перед людьми которых уважают. Вы же своим "стартом", про вида "математики не знаете" (ага, конечн. только вы в школе учились), "ленивые" - явно таких чувств не вызвали.
Во вторых, как я вам уже говорил "к оптимизации нужно подходить осторожно, тестируя и проверя", а не "из житейской логики". Из ваших двух советов, как показали замеры - в одном случае выигрыша вообще небыло, в другом - пару байт. То есть, как миниум в 50% случаев - вы пролетели мимо кассы.
Зато в 100% случаев - ухудшили код. Зато в 100% случаев, учитывая размер скетча - это нафиг было не нужно. И если вы считаете что это "фиг с ним, главное как процессору", а читабельность "дело десятое" - то это говорит только о том, что вы никогда не учавствовали в серьезных проектах. А если учавтсвовали - я сочуствую вашим колегами и жалею того кто, в итоге, оплачивал возросшую, по вашей вине, стоимость сопровождения.
При этом вы еще и новичков пытаетесь учить "нечитабельности". Вы еще ждете извинений?
2kadushkin:
По сути, хоть и не хочется, но вынужден признать что " как только ты написал "attachInterrupt" - обязан делать все, чтоб экономить время" - таки имеет смысл.
Поэтому, в первом варианте, можно пересчет времени между импульсами вынести из функции обработки прерывания. Что-бы уж наверняка было не важно, сколько тактов занимает то деление/умножение :)
Делать пересчет в обороты - где-то в loop(), уже тогда когда реально потребовалось знать именно обороты.
Эффект "при 0 об/мин в переменной Taho сидит последнее значение оборотов" можно победить банальным "если Taho_ImpulseTime сликом большое" - все обнулять.
Кстати Tahometr_impulse_count >=4 - это уже некое "усреднение", можно попробовать увеличить эту цифру.
Или вообще решить "а зачем"? Будем между каждым импульсом засекатьв ремя (просто в формуле Taho=((Tahometr_impulse_count*60*1000000)/(2*Taho_ImpulseTime));
учитывать, что без Tahometr_impulse_count >=4 переменная Tahometr_impulse_count будет расти в четыре раза быстрее. Тогда и не только в комментариям можно будет понять, что у нас два импульса на оборот, но и просто глядя на формулу Taho=(2*Tahometr_impulse_count*1000000*60)/Timer_Time;
"Магическая" двойка в знаменателе исчезнет.
По поводу "иногда проскакивают слишком большие значения". А вы осцилом не смотрели? Может реально есть какие-то наводки, и действительнго пробегают лишние импульсы?
А еще, к сожалению не видно, как вы объявляли переменные Tahometr_impulse_count, Timer_Time . Про необходимость volatile не забыли? Иногда это тоже может довать трудно-ловимые глюки.
P.S. Ну не могу удержаться. "Для Vad" - формула (2*Tahometr_impulse_count*1000000*60)/Timer_Time; компилится в те же самый 726 байт, что и ваш "оптимизированный вариант". А учитывая что при ее использовании можно будет выбросить Tahometr_impulse_count и один If - ваши оптимизации вообще выглядить очень бледно. А требования "извинений" - подавно.
Водолей ))
Водолей ))
Камаз
При таких жестких условиях экономии времени у меня основной код отвалится.
Придется скорость и обороты из OBD-II читать, хотя не вариант.
Возможно есть еще способы определения скорости и оборотов? ну не ставить же еще один контроллер...
При таких жестких условиях экономии времени у меня основной код отвалится.
А с чего ему отваливатся?
Смотрите. В обработке прерывания мы просто делаем "минимально необходимое". Регистриуем факт события (увеличили каунтер) или "когда это произошло". Вообщем пишем туда только то, что может быть "только в обработчике".
А уж все вычисления/расчеты/конвертации - делаем в основом коде, когда потребовалось. Там где пара миллисекунд уже роли не играет и можно не торопится.
Придется скорость и обороты из OBD-II читать, хотя не вариант.
На скажу что "пробовал", но думаю это еще медленее будет.
Возможно есть еще способы определения скорости и оборотов? ну не ставить же еще один контроллер...
Погуглите книгу Arduino Cookbook автора Michael Margolis . Вроде видел там пример использования аппаратных счетчиков и пульсо-измерителей. (Chapter 18, разделы "Counting Pulses" и "Measuring Pulses More Accurately"). Возможно это на какие-то идеи натолкнет.
А на функции PulseIn может забазироваться? или неточно будет?
А на функции PulseIn может забазироваться? или неточно будет?
Можете попробовать. Но IMHO область ее применения - скетчик на 5-ть строк. Просто посмотреть "какие импульсы там идут". В реальный скетч - лучше ее не использовать.
У нее та же история с "нежелательностью в приличном обществе" что и у delay().
Она блокирует скетч. То есть, пока она ждет импульс - скетч стоит. Ни кнопки не обработать, ни на экран вывести.
Плюс, она "слышит" только те импульсы которые произошли именно в момент ее исполнения. Все что происходило пока скетч выполнял какую-то другую работу - для нее не существует.
Вообщем, может это мои предубеждения, но лично я бы не смотрел в ее сторону.
А еще такая мысль пришла в голову.
Откуда вы берете тестовый сигнал? На чем вы скетчи проверяете? Может вам "неточность" дает не "тахометр", а "подопытный"?
Подопытный - мое авто. Беру сигнал непосредственно с комбинации приборов. Результаты работы скетча проверяю на мониторе магнитолы тут же в машине - вывожу информацию через библиотеку TVout.