Мини компьютер на мотоцикл Урал
- Войдите на сайт для отправки комментариев
Чт, 16/05/2013 - 20:08
Делаю микрокомпьютер для урала на дисплее 3310 (Индикатор заряда и напряжения аккумулятора,температура, тахометр цифровой и графическая шкала к нему, индикаторы поворотов и света.)
Сталкнулся с проблемой тахометра. Перечитал много о цифровых тахометрах, но так и разобраться не могу до конца. Кароче не работает, помогите сделать. Сигнал буду брать на прямую с прерывателя (один переход с HIGH на LOW = 1 оборот)
Делал по аналогии с http://cxem.net/arduino/arduino66.php
#include <PCD8544.h> //для индикатора питания int AKB = 12; static const byte sensorPin = 0; static const byte ledPin = 13; //для тахометра volatile float time = 0; volatile float time_last = 0; volatile int rpm_array[5] = {0,0,0,0,0}; // Размеры ЖК-дисплея (в пикселях) ... static const byte LCD_WIDTH = 84; static const byte LCD_HEIGHT = 48; // рисунок аккумулятора без зарядки static const byte AKB_WIDTH = 10; static const byte AKB_HEIGHT = 1; static const byte AKB_nocharge[] = { 0x7C, 0x46, 0x46, 0x44, 0x44, 0x44, 0x46, 0x46, 0x7C, 0x00}; // рисунок аккумулятора с зарядкой static const byte AKB_charge[] = { 0x7C, 0x7E, 0x7E, 0x7C, 0x7C, 0x7C, 0x7E, 0x7E, 0x7C, 0x00}; static PCD8544 lcd; // функция прерывания void chopper_interrupt() { time = (micros() - time_last); time_last = micros(); } void setup() { Serial.begin(9600); lcd.begin(LCD_WIDTH, LCD_HEIGHT); //Цифровой Pin 2 Установить как прерывание attachInterrupt(0, chopper_interrupt, FALLING); pinMode(ledPin, OUTPUT); pinMode(AKB, INPUT); } void loop() { static byte xChart = LCD_WIDTH; digitalWrite(ledPin, HIGH); //=============(Индикатор питания)================== // Считать напряжение float volt = (5 * analogRead(sensorPin) / 1023 / 0.714); // 0.714 переводной коэф делителя напряжения // Нарисуйте аккумулятор lcd.setCursor(0, 0); if ( digitalRead(AKB) == 0 ) { lcd.drawBitmap(AKB_nocharge, AKB_WIDTH, AKB_HEIGHT); } else { lcd.drawBitmap(AKB_charge, AKB_WIDTH, AKB_HEIGHT); } // показать напряжение аккумулятора lcd.setCursor(10, 0); lcd.print(volt, 1); lcd.print("B"); //================================================= //===============(Тахометр)======================== lcd.setCursor(37, 0); lcd.print("RPM:"); int rpm = 0; //delay(400); //Цеферблат оборотов lcd.setCursor(61, 0); lcd.print(rpm); ////lcd.setCursor(4, 1); ////lcd.print(time); //Обновление RPM if(time > 0) { //Усреднение(сглаживание) 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*1)); //Среднее значение по 5 замерам rpm = (rpm_array[0] + rpm_array[1] + rpm_array[2] + rpm_array[3] + rpm_array[4]) / 5; } digitalWrite(ledPin, LOW); delay(500); }
А зажигание у вас электронное или контактное?
контактное
Тогда вы должны знать о таком явлении как дребезг котактов. И рекомендую все-таки поставить опторазвязку иначе можно сжеч дуину.
http://hardlock.org.ua/viewtopic.php?f=9&t=16 я вот так буду делать, через транзистор, только не с катушки наверное буду брать, а с самого прерывателя.
maksim, вы можете мне подсказать по поводу кода? почему не рабаотает. уже 2 день бьюсь...
естественно я сейчас пробуду не на прерыватете а на кнопке простой. и получается так что сейчес RPM показывает 0, и ещё, я же бал код вот этот
и убал while(1), так как получется так что зацикливалась ардунка на нем(тахометре) и как кие-то бешаные цифры показывала в RPM, в том числе и отрицательные
Доброго времени суток !
Я бы тахометр делал через таймер1.
Настройте таймер 1 в нормальный режим (как это сделать написано в datasheet на Ваш контроллер) частота тактирования таймера задается в зависимости от длинны импульса получаемого на вход (извените не знаю частоты вращения двигателя Урала) Об/Мин_мин / 60 получаем = Об/Сек_мин ; 1 / Об/Сек_мин = Длину одного оборота в секундах. После чего подбираем частоту деления таймера так, что бы в "Длину одного оборота в секундах" вошло 50000 - 60000 тактов. Далее настраиваем маску прерываний от таймера на два прерывания TIMSK = 33 (32(прерывание от ICR) и 1(прерывание от переполнения)) и настраиваем два вектора. Вектор от ICR считывает егистр ICR1 и обнуляет TCNT1. Второе прерывание выставляет флаг двигатель остановлен. Число из ICR быдет длинной входного импульса в тактах, чем меньше тактов - тем выше скорость вращения, зная опорную частоту можно перещитать длинну импульса в секундах, а соответственно и количество оборотов в минуту.
Вы рекомендуете человеку разобраться как настраивать и работать с таймером/счетчиком через регистры, который не знает о дребезге контактов и который не может адаптировать под свой дисплей найденную через поиск по сайту программку тахометра (их с пяток здесь есть). Конечно ваше решение получится красивым, но не для новичка.
Это все равно что третьекласснику посоветовать изучить интеграллы, а затем воспользоваться ими для вычисления плошади прямоугольника. Поэтому вот более простое решение:
данный пример будет показывать колличество срабатываний за одну секунду, расчет и частоту обновлений думаю сами сделаете. Еще раз повторюсь, если вы будите проверять этот пример на кнопке или подключите к прерывателю (не важно) и значения будут завышенными, то читайте что такое дребезг и как с ним бороться.
как вы и говорили. дребезг дал свое... возможно ли избавиться от бребезга програмно в этом случае?
Конечно можно
число 10 это промежуток времени в милисекундах в течении которого последующие срабатывания будут игнорироваться.
Так же может применяться такая конструкция
Подскажите пожалуйсто вот ещё в чем. Как сделать мигание индикатора поворота не прерывая основной программы.
получается так что не мигает он на экране... просто хочу сделать так, чтобы прерывание поворотов осуществлялось именно через ардуино т.к. мотоцикл 6 вольтовый и нету нормального реле поворотов.