Raspberry pi, C ++ хронографическая функция, операции над значениями? - PullRequest
1 голос
/ 28 января 2020

Я начинаю с C ++ и с функции "хронограф", и я хотел бы использовать ее для определения скорости двигателя.

Для этого у меня есть колесо кодирования, связанное с двигателем Оптопара используется для сбора прямоугольного сигнала, генерируемого колесом кодирования.

Поэтому мой Raspberry Pi получает прямоугольный сигнал, скорость которого зависит от скорости двигателя.

Я использовал функцию хронографа попытаться вычислить длительность частоты квадратного сигнала. Я добился, чтобы длительность каждого сигнала (почти) составляла 7 мс. Я хотел бы просто извлечь частоту через формулу 1 / F (следовательно, 1 / 0,007 = 142,85).

Я ел документацию по функции хронографа в течение недели, и до сих пор совсем не понимаю ...

Очевидно, все ответы здесь, но я не понимаю этого, я все еще новичок в C ++ :( https://en.cppreference.com/w/cpp/chrono

Это ДЕЙСТВИТЕЛЬНО полезно, но ограничено: https://www.code57.com/cplusplus-programming-beginners-tutorial-utilities-chrono/

Если я правильно понимаю, "значение" 7 мс хранится в "объекте" .. Как я могу просто получить его оттуда и поместить в стандартную переменную, чтобы я мог делить, умножать и делать с ним все, что захочу?

Вот интересная часть кода C ++:

#include <iostream>
#include <wiringPi.h>
#include <cstdio>
#include <csignal>
#include <ctime>
#include <chrono>

// global flag used to exit from the main loop
bool RUNNING = true;
bool StartTimer = false;
//int timer = 0;
std::chrono::steady_clock::time_point BeginMeasurement; //chrono variable representing the beginning of the measurement of a motor speed


//some more code in here, but nothing exceptionnal, just calling the interruption when needed


//interruption function for counting the motor speed
void RPMCounter(){
    using namespace std;
    using namespace std::chrono;

    if (StartTimer == true){
    StartTimer = false;
    steady_clock::duration result = steady_clock::now()-BeginMeasurement;
    if (duration_cast<milliseconds>(result).count() < 150){
        double freq;
        //cout.precision(4);
        std::cout << "Time = " << duration_cast<milliseconds>(result).count() << " ms" << '\n';
// I would like the next line to work and give me the frequency of the detection...
        freq = 1/(duration_cast<milliseconds>(result).count()/1000);
        std::cout << "Frequency = " << freq << " Hz" << '\n';
    }
    }
    else{
    BeginMeasurement = steady_clock::now();
    StartTimer = true;
    }
}

Вот результат в моей командной строке:

enter image description here

значение 7 мс увеличивается, потому что я остановил двигатель, поэтому он вращался медленнее до остановки;)

Редактировать:

Благодаря Говарду Хиннанту и Теду Люнгмо, мой код теперь ks вот так:

void RPMCounter(){
    using namespace std;
    using namespace std::chrono;

    if (StartTimer == true){
    StartTimer = false;
    duration<double> result = steady_clock::now() - BeginMeasurement;
    if (result < milliseconds{150}){
        double freq;//= 1s / result;
        //cout.precision(4);
        std::cout << "Time = " << duration_cast<milliseconds>(result).count() << " ms" << '\n';
        freq = (1.0/(duration<double>{result}.count()/1000))/1000;
        std::cout << "Frequency = " << freq << " Hz" << '\n';
    }
    }
    else{
    BeginMeasurement = steady_clock::now();
    StartTimer = true;
    }
}

и похоже мне дает правильную частоту. Будучи новичком, я непременно пойму все это лучше и улучшу это :) (в основном, я не совсем уверен в том, что я имел в виду ... как "::" и другие способы :) Остальная часть моего кода должна быть более базовой c и позволить мне изучить все настройки C ++

Ответы [ 2 ]

4 голосов
/ 29 января 2020

if (duration_cast<milliseconds>(result).count() < 150){

Вы можете упростить это с помощью:

if (result < 150ms)

Или, если вы находитесь в C ++ 11:

if (result < milliseconds{150})

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

freq = 1/(duration_cast<milliseconds>(result).count()/1000);

Вместо этого:

using dsec = duration<double>;  // define a double-based second
auto freq = 1/dsec{result}.count();

Это также может быть записано:

auto freq = 1/duration<double>{result}.count();

В любом случае это преобразует result прямо в двойные секунды и инвертирует это значение, используя арифметику с плавающей запятой c. Исходный код использует интегральное деление, в результате чего получается интегральный результат, который всегда округляется до 0. Т.е. 1/10 == 0, тогда как 1/10. == 0.1.

2 голосов
/ 29 января 2020

Я бы сделал result a double длительность на основе:

auto BeginMeasurement = std::chrono::steady_clock::now(); 

// some work

// a double based duration
std::chrono::duration<double> result = std::chrono::steady_clock::now() - BeginMeasurement;

Затем можно разделить duration 1s на result, чтобы получить частота:

using namespace std::chrono_literals;

double freq = 1s / result;
std::cout << freq << " Hz\n";

Говард Хиннант указал, что с C ++ 14 вы можете сделать это еще проще для себя, изменив дивиденды на целочисленную длительность, 1s, на удвоенную длительность, 1.0s, и пусть result будет выведено с использованием auto:

auto result = std::chrono::steady_clock::now() - BeginMeasurement;
double freq = 1.0s / result;

Демо

...