Тахометр для двигателя
- Войдите на сайт для отправки комментариев
Чт, 06/08/2015 - 08:55
Кто нибуть реализововал тахометр на ардуино, если да то подскажите в какую сторону копать:)
Кто нибуть реализововал тахометр на ардуино, если да то подскажите в какую сторону копать:)
Если не хотите, чтобы вам предложили копать себе могилку - изъясняйтесь конкретнее. Проектов реализующих тахометр полно. Что именно вы хотите получить?
Ну я себе в семерку делал.
Что сказать-то? Берете ардуину и датчик холла(есть штатные) и через прерывания считаете.
Меня интересует мотоциклетный тахометр, чтоб выводить на дисплей LCD5110
Меня интересует мотоциклетный тахометр, чтоб выводить на дисплей LCD5110
Берете ардуину и датчик холла и через прерывания считаете.
Датчик хола не подойдет нужно импульсы с генератора считывать
А при чем тут генератор? Пусть тс сначала напишет чего он хочет, а потом может ему подскажут. Видишь, уже выясняется что на мотоцикл ему нужно. Пусть скажет на какой ещё.
Идея чтоб на любой двигатель считать обороты коленвала, а хоть мотоцыкл хоть машына, бензопила
Какие такие импульсы на генераторе? Как они выглядят, осциллограмму покаж, тады и будем думать как их считать.
Датчик хола не подойдет нужно импульсы с генератора считывать
1. почему не пойдет?
2. какая разница откуда импульсы считать?
Да вы вообще тупите со своими датчиками и импульсами.. самый верный путь определение оборотов по звуку двигателя!!!
На дисплее делаем пиктограммы
1. Растроеный смайл. Обороты низкие
2. Веселый смайл. Обороты рев на квартал
3. Телки бьются в оргазме от звука вашего мотоцикла!
вижу тут не специалисты а любители по..з...ть :)
вижу тут не специалисты а любители по..з...ть :)
Вам ответили на два бессмысленных вопроса, что вы ещё хотите?
Ну я себе в семерку делал.
Что сказать-то? Берете ардуину и датчик холла(есть штатные) и через прерывания считаете.
P.S. Вы задали тон теме, на себя и пеняйте.
У меня есть глупый вопрос.
ЗАЧЕМ? Зачем тахометр? Когда вы вообще смотрели на тахометр последний раз?
Уточняю тему так как неправильно задал . Кто делал тахометер для двигателя? если делали поделитесь схемкой и прошивкой?
А денег не подкинуть? https://www.google.com/search?newwindow=1&q=тахометр+на+ардуино&oq=тахометр+на+ар&gs_l=serp.1.0.0j0i22i30.49670.60146.0.62143.25.19.1.1.2.3.349.2755.0j2j7j2.11.0....0...1c.1.64.serp..16.9.1651.ui409CMSzqs
это уже видел неподходят, там в основном с датчиками хола а нужно импульсы напряжения считать с генератора
Я выше спрашивал какие импульсы у генератора?
А я выше спрашивал - какая разница, какие импульсы считать?
А у вас импульсный генератор или что?
Если мотоцикл не дизельный ;) то импульсы можно брать с катушки зажигания ( или магнето)
А я выше спрашивал - нафига весь этот геморой? Вы когда едите типа тахометр разглядываете?
Ну хочет человек тахометр. Пусть делает. Вам то что, не вам же городит.
Только универсальных решений нет. ТС так и не сказал, что за мотоцикл у него. И какие импульсы в постоянном токе генератора.
Только универсальных решений нет. ТС так и не сказал, что за мотоцикл у него. И какие импульсы в постоянном токе генератора.
Сама идея считать обороты двигателя кроме как на коленвале мне видится сложно выполнимой. Ибо всякие тама передаточные ремни или шестерни и прочее... тоска в общем
А у вас импульсный генератор или что?
Если мотоцикл не дизельный ;) то импульсы можно брать с катушки зажигания ( или магнето)
Да можно с катушки брать, главно чтоб считало.
Считают обычно счётчиком.......
https://www.google.ru/?gws_rd=ssl#newwindow=1&q=%D1%82%D0%B0%D1%85%D0%BE...
http://cxem.net/arduino/arduino66.php
http://mashinarium.ru/uploads/images/00/00/11/2012/08/20/127f3a.jpg
Салют, товарищам!
Подниму тему, дабы не плодить много однообразных (поправьте, если я не прав)!
Есть копейка 73 года, нужен и спидометр и тахометр - про него-то и пойдёт речь. Для считывания оборотов можно на ВВ провод идущий от катушки намотать медный провод (пару десятков витков) и по количеству импульсов считать обороты - вот вопрос: "Как правильно подать их на ардуинку?" ... как я понимаю - на аналоговый вход? и считать количество отклонений от нуля? ... т.е. я понимаю, что и как надо считать, но не совсем понимаю как увязать всё это на ардуину (просьба не закидывать помидорами, все мы когда-то в чём-то задавали глупые вопросы)...
встречал тут вот такую схему, но это при подключении к управляющему катушкой проводу
или принцип тот же, только без резисторов?
в копейке одна катушка вроде и трамблер, да и ток там переменный. получишь пачки импульсов. просто на прерывание если повесить нужно будет программно отсеивать мусор. может на шестерни приделать?
http://avtopulsar.ru/wp-content/uploads/2013/01/49.jpg
звездочку с магнитом и датчик холла. данные будут лучше
Многие газовые контроллеры легко забирают сигнал с высоковольтных проводов зажигания.
Обычно это импульс амплитудой где-то 300 Вольт появляющееся
за счёт разрыва тока через катушку при транзисторном коммутаторе или,
при тиристорном коммутаторе, это напряжение подавемое на катушку.
Примерная их форма здесь, должны легко фильтроваться стабилитроном и РЦ цепочкой с учётом небольшой их частоты.
6000 оборотов в минуту, 100 в секунду, две искры на оборот (при четырёх горшках) 200 Герц.....
https://www.google.ru/search?q=%D1%81%D0%B8%D0%B3%D0%BD%D0%B0%D0%BB+%D1%...
jeka_tm
Да я думал об этом, там цепь и всё упрятано под клапанную крышку т.е. туда никак ... можно снаружи куда-нить на шкив магнит посадить или сделать с ИК-диодом ... разве с катушки на трамблёр уходит переменное напряжение?.. тогда по управляющему проводу точно должно приходить постоянное-то ... может тогда по вышеупомянутой схеме цепляться?...
trembo
т.е. я правильно тебя понимаю, что если намотать медный провод на ВВ провод от катушки, я таки получу правильные импульсы?
А "провод намотанный на провод" это конденсатор небольшой ёмкости.
Но он может иметь любую полярность.
Поэтому лучше брать сигнал с первичной обмотки
Картинки гляньте..... Там форма выбросов на первичке
trembo Спасибо!))) Буду пробовать по схеме делать, по результату напишу!
Да, я так понимаю, что ему нужно стабилизировать напряжение, и L7812 должен справиться с этой задачей ...
На данный момент код вот такой
int Tahometr_impulse_count; byte TahometrPin = 2; int RPM; unsigned long Check_time ; void setup() { Serial.begin(9600); pinMode(TahometrPin, INPUT); digitalWrite(TahometrPin, HIGH); Check_time = millis(); attachInterrupt(0, TahometrImpulse_on, RISING); } void loop() { delay(500); // произвольное время, чем реже зовем калькулятор РПМ, тем усредненее значение. Calc_RPM(); Serial.println (RPM); } //********************************************************************** void Calc_RPM() { detachInterrupt(0); // запретили считать, на всякий случай, шоб не рыпался float Taho_ChekTime = millis() - Check_time; // время между снятиями показаний счетчика if (Taho_ChekTime > 0) { // проверка на переполнение "милиса" ну вдруг больше 50 дней )) if (Tahometr_impulse_count > 0) { // и наличия насчитанных импульсов (на нолик делить не желательно.. будут запредельные значения в RPM) RPM = (1000/Taho_ChekTime)*(Tahometr_impulse_count*30); // (1000/Taho_ChekTime) - вычисляем множитель (1 секунду делим на наше "замерочное" время) и умножаем на (Tahometr_impulse_count*30) - тут можно было написать *60/2 (* 60 секунд, т.к. у нас есть количество вспышек катушки в секунду и / на 2 т.к. на 1 оборот коленвала 2 искры для 4ёх цилиндрового дрыгателя), но к чему эти сложности } else { RPM = 0; // если нет импульсов за время измерений то RPM=0 } } Tahometr_impulse_count = 0; //сбросили счетчик. Check_time = millis(); // новое время attachInterrupt(0, TahometrImpulse_on, FALLING); // разрешили считать } //********************************************************************** void TahometrImpulse_on() { Tahometr_impulse_count++; }код в принципе почти весь отсюда, с несколькипи изменениями, а именно:
1. изменены типы переменных, для расчётов
2. сам расчёт мне показался немного странным (как минимум не совсем прозрачным, короче я не въехал), ну собственно у меня он и не заработал и поэтому он был переделан
Пока что оно считает импульсы от функции tone(), а вечером или завтра я опробую на машине, ну и отпишусь чего да как.
да странноват. float зачем непонятно. unsigned long по идее должен быть
50 дней ну нереально. никто столько не проедет подряд
#define TahometrPin 2 unsigned long Check_time=0; unsigned long Taho_ChekTime=0; int Tahometr_impulse_count; int RPM; void setup() { Serial.begin(9600); pinMode(TahometrPin, INPUT_PULLUP); Check_time = millis(); attachInterrupt(0, TahometrImpulse_on, RISING); } void loop() { delay(500); // произвольное время, чем реже зовем калькулятор РПМ, тем усредненее значение. Calc_RPM(); Serial.println (RPM); } //********************************************************************** void Calc_RPM() { detachInterrupt(0); // запретили считать, на всякий случай, шоб не рыпался Taho_ChekTime = millis() - Check_time; // время между снятиями показаний счетчика if (Tahometr_impulse_count > 0) { RPM = (1000/Taho_ChekTime)*(Tahometr_impulse_count*30); // (1000/Taho_ChekTime) - вычисляем множитель (1 секунду делим на наше "замерочное" время) и умножаем на (Tahometr_impulse_count*30) - тут можно было написать *60/2 (* 60 секунд, т.к. у нас есть количество вспышек катушки в секунду и / на 2 т.к. на 1 оборот коленвала 2 искры для 4ёх цилиндрового дрыгателя), но к чему эти сложности } else { RPM = 0; // если нет импульсов за время измерений то RPM=0 } Tahometr_impulse_count = 0; //сбросили счетчик. Check_time = millis(); // новое время attachInterrupt(0, TahometrImpulse_on, RISING); } //********************************************************************** void TahometrImpulse_on() { Tahometr_impulse_count++; }Хватит пугать народ переполнением миллиса!
Лешак уже два года назад как доказал на пальцах и примерах что при правильном написании выражения
при переполнении разница ( millis()- PreviousMillis ) выдаёт истинное значение.
Читайте ветку: http://arduino.ru/forum/programmirovanie/eshche-raz-migaem-svetodiodom-b...
если ставить unsigned long, то он отказывался считать вот это (Taho_ChekTime/1000), но это было заблуждением (я вчера на свадьбе был, пузырьки ощущаю до сих пор, так что мне простительно)))))), а тип я исправить забыл :)
а про 50 дней - да, согласен, но сначала хотел проверить на машине, а потом уж начну отметать лишнее, но спасибо за поправки!!! )))
С исправлениями вот
#define TahometrPin 2 unsigned long Check_time = 0; unsigned long Taho_ChekTime = 0; int Tahometr_impulse_count; int RPM; void setup() { Serial.begin(9600); pinMode(TahometrPin, INPUT_PULLUP); Check_time = millis(); attachInterrupt(0, TahometrImpulse_on, RISING); // RISING или FALLING - определяется на месте, с чем стабильней } void loop() { delay(500); // произвольное время, чем реже зовем калькулятор РПМ, тем усредненее значение. Calc_RPM(); Serial.println (RPM); } //********************************************************************** void Calc_RPM() { detachInterrupt(0); // запретили считать, на всякий случай, шоб не рыпался Taho_ChekTime = millis() - Check_time; // время между снятиями показаний счетчика if (Tahometr_impulse_count > 0) { // и наличия насчитанных импульсов (на нолик делить не желательно.. будут запредельные значения в RPM) RPM = (1000 / Taho_ChekTime) * (Tahometr_impulse_count * 30); // (1000/Taho_ChekTime) - вычисляем множитель (1 секунду делим на наше "замерочное" время) и умножаем на (Tahometr_impulse_count*30) - тут можно было написать *60/2 (* 60 секунд, т.к. у нас есть количество вспышек катушки в секунду и / на 2 т.к. на 1 оборот коленвала 2 искры для 4ёх цилиндрового дрыгателя), но к чему эти сложности } else { RPM = 0; // если нет импульсов за время измерений то RPM=0 } Tahometr_impulse_count = 0; //сбросили счетчик. Check_time = millis(); // новое время attachInterrupt(0, TahometrImpulse_on, RISING); // разрешили считать, RISING или FALLING - определяется на месте, с чем стабильней } //********************************************************************** void TahometrImpulse_on() { Tahometr_impulse_count++; }Теперь главное, чтоб заработало на авто!
trembo
Спасибо за ссылочку!
а где исправления? не увидел разницы
изменён тип Taho_ChekTime и убрана проверка на переполнение millis()
так это же я сделал))) про разницу я говорил с кодом который я подкорректированный выложил
так я же написал, что с твоими корректировками код ))))))
Теперь пока на машине не испробую - корректировать нечего)))
А нееееет, float Taho_ChekTime = 0;
В противном случае наш множитель равен только целому числу!
#define TahometrPin 2 unsigned long Check_time = 0; float Taho_ChekTime = 0; int Tahometr_impulse_count; int RPM; void setup() { Serial.begin(9600); pinMode(TahometrPin, INPUT_PULLUP); Check_time = millis(); attachInterrupt(0, TahometrImpulse_on, RISING); // RISING или FALLING - определяется на месте, с чем стабильней } void loop() { delay(200); // произвольное время, чем реже зовем калькулятор РПМ, тем усредненее значение. Calc_RPM(); Serial.println (RPM); } //********************************************************************** void Calc_RPM() { detachInterrupt(0); // запретили считать, на всякий случай, шоб не рыпался Taho_ChekTime = millis() - Check_time; // время между снятиями показаний счетчика if (Tahometr_impulse_count > 0) { // и наличия насчитанных импульсов (на нолик делить не желательно.. будут запредельные значения в RPM) RPM = (1000 / Taho_ChekTime) * (Tahometr_impulse_count * 30); // (1000/Taho_ChekTime) - вычисляем множитель (1 секунду делим на наше "замерочное" время) и умножаем на (Tahometr_impulse_count*30) - тут можно было написать *60/2 (* 60 секунд, т.к. у нас есть количество вспышек катушки в секунду и / на 2 т.к. на 1 оборот коленвала 2 искры для 4ёх цилиндрового дрыгателя), но к чему эти сложности } else { RPM = 0; // если нет импульсов за время измерений то RPM=0 } Tahometr_impulse_count = 0; //сбросили счетчик. Check_time = millis(); // новое время attachInterrupt(0, TahometrImpulse_on, RISING); // разрешили считать, RISING или FALLING - определяется на месте, с чем стабильней } //********************************************************************** void TahometrImpulse_on() { Tahometr_impulse_count++; }Можно захват импульса делать на прерывании по захвату на таймере1. это пин PB1 по моему.
Очень удобно и точное время получается, я тахометр делал на оптопаре . Но это уже не стандартные ардуиновские функции получаются.
Можно захват имльса делать на прерывании по захвату на таймере1. это пин PB1 по моему.
Очень удобно и точное время получается, я тахометр делал на оптопаре . Но это уже не стандартные ардуиновские функции получаютя.
а можно про захват на таймере1 по подробней?.. хочется рассмотреть все варианты :)
да, и можно код Вашего тахометра посмотреть? :)
У меня для atmega 8 код, ошибся -пин PB0 режим ICP1.
Мой код редактировать надо, там мусора много чтоб тут публиковать.
Вот неплохая статья http://radioparty.ru/prog-avr/program-c/548-ispolzovanie-tajmera-v-rezhime-zakhvata-izmerenie-shiriny-skvazhnosti-i-chastoty-signala
ммм, это как раз для реализации ещё одной задумки )))))) там как раз нужно знать ширину и частоту сигнала)))
Спасибо!!!
Вот тут слегка причесал код, остальное лень редактировать.
Это тахометр с четырехразрядным семисегментником на динамической индикации
// сегменты PORTD //_PD0____ //| | //PD1 | PD2 //|__PD3_| //| | //|PD7 |PD4 //|______| // PD6 dp- pd5 #include <avr/wdt.h> //вачдог потом зацепить на 1 секунду к примеру volatile byte screen[4]; //изображения цифр которые копируем в порт чтоб показать цифру volatile static byte number[15] = {//изображения цифр и некоторых букв 0b11010111, // 0 0b00010100, // 1 0b11001101, // 2 0b01011101, // 3 0b00011110, // 4 0b01011011, // 5 0b11011011, // 6 0b00010101, // 7 0b11011111, // 8 0b01011111, // 9 0b00001000,//minus 0b11000011,// С 0b11010111, //А 0b10010111//П //0~9,A,b,C,d,E,F,"-"," " }; //изображения цифр и некоторых букв volatile uint8_t countershiftanode = 0; // для динамичексой индикации счетчик volatile uint8_t shiftanode = B00000001; //для динамической индикации volatile uint8_t scan_number=0;// щетчик оборотов для усреднения volatile uint8_t TIMER1_OVF_counter=0;// щетчик количества срабатываний таймера1 по переполнению volatile uint8_t TIMER1_OVF_counter_final=0;// сюда сохраняем при насткплении прерывания по захвату щетчик TIMER1_OVF_counter volatile uint16_t icr1_filal=0;// сюда сохраняем регистр захвата по наступлению прерывания по захвату volatile boolean data_available=false;// когда 0 то данные захвата готовы и можно считать количество оборотов и выводить на экран volatile uint32_t final_rpm;// расчитанное значение количества оборотов в минуту int main(void) { // initialize the digital pin as an output.ATMEGA8 DDRD = B11111111; // +назначает выводы Arduino 0-7 выходными ПОРТ ДАННЫХ D это сегменты PORTD= 0;// НЕ ГОРЯТ НА СТАРТЕ СЕГМЕНТЫ DDRC = B00001111; //-- аноды выходы PC0-PC3 PORTC=PORTC | B00011111;// ВЫХОДЫ УСТАНАВЛИВАЕМ В HIGH- ЭТО НЕ ГОРИТ , А LOW- ГОРИТ. ОСТАЛЬНЫЕ ПИНЫ ОСТАЮТСЯ ВХОДАМИ С ПОДТЯЖКОЙ DDRB=0;// ВСЕ ВХОДЫ PORTB= PORTB | B00111111;// PB0 У НАС ВХОД РЕГИСТРА ЗАХВАТА, ОСТАЛЬНЫЕ С ПОДТЯЖКОЙ //--------------------------------------------------------------------------------------- // НАСТРАИВАЕМ ПРЕРЫВАНИЕ ДЛЯ ДИНАМИЧЕСКОЙ ИНДИКАЦИИ НА ТАЙМЕРЕ 0 // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: 62,500 kHz 4.096 МС 244 КАДРА ПОЛУЧАЕТСЯ, НОРМАЛЬНО TCCR0=(1<<CS02) | (0<<CS01) | (0<<CS00); TCNT0=0x00;//--------------------------------------------------------------------------------- // НАСТРАИВАЕМ ТАЙМЕР 1 НА ПРЕРЫВАНИЕ ПО ПЕРЕПОЛНЕНИЮ И ПО ЗАХВАТУ ICR ПОРТА PB0 // Timer/Counter 1 initialization // Clock source: System Clock // Clock value: 2000,000 kHz // Mode: Normal top=0xFFFF // OC1A output: Disconnected // OC1B output: Disconnected // Noise Canceler: On // Input Capture on Rising Edge // Timer Period: 32,768 ms // Timer1 Overflow Interrupt: On // Input Capture Interrupt: On // Compare A Match Interrupt: Off // Compare B Match Interrupt: Off TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10); TCCR1B=(1<<ICNC1) | (1<<ICES1) | (0<<WGM13) | (0<<WGM12) | (0<<CS12) | (1<<CS11) | (0<<CS10); TCNT1=0; //TCNT1H=0x00; //TCNT1L=0x00; ICR1=0; //ICR1H=0x00; //ICR1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00;//---------------------------------------------------------------------------------- // Timer(s)/Counter(s) Interrupt(s) initialization TIMSK=(0<<OCIE2) | (0<<TOIE2) | (1<<TICIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (1<<TOIE1) | (1<<TOIE0); // разрешены прерывания TICIE1- по захвату // TOIE1- по переполнению таймера 1 // TOIE0- по переполнению таймера 0 // Watchdog Timer initialization 1second wdt_enable(WDTO_1S); sei(); // the loop routine runs over and over again forever: //void loop() { while(1){ //ATMEGA8------------------------------------------------------------------ // тут рассчитываем количество оборотов если данные для расчета готовы if (data_available==true)// если данные для расчета { //расчет формула // (TIMER1_OVF_counter_final *65535)+ icr1_filal - это у нас сколько занял 1 оборот в тиках таймера. используем переменную uint32_t //1 тик таймера равен 1/2000000 равно = 0.0000005 секунды 5 десятимиллионных секунды. 1 секунда/ 0.0000005 = 2000000 значит 60 секуднд =120000000 // uint32_t более 4х миллиардов final_rpm=((TIMER1_OVF_counter_final*65536)+ icr1_filal); final_rpm= 240000000/final_rpm;// так как замер длительности оборотов у нас на основе 2х оборотов то 240000000 иначе 120000000 //разложим получившиеся обороты на числа //rasklad(final_rpm); if(final_rpm>9999){ final_rpm=0; } data_available= false; }// конец data_available== true //rasklad (TIMER1_OVF_counter_final); rasklad(final_rpm); // ЧТОБ ЭКРАН ОБНОВЛЯЛСЯ НЕ ЧАЩЕ 5 РАЗ В СЕКУНДУ, СДЕЛАЕМ ЗАДЕРЖКУ 200 МС delay_mss(200); wdt_reset(); }// конец-------------------------------------- }//main(void) КОНЕЦ--------------------------------------------------------------- ISR(TIMER0_OVF_vect) {//динамическая индикация----------------------------244 прерываний в секунду // ЗДЕСЬ НАДО ВКЛЮЧИТЬ ПРЕРЫВАНИЯ ЧТОБ МОГЛИ СРАБОТАТЬ ДРУГИЕ ВЛОЖЕННЫЕ ПРЕРЫВАНИЯ И ДИНАМИЧЕСКАЯ ИНДИКАЦИЯ НЕ ТОРМОЗИЛА ПОДСЧЕТ ВРЕМЕНИ И //СРАБАТЫВАНИЯ ТАЙМЕРА ПО ЗАХВАТУ. sei(); // Reinitialize Timer2 value PORTD = screen[countershiftanode]; //ЗАКИНУЛИ ЦИФРУ PORTC = PORTC | B00001111; // В АНОДЫ ПИШЕМ ЕДИНИЦЫ - ЭТО РАВНО ЗАНУЛЕНИЮ pc0 pc3- занулили PORTC = PORTC & ( ~ shiftanode ); // НАЛОЖИЛИ СООТВЕТСТВУЮЩУЮ МАСКУ АНОДА ИНВЕРТИРОВАВ ЕЁ - ЭТИМ ВКЛЮЧАЕМ 0 , ОСТАЛЬНЫЕ ЕДИНИЦЫ ВЫКЛЮЧЕНЫ РАЗРЯДЫ countershiftanode++; shiftanode = (shiftanode << 1); if (countershiftanode == 4) { countershiftanode = 0; shiftanode = B00000001; } } //---------------------------------------------------------------------------- // если таймер переполняется и наступает прерывание то ПРОШЛО 32.768 МИЛИСЕКУНД И ПЛЮСУЕМ TIMER1_OVF_counter ПОКА НЕ ДОСТИГНЕТ 100 // ЭТО ОЗНАЧАЕТ ЧТО двигатель ВРАЩАЕТСЯ МЕДЛЕННЕЕ ЧЕМ 18 ОБОРОТОВ В МИНУТУ, ЧЕГО БЫТЬ НЕ МОЖЕТ ISR(TIMER1_OVF_vect) { TIMER1_OVF_counter++;// количество переполнений 1 байт переменная if (TIMER1_OVF_counter>150){// двигатель стоит, обнуляем щетчики------ TIMER1_OVF_counter_final=0;// двигатель стоит - обнуляем щетчик TCNT1=0;//ОБНУЛЯЕМ СЧЕТНЫЙ РЕГИСТР icr1_filal=0;// финальное содержимое регистра захвата тоже равно нулю TIMER1_OVF_counter=0; data_available=false; final_rpm=0; }// }// это будет происходить раз в 32.2768 секунды или меньше 18 ти оборотов //ПРИШЕЛ ВОСХОДЯЩИЙ ФРОНТ СИГНАЛА С ФОТОДАТЧИКА. СРАБОТАЛО ПРЕРЫВАНИЕ И ЗАПОМНИЛО ВРЕМЯ. ТЕПЕРЬ НАДО СКОПИРОВАТЬ ЭТО ВРЕМЯ В ПЕРЕМЕННУЮ //И ВЫЧИСЛЯТЬ ПОЛНУЮ ДЛИТЕЛЬНОСТЬ ИМПУЛЬСА //если во время выполнения прерывания по захвату происходит переполнение то захват произошел раньШе и мы всеравно обнуляем TCNT1 И ОТМЕНЯЕМ ПРЕРЫВАНИЕ ПО //ПЕРЕПОЛНЕНИЮ СБРОСОМ ФЛАГА ЗАПИСЬЮ 1 В ЭТОТ ФЛАГ ISR(TIMER1_CAPT_vect) { // ЕЩЕ МАЛЕНЬКАЯ ЗАЩИТА ОТ ПОМЕХ - ПРОИЗОШЛО ПРЕРЫВАНИЕ ПО RISING, МЫ ДОЛЖНЫ ПРОЧЕСТЬ HIGH C PB0 if((PINB & B00000001)>0)// ЕСЛИ HIGH ТО ВЫПОЛНЯЕМ, ИНАЧЕ ВЫХОДИМ { if((PINB & B00000001)>0)// ЕСЛИ HIGH ТО ВЫПОЛНЯЕМ, ИНАЧЕ ВЫХОДИМ {// ЕЩЕ РАЗПРОВЕРЯЕМ НА ДРЕБЕЗГ, И ЕСЛИ УШЛО ТО ВЫХОДИМ, ИНАЧЕ СИГНАБ РЕАЛЬНЫЙ if (scan_number==0){ // нифига не делаем, просто выходим из прерывания, а щетчик щитает дальше второй оборот. Далее на основе 2х оборотов будем считать //среднее значение scan_number=1; } else //если равно 1 { TCNT1=0;//ОБНУЛЯЕМ СЧЕТНЫЙ РЕГИСТР ДЛЯ НОВОГО СЧЕТА НОВОГО ОБОРОТА icr1_filal=ICR1;// копируем содержимое регистра захвата TIMER1_OVF_counter_final = TIMER1_OVF_counter;// ЩЕТЧИК КОЛИЧЕСТВА ПЕРЕПОЛНЕНИЙ КОПИРУЕМ В ФИНАЛЬНУЮ ПЕРЕМЕННУЮ TIMER1_OVF_counter=0; // ОБНУЛЯЕМ ЩЕТЧИК КОЛИЧЕСТВА ПЕРЕПОЛНЕНИЙ // тут сбросим прерывание по переполнению если оно удруг уже произошло пока мы в обработчике прерывания по захвату, так как счет длительности оборота // начинается снова //Регистр флагов прерываний таймеров-счетчиков - TIFR Флаг TOV1 сбрасывается аппаратно при переходе на соответствующий вектор прерывания. //Альтернативно, флаг TOV1 сбрасывается путем записи в него лог. 1. //OCF2 TOV2 ICF1 OCF1A OCF1B TOV1 – TOV0 //TIFR TIFR=TIFR | B00000100;// СБРОСИЛИ ЕСЛИ БЫЛо прерывание scan_number=0; data_available=true;// } } } }//ISR(TIMER1_CAPT_vect) void rasklad (int16_t decimal) {// расклад числа ------------------------------------------------------------------------------- byte rasklad_temp[4]; int decimaltemp = decimal; rasklad_temp[1] = decimal / 1000; // сотни decimal = decimal %= 1000; //остаток от деления на 1000 (сотни) rasklad_temp[2] = decimal / 100; // сотни decimal = decimal %= 100; //остаток от деления на 100 (десятки) rasklad_temp[3] = decimal / 10; // десятки rasklad_temp[0] = decimal %= 10; // остаток еденицы if (decimaltemp < 1000) { screen[3] = 0; // если меньше 1000 то ничего не рисуем PC3 } else { screen[3] = number[rasklad_temp[1]]; } if (decimaltemp < 100) { screen[1] = 0; // если меньше 100 то ничего не рисуем PC1 } else { screen[1] = number[rasklad_temp[2]]; } if (decimaltemp < 10) { screen[2] = B00000000; // если меньше 100 то ничего не рисуем кроме точки PC2 } else { screen[2] = (number[rasklad_temp[3]]) ; // рисуем цифру с точкой } screen[0] = number[rasklad_temp[0]]; } // конец расклада числа в screen имеем печатаемые цифры-------------------------------------------------------------------------------------------------- //**************Delay**************************** void delay_mss(uint16_t tic_ms) { while (tic_ms) { delay_us(999); tic_ms--; } } void delay_us(uint16_t tic_us) { tic_us *= 4; //1us = 4 цикла __asm__ volatile ( "1: sbiw %0,1" "\n\t" //; вычесть из регистра значение N "brne 1b" : "=w" (tic_us) : "0" (tic_us) ); }фигасе ... к такому я ещё не готов ))) avr для меня пока тёмный лес ... Но спасибо!!! Для ознакомления и разбора кода самое то)))
это код для атмега 8 на 16мгц. В среде ардуины компилируется:))
на атмега 328 только инициализацию таймеров надо поменять вроде
то что AVR в среде ардуины нормально себя чувствует я знаю, просто ардуина сама по себе (язык) расслабляет и делает "себя" более общедоступным и "без заморочек" нежели AVR или STM ... при этом прекрасно понимаю, что надо всё же пробовать осваиватть либо AVR либо STM, а лучше сразу обои два, но в виду малого количества свободного времени это сложно сделать ... вот тут-то как раз ардуина и выигрывает ))))))