Тахометр

Mattias
Offline
Зарегистрирован: 06.01.2016

Подскажите, пожалуйста, как реализовать тахометр с использованием геркона?

Мне кажется, что нужно:

1. считать срабатывания геркона в течение какого-то времени (например, одной секунды),

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

3. вывести значение количества оборотов в последовательный порт.

С пунктом 3 проблем нет, а вот со всем остальным - не ясно, какие именно функции как применять.
Мне кажется, что я использую не те операции для циклов и неправильно считаю нажатия:

unsigned long time;
unsigned long Rotation=0;
unsigned long RPM=0;

#define GERK_PIN 3

void setup()

{
  Serial.begin(9600);
pinMode(GERK_PIN, INPUT PULLUP);

}

void loop()

//считаем срабатывания геркона в течение какого-то времени (например, одной секунды),
{
  time = millis();

while(millis<1000)
{
if (digitalRead(GERK_PIN=true)
Rotation=+Rotation;
}

// поделить количество срабатываний на прошедшее время в миллисекундах
// умножить результат на 1000 и ещё на 60, чтобы получить количество оборотов в минуту

RPM=Rotation/time*60;

// вывод значения количества оборотов в последовательный порт.
  Serial.print("RPM: ");
  //выводит количество миллисекунд с момента начала выполнения программы
  Serial.println(RPM);
  // ждет секунду перед следующей итерацией цикла.
  delay(1000);
}
 

Заранее спасибо за помощь!

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

1. http://arduino.ru/forum/obshchii/vstavka-programmnogo-koda-v-temukommentarii

Ваш цикл
 
while(millis<1000) {
   if (digitalRead(GERK_PIN=true) Rotation=+Rotation;
}

вообще никогда не закончится. millis то в нём не меняется и с какого перепугу ему заканчиваться?

Но, даже если бы Вы его правильно написали, всё равно, так не пойдёт. Вы получите "цену на пролшогодний овёс".

while(millis()-start_millis < 1000) {
    if (digitalRead(GERK_PIN)) Rotation++;
}

Как Вы думаете, сколько раз этот цикл успеет сработать за время одного единственного замыкания геркона? Раз 100!. Ну, если очень быстро крутится, то 10.

Вам надо ловить последовательно замыкание - размыкание и только тогда засчитывать срабатывание.

Ну и не забывайте про дребезг контакта. Нужен либо ртутный геркон, либо надо как-то позаботиться о дребезге.

И, кстати, то, что Вы написали, элементарно не скомпилируется. Почему Вы не попробуете сами хотя бы раз запустить, а сразу постите вопрос? Ну, почему сначала не посробовать самому?

Mattias
Offline
Зарегистрирован: 06.01.2016

Спасибо за быстрый ответ!
Насчёт цикла более-менее понял, наверное, надо считать секунды внутри цикла, верно?
Т.е сняли значение секунд, если оно меньше 1000 - прокрутили цикл ещё раз.

Да, со скоростью срабатывания тоже ясно - я добавил задержку внутри цикла.

Про ловлю замыкания-размыкания непонятно вообще. Нужно ждать замыкания, потом размыкания
и только если эти два события произошли - увеличивать на единицу счётчик?

Дребезг контактов сейчас не так важен, либо переделаю схему на униполярный датчик Холла, либо триггер Шмитта использую.
Мне главное принцип понять, как организовать подсчёт замыканий.

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

unsigned long time;
unsigned long Rotation=0;
unsigned long RPM=0;

#define GERK_PIN 3
int GERK_STATE=0;

void setup()

{
  Serial.begin(9600);
pinMode(GERK_PIN, INPUT);

}

void loop()
{
// Цикл, подсчитывающий нажатия
  do 
  {
  time = millis();
  GERK_STATE = digitalRead(GERK_PIN); 
    if (GERK_STATE=HIGH)
  Rotation=+Rotation;
  delay(10);
  } while (time < 1000);



// поделить количество срабатываний на прошедшее время в миллисекундах
// умножить результат на 1000 и ещё на 60, чтобы получить количество оборотов в минуту

RPM=Rotation/time*60;

// вывод значения количества оборотов в последовательный порт.
  Serial.print("RPM: ");
  //выводит количество миллисекунд с момента начала выполнения программы
  Serial.println(RPM);
  // ждет секунду перед следующей итерацией цикла.
  delay(1000);
}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Mattias пишет:

Нужно ждать замыкания, потом размыкания
и только если эти два события произошли - увеличивать на единицу счётчик?
 

Конечно.

Andy
Andy аватар
Offline
Зарегистрирован: 01.01.2016

Mattias пишет:

Подскажите, пожалуйста, как реализовать тахометр с использованием геркона?

Мне кажется, что нужно:

1. считать срабатывания геркона в течение какого-то времени (например, одной секунды),

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

А чем не устраивает измерение времени одного оборота? 60 000 деленное на время одного оборота даст количество оборотов в минуту.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

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

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

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

Например:

1. Ждем переднего фронта импульса.

2. Импульс пришел - запоминаем время его прихода, например, 32431 мс.

3. Вычисляем, когда _примерно_ заканчивать отсчет времени, например, 32431 + 1000 = 33431 мс.

4. Подсчитывая поступающие импульсы, дожидаемся наступления 33431 мс. Пусть насчитали 3 штуки.

5. Ждем переднего фронта очередного импульса - 4-го по счету.

6. Импульс пришел - запоминаем время его прихода, скажем, 33653 мс.

Частота: 4/(33653 - 32431) = 0,0032733 оборота за мс = 3,2733 об/с = 196,4 об/мин.

Mattias
Offline
Зарегистрирован: 06.01.2016

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

Эта версия кода действительно считает нажатия, проблема в том, что она не перестаёт считать их по прошествии одной секунды. Что можно исправить, подскажите?

 

#define LED_PIN 3
#define GERK_PIN 7
#define TIME 1000 // время, в течение которого будет производится подсчёт оборотов - 1 секунда

boolean gerk = false;       //состояние геркона
boolean previous = false;   //предыдущее состояние геркона
unsigned long prev_time = 0; // время с момента прошлой проверки
unsigned long curr_time = 0; // текущее время

long rotation = 0; // счётчик срабатываний геркона
long RPS = 0; // количество оборотов в секунду

void setup() {
pinMode(LED_PIN,OUTPUT); // режим работы пина диода
pinMode(GERK_PIN,INPUT); // режим работы пина геркона
 Serial.begin(9600); // инициализация последовательного порта
}

void loop() {
prev_time = millis(); // считываем значение текущего времени
do
    { //подсчёт оборотов
    boolean current = digitalRead(GERK_PIN); //проверка геркона
   if(current && !previous)    //если текущее состояние - 1 и прошлое - 0, то    
      {
        prev_time = curr_time; // сохранить время последнего переключения
        gerk = !gerk; // переключить геркон в противоположное состояние
        rotation==rotation++; // увеличение счётчика оборотов на 1
      }
    previous = current; // записать в ячейку прошлого состояния текущее 
    curr_time = millis(); // считываем значение времени, прошедшего с прошлого измерения  
    }
while (curr_time - prev_time < TIME); //проверяем, прошла ли секунда 
    
// и если прошла, передаём количество оборотов по последовательному порту
    

Serial.println(rotation); 
rotation=0; //обнуляем счётчик оборотов

}

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Стандартно - вести переменную состояния: считать/не считать.