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

Vad
Offline
Зарегистрирован: 26.05.2013
unsigned long Tahometr_impulse_count;
byte TahometrPin=12;
double RPM;  
unsigned long Check_time ; 



void setup() {
            Serial.begin(115200);  
            pinMode(TahometrPin, INPUT); 
            digitalWrite(TahometrPin, HIGH);
            
            Check_time = millis(); 
            attachInterrupt(5, TahometrImpulse_on, FALLING);
}


void loop() {
      delay(1000);  // произвольное время, чем реже зовем калькулятор РПМ, тем усредненее значение.
      Calc_RPM();
      Serial.println (RPM);

}


//**********************************************************************
void Calc_RPM(){

            detachInterrupt(5);                                        // запретили считать, на всякий случай, шоб не рыпался            
            int Taho_ChekTime = millis()-Check_time;                   // время между снятиями показаний счетчика              
            if (Taho_ChekTime > 0)  {                                  // проверка на переполнение "милиса" ну вдруг больше  50 дней ))
            if (Tahometr_impulse_count > 0){                           // и  наличия насчитанных импульсов (на нолик делить не желательно.. будут запредельные значения в RPM)
                 RPM=(1/(Taho_ChekTime/Tahometr_impulse_count))*30000;  //подсчитываем среднее время периода, переводим в частоту, и приводим к об/минам уже деленым на 2
                }else{
		RPM=0;							// если нет импульсов за время измерений  то  RPM=0
		      }
            }

            Tahometr_impulse_count = 0;                                //сбросили счетчик.
            Check_time = millis();                                     // новое время
            attachInterrupt(5, TahometrImpulse_on, FALLING);           // разрешили считать      
}
//**********************************************************************

 void  TahometrImpulse_on(){ 
 Tahometr_impulse_count++; 
 }

пробуйте

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

Vad

Попробую.

Сие Ваше произведение?

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

да.. можно сказать мое.. )) 

компиляция двух ваших ))

Probelzaelo
Offline
Зарегистрирован: 15.04.2011

kadushkin пишет:
Возможно есть еще способы определения скорости и оборотов?

а с какой частотой и точностью тебе хотелось бы измерять обороты? например +- 50 об/мин на 3000 при измерении один-два раза в секунду устроит?

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

Probelzaelo

Думаю устроит.

Probelzaelo
Offline
Зарегистрирован: 15.04.2011

kadushkin пишет:

Думаю устроит.

В таком случае есть решение что называется в лоб. считаемые импульсы подаем прямо на вход таймера счетчика. Раз в пол секунды уходим в прерывание и считываем то, что там образовалось одновременно обнуляя содержимое счетчика для следующего подсчета, это число как раз будет соответствовать количеству оборотов в секунду умножаем его на 60 и получаем об/мин. Таким образом получается единица измерения или цена деления счетчика 1 = 60 об/мин, а погрешность в таком случае только половина от цены деления те 30 об/мин  время выполнения всего этого расчета будет в пределах сотни-полутора тактов процессора примерно 0.001%, остальное же из 16 миллионовтактов остаются в полном расторяжении главной программы. 

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

я скеч выше положил )) он времянезависимый вообще..

сам расчет можно  обрабатывать в любое свободное/удобное  время

не чаще 100 раз в сек. но не  реже 1 раза в 50 дней,

при  опросе  2 раза в сек при  1000 об./мин получается  разрешение около 3-6 об..мин

за счет усреднения последних N оборотов..  точность с 2мя знаками после запятой ))

 

PS

может ошибся в расчетах..  считал  в уме.. и на пальцах ))

 

Probelzaelo
Offline
Зарегистрирован: 15.04.2011

однако готовые решения прямо на поверхности

http://forum.arduino.cc/index.php?topic=108215.0

http://www.avdweb.nl/arduino/hardware-interfacing/frequency-period-count...

 

kadushkin
Offline
Зарегистрирован: 18.12.2011
Код модифицировал, исправил формулу оборотов, обороты худо бедно считывает, плюс-минус 100.
А вот скорость, что-то пляшет...
Интересно, что переменные Tahometr_impulse_count и Speed_impulse_count при объявлении с volatile приводили к тому, что скетч не работал, может тут загвоздка


#define  TahometrPin 18  // Контакт 18 для тахометра !!!!!!!!! ПРЕРЫВАНИЕ 5
#define  SpeedSensorPin 19 // Контакт 19 для датчика скорости !!!!!!!!!ПРЕРЫВАНИЕ 4

unsigned long Speed_impulse_count;  // кол-во импульсов датчика скорости
double Speed; // скорость с датчика скорости
unsigned long Tahometr_impulse_count;
double RPM;
unsigned long Check_time ;

//Контакт 18  !!!!!!!!!ПРЕРЫВАНИЕ 5
pinMode(TahometrPin, INPUT); // Контакт для тахометра !!!!!!!!!ПРЕРЫВАНИЕ 5
digitalWrite(TahometrPin, HIGH); //внутренняя подтяжка входа тахометра
attachInterrupt(5, TahometrImpulse_on, FALLING); //RISING);// настройка прерывания и функции на него


//Контакт 19  !!!!!!!!!ПРЕРЫВАНИЕ 4
pinMode(SpeedSensorPin, INPUT); // Контакт для датчика скорости !!!!!!!!!ПРЕРЫВАНИЕ 4
digitalWrite(SpeedSensorPin, HIGH); //внутренняя подтяжка входа датчика скорости
attachInterrupt(4, SpeedImpulse_on, FALLING); // настройка прерывания и функции на него
Check_time = millis();

//###################################################################
// обработчик событий тахометра
void  TahometrImpulse_on() //сидит на прерывании, срабатывает при возникновении событий на цифровом входе
{
Tahometr_impulse_count++; //увеличить счетчик импульсов
}


//###################################################################
// обработчик событий датчика скорости
void  SpeedImpulse_on() //сидит на прерывании, срабатывает при возникновении событий на  цифровом входе
{
Speed_impulse_count++; //увеличить счетчик импульсов
} 


//**********************************************************************
void Calc_RPM_Speed(){
detachInterrupt(5); // запретили считать, на всякий случай, шоб не рыпался 
detachInterrupt(4); // запретили считать, на всякий случай, шоб не рыпался 

int Taho_Speed_ChekTime = millis()-Check_time; // время между снятиями показаний счетчика 

if (Taho_Speed_ChekTime > 0) { // проверка на переполнение "милиса" ну вдруг больше 50 дней ))

if (Tahometr_impulse_count > 0){ // и наличия насчитанных импульсов (на нолик делить не желательно.. будут запредельные значения в RPM)
RPM=((Tahometr_impulse_count*30000)/(Taho_Speed_ChekTime));   // перевод в об/мин, 1 об на 2 ммпульса,1000 - перевод мс в сек., 60 - перевод сек в мин.

}
else {RPM=0;}// если нет импульсов за время измерений  то  RPM=0
 
if (Speed_impulse_count > 0){ // и наличия насчитанных импульсов 

// перевод в км/ч,  2м за 5 импульсов, 3.6 - перевод м/с в км/ч, 1000 - перевод мс в сек.,60 - перевод сек в мин.
Speed=((Speed_impulse_count*1440)/(Taho_Speed_ChekTime));   
 }
else {Speed=0;}// если нет импульсов за время измерений 
 }
 
 if (Speed<0) {Speed=0;}
 if (Speed>160) {Speed=0;}
 if (RPM<0) {RPM=0;}
 if (RPM>5000) {RPM=0;}
 
Tahometr_impulse_count = 0; //сбросили счетчик.
Speed_impulse_count = 0;

Check_time = millis(); // новое время
attachInterrupt(5, TahometrImpulse_on, FALLING); // разрешили считать 
attachInterrupt(4, SpeedImpulse_on, FALLING); // разрешили считать 
}
//*********************************************************************
      
kadushkin
Offline
Зарегистрирован: 18.12.2011

Вот видео работы скетча, параметр TAH на экране содержит значение оборотов двигателя, почему значения плавают...

http://www.youtube.com/watch?v=FgO0EObwMg0&feature=youtu.be

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

А можно весь ваш скеч...

я его погоняю у себя..

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

случаем  tvout  не использует таймеры..?

Я ниразу не пробовал ее руками... надо скачать посмотреть как устроена))

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

щас скачаю.. посмотрю..

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

Скетч очень большой, но сейчас все функции в нем отключены и обрабатывается только Calc_RPM_Speed()

Насчет таймеров не скажу, не знаю...

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

я поковырял  tvout.. использует и таймеры и прерывания... очень активно использует, там черт нугу сломит ))

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

давайте попробуем выкинуть отключение прерываний у нас... должно немножко исправить ситуацию... но не думаю что сильно))

detachInterrupt 5

detachInterrupt 4

attachInterrupt 4

attachInterrupt 5

tvout  прерывается 15625 раз в секунду.. только на  синхронизацию... и еще по ~100 раз  на  формирование  точек ... в каждой из 15625 строк...

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

Попробую.

Также планирую использовать библиотеки:

#include <SPI.h>
#include <avr/wdt.h>
#include <SoftwareSerial.h>

Надеюсь они без прерываний...

Sirocco
Offline
Зарегистрирован: 28.09.2013

У меня вопросы по железу.

Сколько в теории можно снять импульсов в секунду с Atmega8 с кварцом 16Мгц? Другими словами, максимальная частота какая? Наличие кварца на это влияет? Какая точность? Хочу сделать для мото тахометр, экран не нужен, будут светодиоды, каждые 500 оборотов, начиная с 1000, т.е. 1000, 1500, 2000... и до 7000. Нужно, как понимаю, 13 выходов для светодиодов, и один вход для снятия импульса с датчика холла, или с низкой стороны высоковольтного трансформатора. Откуда, кстати, проще или удобнее брать импульс? Двигатель четырёхтактный одноцилиндровый, кроссовый мот.

Можно ли это реализовать на Atmega8 (С кварцем или без? нужно максимум компактности) Если светодиод потребляет 15-20 мА, можно обойтись без усилителей, сразу припаяв к ноге контроллера через резистор? От 13 светодиодов микрухе плохо не станет?

 

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

приблизительно 8 миллионов импульсов в секунду с Atmega8 с кварцом 16Мгц

кварц влияет конечно ))

он же сердце..

на каждом "ударе сердца"  - проверять прерывание

 

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

>Наличие кварца на это влияет?  

Для точности - обязательно.

>Какая точность? 

micros() идет с точностью 4ms. (это в доке написано).

>Нужно, как понимаю, 13 выходов для светодиодов

Не обязательно. Смотрите раздел програмирование, раздел "базовые и полезные знания" (74HC595).

>Если светодиод потребляет 15-20 мА, можно обойтись без усилителей, сразу припаяв к ноге контроллера через резистор

Можно. Опять-таки документации Цифровые выводы | Аппаратная платформа Arduino и даташите на камень четко отвечено какие токи можно брать с пина.

>От 13 светодиодов микрухе плохо не станет?

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

 

 

Sirocco
Offline
Зарегистрирован: 28.09.2013

Открыл для себя такую штуку - Датчик Холла А3144. http://arduino-lipetsk.ru/Detal39519506.html

Я правильно понимаю, что он работает как геркон, только с большей частотой переключения (меньшей инерционностью)?  Тоесть подав на него питание, я смогу снять питание с него, если приближу к нему магнит? Можно его использовать в тахометре мотоцикла, поместив рядом со штатным датчиком Холла в системе зажигания? А то что-то не охота вмешиваться в штатную проводку.

P.S. А как работает система определения оборотов компьютерного куллера?

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

> Тоесть подав на него питание, я смогу снять питание с него, если приближу к нему магнит? 

Ну точно на это ответить можно только найдя даташит на него. "Чисты датчик" - он еще усилителя требует (очень малые напряжения он выдает). Правда в описании вашего датчика говорится, что он "Цифровой выход 25 мА, совместим с цифровой логикой" что, я для себя перевел-бы как: "не партесь, усилитель у него уже внутри".

>P.S. А как работает система определения оборотов компьютерного куллера?

Общее представление о холе можно тут почитать http://easyelectronics.ru/datchik-xolla.html

Там и про комьютерные куллеры упоминается.

Probelzaelo
Offline
Зарегистрирован: 15.04.2011

sitromon пишет:
я незнаю можно ли подружить ардуино с обд портом _ компьютером, но если можно то проще будет сделать тахометр от обд типо такой бортовой компьютер, модно расход смотреть и всякую разную информацию. на обд раьеме воре один проводок отвечает за передачу данных

 

Вовсяком случае Дуину уже не раз сдружали с ELM-327 и через синезуб и через проволоку... и вот так Кто не верит спросите у гугля )) А там обороты можно уже не считать, они читаются или совсем по простому просятся через библиотеку ArduinoOBD

http://www.youtube.com/watch?v=P_vt0CDVI8E

kadushkin пишет:
Вот видео работы скетча, параметр TAH на экране содержит значение оборотов двигателя, почему значения плавают...

потому что ни кто не задавался целью их стабилизировать с высокой точностью в паспорте если сказано +-50, значит могут гулять +-50 ...

Sirocco
Offline
Зарегистрирован: 28.09.2013

leshak пишет:

> Тоесть подав на него питание, я смогу снять питание с него, если приближу к нему магнит? 

Ну точно на это ответить можно только найдя даташит на него. "Чисты датчик" - он еще усилителя требует (очень малые напряжения он выдает). Правда в описании вашего датчика говорится, что он "Цифровой выход 25 мА, совместим с цифровой логикой" что, я для себя перевел-бы как: "не партесь, усилитель у него уже внутри".

>P.S. А как работает система определения оборотов компьютерного куллера?

Общее представление о холе можно тут почитать http://easyelectronics.ru/datchik-xolla.html

Там и про комьютерные куллеры упоминается.

А какой тогда будет лучше для моей задачи? Посмотрел в Чип и Дип, много всяких. Что значит биполярные?

Sirocco
Offline
Зарегистрирован: 28.09.2013

Vad пишет:

unsigned long Tahometr_impulse_count;
byte TahometrPin=12;
double RPM;  
unsigned long Check_time ; 



void setup() {
            Serial.begin(115200);  
            pinMode(TahometrPin, INPUT); 
            digitalWrite(TahometrPin, HIGH);
            
            Check_time = millis(); 
            attachInterrupt(5, TahometrImpulse_on, FALLING);
}


void loop() {
      delay(1000);  // произвольное время, чем реже зовем калькулятор РПМ, тем усредненее значение.
      Calc_RPM();
      Serial.println (RPM);

}


//**********************************************************************
void Calc_RPM(){

            detachInterrupt(5);                                        // запретили считать, на всякий случай, шоб не рыпался            
            int Taho_ChekTime = millis()-Check_time;                   // время между снятиями показаний счетчика              
            if (Taho_ChekTime > 0)  {                                  // проверка на переполнение "милиса" ну вдруг больше  50 дней ))
            if (Tahometr_impulse_count > 0){                           // и  наличия насчитанных импульсов (на нолик делить не желательно.. будут запредельные значения в RPM)
                 RPM=(1/(Taho_ChekTime/Tahometr_impulse_count))*30000;  //подсчитываем среднее время периода, переводим в частоту, и приводим к об/минам уже деленым на 2
                }else{
		RPM=0;							// если нет импульсов за время измерений  то  RPM=0
		      }
            }

            Tahometr_impulse_count = 0;                                //сбросили счетчик.
            Check_time = millis();                                     // новое время
            attachInterrupt(5, TahometrImpulse_on, FALLING);           // разрешили считать      
}
//**********************************************************************

 void  TahometrImpulse_on(){ 
 Tahometr_impulse_count++; 
 }

пробуйте

Чёт не понял, что куда подключать в этом коде? Куда импульс подавать от зажигания? На пятый пин?

Зачем нужен пин 12?

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

где там 5 пин?

подавать на 12 ессесно

Sirocco
Offline
Зарегистрирован: 28.09.2013

Vad, у меня атмега8. Я заменил 

byte TahometrPin=12;

на 

byte TahometrPin=2;

и прерывания Interrupt(5) на Interrupt(0).

Но код что-то не работает. Выводит 0.00

Код такой получился:

unsigned long Tahometr_impulse_count;
byte TahometrPin=2;
double RPM;  
unsigned long Check_time ; 



void setup() {
            Serial.begin(115200);  
            pinMode(TahometrPin, INPUT); 
            digitalWrite(TahometrPin, HIGH);
            
            Check_time = millis(); 
            attachInterrupt(0, TahometrImpulse_on, FALLING);
}


void loop() {
      delay(500);  // произвольное время, чем реже зовем калькулятор РПМ, тем усредненее значение.
      Calc_RPM();
      Serial.println (RPM);

}


//**********************************************************************
void Calc_RPM(){

            detachInterrupt(0);                                        // запретили считать, на всякий случай, шоб не рыпался            
            int Taho_ChekTime = millis()-Check_time;                   // время между снятиями показаний счетчика              
            if (Taho_ChekTime > 0)  {                                  // проверка на переполнение "милиса" ну вдруг больше  50 дней ))
            if (Tahometr_impulse_count > 0){                           // и  наличия насчитанных импульсов (на нолик делить не желательно.. будут запредельные значения в RPM)
                 RPM=(1/(Taho_ChekTime/Tahometr_impulse_count))*30000;  //подсчитываем среднее время периода, переводим в частоту, и приводим к об/минам уже деленым на 2
                }else{
		RPM=0;							// если нет импульсов за время измерений  то  RPM=0
		      }
            }

            Tahometr_impulse_count = 0;                                //сбросили счетчик.
            Check_time = millis();                                     // новое время
            attachInterrupt(0, TahometrImpulse_on, FALLING);           // разрешили считать      
}
//**********************************************************************

 void  TahometrImpulse_on(){ 
 Tahometr_impulse_count++; 
 }

 

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

а что на 2 пин подаешь?

Sirocco
Offline
Зарегистрирован: 28.09.2013

Vad пишет:

а что на 2 пин подаешь?

Импульсы, которые считать нужно.

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

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

импульсы разные бывают ))  бывает 1 наносек.. бывает  1 сек..

откуда они?(устройство)

какой период у них..?

минимальная частота следования импульсов 2 герц

 

 

Sirocco
Offline
Зарегистрирован: 28.09.2013

Вручную кнопку тыкал. Герца четыре было. Ща куллер взял от компа. Если на него подать напряжение на чёрный и красный провод, то при его вращении оставшийся желтый провод замыкается на минус два раза за оборот. Подключил его. По этой программе работает:

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x38,16,2);
volatile float time = 0;
volatile float time_last = 0;
volatile int rpm_array[5] = {0,0,0,0,0};

void setup()
{
  lcd.init();
  //Digital Pin 2 Set As An Interrupt
 attachInterrupt(0, fan_interrupt, FALLING);

  // set up the LCD's number of columns and rows: 
 
  // Print a message to the LCD.
  lcd.print("Current RPM:");
}

void loop()
{
  int rpm = 0;
  
  while(1){    

     //Slow Down The LCD Display Updates
  delay(250);
  
  //Clear The Bottom Row
  lcd.setCursor(0, 1);
  lcd.print("                ");   
  
  //Update The Rpm Count
  lcd.setCursor(0, 1);
  lcd.print(rpm);   

  ////lcd.setCursor(4, 1);
  ////lcd.print(time);   

  //Update The RPM
  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));    
    //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();
}

Но тут какие-то бешенные значения порой пролетают, и даже отрицательные.

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

Probelzaelo
Offline
Зарегистрирован: 15.04.2011

Vad пишет:
импульсы разные бывают ))  бывает 1 наносек.. бывает  1 сек..

откуда они?(устройство)

какой период у них..?

минимальная частота следования импульсов 2 герц

откуда 2 Гц? это же соответствует всего 60 об/мин, реально же минимальные обороты ДВС не меньше 300 а реальные ХХ у большинства авто находятся в пределах 750-950, а это уже порядка от 10 Гц минимально.

и кстати. у современных моторов обычно используют многоискровое зажигание, а это 2-4 импульса подряд для каждого рабочего хода.

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

Я о  коде скетча.. а не о двс

при 2х герцах он будет 0-1 показывать

Sirocco
Offline
Зарегистрирован: 28.09.2013

Я не знаю под какую технику Вы считали. Но точно знаю, что если техника одно цилиндровая и четырёх тактная, то искра образуется каждый второй так, тоесть каждый оборот двигателя. Почему? Да потому, что в таких движках просто нет системы определения текущего такта. И это, в принципе, и не нужно. Так что один оборот - один импульс, одна искра, несмотря на четырёх тактность. И в рабочий такт искра, и на выхлопе тоже искра. По крайней мере на всей китайской технике так.

Так что не ошибитесь, кто длает для скутеров и им подобных.

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

на данный момент - вентилятор..))

и то ноль кажет

а считалось для 4ц движка..  читаните первую страницу 

Sirocco
Offline
Зарегистрирован: 28.09.2013

Сижу туплю. Не погу просчитать погрешность измерения оборотов (максимальную) в диапазоне от 1000 до 8500. На атмеге 328 для двухтактного двтгателя, тоесть 1 оборот=1импульс.

Нужно очень точно и быстро (примерно за 0.1-0.15 сек)определять текущие обороты, для того, чтоб вводить отсечку двигателя. 

Вообще, как думаете, электронное зажигание можно постороить на 328 атмеге? Если импульс приходит за 3мм до ВМТ с датчика холла, и сразу же образуется искра, то каково будет задержка, если посредником будет атмега? Просто в момент старта двигателя, при оборотах до ~800 хорошо бы вводить задержку на искру, тем самым делая зажигание поздним. 

Probelzaelo
Offline
Зарегистрирован: 15.04.2011

Ну давай посчитаем в лоб.

для максимальной скорости которая задана - 8500 об/мин = 142 оборотов или 51120 градусов в сек.

при 16 МГц. на каждый градус приходится 312 тактов. это значит что успеет выполниться в среднем программа длиной до 70++ комманд(считая в среднем 4 такта на комманду), что не так уж и мало, учитывая что на максимальных оборотах задержек вносить не требуется значит можем сразу запускать искру и выходить, я предполагаю что обработчик вполне уложится по времени в 0.2-0.5 градуса, а на меньших оборотах времени еще и на перекурить хватит.

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

Sirocco
Offline
Зарегистрирован: 28.09.2013

Probelzaelo пишет:

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

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

А как выяснилось, УОЗ - это не статичная штука. На низких оборотах должно быть позднее, на средних, до ~3000 среднее, а на <3000 раннее, и чем выше обороты, тем более раннее. Связано с конкретным типом двигателя и с детонацией определённой марки топлива. 

Но так сильно засирать мозг не собираюсь, попробую реализовать позднее на низких оборотах, чтоб отдачи в стартер или ногу небыло, и отсечку при 7500об\мин. Возможно, стоит продумать схему, при которой атмега переставала бы учавствовать в формировании искры. После того, как двигатель завёлся нужно переводить на штатную систему зажигания, которую просто блокировать при 7500 об\мин для отсечки. 

P.S. Это одноциллиндровый 400 кубовый китаец.

bear
Offline
Зарегистрирован: 16.08.2015

Sirocco пишет:
 Можно его использовать в тахометре мотоцикла, поместив рядом со штатным датчиком Холла в системе зажигания? А то что-то не охота вмешиваться в штатную проводку.

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

С обработкой сигнала всё понятно, но как взять сигнал бесконтактно?

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

http://ru.aliexpress.com/item/New-hot-Hour-meter-Tachometer-2-4-Stroke-Engine-Spark-For-Boat-Motorcycle-Bike-12V-CAR/2046063868.html

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

У кого какие мысли, как правильно согласовать с Иной этот провод, обернутый вокруг изолированного высоковольтного повода ДВС?

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

Sirocco пишет:
Нужно очень точно и быстро (примерно за 0.1-0.15 сек)определять текущие обороты, для того, чтоб вводить отсечку двигателя.  

А куда спешить?

за 1-2-3 оборота  КВ обороты не могут измениться на СТОЛЬКО, чтоб это стало критичным.

если мы на измерение и расчет оборотов  израсходуем 2-3 оборота КВ - ничего не случится..

На меге, конечно.. можно сделать электронное зажигание))

почему нет?

у меня на  старичке 89с2051  был собран электронный "табличный контроллер" УОЗ для ВАЗ 21093, с изменяемыми, загружаемыми таблицами опережения зажигания.. 10 лет отработал.. так с ним и продал))

хотел еще датчик детонации к нему прикрутить - тогда совсем было бы круто)) но не успел

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

bear пишет:

У кого какие мысли, как правильно согласовать с Иной этот провод, обернутый вокруг изолированного высоковольтного повода ДВС?

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

tbstdt
Offline
Зарегистрирован: 21.11.2015

Вот мой код, собранный из того что было раньше, который вполне работает и выводит обороты на дисплей. Сегодня проверял.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3F,16,2); 

unsigned long Tahometr_impulse_count;
float RPM;  
unsigned long Check_time ; 

void setup()
{ 
  Serial.begin(9600);    
  attachInterrupt(0, TahometrImpulse_on, FALLING);
  LCDinit();
 
}
void LCDinit()
{
  lcd.init(); // Инициализируем экран    
  lcd.backlight(); //включаем подсветку  
  lcd.setCursor(0,0);   
  lcd.print("RPM: ");//выводим строку 1    
}
void loop()
{
  delay(1000);   
  Calc_RPM();  
  lcd.setCursor(5,0);  
  lcd.print(ToString(RPM));
  
  
}

//**********************************************************************
void Calc_RPM(){
  
          

            detachInterrupt(0);                                        // запретили считать, на всякий случай, шоб не рыпался            
            int Taho_ChekTime = millis()-Check_time;                   // время между снятиями показаний счетчика              
            if (Taho_ChekTime > 0)  
            {                                                        // проверка на переполнение "милиса" ну вдруг больше  50 дней ))
              if (Tahometr_impulse_count > 0)                            // и  наличия насчитанных импульсов (на нолик делить не желательно.. будут запредельные значения в RPM)
              {                          
                  RPM=((float)Tahometr_impulse_count/((float)Taho_ChekTime/1000))*30;  //подсчитываем среднее время периода, переводим в частоту, и приводим к об/минам уже деленым на 2
              }
                else
                  {
  		  RPM=0;							// если нет импульсов за время измерений  то  RPM=0
  		}
            }
             
              Tahometr_impulse_count = 0;                                //сбросили счетчик.
            Check_time = millis();                                     // новое время
            attachInterrupt(0, TahometrImpulse_on, FALLING);           // разрешили считать      
}
//**********************************************************************

 void  TahometrImpulse_on()
 { 
     Tahometr_impulse_count++;     
 }


String ToString(int i)
{
  String s =  String(i, DEC);
  while (s.length()<6) s=s+" ";
  return s;
}

 

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

Я, конечно, сильно извиняюсь, что поднимаю опять эту тему, но где видно из текста последнего поста, с какой ноги считывается сигнал ? Я что-то либо не дочитал, либо  - недопонял.

Переделал под свой дисплей. Вроде ничего нигде не упустил:

// Объявляем библиотеки
#include <Adafruit_GFX.h>
#include <Adafruit_TFTLCD.h>
#include <TouchScreen.h>
//#include <SD.h>
//#include <SPI.h>

// Устанавливаем пины для тачскрина. Что куда - не знаю. Содрал))
#define YP A1  // must be an analog pin, use "An" notation!
#define XM A2  // must be an analog pin, use "An" notation!
#define YM 7   // can be a digital pin
#define XP 6   // can be a digital pin

// Устанавливаем диапазон считывания в омах наверно. Точно не скажу
#define TS_MINX 150
#define TS_MINY 120
#define TS_MAXX 920
#define TS_MAXY 940

// Устанавливаем цвета для элементов меню
#define BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define REDD    0xF422
#define GREEN   0x07E0
#define LGREEN  0x17E1
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF
#define PINK    0xF273
#define LGREY   0x836A
#define LLGREY  0xEED2
#define SPEC1   0x28E2
#define SPEC2   0x23F3
#define SPEC3   0x5273
#define SPEC4   0x0551 // Windows 98 default color
#define SPEC5   0x2A20


// Устанавливаем диапазон усилия нажатия на тачскрин
// For better pressure precision, we need to know the resistance
// between X+ and X- Use any multimeter to read it
// For the one we're using, its 300 ohms across the X plate
#define MINPRESSURE 1
#define MAXPRESSURE 1200

// Инициализируем дисплей
Adafruit_TFTLCD tft(A3, A2, A1, A0, A4);

// Инициализируем тачскрин
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);

// Флаг выбранного меню. Пока не используется, но смысл - понятен
int ms = 0;

// Объявляем переменные для обработки данных
unsigned long Tahometr_impulse_count;
float RPM;
unsigned long Check_time ;

void setup()
{

  // Serial.begin(9600);
  attachInterrupt(0, TahometrImpulse_on, FALLING);
  
  // запускаем экран
  tft.begin(0x9341);
  // переворачиваем на 90град. и заливаем черным цветом
  tft.setRotation((tft.getRotation() - 1));
  tft.fillScreen(BLACK);
  tft.setTextSize(3);
  tft.setTextColor(WHITE, BLACK);
  tft.setCursor(20, tft.height() - 50);
  tft.print("RPM: ");               //выводим строку 1

}


void loop()
{
  delay(1000);
  Calc_RPM();
  tft.setCursor(90, tft.height() - 50);
  tft.print(ToString(RPM));


}

//**********************************************************************
void Calc_RPM() {



  detachInterrupt(0);                    // запретили считать, на всякий случай, шоб не рыпался
  int Taho_ChekTime = millis() - Check_time;  // время между снятиями показаний счетчика
  if (Taho_ChekTime > 0)
  { // проверка на переполнение "милиса" ну вдруг больше  50 дней ))
    if (Tahometr_impulse_count > 0) // и  наличия насчитанных импульсов (на нолик делить не желательно.. будут запредельные значения в RPM)
    {
      RPM = ((float)Tahometr_impulse_count / ((float)Taho_ChekTime / 1000)) * 30; //подсчитываем среднее время периода, переводим в частоту, и приводим к об/минам уже деленым на 2
    }
    else
    {
      RPM = 0; // если нет импульсов за время измерений  то  RPM=0
    }
  }

  Tahometr_impulse_count = 0;  //сбросили счетчик.
  Check_time = millis();       // новое время
  attachInterrupt(0, TahometrImpulse_on, FALLING); // разрешили считать
}
//**********************************************************************

void  TahometrImpulse_on()
{
  Tahometr_impulse_count++;
}


String ToString(int i)
{
  String s =  String(i, DEC);
  while (s.length() < 6) s = s + " ";
  return s;
}

 

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

12я строчка ..

 

attachInterrupt(0, TahometrImpulse_on, FALLING);

 

На пин 0го прерывания подаются импульсы

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

Vad пишет:

12я строчка ..

 

attachInterrupt(0, TahometrImpulse_on, FALLING);

 

На пин 0го прерывания подаются импульсы

Эмм... А как это выглядит в реале? В смысле - в пинах платы "arduino"...

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

Я так понял что в "attachInterrupt(0, ..." , ноль - это номер вывода и есть. Это что-то типа: "AnalogRead(0, ....)", только как-то более хитро. Как именно - я еще не разобрался.

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

Ну... блин.. как... как дырочка..в пласмасске.. с контактом внутри..))

также, как и все пины))

Ну, а номер дырочки зависит от платформы.. которую вы применили..

http://arduino.ru/Reference/AttachInterrupt

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

Vad пишет:

Ну... блин.. как... как дырочка..в пласмасске.. с контактом внутри..))

также, как и все пины))

Ну, а номер дырочки зависит от платформы.. которую вы применили..

http://arduino.ru/Reference/AttachInterrupt

Да пофиг на платформу в моем случае: шилд лёг на все контакты. Так что выбор не большой: 1 аналоговый и 1 цифровой остались только. Правда можно еще один задействовать если кнопку "Reset" на шилде не использовать. Так что разгуляться есть где, собственно:

На один пин посажу сигнал с тахометра, на другой - пару DS18B20, на третий - не придумал еще. Могу так "Reset" и оставить. А скетч с большим числом строк, все равно, уже не влезет. Библиотеки жрут памяти нормально тоже.

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

как, нафиг, "пофиг"?

каждое прерывание ЖЕСТКО привязано к КОНКРЕТНОМУ пину

в зависимости от платформы...

ссылку читали? и ли опять "мимо"?

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

дубль

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

Vad пишет:

как, нафиг, "пофиг"?

каждое прерывание ЖЕСТКО привязано к КОНКРЕТНОМУ пину

в зависимости от платформы...

ссылку читали? и ли опять "мимо"?

Так... С этого места по подробней, если можно. Как это: "каждое прерывание ЖЕСТКО привязано к КОНКРЕТНОМУ пину" ? То есть номер прерывания и номер пина - не одно и тоже? Я подозреваю что не одно, но хотелось бы узнать, как считать прерывание с какого-то конкретного пина.

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

Так. Почитать ссылку-то я почитал, только бестолку.

А вот  - с толком:

Плата int.0 int.1 int.2 int.3 int.4 int.5
UNO, Ethernet 2 3        

Другими словами с UNO я могу считывать только 2 прерывания. На втором и третем пине. Блин.. А они - заняты, ска...

cezar.akkel
Offline
Зарегистрирован: 10.09.2016

С ардуино только начинаю знакомиться. Тоже решил сделать в авто тахометр. Из кода, приведенного уважаемым tbstdt понял практически все. Непонятными для меня остались только вот эти вычисления:

  {                         
44                   RPM=((float)Tahometr_impulse_count/((float)Taho_ChekTime/1000))*30;  //подсчитываем среднее время периода, переводим в частоту, и приводим к об/минам уже деленым на 2
45               }

Зачем мы делим на 1000? у нас задержка между подсчетами стоит 1 секунда (или нет?)

void loop()
24 {
25   delay(1000);  
26   Calc_RPM(); 

следовательно Taho_ChekTime будет равен 1000мс. Tahometr_impulse_count насчитает количество мпульсов в секунду, которые нужно умножить на 30. Итоговый код должен выйти (IMHO) такой:

RPM=((float)Tahometr_impulse_count)*30;

Поправьте меня, если я что то не так понял...

------------------

upd спустя два часа размышлений понял  - все правильно было изначально написано... Видимо пора повторить курс математики. Или выспаться.