автомобильный тахометр на ардуино

leshak
Offline
Зарегистрирован: 29.09.2011

dronsoft пишет:

я имею ввиду просто колличество нажатий например на кнопку на за время а вообще просто нажатия например на кнопку но при этом если нет сигнала напрмер через 10 мс брос счетчика

 

В обработчике прерывания просто увеличиваете какой-то счетчик. И каждый раз запоминаете когда вы его увеличили.  lastChangeTime=millis();

А в loop() все ремя поверяете сколько прошло времени с lastCHangeTime;   Если больше какого-то промежутку - обнуляете счетчик.  if(millis()-lastCHangeTime>10000) обнуляем.

Ну и, в том же loop(), аналогично время от времени "делаете расчеты, выводите счетчик в serial и т.п.)

По томуже принципу: сделали расчет, вывели, запомнили когда это сделали в lastReportTime=millis();, а потом проверяем if(millis()-lastReportTime>КАКОЕ-то время){повсторяем расчет, вывод, запоминание времени отчета}

 

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

 

dronsoft пишет:

 

#define RPMpin 2 // катушка зажигания
volatile long rpm = 0;

void setup() 
{ 
  Serial.begin(9600);
  attachInterrupt(0, RPM, FALLING);
}

void loop() 
{
  Serial.println(rpm, DEC); // об/мин
  delay(100);
}

void RPM ()
{
  static unsigned long micros_prev;
  rpm = (1000000.0/(micros() - micros_prev))*60/2;
  micros_prev = micros();
}

 

Maksim , попробовал код на мониторе но там идет мусор если я правильно понял то цеплять надо на 2пин

maksim
Offline
Зарегистрирован: 12.02.2012

Значит что то не так делаете или не так подключаете.  
Да к 2 цифровому выводу. Если собрать схему из сообщения #16  и не подключать к катушке, то в сериал-монитор должны идти одни нули, у вас так?
Если же вы просто проверяете код без схемы, то так и должно быть - мусор.

 

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

Да я именно без схемы проверял.

leshak
Offline
Зарегистрирован: 29.09.2011

leshak пишет:

msng пишет:

а вот разберем такую ситуацию на катоде диода +5v, он ведь ничего не пропустит и на аноде нибудет ничего (или почти ничего),

Вы верно подметили "почти ничего". Но все-таки будет. В режиме "вход" через мегамный резистор пин, все-таки, подключен к питанию. По идее этого должно хватить что-бы analogRead намерял 1024.

Если не будет хватать - можно самому подтянуть ногу вверх (или включить внутрений подтягивающий резистор).

Приложился я, все-таки, по этому поводу  "мордой об стол".  

Как я сказал подключил по этой схеме без подтягивания ноги. Померял analogRead(A0). Вроде все хорошо. Все работает. Четко ловит и 0 и 1024. И чувствовал что "нужна", но "вроде работает и так" - сбило с толку.

Начал дальше скетч писать и в какой-то момент "поймал глюки". Чуть с ума не сошел почему вдруг, начало вместо 1024, что-то в районе 124 вовращать. Причем пускаю проверочный скетч упрощенный, на этом же пине как и положено 1024. Все логику излазил (может где-то включаю что-то не то) :(

А оказалось, что без подтяжки, если слишком часто ЧИТАТЬ (!!!!) СОСЕДНИЙ(!!!) пин  (делать analogRead(A1)), то A0 - начинает "врать". Причем разница в "слишком часто" и "не слишком" - милисекунды (даже микро).  Причем важно, даже, не "время между чтением A0 и A1", а именно "как часто A1" (разовое чтение - не портит картины).

Поэтому уловить это ошибку - очень трудно. На большом скетче найти это - взрыв мозга. Добавил пару строк в совершенно другое место - уменьшилась, оптимизировал логику - увеличилась.

Вообщем лучше сразу "делать подтяжку к питанию" что-бы потом не иметь сексуальных развлечений. Думаю и другие причину могут заставить "врать" A0. Без подтяжки "слишком не надежно" выходит.

 

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

Вопрос. Причем тут аналоговые пины? если код собирался для цифровых!

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

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

 

leshak
Offline
Зарегистрирован: 29.09.2011

 

dronsoft пишет:

Вопрос. Причем тут аналоговые пины? если код собирался для цифровых!

Вопрос причем тут аналоговость и цифровость пина? Ну у меня были аналоговые, у вас цифровые.

Или вы считаете, что цифровой на месте аналогово врать не будет?  Он что, на 0.6V вместо ожидаемых 5v будет продолжать возвращать единицу?

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

Суть моего сообщения в том что предположение "По идее этого должно хватить" - не оправдалось. Иногда хватает, иногда нет. Мне понимание того что "не стоит полагатся на судьбу" - обшолось в три часа матюкания на морозе (ловить ее пришлось уже в "полевых условиях"). Решил поделиться этим, авось кому пригодится предупреждения о граблях(раз уж обсуждали эту схему измерения в чего-нибудь в автомобиле).

Считаете что к вашей схеме это не имеет отношения, и она не подвержена таким проблемам - ради бога. можете проигнорировать мой пост (у меня "на столе" тоже все работало хорошо ;).

leshak
Offline
Зарегистрирован: 29.09.2011

kisoft пишет:

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

Я думаю вы наблюдали просто "висящие в воздухе ноги". А тут засада в том, что они как-бы "подключены", но "не достаточно". Типичный "шум из эфира" - не наблюдается. Вход не "скачет", а как-бы "просаживается". Врет только при больших значениях. На малых продолжает возвращать правдоподобную картину.  У меня проблема проявилась только при высокой частоте опроса. Включение подтяжки - решило проблему (или снижение частоты опроса, но IMHO это не надежное решение).

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Может быть правильно предлагают неиспользуемые пины на OUTPUT программировать? Я не пробовал, правда, но такая рекомендация где то была. Для PICов тоже самое, вчера где то натыкался на статью.

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

UPD: можно на ты, если что

 

leshak
Offline
Зарегистрирован: 29.09.2011

kisoft пишет:

Может быть правильно предлагают неиспользуемые пины на OUTPUT программировать? Я не пробовал, правда, но такая рекомендация где то была. Для PICов тоже самое, вчера где то натыкался на статью.

Не знаю как для пиков, для AVR это КРАЙНЕ плохая идея. Когда он на INPUT то он хоть как-то защищен. Если вы на него дадите случайно 5v от питания - с ним ничего не случится. А вот если он на OUTPUT - тут ему карачун и настанет. Или будет заземлен, а вы случайно digitalWrite(..,HIGH) сделаете.

Не зря, все-таки, разработчики камня сделали, по умолчанию, все пины "на вход" и Z-состояние.

Да банально начинать любой скетч с переключения ВСЕХ пинов (у меги их 54-ре), кроме парочки, на OUTPUT будет выглядеть как.... вообщем не очень красиво :)

maksim
Offline
Зарегистрирован: 12.02.2012

Честно говоря сложно сказать откуда такие глюки лезут, но включение подтяжки это не выход, потому как получается "пертягивание" вывода внутренней подтяжкой к +5V, а внешним резистором(при отсутствии 12 вольт) к земле. И тут уже получается кто кого перетянет. Можно попробовать уменьшить номиналы резисторов.

leshak
Offline
Зарегистрирован: 29.09.2011

maksim пишет:

Честно говоря сложно сказать откуда такие глюки лезут, но включение подтяжки это не выход, потому как получается "пертягивание" вывода внутренней подтяжкой к +5V, а внешним резистором(при отсутствии 12 вольт) к земле. И тут уже получается кто кого перетянет. Можно попробовать уменьшить номиналы резисторов.

Ну, собственно "а почему-бы и нет"? В этом же принцип работы  подтяжки и состоит. Разрешать себя "перетянуть" :) Естественно в делителе нижние плечо должно быть существенно меньше чем внутреняя подтяжка  (или сделать внешнюю резистором поболее).

В моем случае "повезло" уже стоящие номиналы справились с подтяжкой. Ну разве что analogRead начал не чистый 0 возвращать. Сузилась точность измерения. Но в моей задаче это не критично было.

P.S. Хе-хе, думаю давно Максиму никто не объяснял что как работает подтяжка ;) ;)

maksim
Offline
Зарегистрирован: 12.02.2012

Так в том то и дело что нуля не будет, так и какая разница, что показания при отсутствии внешнего сигнала скачут от 0 до 124 или висят постоянно в районе 200. Для цифрового входа лучше не включать подтяжку.

Вам ввиду какойто не стандартной задачи помогло включение внутренней подтяжки.

leshak
Offline
Зарегистрирован: 29.09.2011

maksim пишет:

так и какая разница,что показания при отсутствии внешнего сигнала скачут от 0 до 124 

Не скачут!!! Без подтяжки, без внешнего сигнала - ноль (или очень близко). При наличии внешнего сигнала - 124 максимум выходило. Вместо ожидаемых 1024. То есть диапазон возвращаем analogRead сузился от 0 (без внешнего сигнала) до 124 (при полном внешнем сигнале) . Причем еще и не линейно (поэтому фиг в вольты пересчитаешь). Плюс зависит от частоты чтения соседнего пина. 

Разве такое лучше, чем с подтяжкой небольшой "подъем нуля" из-за подтяжки? Зато линейно, не зависит от фазы луны и проч. Imho написать map(200,1024,....) вместо map(0,1024) - не такая уж и большая расплата за предсказуемость. А, в случае цифрогого 200 - это 0.9 вольта, что, вообщем-то должно четко как ноль ловится.

А если поигратся с номиналами резисторов и взять диод шотки, то и еще ниже "ноль опустить" можно.

maksim
Offline
Зарегистрирован: 12.02.2012

А у делителя номиналы какие и какое напряжение подаете?

leshak
Offline
Зарегистрирован: 29.09.2011

maksim пишет:

А у делителя номиналы какие и какое напряжение подаете?

Да не важно :) Уже все работает. Все равно я ничего не могу их поменять. Клиент самостоятельно заказал/изготовил плату, поставил ее в машину, а потом начали код писать :)

Оба резистора по 100K. Вольтаж - 12V, естественно. Диод - 1N4004. Ну и нижний резистор запаралелен с еще с 22p кондером (оппа! а вот на это я как-то не обратил внимание).

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

все равно. Внутреняя подтяжка решила вопрос.  :)

leshak
Offline
Зарегистрирован: 29.09.2011

maksim пишет:

А у делителя номиналы какие и какое напряжение подаете?

Му-ха-ха. Как выяснилось PCB дизайн вы же и делали :) Так что "какие резисторы" - скорее у вас спрашивать нужно было :)  Вот так "заочно" нас женили :) Участвовали в одном проекте - не зная об этом. Ну, как я говорил уже, не важно. Все заработало, владелец авто счастлив :)

maksim
Offline
Зарегистрирован: 12.02.2012

Да я тоже это понял, толко зачем вы пытались считать с делителя предназначенного для цифрового сигнала аналоговый для меня загадка. Или ТЗ поменялось когда плата уже была готова? Аналоговый делитель был только один, который измерял напряжение питания, все остальные делители предназначались для цифровых входов.

leshak
Offline
Зарегистрирован: 29.09.2011

maksim пишет:

Да я тоже это понял, толко зачем вы пытались считать с делителя предназначенного для цифрового сигнала аналоговый для меня это загадка. Или ТЗ поменялось когда плата уже была готова? Аналоговый делитель был только один, который измерял напряжение питания, все остальные делители предназначались для  цифровых входов.

Я не знаю. Может и поменялось. Мне же не ведомо в каком виде задача ставилась перед вами. Ко мне оно попало уже в виде "GENERATOR IN (A0) и GLOW IN (A1) достигают определеного уровня (и не обязательно это "цифровой уровень"). То есть должны использоватся как "аналоговые" (плюс еще в ТЗ ошибочно было ошибочное указание что ни должны "падать"). И, сейчас точно не помню, но через какое-то время (не сразу, видимо от погоды или еще чего), но и A4 (напряжение питания) тоже начал подобным образом подключивать.

Простейший код

loop(){
  Serial.println(analogRead(A0));
  delay(5); // без этого могут врать
  Serial.println(analogRead(A1));
}

давал неверный значения. А если читать только A0 или только A1 - все хорошо. Либо "не слишком часто", либо "подтяжку" включать.

maksim
Offline
Зарегистрирован: 12.02.2012

Странно конечно, но расчет был на то что эти выводы будут использоваться так:

loop(){
  Serial.println(digitalRead(A0));
  Serial.println(digitalRead(A1));
}

Но не знаю может там небыло 12 вольт. В общем сейчас уже не важно.

Suhoffff
Offline
Зарегистрирован: 30.04.2013

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

Во первых когда я беру питание с замка зажигания (ведь работающая ардуина не нужна на незаведенной машине), не подключенная к катушке ардуина на средних оборотах двигателя захватывает наводки и считает обороты (в пределах 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();
}

 

Suhoffff
Offline
Зарегистрирован: 30.04.2013

Я вот только что подумал, а стягавающий резистор ведь нужно поставить как можно ближе к дуине?

maksim
Offline
Зарегистрирован: 12.02.2012

Да, способ усреднения жесткий вы выбрали... но не суть. Попробуйте более простой способ измерения оборотов:

#define RPMpin 2 // катушка зажигания
volatile long rpm = 0;

void setup() 
{ 
  Serial.begin(9600);
  attachInterrupt(0, RPM, FALLING);
}

void loop() 
{
  Serial.println(rpm*60/2, DEC); // об/мин
  rpm = 0;
  delay(1000);
}

void RPM ()
{
  rpm++;
}

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

Suhoffff
Offline
Зарегистрирован: 30.04.2013

Код не мой. Взят из этой статьи http://cxem.net/arduino/arduino66.php. Мне этот фильтр то жене нравится, но я в них профан начинающий. Сейчас главная проблема в железе. Притом хочется собрать из подручных средств т.к. радиодетали брать негде...

По теме. Ставил сигнальный провод к дуине на аналоговый вход, чтоб глянуть, что там творится. На входе показало где-то 50 из 1024. Этого вполне хватает(как оказалось) для срабатывания прерывания. Веше описанный код попробую, как только разберусь со своей ЛСД-шкой. Здается мне она сдохла(три четверти символов светятся сплошными кубиками, а остальные вообще молчат даже при отключении всех сигнальных проводов. Тость на самом питании). Нужно прозвонить каждый контакт мультиметром, который появится у меня только завтра.

kadushkin
Offline
Зарегистрирован: 18.12.2011

Отрабатывал два варианта кода тахометра, обоим нужны усреднения параметром, так как в переменной 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.

Vad
Offline
Зарегистрирован: 26.05.2013

Даже зарегистрироваться не поленился ;)

Господа, я понимаю.. писать вы только учитесь.. но что у вас с математикой?

ну нафига такие конструкции?

Taho=((Tahometr_impulse_count*60*1000000)/(2*Taho_ImpulseTime));

вполне заменимо на

Taho=((Tahometr_impulse_count*30000000)/Taho_ImpulseTime); 

 

тоже самое и сдесь

TaTaho=(Tahometr_impulse_count*1000000*60)/(2*Timer_Time);

укорачивается до

TaTaho=(Tahometr_impulse_count*30000000)/Timer_Time; 

 

Это если вам понадобится  где-то в коде количество секунд в сутках.. вы бедную мегу, каждый раз напрягать будите  умножением 60*60*24? :))

 

kadushkin
Offline
Зарегистрирован: 18.12.2011

Оптимизация кода отдельная песня....

Меня вопрос усреднения волнует.

Andrey_Y_Ostanovsky
Offline
Зарегистрирован: 03.12.2012

kadushkin пишет:

в переменной Taho проскакивают завышенные значения

Что значит "проскакивают"? Сравнивайте с предыдущим, и если оно отличается больше, чем на N - считайте его "завышенным" и заменяйте на предыдущее+N (или N/2) и наоборот, если меньше... http://arduino.ru/forum/apparatnye-voprosy/izmeryaem-tok#comment-31149 - вот тут кусочек моего кода для усреднения измерения тока, который изменяется медленнее, чем обороты, так что есть время проверить...

 

Vad
Offline
Зарегистрирован: 26.05.2013

это не оптимизация .. как только ты написал "attachInterrupt" - обязан делать все, чтоб экономить время...   

к этому нужно привыкать, что бы потом не "проскакивало"..

усреднение для тахометра красиво делается по принципу "скользящего окна"

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

 

 

 

kadushkin
Offline
Зарегистрирован: 18.12.2011

Спасибо за науку.

А как же быть если замеры скорости и оборотов это только часть программы, причем не основная?

leshak
Offline
Зарегистрирован: 29.09.2011

Vad пишет:

Это если вам понадобится  где-то в коде количество секунд в сутках.. вы бедную мегу, каждый раз напрягать будите  умножением 60*60*24? :))

Ну, во первых, лучше уже "напрячь" и получить более читабельный код. Вот будете вы читать чей-то чужой код, и увидите какое-то "магическое число" 86400. И что оно значит - фиг его пойми. Так что с точки зрения сопровождения - лучше все-таки 60*60*24. Все таки эти цифры средний человек "узнает" гораздо легче. 

Лично я бы - с легкостью пожертвую парой тактов, в угоду читабельности. Хотя, конечно, лучше вообще это заменить константами/директивами препроцессора с говорящими именами. "Магические числа" в коде - это вообще не сдорово.

Это к вопросу "нафига вы такие конструкции".

Во вторых, к вопросу "о напряжности". А вы проверяли что это действительно "напряжно?"  Практически уверен, что  что никакой "расплаты" за читабильность нет вовсе. И ваше выражение "*60*60*24" для меги ни на йоту не менее напряжно чем "*86400". Так как любой современный компилятор применяет оптимизации. И то что это выражение можно упростить - заметит не хуже вас. И самостоятельно сделает эту подмену. Так что итог - будет тот же самый. А потом, возможно, пойдет еще дальше. Где возможно - заменит деление на операции сдвига, как менее "напряжные" (вот как раз там где у нас было умножение деление на двойку, он имел шанс это сделать, а "свернув" это - вы лишили его возможность сделать это).

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

 

Vad
Offline
Зарегистрирован: 26.05.2013

leshak пишет:
Тонкое это дело, замеров требует, эксперементов. Иначе, вместо оптимизации, можно получить просто несопровождаемый код, да еще менее эффективный.

ну так.. проведите эксперимент.. )) измерьте.. доложите тут..

на компилятор полагайся но сам не плошай))

 

ленивое поколение)))

maksim
Offline
Зарегистрирован: 12.02.2012

Ну так сами и проводите, нам это зачем? Вы считаете что с математекой у людей плохо и рекомендуете отказаться от читабельных конструкций в пользу нечитабельных, вот сами и докладывайте.

А то получается:

  - Господа, вы не правы!
  - Почему?

  - Так сами и проверяйте почему.

 

Vad
Offline
Зарегистрирован: 26.05.2013

:)

к чему полемика?

- Господа, вы не правы! потому что ТАК будет лучще!

- Почему?

- потому, что будет ЛУЧШЕ.

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

-так проверьте и расскажите раз не знаете
 

- Так сами и проверяйте. 

 

Да ради бога..  делайте как хотите.. 

msng
Offline
Зарегистрирован: 07.06.2012

да спор ни о чём....

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

leshak
Offline
Зарегистрирован: 29.09.2011

Vad пишет:

ну так.. проведите эксперимент.. )) измерьте.. доложите тут..

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

Vad пишет:

на компилятор полагайся но сам не плошай))

"Компьютер должен работать, а человек - думать". Поэтому все что возможно - должно быть автоматизированно. Тем более где "оплошать" - очень вероятно (что вы и сделали).

Vad пишет:

ленивое поколение)))

Так кто тут поленился проверить собственные предположения, а сразу выдал их за истину? Да еще с диким апломбом? 

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

Но то что вы свой совет "приправили" поучениями про школу, поколения и т.п. - это "ты, Зин, на грубость нарываешься..". Хотели выступить в качестве "гуру математики", а получился банальный Шариков: "...позволяете себе с развязностью совершенно невыносимой подавать какие-то советы космического масштаба и космической же глупости ...." (C)

 

 

leshak
Offline
Зарегистрирован: 29.09.2011

msng пишет:

 он их хам перемнодит и в контроллер пропишет уже готовое число 

Ну я это и имел ввиду, когда говорил что "компилятор сам сделает замену".

А "Хам ПеремНодит" - это здорово :). Конечно, не мне (с моей безграмотностью) смеятся над опечатками, но юмор в том что эта опечатка, в принципе, отражает то как именно парсер-компилятор выполняет эту работу.

При анализе кода он выстраивает AST-дерево. У которого узлы называются Ноды (Node). И если у ноды типа "умножение", оба дочерних узла "константы", он заменяет ее на ноду типа "константа". И уж только потом отправит это на компиляцию. Думаю вполне можно обозвать эту операцию ПеремНодиванием ;)  , а за то что он "вмешался в авторский замысел" - можно и Хамом обозвать ;)

P.S. Сдорово, что вы не поленились проверить наш спор. В данном случае одинаковый размер, действительно, вышел именно потому что в итоге получается одинаковый результат. Но в общем виде - одинаковый размер не говорит о том, что мы в контроллер загрузится одинаковые скетчи и использовать они будут одинаковое количество памяти. 100% подтверждением, идентичности обоих вариантов будет только бинарное сравнение сгенерированных HEX-сов (или дизасемблироваи и просмотр в какие же именно команды скомпилировался наш исходник).

P.S.S. Я не говорю что "нужно было еще и HEX-сы проверять". Ваша проверка, в данном случае, вполне достаточно-показательна.

 

 

msng
Offline
Зарегистрирован: 07.06.2012

leshak пишет:

А "Хам ПеремНодит" - это здорово :). Конечно, не мне (с моей безграмотностью) смеятся над опечатками, но юмор в том что эта опечатка, в принципе, отражает то как именно парсер-компилятор выполняет эту работу.

 

очепятка зачОтная ))) я не хотел))))

Vad
Offline
Зарегистрирован: 26.05.2013

человек должен думать.. но...  не хочет

вы определитесь..  вы пишете чтоб контроллер  работал с вашей писаниной или чтоб читать приятно было.

И хватит спорить "ниочем"...

kadushkin
Offline
Зарегистрирован: 18.12.2011

По существу вопроса давайте.

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

Vad
Offline
Зарегистрирован: 26.05.2013

по существу вопроса - жду извинений ))

leshak
Offline
Зарегистрирован: 29.09.2011

 

Vad пишет:

по существу вопроса - жду извинений ))

Ню-ню.... ждите.

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

Во вторых, как я вам уже говорил "к оптимизации нужно подходить осторожно, тестируя и проверя", а не "из житейской логики". Из ваших двух советов, как показали замеры - в одном случае выигрыша вообще небыло, в другом - пару байт. То есть, как миниум в 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 - ваши оптимизации вообще выглядить очень бледно. А требования "извинений" - подавно.

 

 

Vad
Offline
Зарегистрирован: 26.05.2013

Водолей ))

leshak
Offline
Зарегистрирован: 29.09.2011

Vad пишет:

Водолей ))

Камаз

kadushkin
Offline
Зарегистрирован: 18.12.2011

При таких жестких условиях экономии времени у меня основной код отвалится.

Придется скорость и обороты из OBD-II читать, хотя не вариант.

Возможно есть еще способы определения скорости и оборотов? ну не ставить же еще один контроллер...

leshak
Offline
Зарегистрирован: 29.09.2011

kadushkin пишет:

При таких жестких условиях экономии времени у меня основной код отвалится.

А с чего ему отваливатся?

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

А уж все вычисления/расчеты/конвертации - делаем в основом коде, когда потребовалось. Там где пара миллисекунд уже роли не играет и можно не торопится.

kadushkin пишет:

Придется скорость и обороты из OBD-II читать, хотя не вариант.

На скажу что "пробовал", но думаю это еще медленее будет.

kadushkin пишет:

Возможно есть еще способы определения скорости и оборотов? ну не ставить же еще один контроллер...

Погуглите книгу Arduino Cookbook автора Michael Margolis . Вроде видел там пример использования аппаратных счетчиков и пульсо-измерителей.  (Chapter 18, разделы "Counting Pulses" и "Measuring Pulses More Accurately"). Возможно это на какие-то идеи натолкнет.

kadushkin
Offline
Зарегистрирован: 18.12.2011

А на функции PulseIn может забазироваться? или неточно будет?

leshak
Offline
Зарегистрирован: 29.09.2011

kadushkin пишет:

А на функции PulseIn может забазироваться? или неточно будет?

Можете попробовать. Но IMHO область ее применения - скетчик на 5-ть строк. Просто посмотреть "какие импульсы там идут". В реальный скетч - лучше ее не использовать.

У нее та же история с "нежелательностью в приличном обществе" что и у delay().

Она блокирует скетч. То есть, пока она ждет импульс - скетч стоит. Ни кнопки не обработать, ни на экран вывести.

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

Вообщем, может это мои предубеждения, но лично я бы не смотрел в ее сторону.

А еще такая мысль пришла в голову. 

Откуда вы берете тестовый сигнал? На чем вы скетчи проверяете? Может вам "неточность" дает не "тахометр", а "подопытный"?

kadushkin
Offline
Зарегистрирован: 18.12.2011

Подопытный - мое авто. Беру сигнал непосредственно с комбинации приборов. Результаты работы скетча проверяю на мониторе магнитолы тут же в машине - вывожу информацию через библиотеку TVout.