Чтение RPM и таймер?

Ореховый
Ср 17 августа 2016 г. 15:48
Ну, я пытаюсь сделать код обнаружения RPM, и я написал кое -что, что я думал, должно работать. Однако это не так, хотя это также может быть генератор RPM, который не работает....

Вместо того, чтобы показывать весь эскиз, вот функция, которая делает это... Или должно быть что -то явно неправильное? void findRPM() { static unsigned long oldTime; unsigned long currentTime; unsigned long timeDiff; unsigned int blah; while (digitalRead(12) == LOW) {blah =0;} // pause code waiting for a pulse, theyre regular enough so dont need to wait long currentTime = micros(); for (int i = 0; i < 4; i++) { while (digitalRead(12) == LOW) {blah =0;} // taking the time difference between 4 rev samples... } timeDiff = micros() - currentTime; Serial.println(timeDiff); RPM = 1000000 / (timeDiff / 4) * 60; //uses 4 rev samples to get a fair average between them also creating higher accuracy ////// code to calculate RPM here //random generator with more realistic increases decreases.... // RPM = random((RPM - 1500),(RPM + 1500)); // RPM = (RPM <0) ? 0:RPM; // RPM = (RPM > rpmRange) ? rpmRange:RPM; }

Ахулл
Ср 17 августа 2016 г. 15:54
Я бы пойти на один этап дальше.. Используйте булавку, чтобы сгенерировать прерывание каждой революции (с залом или оптическим датчиком)... Затем используйте таймер, чтобы увидеть, сколько времени прошло с момента последнего прерывания. Это дает вам ваш период (один цикл)... Затем вы выясняете, сколько раз вы можете разделить на минуту к своему периоду, и у вас есть RPM... Поскольку вы переигрываете для каждой революции, она остается точной, и, поскольку вы используете прерывание, ваш STM32 может делать что-то полезное для остального времени. Одна из них состоит в том, чтобы в среднем измерения в течение нескольких революций и отказаться от любых дико разных измерений, так как они, вероятно, пропущены, или шум.

Чтобы сохранить короткую подпрограмму службы прерывания (всегда очень хорошая идея), вы также можете просто зарегистрировать значение таймера при каждом прерывании переменной и выполните фактические расчеты времени в вашем основном цикле.

Ореховый
Ср 17 августа 2016 г. 15:59
Я думал, что использование прерываний приостановил весь внутренний код таймера, когда они запускаются?
Ох, и в моем коде выше я делаю это через 4 средних импульса...

Но эффект зала? Это порция RPM, а не сторона MPH...

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

Ореховый
Ср 17 августа 2016 г., 18:13
Итак, как мне использовать таймеры и прерывания? Мне жаль, что это относительно новая концепция для меня...

Ахулл
Ср 17 августа 2016 г. 20:03
Черная писала:Итак, как мне использовать таймеры и прерывания? Мне жаль, что это относительно новая концепция для меня...

Rogerclark
Ср 17 августа 2016 г., 21:46
У меня был бы глобальный для хранения количества импульсов.

Затем в вашем коде отображения прочитайте это значение и преобразуйте в RPM (как работает ваш код отображения с фиксированным интервалом)
Тогда нулевой глобальный ценность

В вашем ISR просто увеличивает, что Gobal

Ореховый
Чт 18 августа 2016 г. 8:49
Привет, Роджер, да, я думал в этом направлении.... Теперь я просто пытаюсь понять, как использовать прерывания и таймер :(

Rogerclark
Чт 18 августа 2016 г., 9:47
Смотрите старые документы Leaflabs

http: // docs.Leaflabs.com/static.Leaflab ... разорение.HTML

Я думаю, что единственное, о чем нужно знать, это то, как часто ваша функция RPM -дисплея называется по сравнению с тем, как часто запускается прерывание RPM.

эн.глин. При 1500 об / мин вы получите только 25 импульсов в секунду. И если ваша функция отображения вызывается каждые 100 мс, у вас будет только 2 или 3 импульса между обновлениями дисплея.

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

Или даже лучше использовать более длинное окно образца, я.e На самом деле получайте подсчет импульсов каждые 250 мс или 500 мс и анимируйте ваш RPM -дисплей до нового значения более 250 или 500 мс

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

http: // incedded-lab.com/blog/stm32-timers/

Это позволяет очень точное измерение входящих импульсов, так как я думаю, что он запускает счетчик (от разделителя от основных часов процессора). Но я не уверен, есть ли у него режим, в котором счетчик запускается одним импульсом и останавливается другим - кажется, что он должен иметь, но вам нужно прочитать Master Programming Doc (что несколько сложно идти )


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

Ореховый
Четверг 18 августа 2016 г., 13:42
Да, мне удалось сделать быструю простую скидку на основе прерываний, чтобы моргнуть светодиод на рупий -импульс с генератора... Это сработало...

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

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

Ореховый
Чт 18 августа 2016 г., 17:28
Что ж, я получил межветопроседание, подсчитывая импульсы, а затем использовал планировщик, чтобы сделать сумму, чтобы найти обороты... Это вроде как работает...

Проблема не очень точная. Если генератор импульсов не работает не совсем правильно и немного не уходит, даже если он установлен на 1000...

Я попытался возиться с кодом, чтобы произвести немного более четкое время, и он не имеет никакого значения... 1000 об / мин приближается около 1900-2500 об / мин
5000 об / мин идет около 4800-5200 ISH.

Теперь, что странно, я получил цифры на серийном принте, и есть узор в неточностях... Это не случайно неточно.
Даже когда я получил калькулятор RPM, работающий один раз за секунду, цифры все еще неточны довольно заметной суммой. Это близко, но еще не там...

Вот эскиз, который я использую в качестве теста #include #include // new scheduler ThreadController controll = ThreadController(); Thread ReadRPM = Thread(); long rpmSample = 0; unsigned long oldTime = 0; unsigned long timeDiff = 0; long RPM; void setup() { Serial.begin(9600); pinMode(33, OUTPUT); pinMode(12, INPUT); ReadRPM.onRun(findRPM); ReadRPM.setInterval(100); controll.add(&ReadRPM); attachInterrupt(12, sampleRPM, RISING); oldTime = micros(); } void findRPM() { RPM = 1000000 / ((micros() - oldTime) / rpmSample) * 60; rpmSample = 0; //oldTime = micros(); Serial.println(RPM); } void loop() { controll.run(); } void sampleRPM() { //This if sets the oldTime, this was in the findRPM loop but I put it here in case the oldtime //varible wasnt capturing the correct microsecond on the first sample, dunno. Didnt make a difference. if (rpmSample == 0) { oldTime = micros(); } rpmSample++; }

Ахулл
Чт 18 августа 2016 г., 8:48 вечера
Может быть, я ошибаюсь, но разве это не... // RPM = 60 * (1/timediff in seconds) RPM = 60*(1000000/(micros() - oldTime )) ; // i.e. RPM = 60 seconds divided by (1000000/(timediff uS))

Ореховый
Чт 18 августа 2016 г., 21:47
Как часто заворачиваются Миллис и Микрос?

Ахулл
Чт 18 августа 2016 г., 21:56
Черная писала:Как часто заворачиваются Миллис и Микрос?

Martinayotte
Четверг 18 августа 2016 г., 22:02
довольно легко обнаружить переполнение:
if (micros() < oldTime) { // handle the overflow (or throw away this sample) }

victor_pv
Вторник 30 августа 2016 г., 4:15 утра
Я бы использовал аппаратный таймер в режиме захвата ввода.
Вы можете либо установить таймер для создания прерывания при переполнении, и сравнить время между переполнением или просто прочитать значение таймера каждые X миллисекунды и сравните увеличение счетчика таймера в этом периоде. Вы также можете установить предварительные эскалеры. Все зависит от того, сколько оборотов вы измеряете и сколько дисперсии между минимумом и максимальной скоростью.
Если вы измеряете высокое значение RPM, опрашивание PIN -кода или сервирования и прерывания на революцию потребляет много времени процессора, в то время как при аппаратном таймере вы не потребляете какое -либо время ЦП, чтобы подсчитать чиклы, только для того, чтобы проверить значение таймера так часто так Как вы хотите, или для сервера прерывание таймера при переполнении, которое может быть более или реже в зависимости от предварительного эскалятора и значения переполнения.

Rogerclark
Вторник 30 августа 2016 г., 4:22 утра
Добро пожаловать обратно @victor_pv ;-)

Я упомянул захват ввода в одном из моих ответов в эту ветку http: // www.STM32duino.com/viewtopic.PHP ... 322#P17059 Но я думаю, что @nutsy надеялся, что он сможет сделать это, просто используя ISR

Но теперь это звучит так, будто метод захвата ввода даст лучшее значение, которое подсчет в течение известного периода времени (поскольку количество импульсов слишком мало)

Ореховый
Вторник 30 августа 2016 г. 22:48
Извините за мой поздний ответ, был занят всевозможным. Но не уверен, что кто -то заметил. Я даже поместил свой проект на Hackaday...

Ну, подсчет прерываний, кажется, в настоящее время работает достаточно хорошо.

Я думал, что у меня есть подходящий защитный транзистор для проверки реального сигнала RPM, но я мог бы подключить его неправильно, и PIN 12 умер: P: P

Я разработал и заказал детали для настройки Opto изолятора для безопасного чтения RPM... Затем я снова проверьте с другой булавок...