每秒获取传感器的值 C++

getting value of sensor each second c++

我最近试图将我的湿度传感器测量的数据存储到我的 MYSQL 数据库中。我已经编写了必要的 C++ 程序,从传感器获取数据,将其存储在我的 MYSQL 数据库中,并获取当前的 UnixTime。

但是,我想每秒存储数据,并且认为使用线程似乎不是解决此问题的好方法。我也不希望 MYSQL 自动插入 UnixTime。为此,我想继续使用我的 C++ 程序。

有人知道使用 C++ 以必要的 UnixTime 每秒存储数据的更简单方法吗?

线程实际上是后台任务的巧妙解决方案。考虑这个例子:

#include <iostream>
#include <thread>
#include <chrono>

void everySecondTask() {
  while (true) {
    // Do actual work here, e.g. get sensor data and write to db
    std::cout << "second passed" << std::endl;

    std::this_thread::sleep_for(std::chrono::seconds(1));
  }
}

int main() {
  // operations and sleep in everySecondTask is done in different thread, code
  // in main is not paused.
  std::thread background(everySecondTask);

  // do you 200 lines of code here, while task is called every second

  background.join();
} 

我也会使用线程来解决这个问题。但是,我不会依赖一个工作线程。如果您的过程花费超过 1 秒的时间到 运行,会发生什么情况?

相反,我会创建一组工作线程。让每个线程等待 std::condition_variable。这样你就不会拉你的线程的状态,而是依赖条件变量在它们在某个工作队列中工作时得到通知。

有一个专用线程就可以了。但是这里有一种方法可以在没有专用线程的情况下做到这一点。而且这种技术也可以与专用线程一起使用。

底线是:

不要为这个任务使用 sleep_for

改用sleep_until

您可以获得一次正确的唤醒时间。然后在循环中做任何你需要做的工作。并且下次醒来时睡到比上次醒来时间长 1s(而不是睡 1s)。

注意上面描述中的英文:"sleep until" vs "sleep for".

下面是具体化的代码:

#include "date.h"
#include <iomanip>
#include <iostream>
#include <random>
#include <thread>

std::mt19937_64 eng;

void
do_other_work()
{
    using namespace std;
    using namespace std::chrono;
    static uniform_int_distribution<> dist{2, 600};
    this_thread::sleep_for(milliseconds{dist(eng)});
}

std::pair<double, date::sys_seconds>
get_humidity()
{
    using namespace std;
    using namespace std::chrono;
    using namespace date;
    static uniform_real_distribution<> dist;
    return {dist(eng), round<seconds>(system_clock::now())};
}

int
main()
{
    using namespace std;
    using namespace std::chrono;
    using namespace date;
    cout << fixed << setprecision(2);
    auto wakeup = system_clock::now() + 1s;
    while (true)
    {
        auto data = get_humidity();
        cout << data.first << " : " << data.second << '\n';
        do_other_work();
        this_thread::sleep_until(wakeup);
        wakeup += 1s;
    }
}

我添加了 header-only library "date.h" 只是为了方便格式化您当前的 UnixTime 时间戳。但是上面的 take-home 点是用 system_clock::now() 设置 time_point wakeup 一次,然后在每次迭代时简单地增加 1s 并使用 this_thread::sleep_until 睡到 time_point。只要你的其他工作不超过1s,这个程序就会可靠地每秒输出一次数据:

0.79 : 2017-01-23 02:06:21
0.40 : 2017-01-23 02:06:22
0.02 : 2017-01-23 02:06:23
0.27 : 2017-01-23 02:06:24
0.14 : 2017-01-23 02:06:25
0.86 : 2017-01-23 02:06:26
...

如果你想把 get_humidity() 放在另一个线程中,那也没关系。但是要在另一个线程(仍然必须做其他工作)中保持准确的 per/sec 报告,请使用 sleep_until 而不是 sleep_for 因为您不知道其他工作需要多长时间.