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++;
}
В таком случае есть решение что называется в лоб. считаемые импульсы подаем прямо на вход таймера счетчика. Раз в пол секунды уходим в прерывание и считываем то, что там образовалось одновременно обнуляя содержимое счетчика для следующего подсчета, это число как раз будет соответствовать количеству оборотов в секунду умножаем его на 60 и получаем об/мин. Таким образом получается единица измерения или цена деления счетчика 1 = 60 об/мин, а погрешность в таком случае только половина от цены деления те 30 об/мин время выполнения всего этого расчета будет в пределах сотни-полутора тактов процессора примерно 0.001%, остальное же из 16 миллионовтактов остаются в полном расторяжении главной программы.
Код модифицировал, исправил формулу оборотов, обороты худо бедно считывает, плюс-минус 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); // разрешили считать
}
//*********************************************************************
я поковырял tvout.. использует и таймеры и прерывания... очень активно использует, там черт нугу сломит ))
так что .. скачики оборотов вполне могут быть из за того, что прерывание по тахометру должно случиться .. но.. проц находится в обработчике прерывания которое нужно tvout.. вот он и пропускает некоторые из импульсов ...
давайте попробуем выкинуть отключение прерываний у нас... должно немножко исправить ситуацию... но не думаю что сильно))
detachInterrupt 5
detachInterrupt 4
attachInterrupt 4
attachInterrupt 5
tvout прерывается 15625 раз в секунду.. только на синхронизацию... и еще по ~100 раз на формирование точек ... в каждой из 15625 строк...
Сколько в теории можно снять импульсов в секунду с Atmega8 с кварцом 16Мгц? Другими словами, максимальная частота какая? Наличие кварца на это влияет? Какая точность? Хочу сделать для мото тахометр, экран не нужен, будут светодиоды, каждые 500 оборотов, начиная с 1000, т.е. 1000, 1500, 2000... и до 7000. Нужно, как понимаю, 13 выходов для светодиодов, и один вход для снятия импульса с датчика холла, или с низкой стороны высоковольтного трансформатора. Откуда, кстати, проще или удобнее брать импульс? Двигатель четырёхтактный одноцилиндровый, кроссовый мот.
Можно ли это реализовать на Atmega8 (С кварцем или без? нужно максимум компактности) Если светодиод потребляет 15-20 мА, можно обойтись без усилителей, сразу припаяв к ноге контроллера через резистор? От 13 светодиодов микрухе плохо не станет?
Я правильно понимаю, что он работает как геркон, только с большей частотой переключения (меньшей инерционностью)? Тоесть подав на него питание, я смогу снять питание с него, если приближу к нему магнит? Можно его использовать в тахометре мотоцикла, поместив рядом со штатным датчиком Холла в системе зажигания? А то что-то не охота вмешиваться в штатную проводку.
P.S. А как работает система определения оборотов компьютерного куллера?
> Тоесть подав на него питание, я смогу снять питание с него, если приближу к нему магнит?
Ну точно на это ответить можно только найдя даташит на него. "Чисты датчик" - он еще усилителя требует (очень малые напряжения он выдает). Правда в описании вашего датчика говорится, что он "Цифровой выход 25 мА, совместим с цифровой логикой" что, я для себя перевел-бы как: "не партесь, усилитель у него уже внутри".
>P.S. А как работает система определения оборотов компьютерного куллера?
я незнаю можно ли подружить ардуино с обд портом _ компьютером, но если можно то проще будет сделать тахометр от обд типо такой бортовой компьютер, модно расход смотреть и всякую разную информацию. на обд раьеме воре один проводок отвечает за передачу данных
Вовсяком случае Дуину уже не раз сдружали с ELM-327 и через синезуб и через проволоку... и вот так Кто не верит спросите у гугля )) А там обороты можно уже не считать, они читаются или совсем по простому просятся через библиотеку ArduinoOBD .
> Тоесть подав на него питание, я смогу снять питание с него, если приближу к нему магнит?
Ну точно на это ответить можно только найдя даташит на него. "Чисты датчик" - он еще усилителя требует (очень малые напряжения он выдает). Правда в описании вашего датчика говорится, что он "Цифровой выход 25 мА, совместим с цифровой логикой" что, я для себя перевел-бы как: "не партесь, усилитель у него уже внутри".
>P.S. А как работает система определения оборотов компьютерного куллера?
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++;
}
пробуйте
Чёт не понял, что куда подключать в этом коде? Куда импульс подавать от зажигания? На пятый пин?
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++;
}
Вручную кнопку тыкал. Герца четыре было. Ща куллер взял от компа. Если на него подать напряжение на чёрный и красный провод, то при его вращении оставшийся желтый провод замыкается на минус два раза за оборот. Подключил его. По этой программе работает:
#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();
}
Но тут какие-то бешенные значения порой пролетают, и даже отрицательные.
А по Вашей проге нули показывает. Может оно и не будет работать на восьмой атмеге, зря мучаюсь?
импульсы разные бывают )) бывает 1 наносек.. бывает 1 сек..
откуда они?(устройство)
какой период у них..?
минимальная частота следования импульсов 2 герц
откуда 2 Гц? это же соответствует всего 60 об/мин, реально же минимальные обороты ДВС не меньше 300 а реальные ХХ у большинства авто находятся в пределах 750-950, а это уже порядка от 10 Гц минимально.
и кстати. у современных моторов обычно используют многоискровое зажигание, а это 2-4 импульса подряд для каждого рабочего хода.
Я не знаю под какую технику Вы считали. Но точно знаю, что если техника одно цилиндровая и четырёх тактная, то искра образуется каждый второй так, тоесть каждый оборот двигателя. Почему? Да потому, что в таких движках просто нет системы определения текущего такта. И это, в принципе, и не нужно. Так что один оборот - один импульс, одна искра, несмотря на четырёх тактность. И в рабочий такт искра, и на выхлопе тоже искра. По крайней мере на всей китайской технике так.
Так что не ошибитесь, кто длает для скутеров и им подобных.
Сижу туплю. Не погу просчитать погрешность измерения оборотов (максимальную) в диапазоне от 1000 до 8500. На атмеге 328 для двухтактного двтгателя, тоесть 1 оборот=1импульс.
Нужно очень точно и быстро (примерно за 0.1-0.15 сек)определять текущие обороты, для того, чтоб вводить отсечку двигателя.
Вообще, как думаете, электронное зажигание можно постороить на 328 атмеге? Если импульс приходит за 3мм до ВМТ с датчика холла, и сразу же образуется искра, то каково будет задержка, если посредником будет атмега? Просто в момент старта двигателя, при оборотах до ~800 хорошо бы вводить задержку на искру, тем самым делая зажигание поздним.
для максимальной скорости которая задана - 8500 об/мин = 142 оборотов или 51120 градусов в сек.
при 16 МГц. на каждый градус приходится 312 тактов. это значит что успеет выполниться в среднем программа длиной до 70++ комманд(считая в среднем 4 такта на комманду), что не так уж и мало, учитывая что на максимальных оборотах задержек вносить не требуется значит можем сразу запускать искру и выходить, я предполагаю что обработчик вполне уложится по времени в 0.2-0.5 градуса, а на меньших оборотах времени еще и на перекурить хватит.
И кроме того, если заведомо известно про возможную задержку, так поставь зажигание на полградусика раньше и время на обработку увеличится в некоторое число раз )))
И кроме того, если заведомо известно про возможную задержку, так поставь зажигание на полградусика раньше и время на обработку увеличится в некоторое число раз )))
Конструктивно не желательно. Сейчас на технике нет возможности регулировать угол опережения. Всё жестко вставлено в свои пазы и прикручено намертво. Изначально настроено на среднее значение. Можно, конечно, зубилом и напильником подшаманить, но это будет не обратимо.
А как выяснилось, УОЗ - это не статичная штука. На низких оборотах должно быть позднее, на средних, до ~3000 среднее, а на <3000 раннее, и чем выше обороты, тем более раннее. Связано с конкретным типом двигателя и с детонацией определённой марки топлива.
Но так сильно засирать мозг не собираюсь, попробую реализовать позднее на низких оборотах, чтоб отдачи в стартер или ногу небыло, и отсечку при 7500об\мин. Возможно, стоит продумать схему, при которой атмега переставала бы учавствовать в формировании искры. После того, как двигатель завёлся нужно переводить на штатную систему зажигания, которую просто блокировать при 7500 об\мин для отсечки.
Можно его использовать в тахометре мотоцикла, поместив рядом со штатным датчиком Холла в системе зажигания? А то что-то не охота вмешиваться в штатную проводку.
Я в похожих раздумьях, хочу попробовать снять количество оборотов с двигателя бензопилы.
С обработкой сигнала всё понятно, но как взять сигнал бесконтактно?
У китайцев есть интересное решение бесконтактных тахметров, тонкий изолированный одножильный провод, который выходит из тахометра, просто оборачивается в несколько витков вокруг высоковольтного провода.. И всё!
Нужно очень точно и быстро (примерно за 0.1-0.15 сек)определять текущие обороты, для того, чтоб вводить отсечку двигателя.
А куда спешить?
за 1-2-3 оборота КВ обороты не могут измениться на СТОЛЬКО, чтоб это стало критичным.
если мы на измерение и расчет оборотов израсходуем 2-3 оборота КВ - ничего не случится..
На меге, конечно.. можно сделать электронное зажигание))
почему нет?
у меня на старичке 89с2051 был собран электронный "табличный контроллер" УОЗ для ВАЗ 21093, с изменяемыми, загружаемыми таблицами опережения зажигания.. 10 лет отработал.. так с ним и продал))
хотел еще датчик детонации к нему прикрутить - тогда совсем было бы круто)) но не успел
Я, конечно, сильно извиняюсь, что поднимаю опять эту тему, но где видно из текста последнего поста, с какой ноги считывается сигнал ? Я что-то либо не дочитал, либо - недопонял.
Переделал под свой дисплей. Вроде ничего нигде не упустил:
// Объявляем библиотеки
#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;
}
Я так понял что в "attachInterrupt(0, ..." , ноль - это номер вывода и есть. Это что-то типа: "AnalogRead(0, ....)", только как-то более хитро. Как именно - я еще не разобрался.
Да пофиг на платформу в моем случае: шилд лёг на все контакты. Так что выбор не большой: 1 аналоговый и 1 цифровой остались только. Правда можно еще один задействовать если кнопку "Reset" на шилде не использовать. Так что разгуляться есть где, собственно:
На один пин посажу сигнал с тахометра, на другой - пару DS18B20, на третий - не придумал еще. Могу так "Reset" и оставить. А скетч с большим числом строк, все равно, уже не влезет. Библиотеки жрут памяти нормально тоже.
каждое прерывание ЖЕСТКО привязано к КОНКРЕТНОМУ пину
в зависимости от платформы...
ссылку читали? и ли опять "мимо"?
Так... С этого места по подробней, если можно. Как это: "каждое прерывание ЖЕСТКО привязано к КОНКРЕТНОМУ пину" ? То есть номер прерывания и номер пина - не одно и тоже? Я подозреваю что не одно, но хотелось бы узнать, как считать прерывание с какого-то конкретного пина.
Вернее даже не так. Считать с пина можно только значение потенциала, которое там возникло... Тогда - я совсем запутался. А что такое, собственно: "прерывание" ?
Так. Почитать ссылку-то я почитал, только бестолку.
А вот - с толком:
Плата
int.0
int.1
int.2
int.3
int.4
int.5
UNO, Ethernet
2
3
Другими словами с UNO я могу считывать только 2 прерывания. На втором и третем пине. Блин.. А они - заняты, ска...
С ардуино только начинаю знакомиться. Тоже решил сделать в авто тахометр. Из кода, приведенного уважаемым tbstdt понял практически все. Непонятными для меня остались только вот эти вычисления:
{
44
RPM=((float)Tahometr_impulse_count/((float)Taho_ChekTime/1000))*30; //подсчитываем среднее время периода, переводим в частоту, и приводим к об/минам уже деленым на 2
45
}
Зачем мы делим на 1000? у нас задержка между подсчетами стоит 1 секунда (или нет?)
voidloop()
24
{
25
delay(1000);
26
Calc_RPM();
следовательно Taho_ChekTime будет равен 1000мс. Tahometr_impulse_count насчитает количество мпульсов в секунду, которые нужно умножить на 30. Итоговый код должен выйти (IMHO) такой:
RPM=((float)Tahometr_impulse_count)*30;
Поправьте меня, если я что то не так понял...
------------------
upd спустя два часа размышлений понял - все правильно было изначально написано... Видимо пора повторить курс математики. Или выспаться.
пробуйте
Vad
Попробую.
Сие Ваше произведение?
да.. можно сказать мое.. ))
компиляция двух ваших ))
а с какой частотой и точностью тебе хотелось бы измерять обороты? например +- 50 об/мин на 3000 при измерении один-два раза в секунду устроит?
Probelzaelo
Думаю устроит.
Думаю устроит.
В таком случае есть решение что называется в лоб. считаемые импульсы подаем прямо на вход таймера счетчика. Раз в пол секунды уходим в прерывание и считываем то, что там образовалось одновременно обнуляя содержимое счетчика для следующего подсчета, это число как раз будет соответствовать количеству оборотов в секунду умножаем его на 60 и получаем об/мин. Таким образом получается единица измерения или цена деления счетчика 1 = 60 об/мин, а погрешность в таком случае только половина от цены деления те 30 об/мин время выполнения всего этого расчета будет в пределах сотни-полутора тактов процессора примерно 0.001%, остальное же из 16 миллионовтактов остаются в полном расторяжении главной программы.
я скеч выше положил )) он времянезависимый вообще..
сам расчет можно обрабатывать в любое свободное/удобное время
не чаще 100 раз в сек. но не реже 1 раза в 50 дней,
при опросе 2 раза в сек при 1000 об./мин получается разрешение около 3-6 об..мин
за счет усреднения последних N оборотов.. точность с 2мя знаками после запятой ))
PS
может ошибся в расчетах.. считал в уме.. и на пальцах ))
однако готовые решения прямо на поверхности
http://forum.arduino.cc/index.php?topic=108215.0
http://www.avdweb.nl/arduino/hardware-interfacing/frequency-period-count...
Вот видео работы скетча, параметр TAH на экране содержит значение оборотов двигателя, почему значения плавают...
http://www.youtube.com/watch?v=FgO0EObwMg0&feature=youtu.be
А можно весь ваш скеч...
я его погоняю у себя..
случаем tvout не использует таймеры..?
Я ниразу не пробовал ее руками... надо скачать посмотреть как устроена))
вобще формирование ПТС дело достаточно точное... и может вполне "отнимать" прерывания ... иначе. сбой синхронизации.. и поломаная картинка на экране..
щас скачаю.. посмотрю..
Скетч очень большой, но сейчас все функции в нем отключены и обрабатывается только
Calc_RPM_Speed()
Насчет таймеров не скажу, не знаю...
я поковырял tvout.. использует и таймеры и прерывания... очень активно использует, там черт нугу сломит ))
так что .. скачики оборотов вполне могут быть из за того, что прерывание по тахометру должно случиться .. но.. проц находится в обработчике прерывания которое нужно tvout.. вот он и пропускает некоторые из импульсов ...
давайте попробуем выкинуть отключение прерываний у нас... должно немножко исправить ситуацию... но не думаю что сильно))
detachInterrupt 5
detachInterrupt 4
attachInterrupt 4
attachInterrupt 5
tvout прерывается 15625 раз в секунду.. только на синхронизацию... и еще по ~100 раз на формирование точек ... в каждой из 15625 строк...
Попробую.
Также планирую использовать библиотеки:
#include <SPI.h>
#include <avr/wdt.h>
#include <SoftwareSerial.h>
Надеюсь они без прерываний...
У меня вопросы по железу.
Сколько в теории можно снять импульсов в секунду с Atmega8 с кварцом 16Мгц? Другими словами, максимальная частота какая? Наличие кварца на это влияет? Какая точность? Хочу сделать для мото тахометр, экран не нужен, будут светодиоды, каждые 500 оборотов, начиная с 1000, т.е. 1000, 1500, 2000... и до 7000. Нужно, как понимаю, 13 выходов для светодиодов, и один вход для снятия импульса с датчика холла, или с низкой стороны высоковольтного трансформатора. Откуда, кстати, проще или удобнее брать импульс? Двигатель четырёхтактный одноцилиндровый, кроссовый мот.
Можно ли это реализовать на Atmega8 (С кварцем или без? нужно максимум компактности) Если светодиод потребляет 15-20 мА, можно обойтись без усилителей, сразу припаяв к ноге контроллера через резистор? От 13 светодиодов микрухе плохо не станет?
приблизительно 8 миллионов импульсов в секунду с Atmega8 с кварцом 16Мгц
кварц влияет конечно ))
он же сердце..
на каждом "ударе сердца" - проверять прерывание
>Наличие кварца на это влияет?
Для точности - обязательно.
>Какая точность?
micros() идет с точностью 4ms. (это в доке написано).
>Нужно, как понимаю, 13 выходов для светодиодов
Не обязательно. Смотрите раздел програмирование, раздел "базовые и полезные знания" (74HC595).
>Если светодиод потребляет 15-20 мА, можно обойтись без усилителей, сразу припаяв к ноге контроллера через резистор
Можно. Опять-таки документации Цифровые выводы | Аппаратная платформа Arduino и даташите на камень четко отвечено какие токи можно брать с пина.
>От 13 светодиодов микрухе плохо не станет?
Открывайте даташит на камень и смотрите сколько тока можно взять "с одного пина", "суммарно с пинов одного порта", "суммарно со всех пинов".
Открыл для себя такую штуку - Датчик Холла А3144. http://arduino-lipetsk.ru/Detal39519506.html
Я правильно понимаю, что он работает как геркон, только с большей частотой переключения (меньшей инерционностью)? Тоесть подав на него питание, я смогу снять питание с него, если приближу к нему магнит? Можно его использовать в тахометре мотоцикла, поместив рядом со штатным датчиком Холла в системе зажигания? А то что-то не охота вмешиваться в штатную проводку.
P.S. А как работает система определения оборотов компьютерного куллера?
> Тоесть подав на него питание, я смогу снять питание с него, если приближу к нему магнит?
Ну точно на это ответить можно только найдя даташит на него. "Чисты датчик" - он еще усилителя требует (очень малые напряжения он выдает). Правда в описании вашего датчика говорится, что он "Цифровой выход 25 мА, совместим с цифровой логикой" что, я для себя перевел-бы как: "не партесь, усилитель у него уже внутри".
>P.S. А как работает система определения оборотов компьютерного куллера?
Общее представление о холе можно тут почитать http://easyelectronics.ru/datchik-xolla.html
Там и про комьютерные куллеры упоминается.
Вовсяком случае Дуину уже не раз сдружали с ELM-327 и через синезуб и через проволоку... и вот так Кто не верит спросите у гугля )) А там обороты можно уже не считать, они читаются или совсем по простому просятся через библиотеку ArduinoOBD .
http://www.youtube.com/watch?v=P_vt0CDVI8E
потому что ни кто не задавался целью их стабилизировать с высокой точностью в паспорте если сказано +-50, значит могут гулять +-50 ...
> Тоесть подав на него питание, я смогу снять питание с него, если приближу к нему магнит?
Ну точно на это ответить можно только найдя даташит на него. "Чисты датчик" - он еще усилителя требует (очень малые напряжения он выдает). Правда в описании вашего датчика говорится, что он "Цифровой выход 25 мА, совместим с цифровой логикой" что, я для себя перевел-бы как: "не партесь, усилитель у него уже внутри".
>P.S. А как работает система определения оборотов компьютерного куллера?
Общее представление о холе можно тут почитать http://easyelectronics.ru/datchik-xolla.html
Там и про комьютерные куллеры упоминается.
А какой тогда будет лучше для моей задачи? Посмотрел в Чип и Дип, много всяких. Что значит биполярные?
пробуйте
Чёт не понял, что куда подключать в этом коде? Куда импульс подавать от зажигания? На пятый пин?
Зачем нужен пин 12?
где там 5 пин?
подавать на 12 ессесно
Vad, у меня атмега8. Я заменил
на
и прерывания Interrupt(5) на Interrupt(0).
Но код что-то не работает. Выводит 0.00
Код такой получился:
а что на 2 пин подаешь?
а что на 2 пин подаешь?
Импульсы, которые считать нужно.
Пробовал минус подавать, подтянув к плюсу резистором. Не пошли данные. Потом подтянул к минусу и подавал плюс, тоже не заработало.
импульсы разные бывают )) бывает 1 наносек.. бывает 1 сек..
откуда они?(устройство)
какой период у них..?
минимальная частота следования импульсов 2 герц
Вручную кнопку тыкал. Герца четыре было. Ща куллер взял от компа. Если на него подать напряжение на чёрный и красный провод, то при его вращении оставшийся желтый провод замыкается на минус два раза за оборот. Подключил его. По этой программе работает:
Но тут какие-то бешенные значения порой пролетают, и даже отрицательные.
А по Вашей проге нули показывает. Может оно и не будет работать на восьмой атмеге, зря мучаюсь?
откуда они?(устройство)
какой период у них..?
минимальная частота следования импульсов 2 герц
откуда 2 Гц? это же соответствует всего 60 об/мин, реально же минимальные обороты ДВС не меньше 300 а реальные ХХ у большинства авто находятся в пределах 750-950, а это уже порядка от 10 Гц минимально.
и кстати. у современных моторов обычно используют многоискровое зажигание, а это 2-4 импульса подряд для каждого рабочего хода.
Я о коде скетча.. а не о двс
при 2х герцах он будет 0-1 показывать
Я не знаю под какую технику Вы считали. Но точно знаю, что если техника одно цилиндровая и четырёх тактная, то искра образуется каждый второй так, тоесть каждый оборот двигателя. Почему? Да потому, что в таких движках просто нет системы определения текущего такта. И это, в принципе, и не нужно. Так что один оборот - один импульс, одна искра, несмотря на четырёх тактность. И в рабочий такт искра, и на выхлопе тоже искра. По крайней мере на всей китайской технике так.
Так что не ошибитесь, кто длает для скутеров и им подобных.
на данный момент - вентилятор..))
и то ноль кажет
а считалось для 4ц движка.. читаните первую страницу
Сижу туплю. Не погу просчитать погрешность измерения оборотов (максимальную) в диапазоне от 1000 до 8500. На атмеге 328 для двухтактного двтгателя, тоесть 1 оборот=1импульс.
Нужно очень точно и быстро (примерно за 0.1-0.15 сек)определять текущие обороты, для того, чтоб вводить отсечку двигателя.
Вообще, как думаете, электронное зажигание можно постороить на 328 атмеге? Если импульс приходит за 3мм до ВМТ с датчика холла, и сразу же образуется искра, то каково будет задержка, если посредником будет атмега? Просто в момент старта двигателя, при оборотах до ~800 хорошо бы вводить задержку на искру, тем самым делая зажигание поздним.
Ну давай посчитаем в лоб.
для максимальной скорости которая задана - 8500 об/мин = 142 оборотов или 51120 градусов в сек.
при 16 МГц. на каждый градус приходится 312 тактов. это значит что успеет выполниться в среднем программа длиной до 70++ комманд(считая в среднем 4 такта на комманду), что не так уж и мало, учитывая что на максимальных оборотах задержек вносить не требуется значит можем сразу запускать искру и выходить, я предполагаю что обработчик вполне уложится по времени в 0.2-0.5 градуса, а на меньших оборотах времени еще и на перекурить хватит.
И кроме того, если заведомо известно про возможную задержку, так поставь зажигание на полградусика раньше и время на обработку увеличится в некоторое число раз )))
И кроме того, если заведомо известно про возможную задержку, так поставь зажигание на полградусика раньше и время на обработку увеличится в некоторое число раз )))
Конструктивно не желательно. Сейчас на технике нет возможности регулировать угол опережения. Всё жестко вставлено в свои пазы и прикручено намертво. Изначально настроено на среднее значение. Можно, конечно, зубилом и напильником подшаманить, но это будет не обратимо.
А как выяснилось, УОЗ - это не статичная штука. На низких оборотах должно быть позднее, на средних, до ~3000 среднее, а на <3000 раннее, и чем выше обороты, тем более раннее. Связано с конкретным типом двигателя и с детонацией определённой марки топлива.
Но так сильно засирать мозг не собираюсь, попробую реализовать позднее на низких оборотах, чтоб отдачи в стартер или ногу небыло, и отсечку при 7500об\мин. Возможно, стоит продумать схему, при которой атмега переставала бы учавствовать в формировании искры. После того, как двигатель завёлся нужно переводить на штатную систему зажигания, которую просто блокировать при 7500 об\мин для отсечки.
P.S. Это одноциллиндровый 400 кубовый китаец.
Я в похожих раздумьях, хочу попробовать снять количество оборотов с двигателя бензопилы.
С обработкой сигнала всё понятно, но как взять сигнал бесконтактно?
У китайцев есть интересное решение бесконтактных тахметров, тонкий изолированный одножильный провод, который выходит из тахометра, просто оборачивается в несколько витков вокруг высоковольтного провода.. И всё!
http://ru.aliexpress.com/item/New-hot-Hour-meter-Tachometer-2-4-Stroke-Engine-Spark-For-Boat-Motorcycle-Bike-12V-CAR/2046063868.html
Я так понимаю, наводки, которая возникает при искровом разряде, хватает, чтобы бесконтактно считать сигнал!
У кого какие мысли, как правильно согласовать с Иной этот провод, обернутый вокруг изолированного высоковольтного повода ДВС?
А куда спешить?
за 1-2-3 оборота КВ обороты не могут измениться на СТОЛЬКО, чтоб это стало критичным.
если мы на измерение и расчет оборотов израсходуем 2-3 оборота КВ - ничего не случится..
На меге, конечно.. можно сделать электронное зажигание))
почему нет?
у меня на старичке 89с2051 был собран электронный "табличный контроллер" УОЗ для ВАЗ 21093, с изменяемыми, загружаемыми таблицами опережения зажигания.. 10 лет отработал.. так с ним и продал))
хотел еще датчик детонации к нему прикрутить - тогда совсем было бы круто)) но не успел
У кого какие мысли, как правильно согласовать с Иной этот провод, обернутый вокруг изолированного высоковольтного повода ДВС?
вплоть до того, что ногу меги защитить двумя диодами шотки и резистором... и ее прямо обмотать вокруг ВВ проовода
Вот мой код, собранный из того что было раньше, который вполне работает и выводит обороты на дисплей. Сегодня проверял.
Я, конечно, сильно извиняюсь, что поднимаю опять эту тему, но где видно из текста последнего поста, с какой ноги считывается сигнал ? Я что-то либо не дочитал, либо - недопонял.
Переделал под свой дисплей. Вроде ничего нигде не упустил:
12я строчка ..
attachInterrupt(0, TahometrImpulse_on, FALLING);
На пин 0го прерывания подаются импульсы
12я строчка ..
attachInterrupt(0, TahometrImpulse_on, FALLING);
На пин 0го прерывания подаются импульсы
Эмм... А как это выглядит в реале? В смысле - в пинах платы "arduino"...
Я так понял что в "attachInterrupt(0, ..." , ноль - это номер вывода и есть. Это что-то типа: "AnalogRead(0, ....)", только как-то более хитро. Как именно - я еще не разобрался.
Ну... блин.. как... как дырочка..в пласмасске.. с контактом внутри..))
также, как и все пины))
Ну, а номер дырочки зависит от платформы.. которую вы применили..
http://arduino.ru/Reference/AttachInterrupt
Ну... блин.. как... как дырочка..в пласмасске.. с контактом внутри..))
также, как и все пины))
Ну, а номер дырочки зависит от платформы.. которую вы применили..
http://arduino.ru/Reference/AttachInterrupt
Да пофиг на платформу в моем случае: шилд лёг на все контакты. Так что выбор не большой: 1 аналоговый и 1 цифровой остались только. Правда можно еще один задействовать если кнопку "Reset" на шилде не использовать. Так что разгуляться есть где, собственно:
На один пин посажу сигнал с тахометра, на другой - пару DS18B20, на третий - не придумал еще. Могу так "Reset" и оставить. А скетч с большим числом строк, все равно, уже не влезет. Библиотеки жрут памяти нормально тоже.
как, нафиг, "пофиг"?
каждое прерывание ЖЕСТКО привязано к КОНКРЕТНОМУ пину
в зависимости от платформы...
ссылку читали? и ли опять "мимо"?
дубль
как, нафиг, "пофиг"?
каждое прерывание ЖЕСТКО привязано к КОНКРЕТНОМУ пину
в зависимости от платформы...
ссылку читали? и ли опять "мимо"?
Так... С этого места по подробней, если можно. Как это: "каждое прерывание ЖЕСТКО привязано к КОНКРЕТНОМУ пину" ? То есть номер прерывания и номер пина - не одно и тоже? Я подозреваю что не одно, но хотелось бы узнать, как считать прерывание с какого-то конкретного пина.
Вернее даже не так. Считать с пина можно только значение потенциала, которое там возникло... Тогда - я совсем запутался. А что такое, собственно: "прерывание" ?
Так. Почитать ссылку-то я почитал, только бестолку.
А вот - с толком:
Другими словами с UNO я могу считывать только 2 прерывания. На втором и третем пине. Блин.. А они - заняты, ска...
С ардуино только начинаю знакомиться. Тоже решил сделать в авто тахометр. Из кода, приведенного уважаемым 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 спустя два часа размышлений понял - все правильно было изначально написано... Видимо пора повторить курс математики. Или выспаться.