расчет оборотов двигателя по датчику

Signalsus
Offline
Зарегистрирован: 04.11.2018

Привет комрады.

вопрос такой, есть датчик tcrt5000

от оборотов двигателя, получаю импульс через attachInterrupt(0, OkHoll, FALLING);

 

void OkHoll() {
  //int tcn =  TCNT0;
  long mil = millis();
  long raznMilis = mil - HollaTimeOld;
  HollaTimeOld = mil;
  Serial.println(raznMilis);

}

результат raznMilis:

36
36
36
36
36
36
35
36
36
36
36
37

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

вообще задача такая:

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

вообщем нужно поддерживать обороты движка

sadman41
Offline
Зарегистрирован: 19.10.2016

Один оборот выполняется за raznMilis мс (переведите в секунды). Сколько raznMilis содержится в одной секунде?

-NMi-
Offline
Зарегистрирован: 20.08.2018

А чё не на таймере? На нём точнее будет.

b707
Offline
Зарегистрирован: 26.05.2017

Signalsus пишет:

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

это вопрос не по программированию, а чисто по школьной математике.

Задачка полностью аналогична примерно такой - "Пешеход проходит 80 метров за 55 секунд. Рассчитайте его скорость в километрах в час"

-NMi-
Offline
Зарегистрирован: 20.08.2018

5,23 да?

Signalsus
Offline
Зарегистрирован: 04.11.2018

-NMi- пишет:

5,23 да?

 

ну вообще-то у меня получается 1304 в минуту

long raznMilis = mil - HollaTimeOld;
  HollaTimeOld = mil;
  //Serial.println(raznMilis);
  long ObMin = 60000/(raznMilis);

Signalsus
Offline
Зарегистрирован: 04.11.2018

-NMi- пишет:

А чё не на таймере? На нём точнее будет.

 

так а вот тут по подробнее, в теории же прерывание срабатывает при событии, а таймером нужно постоянно опрашивать порт?

я не силен в ардуино-кодинге, мож я просто что-то не так понимаю

b707
Offline
Зарегистрирован: 26.05.2017

Signalsus пишет:

ну вообще-то у меня получается 1304 в минуту

long raznMilis = mil - HollaTimeOld;
  HollaTimeOld = mil;
  //Serial.println(raznMilis);
  long ObMin = 60000/(raznMilis);

вообще-то если подставить сюда цифру 36 из заглавного сообщения - 1300 не получится...

Signalsus
Offline
Зарегистрирован: 04.11.2018

b707 пишет:

Signalsus пишет:

ну вообще-то у меня получается 1304 в минуту

long raznMilis = mil - HollaTimeOld;
  HollaTimeOld = mil;
  //Serial.println(raznMilis);
  long ObMin = 60000/(raznMilis);

вообще-то если подставить сюда цифру 36 из заглавного сообщения - 1300 не получится...

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

вопрос, кстати, как эти данные подкинуть в PID регулятор оборотов движка?

SHVED
Offline
Зарегистрирован: 29.07.2020
#define TACHOMETER_PIN 21
#define TACHOMETER_TIME_INTERVAL 200

volatile unsigned long t_interruptionTime;
volatile byte t_interruptionCounter;
unsigned long t_previousTime;

void setup() {

  attachInterrupt(digitalPinToInterrupt(TACHOMETER_PIN), t_interruption, RISING);

}

void loop() {

  if (millis() - t_previousTime >= TACHOMETER_TIME_INTERVAL) {

    unsigned long t_currentTime;
    unsigned int t_RPM;
    byte t_counter;

    noInterrupts();
    t_counter = t_interruptionCounter;
    t_currentTime = t_interruptionTime;
    t_interruptionCounter = 0;
    interrupts();

    t_RPM = 60000 / ((t_currentTime - t_previousTime) * 2 / t_counter); // Умножить на 2 потому что в моем случае 2 импульса = 1 оборот
    t_previousTime = t_currentTime;

  }
}

void t_interruption() {

  t_interruptionTime = millis();
  t_interruptionCounter++;

}

Вот так считаю обороты на моте, показывает ровно, но если двигатель малооборотистый то лучше интервал расчетов увеличить конечно. Можно не запоминать время прошлого расчета и вместо "(t_currentTime - t_previousTime)" использовать просто 200мс, как например в моем случае, но если между расчетами есть другие задачи то точность может сильно упасть, ибо там уже может быть уже не 200мс, а 230мс например.

Вообще очень советую вот эту статью: https://habr.com/ru/post/346126/

Signalsus
Offline
Зарегистрирован: 04.11.2018

SHVED пишет:

#define TACHOMETER_PIN 21
#define TACHOMETER_TIME_INTERVAL 200

volatile unsigned long t_interruptionTime;
volatile byte t_interruptionCounter;
unsigned long t_previousTime;

void setup() {

  attachInterrupt(digitalPinToInterrupt(TACHOMETER_PIN), t_interruption, RISING);

}

void loop() {

  if (millis() - t_previousTime >= TACHOMETER_TIME_INTERVAL) {

    unsigned long t_currentTime;
    unsigned int t_RPM;
    byte t_counter;

    noInterrupts();
    t_counter = t_interruptionCounter;
    t_currentTime = t_interruptionTime;
    t_interruptionCounter = 0;
    interrupts();

    t_RPM = 60000 / ((t_currentTime - t_previousTime) * 2 / t_counter); // Умножить на 2 потому что в моем случае 2 импульса = 1 оборот
    t_previousTime = t_currentTime;

  }
}

void t_interruption() {

  t_interruptionTime = millis();
  t_interruptionCounter++;

}

Вот так считаю обороты на моте, показывает ровно, но если двигатель малооборотистый то лучше интервал расчетов увеличить конечно. Можно не запоминать время прошлого расчета и вместо "(t_currentTime - t_previousTime)" использовать просто 200мс, как например в моем случае, но если между расчетами есть другие задачи то точность может сильно упасть, ибо там уже может быть уже не 200мс, а 230мс например.

Вообще очень советую вот эту статью: https://habr.com/ru/post/346126/

так в том и дело, что в основном цикле куча других датчиков, вывод на экран lcd, поэтому и ковыряюсь, не ну впринципе сделал, осталось все это дело в PID передавать

SHVED
Offline
Зарегистрирован: 29.07.2020

Signalsus пишет:

так в том и дело, что в основном цикле куча других датчиков, вывод на экран lcd

Код выше вам в помощь.

void OkHoll() {
  //int tcn =  TCNT0;
  long mil = millis();
  long raznMilis = mil - HollaTimeOld;
  HollaTimeOld = mil;
  Serial.println(raznMilis);

}

Еще бы я вам не советовал делать какие то долгие вычисления (а лучше вообще без них) в прерывании, иначе при увеличении оборотов ардуина большую часть времени будет обрабатывать прерывания а не основной loop, вплоть до того что прерывания будут становится в очередь и loop будет "зависать"

v258
v258 аватар
Offline
Зарегистрирован: 25.05.2020

SHVED пишет:

Код выше вам в помощь.

void OkHoll() {
  //int tcn =  TCNT0;
  long mil = millis();
  long raznMilis = mil - HollaTimeOld;
  HollaTimeOld = mil;
  Serial.println(raznMilis);

}

unsigned long mil
unsigned long raznMilis
unsigned long HollaTimeOld

SHVED
Offline
Зарегистрирован: 29.07.2020

v258 пишет:

SHVED пишет:

Код выше вам в помощь.

void OkHoll() {
  //int tcn =  TCNT0;
  long mil = millis();
  long raznMilis = mil - HollaTimeOld;
  HollaTimeOld = mil;
  Serial.println(raznMilis);

}

unsigned long mil
unsigned long raznMilis
unsigned long HollaTimeOld

Согласен, только код выше это вот тут http://arduino.ru/forum/programmirovanie/raschet-oborotov-dvigatelya-po-datchiku#comment-550837