Как посчитать количество импульсов на цифровом порту

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

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

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

А можно посчитать время между 10 импульсов или 100. millis() и в подобном поможет и усреднит.

Сохранили время 1 импульса, а потом 101. Разницу на 100. Вот вам и длительность импульсов.

elbugs
Offline
Зарегистрирован: 02.09.2016

Привет всем я прибыл из больницы. Пока лазил мерял импульсы увидел что фрион уходит потихоньку. Завтра займусь утечкой. 

Потом попробую вот эти скетчи от evgta.

#include <Wire.h>               //Библиотека для работы с I2C
#include <LiquidCrystal_I2C.h>  //Библиотека для работы с экраном
LiquidCrystal_I2C lcd(0x27,16,2);  // Устанавливаем дисплей
long yyy = 0;
long zzz = 0; 
int xxx;
void setup() 
{
 pinMode(2, INPUT);
 lcd.begin();                     
  lcd.backlight();// Включаем подсветку дисплея 
}
void loop() 
{   
     zzz=0;
    for(xxx=0; xxx<20; xxx++)
    {
    yyy = pulseIn(2, LOW);
     yyy=yyy*2;
     yyy=1000000/yyy;
     yyy=yyy*60;
     yyy=yyy/108; 
    zzz =zzz+yyy;
    }
   zzz=zzz/20;
   lcd.print("RPM=");
  lcd.print(zzz);
} 

И вот этот

 

#include <Wire.h>               //Библиотека для работы с I2C
#include <LiquidCrystal_I2C.h>  //Библиотека для работы с экраном
LiquidCrystal_I2C lcd(0x27,16,2);  // Устанавливаем дисплей
unsigned long xxx = 0;
unsigned long yyy = 0; 
unsigned long zzz=0;
 
 
void setup() {
pinMode(2, INPUT);
 lcd.begin();                     
  lcd.backlight();// Включаем подсветку дисплея 
 detachInterrupt(0);
}
 
 
 
void loop() 
{
  lcd.print("RPM=");
  lcd.print(zzz);
   attachInterrupt(0, RPM, FALLING);
     zzz=0;
     for(xxx=micros(); yyy<100000; yyy=micros()-xxx){  }
   detachInterrupt(0);
zzz=(zzz*600)/108; 
}
 
void RPM ()
{                                   
zzz++;
}

Как оттестю сообщу

elbugs
Offline
Зарегистрирован: 02.09.2016

Сегодня собрал тестовый макет с оптроном. 

На оптрон подал синус от генератора импульсов (пробовал разные частоты)

скетч ниже 

#include <Wire.h>               //Библиотека для работы с I2C
#include <LiquidCrystal_I2C.h>  //Библиотека для работы с экраном
LiquidCrystal_I2C lcd(63,16,2);  // Устанавливаем дисплей
unsigned long xxx = 0;
unsigned long yyy = 0; 
unsigned long zzz=0;
 
 
void setup() {
pinMode(2, INPUT);
 lcd.begin();                     
  lcd.backlight();// Включаем подсветку дисплея 
 detachInterrupt(0);
}
 
 
 
void loop() 
{
    lcd.setCursor(0, 0);
    lcd.println(zzz);
    lcd.clear();
   attachInterrupt(0, RPM, FALLING);
     zzz=0;
     for(xxx=micros(); yyy<100000; yyy=micros()-xxx){  }
   detachInterrupt(0);
zzz=(zzz*600)/108; 
}
 
void RPM ()
{                                   
zzz++;
}

Т.к. компа нет прилипил экран 1602 по i2c

Прошил запускаю а на экране пишет что то непонятное например 5ХХ и такое чувство что не обновляется. Вместо иксов еще палочки какае то.

Не пойму чего за беда.

Осцилом мерил синус на 4-ю ногу микрухи приходит +5 - 0 В.

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Ну у меня 2 замечания.

1

  lcd.setCursor(0, 0);
    lcd.println(zzz);
    lcd.clear();

не заменить на это

    lcd.clear();
    lcd.println(zzz);

И где 

unsigned long zzz=0;

Слово volatile http://robocraft.ru/blog/arduino/45.html

ПС: И наконец. Мы ж все таки находимся не в Зазеркалье. Это Алисе надо было сначало раздать зазеркальный пирог, а потом разрезать. То есть вывод на экран zzz надо после а не до его нахождения.

ВН
Offline
Зарегистрирован: 25.02.2016

ххх

 

elbugs
Offline
Зарегистрирован: 02.09.2016

qwone пишет:

Ну у меня 2 замечания.

1

  lcd.setCursor(0, 0);
    lcd.println(zzz);
    lcd.clear();

не заменить на это

    lcd.clear();
    lcd.println(zzz);

И где 

unsigned long zzz=0;

Слово volatile http://robocraft.ru/blog/arduino/45.html

ПС: И наконец. Мы ж все таки находимся не в Зазеркалье. Это Алисе надо было сначало раздать зазеркальный пирог, а потом разрезать. То есть вывод на экран zzz надо после а не до его нахождения.

Вот подкорректировал. Сегодня попробую

#include <Wire.h>               //Библиотека для работы с I2C
#include <LiquidCrystal_I2C.h>  //Библиотека для работы с экраном
LiquidCrystal_I2C lcd(63,16,2);  // Устанавливаем дисплей
unsigned long xxx = 0;
unsigned long yyy = 0; 
volatile unsigned long zzz=0;
 
 
void setup() {
pinMode(2, INPUT);
 lcd.begin();                     
  lcd.backlight();// Включаем подсветку дисплея 
 detachInterrupt(0);
}
 
 
 
void loop() 
{
     attachInterrupt(0, RPM, FALLING);
     zzz=0;
     for(xxx=micros(); yyy<100000; yyy=micros()-xxx){  }
   detachInterrupt(0);
zzz=(zzz*600)/108; 
lcd.clear();
lcd.println(zzz);
}
 
void RPM ()
{                                   
zzz++;
}

 

evgta
Offline
Зарегистрирован: 02.09.2016

Lcd так быстро обновлять неумеет, ему время надо, так что лучше паузу делеем пока сделать перед или после вывода на экран. В цикле прерывания сначало его отключить, дать +1, паузу в 1/6 периода(для макс рботротов), включить прерывание. Это в симуляторах все стабильно, а в жизни все печально.

Оптопара резисторами с обоих сторон притянута?

nik182
Offline
Зарегистрирован: 04.05.2015

А почему не так:

#include <Wire.h>               //Библиотека для работы с I2C
#include <LiquidCrystal_I2C.h>  //Библиотека для работы с экраном
LiquidCrystal_I2C lcd(63,16,2);  // Устанавливаем дисплей
unsigned long xxx = 0;
unsigned long yyy = 0; 
unsigned long timo,zzz1; 
volatile unsigned long zzz=0;
 
 
void setup() {
  pinMode(2, INPUT);
  lcd.begin();           
  lcd.clear();          
  lcd.backlight();// Включаем подсветку дисплея 

  zzz=0;
  timo=millis();
  attachInterrupt(0, RPM, FALLING);
}
 
void loop() 
 {
   while((millis()-timo) < 1000) ;   
   noInterrupts();
   zzz1=zzz;
   zzz=0;  
   interrupts();
   timo=millis();  
   zzz1=(zzz*60)/108; 
   lcd.setCursor(0,0);
   lcd.print(zzz1);
   lcd.print("      ");
 }
 
void RPM ()
{                                   
 zzz++;
}

?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

nik182 эпиграф "Скорая помощь так спешила, что еще двух придавила". Если вы пытаетесь помогать новичкам, то хотя бы не вставляейте в свой код новых багов. Это не к вам лично а вообще.

А теперь к вам.

zzz1=zzz;
zzz=0;  
//  
zzz1=(zzz*60)/108; 

 

nik182
Offline
Зарегистрирован: 04.05.2015

Ok. Согласен. Баг. Вместо zzz надо zzz1. Каюсь. Правил чужой код, не все zzz поправил. Но при чем здесь скорая помощь? К алгоритму притензии есть? Я не писал готовый код для новичка. Притензии к багам принимаются в другом разделе, где пишут за деньги. Такой баг хорошая тренировка новичку - найди ошибку. Првада я это не специально :-) Так получилось.

Ну а по сути. Clear очень долгая операция на многих LCD. Поэтому надо ставить задержку после clear, или использовать setcursor, иначе может быть глюк на выводе или неприятное мерцание. Но тогда надо подчищаить за print. Детачить интерапт  - терять импульсы. За секунду усредниться лучше, чем 100 мс.  

evgta
Offline
Зарегистрирован: 02.09.2016

Детатачить интерупт потому как сигнал может быть неидеальным и при переходе с low на high может быть несколько прерываний в одном периоде датчика

nik182
Offline
Зарегистрирован: 04.05.2015

А в остальное время он идеален и только во время детача дурит? Как я понимаю 108 - это количество зубцов датчика на оборот и zzz снимается случайным образом? Вообще , если датчик не идеален, то внутри прерывания нужно поставить задержку на время дребезга - ну хоть бы простой пустой цикл for с количеством циклов по времени превышающий дребезг, но меньшем ,чем период следования импульсов при максимальной скорости врашения. Перед выходом из прерывания чистить флаг прерывания. Гарантировано ошибок не будет. 

elbugs
Offline
Зарегистрирован: 02.09.2016

Раз 20 шил микрухи разными вариантами. 

Вот этот работает на ура. Вопрос только не зависнет ли контроллер через какое то количество часов????

#include <Wire.h>               //Библиотека для работы с I2C
#include <LiquidCrystal_I2C.h>  //Библиотека для работы с экраном
LiquidCrystal_I2C lcd(63,16,2);  // Устанавливаем дисплей
unsigned long xxx = 0;
unsigned long yyy = 0; 
volatile unsigned long zzz=0;
 
 
void setup() {
pinMode(2, INPUT);
Serial.begin(9600);
 lcd.begin();                     
  lcd.backlight();// Включаем подсветку дисплея 
 attachInterrupt(0, RPM, FALLING); 
}
 
 
 
void loop() 
{
 delay(1000);    

     for(xxx=micros(); yyy<100000; yyy=micros()-xxx){  }
   detachInterrupt(0);
zzz=(zzz*60)/108; 
lcd.clear();
lcd.print(zzz);
zzz=0;
attachInterrupt(0, RPM, FALLING);
}
 
void RPM ()
{                                   
zzz++;
}

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

evgta
Offline
Зарегистрирован: 02.09.2016

Странно
Может всетаки delay(1000); поставить после zzz=0, так правильней должно быть.

А с чего ему виснуть? Правда по авр незнаю но пики у меня не висли никогда, проц может только в бесконечный цикл уйти, но это косяки софта

elbugs
Offline
Зарегистрирован: 02.09.2016

nik182 пишет:

Ok. Согласен. Баг. Вместо zzz надо zzz1. Каюсь. Правил чужой код, не все zzz поправил. Но при чем здесь скорая помощь? К алгоритму притензии есть? Я не писал готовый код для новичка. Притензии к багам принимаются в другом разделе, где пишут за деньги. Такой баг хорошая тренировка новичку - найди ошибку. Првада я это не специально :-) Так получилось.

Ну а по сути. Clear очень долгая операция на многих LCD. Поэтому надо ставить задержку после clear, или использовать setcursor, иначе может быть глюк на выводе или неприятное мерцание. Но тогда надо подчищаить за print. Детачить интерапт  - терять импульсы. За секунду усредниться лучше, чем 100 мс.  

Ваш скетч исправил и проверил обороты кажет четко. 

#include <Wire.h>               //Библиотека для работы с I2C
#include <LiquidCrystal_I2C.h>  //Библиотека для работы с экраном
LiquidCrystal_I2C lcd(63,16,2);  // Устанавливаем дисплей
unsigned long xxx = 0;
unsigned long yyy = 0; 
unsigned long timo,zzz1; 
volatile unsigned long zzz=0;
 
 
void setup() {
  pinMode(2, INPUT);
  lcd.begin();           
  lcd.clear();          
  lcd.backlight();// Включаем подсветку дисплея 

  zzz=0;
  timo=millis();
  attachInterrupt(0, RPM, FALLING);
}
 
void loop() 
 {
   while((millis()-timo) < 1000) ;   
   noInterrupts();
   zzz1=zzz;
   zzz=0;  
   interrupts();
   timo=millis();  
   zzz1=(zzz1*60)/108; 
   lcd.setCursor(0,0);
   lcd.print(zzz1);
   lcd.print("      ");
 }
 
void RPM ()
{                                   
 zzz++;
}

Вопрос тот же не будет ли проблем с зависанием через определенное количество часов???

nik182
Offline
Зарегистрирован: 04.05.2015

evgta пишет:
Странно Может всетаки delay(1000); поставить после zzz=0, так правильней должно быть. А с чего ему виснуть? Правда по авр незнаю но пики у меня не висли никогда, проц может только в бесконечный цикл уйти, но это косяки софта

Почему правильно после zzz=0?

elbugs
Offline
Зарегистрирован: 02.09.2016

evgta пишет:
Странно Может всетаки delay(1000); поставить после zzz=0, так правильней должно быть. А с чего ему виснуть? Правда по авр незнаю но пики у меня не висли никогда, проц может только в бесконечный цикл уйти, но это косяки софта

Проверил кстати и Ваш скетч тот что с pulsin. Обороты показывает но не правильно. Меньше чем нужно. должен показать 556 а показывает 184. 

Не подскажите с чем связано??? 

Ниже скетч который тестил

#include <Wire.h>               //Библиотека для работы с I2C
#include <LiquidCrystal_I2C.h>  //Библиотека для работы с экраном
LiquidCrystal_I2C lcd(63,16,2);  // Устанавливаем дисплей
long yyy = 0;
long zzz = 0; 
int xxx;
void setup() 
{
 pinMode(2, INPUT);
 lcd.begin();                     
  lcd.backlight();// Включаем подсветку дисплея 
}
void loop() 
{   
     zzz=0;
    for(xxx=0; xxx<20; xxx++)
    {
    yyy = pulseIn(2, LOW);
     yyy=yyy*2;
     yyy=1000000/yyy;
     yyy=yyy*60;
     yyy=yyy/108; 
    zzz =zzz+yyy;
    }
   zzz=zzz/20;
   lcd.clear();
   lcd.print("RPM=");
   lcd.setCursor(5,0);
  lcd.print(zzz);
} 

 

elbugs
Offline
Зарегистрирован: 02.09.2016

elbugs пишет:

evgta пишет:
Странно Может всетаки delay(1000); поставить после zzz=0, так правильней должно быть. А с чего ему виснуть? Правда по авр незнаю но пики у меня не висли никогда, проц может только в бесконечный цикл уйти, но это косяки софта

Проверил кстати и Ваш скетч тот что с pulsin. Обороты показывает но не правильно. Меньше чем нужно. должен показать 556 а показывает 184. 

Не подскажите с чем связано??? 

Ниже скетч который тестил

#include <Wire.h>               //Библиотека для работы с I2C
#include <LiquidCrystal_I2C.h>  //Библиотека для работы с экраном
LiquidCrystal_I2C lcd(63,16,2);  // Устанавливаем дисплей
long yyy = 0;
long zzz = 0; 
int xxx;
void setup() 
{
 pinMode(2, INPUT);
 lcd.begin();                     
  lcd.backlight();// Включаем подсветку дисплея 
}
void loop() 
{   
     zzz=0;
    for(xxx=0; xxx<20; xxx++)
    {
    yyy = pulseIn(2, LOW);
     yyy=yyy*2;
     yyy=1000000/yyy;
     yyy=yyy*60;
     yyy=yyy/108; 
    zzz =zzz+yyy;
    }
   zzz=zzz/20;
   lcd.clear();
   lcd.print("RPM=");
   lcd.setCursor(5,0);
  lcd.print(zzz);
} 

 

Да и показания мерцают почтоянно

nik182
Offline
Зарегистрирован: 04.05.2015

Чисто с программной точки зрения зависать нечему. Другое дело разные электрические наводки и прочие прочие обстоятельства непреодолимой силы. Добавте вачдог таймер на время чуть больше секунды и обнуляйте его в конце цикла. При любом зависании потеря информации будет не больше секунды.

evgta
Offline
Зарегистрирован: 02.09.2016

Нечего паузе делать когда прерывание активно,

evgta
Offline
Зарегистрирован: 02.09.2016

Делей добавить после принта надо , lcd дисплей очень медленные и быстро обновляться неумеют. Это к 69 посту

А заниженные показания скорее всего потому что hi в low переходит при значении 2.5 вольта а там время между точками полупериода меньше , корректировку в значение yyy после pulsein внесите

nik182
Offline
Зарегистрирован: 04.05.2015

Вау! Новое в искустве програмирования! Раньше было процессор спал или висел в паузе пока активное прерывание работало. Новое веяние - прерывание активно - пауза запрещена. А что программе делать то? Ей же как то надо ждать 1 секунду, пока данные соберуться? Вывод на экран занимает несколько десятков милисекунд. 

evgta
Offline
Зарегистрирован: 02.09.2016

А что разве вызов прерывания в прцессе делей идет? Или только после того как делей закончится?

nik182
Offline
Зарегистрирован: 04.05.2015

Занижение показаний из за того, что функция pulseIn считает нахождение датчика в состоянии LOW. Если скважность сигнала датчика не 50% то нужно вводить коэффициент, либо считать один раз LOW, один раз HIGH и брать среднее. Измеряться будет быстро, за 2 зуба датчика но будет сильно плавать из за неоднородности зубов датчика. В случае использования накопления оборотов за секунду все неоднородности сигнала датчика усредняются. В предложенном мною алгоритме не теряются импульсы и точно выдерживается интервал измерения. Паузы отсутстствуют и у процессора есть целая секунда, когда он может спокойно выводить на экран или передавать куда нибудь текущую информацию. Мне кажется, что для мотора 1 секунда это не критичное время из-за инерции.

nik182
Offline
Зарегистрирован: 04.05.2015

evgta пишет:
А что разве вызов прерывания в прцессе делей идет? Или только после того как делей закончится?

Делей не нужен. Вообще он идёт, если другое прерывание занимает меньше 4 микросекунд. Если больше, то идет медленне, во столько раз сколько время кратно четырём микросекндам. Здесь прерывание со всеми накладными расходами около микросекунды. Никаких ограничений на делей. Но делей в данном случае зло. Если его использовать для задачи интервала, то нужно прибавлять время других команд. Прочитайте тему blink без delay.   Другим прерываниям делей не мешает.

evgta
Offline
Зарегистрирован: 02.09.2016

Как сделать блинк без делей понятно.
В пикбейсике, если идет делей то при вызове прерывания ствится флаг и вызов функции прерывания произойдет только после того как делей будет завершен, здесь так же или нет ?

nik182
Offline
Зарегистрирован: 04.05.2015

Странно. Пикбейсик не знаю. С пиками работал в MPLAB. Там никаких ограничений на прерывания во время делей не было. Но и делей всегда там писал сам. Вообще ни разу не встречал такого. Сама идея микроконтроллера противоречит такому поведению. Прерывания глобально запрещены на время прерывания. Делей не является прерыванием. Это обычная подпрограмма.  

evgta
Offline
Зарегистрирован: 02.09.2016

Хотя может чего уже и путаю, давно было.

evgta
Offline
Зарегистрирован: 02.09.2016

elbugs пишет:

elbugs пишет:

evgta пишет:
Странно Может всетаки delay(1000); поставить после zzz=0, так правильней должно быть. А с чего ему виснуть? Правда по авр незнаю но пики у меня не висли никогда, проц может только в бесконечный цикл уйти, но это косяки софта

Проверил кстати и Ваш скетч тот что с pulsin. Обороты показывает но не правильно. Меньше чем нужно. должен показать 556 а показывает 184. 

Не подскажите с чем связано??? 

Ниже скетч который тестил

#include <Wire.h>               //Библиотека для работы с I2C
#include <LiquidCrystal_I2C.h>  //Библиотека для работы с экраном
LiquidCrystal_I2C lcd(63,16,2);  // Устанавливаем дисплей
long fff =0;
long yyy = 0;
long zzz = 0; 
int xxx;
void setup() 
{
 pinMode(2, INPUT);
 lcd.begin();                     
  lcd.backlight();// Включаем подсветку дисплея 
}
void loop() 
{   
     zzz=0;
    for(xxx=0; xxx<20; xxx++)
    {
    yyy = pulseIn(2, LOW);
    fff=pulseIn(2, HIGH);
yyy=yyy+fff;
 
     yyy=1000000/yyy;
     yyy=yyy*60;
     yyy=yyy/108; 
    zzz =zzz+yyy;
    }
   zzz=zzz/20;
   lcd.clear();
   lcd.print("RPM=");
   lcd.setCursor(5,0);
  lcd.print(zzz);
delay (1000);
} 

 

Да и показания мерцают почтоянно

Вот так посмотрите

nik182
Offline
Зарегистрирован: 04.05.2015

Уже лучше будет. Сейчас вы усреднили примерно 70 из 108 зубов (почему догадаетесь?), т.е. цикл крутится примерно 2/3 секунды. Будет мерцать реже, но будет, потому что clear. Потом секунду будет спать, ничего не делать. Вопрос зачем? 

evgta
Offline
Зарегистрирован: 02.09.2016

nik182 пишет:

Уже лучше будет. Сейчас вы усреднили примерно 70 из 108 зубов (почему догадаетесь?), т.е. цикл крутится примерно 2/3 секунды. Будет мерцать реже, но будет, потому что clear. Потом секунду будет спать, ничего не делать. Вопрос зачем? 

2/3 оборота скорее

Вопрос был в том как считать обороты, а о выводе на лцд не ставился, делей просто чтобы реже моргало

nik182
Offline
Зарегистрирован: 04.05.2015

Да и считать обороты при стоящим моторе не получится. Первое значение 0 на дисплее появится через 72 минуты.

evgta
Offline
Зарегистрирован: 02.09.2016

nik182 пишет:

Да и считать обороты при стоящим моторе не получится. Первое значение 0 на дисплее появится через 72 минуты.

По умолчанию секунда, знчит через 40 секунд , а так да yyy=pulseIn(2,LOW,100000) как-то так наверное

evgta
Offline
Зарегистрирован: 02.09.2016

nik182 пишет:

Да и считать обороты при стоящим моторе не получится. Первое значение 0 на дисплее появится через 72 минуты.

По умолчанию секунда, знчит через 40 секунд , а так да yyy=pulseIn(2,LOW,100000) как-то так наверное

evgta
Offline
Зарегистрирован: 02.09.2016

nik182 пишет:

Да и считать обороты при стоящим моторе не получится. Первое значение 0 на дисплее появится через 72 минуты.

По умолчанию секунда, знчит через 40 секунд , а так да yyy=pulseIn(2,LOW,20000) как-то так наверное

elbugs
Offline
Зарегистрирован: 02.09.2016

evgta пишет:
elbugs пишет:

elbugs пишет:

evgta пишет:
Странно Может всетаки delay(1000); поставить после zzz=0, так правильней должно быть. А с чего ему виснуть? Правда по авр незнаю но пики у меня не висли никогда, проц может только в бесконечный цикл уйти, но это косяки софта

Проверил кстати и Ваш скетч тот что с pulsin. Обороты показывает но не правильно. Меньше чем нужно. должен показать 556 а показывает 184. 

Не подскажите с чем связано??? 

Ниже скетч который тестил

#include <Wire.h>               //Библиотека для работы с I2C
#include <LiquidCrystal_I2C.h>  //Библиотека для работы с экраном
LiquidCrystal_I2C lcd(63,16,2);  // Устанавливаем дисплей
long fff =0;
long yyy = 0;
long zzz = 0; 
int xxx;
void setup() 
{
 pinMode(2, INPUT);
 lcd.begin();                     
  lcd.backlight();// Включаем подсветку дисплея 
}
void loop() 
{   
     zzz=0;
    for(xxx=0; xxx<20; xxx++)
    {
    yyy = pulseIn(2, LOW);
    fff=pulseIn(2, HIGH);
yyy=yyy+fff;
 
     yyy=1000000/yyy;
     yyy=yyy*60;
     yyy=yyy/108; 
    zzz =zzz+yyy;
    }
   zzz=zzz/20;
   lcd.clear();
   lcd.print("RPM=");
   lcd.setCursor(5,0);
  lcd.print(zzz);
delay (1000);
} 

 

Да и показания мерцают почтоянно

Вот так посмотрите

Работает спасибо. Единственно при пока нет импульсов RPM показывает 27. и после того как импульсы пропадают обороты не сразу падают а только по прошествии примерно 1 сек опять же до 27 об/мин

elbugs
Offline
Зарегистрирован: 02.09.2016

Кстати что на прерываниях что на пульсине при подключении сигнала через оптопару обороты не показывают. Дотрагиваешся осцилографом до 4-й ноги чтобы посмотреть идет ли сигнал и сразу начинает показывать.

Непойму что за глюк. При этом показывает при частоте импульсов до 2кГц. Если подаеш больше показывает 0.

Непойму что за глюк.

evgta
Offline
Зарегистрирован: 02.09.2016

 

мне кажется что датчик вот так надо подключать, стабилитрон на 4,7в, конденсатор неполярный керамический

 

evgta
Offline
Зарегистрирован: 02.09.2016

elbugs пишет:

Не подскажите с чем связано??? 

Ниже скетч который тестил



1
 
#include <Wire.h>               //Библиотека для работы с I2C
#include <LiquidCrystal_I2C.h>  //Библиотека для работы с экраном
LiquidCrystal_I2C lcd(63,16,2);  // Устанавливаем дисплей
long fff =0;
long yyy = 0;
long zzz = 0; 
int xxx;
void setup() 
{
 pinMode(2, INPUT);
 lcd.begin();                     
 lcd.clear(); 
  lcd.backlight();// Включаем подсветку дисплея 
}
void loop() 
{   
     zzz=0;
    for(xxx=0; xxx<20; xxx++)
    {
    yyy = pulseIn(2, LOW,20000);  // должно быстрее работать при неработающем движке
    fff=pulseIn(2, HIGH,20000);
yyy=yyy+fff;
 
     yyy=1000000/yyy;
     yyy=yyy*60;
     yyy=yyy/108; 
    zzz =zzz+yyy;
    }
   zzz=zzz/20;
If (zzz<30){zzz=0;}  // как-то вот так получится 0 , всеравно такие обороты мерить ненадо )))  
// zzz=zzz-27;      // ну или вот так
   lcd.setCursor(0,0);
   lcd.print(zzz);
   lcd.print("      ");
} 

 

Работает спасибо. Единственно при пока нет импульсов RPM показывает 27. и после того как импульсы пропадают обороты не сразу падают а только по прошествии примерно 1 сек опять же до 27 об/мин

так замер шел 1 раз в секунду, делей на 1000 же стоял.

nik182
Offline
Зарегистрирован: 04.05.2015

Когда нет импульсов в строке 26 происходит деление на ноль. Что покажет при этом дисплей одному богу известно. 

Такая схема подключения продифференцирует сигнал - увеличится реакция на импульсные наводки. Скорее конденсатор следует подключить параллельно стабилитрону. Будет уменьшать дребезг.

 

evgta
Offline
Зарегистрирован: 02.09.2016

 
#include <Wire.h>               //Библиотека для работы с I2C
#include <LiquidCrystal_I2C.h>  //Библиотека для работы с экраном
LiquidCrystal_I2C lcd(63,16,2);  // Устанавливаем дисплей
long fff =0;
long yyy = 0;
long zzz = 0; 
int xxx;
void setup() 
{
 pinMode(2, INPUT);
 lcd.begin();                     
 lcd.clear(); 
  lcd.backlight();// Включаем подсветку дисплея 
}
void loop() 
{   
     zzz=0;
    for(xxx=0; xxx<20; xxx++)
    {
    yyy = pulseIn(2, LOW,20000);  // должно быстрее работать при неработающем движке
    fff=pulseIn(2, HIGH,20000);
yyy=yyy+fff;
     if (yyy==0){break;}  //или так
     yyy=1000000/yyy;
     yyy=yyy*60;
     yyy=yyy/108; 
    zzz =zzz+yyy;
    }
zzz=yyy; ///    
zzz=zzz/20;
   lcd.setCursor(0,0);
   lcd.print(zzz);
   lcd.print("      ");
} 

значит так

 

nik182
Offline
Зарегистрирован: 04.05.2015

Или так : if (yyy==0){zzz=0; break;}  

elbugs
Offline
Зарегистрирован: 02.09.2016

Ребят всем спасибо огромное. Помогли здорово.

  Сейчас макетирую контроллер двигателя залью  в него скетч с встоенным кодом на pulsIn от evgta о и буду проверять реакции на кнопки сработку различных функций.

 

Еще раз всем ОГРОМНОЕ СПАСИБО!!!!!!!!!!!!

surkovalexandr
Offline
Зарегистрирован: 09.11.2017

elbugs пишет:

Добрый день.

Делаю контроллер двигателя (дизельного) от рефрежератора. (на микрухе Atmega 328 boot уже залил в нее)

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

Подскажите как организавать подсчет скорости вращения коленвала програмно???

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

Т.е. если столько то импульсов в секунду значит двигатель работает и нужно выключать стартер - вернуть 1

      а если меньше то возращаем 0 т.е. крутим стартером дальше.

Ребят помогите уже всю голову сломал. Я не программист великий поэтому не могу понять как это сделать.

Светодиодом там помигать с условиями поиграться не промлема но это не пойму как сделать.

Заранее благодарен,

Александр

 

Привет, оставь свой адрес эл. почты, скайп или номер телефона.