【问题标题】:Splitting ESP32 sketch into multiple threads and files将 ESP32 草图拆分为多个线程和文件
【发布时间】:2022-01-03 21:29:39
【问题描述】:

我正在为我的 ESP32 绘制一个非常复杂且大型的草图,并将其划分为线程和类,将所有内容拆分到不同的文件中。为简单起见,我将向您展示我的项目设置的想法。

例如,我使用 BME280 传感器来读取温度、湿度和压力值。因此,我创建了一个名为bme280.h 的头文件和一个名为bme280.cpp 的关联cpp 文件。这是两个文件的内容。

bme280.h

#ifndef BME280_H
#define BME280_H

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

#define SEALEVELPRESSURE_HPA (1013.25)

typedef struct {
  float temperature;
  float pressure;
  float humidity;
}bmeData;

class BME280_sensor {  
  public:
    BME280_sensor();
    bmeData readBmeData();

  private:
    Adafruit_BME280 bme;
};

#endif

bme280.cpp

#include "bme280.h"

BME280_sensor::BME280_sensor() {
  bool status;
  
  status = bme.begin(0x76);  
  if (!status) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }
  Serial.println("BME280 sensor correctly initialized!");
}

bmeData BME280_sensor::readBmeData() {
  bmeData bmeValues;

  bmeValues.temperature = bme.readTemperature();
  bmeValues.pressure = bme.readPressure() / 100.0F;
  bmeValues.humidity = bme.readHumidity();

  return bmeValues;
}

这基本上就是我使用每个传感器的方式。

现在,我的.ino 文件正忙于做其他工作,所以我使用pthread 库来创建一个不同的线程来负责读取传感器值。因此,我的.ino 文件在完成工作之前启动了这个线程,我将其命名为mainThread。这是一个例子:

file.ino

#include <pthread.h>
#include "main.h"

void setup() {
  delay(1000);
  Serial.begin(115200);
  Serial.println("Serial initialized");

  pthread_t mainThreadRef;
  int mainValue;

  mainValue = pthread_create(&mainThreadRef, NULL, mainThread, (void*)NULL);

  if (mainValue) {
     Serial.println("Main thread error occured");
  }
}

void loop() {
  // Some other job
}

相反,主线程是使用main.h 文件和main.cpp 文件实现的。这是一个例子:

ma​​in.h

#ifndef MAIN_H
#define MAIN_H

#include <Arduino.h>

void *mainThread();

#endif

ma​​in.cpp

#include "main.h"
#include "bme280.h"

void *mainThread() {
  BME280_sensor bme;
  
  while (1) {
    bmeData bmeValues = bme.readBmeData();
    
    Serial.println(bmeValues.temperature);
    Serial.println(bmeValues.humidity);
    Serial.println(bmeValues.pressure);
    
    delay(3000);
  }
}

现在,我想知道这个项目的整个结构是否良好,因为我面临着奇怪的读数,比如温度超过 100 或压力低于 0,以及其他一些奇怪的东西。更准确地说:

  1. 让一个线程充当主线程来完成所有工作是否“安全”?
  2. 为我正在使用的每个传感器设置不同的类别是不是很好,还是会干扰传感器读数?

提前感谢大家的帮助!

【问题讨论】:

    标签: c++ multithreading arduino microcontroller esp32


    【解决方案1】:

    让一个线程充当主线程来完成所有工作是否“安全”?

    是的。 setup()loop() 函数被执行的地方也是一个线程。它可能是系统中的第一个线程,但除此之外它与您自己创建的线程没有区别。

    困难的部分是不在自己的线程中运行一个孤立的进程——这通常很容易,而且通常是个好主意。困难的部分是跨不同线程获取数据。我推荐 Mastering the FreeRTOS Real Time Kernel 阅读有关 FreeRTOS 线程(这是 ESP32 真正使用的,pthreads 只是它的包装器)如何工作以及它们之间如何通信的信息。

    为我正在使用的每个传感器设置不同的类是否很好,或者它是否会干扰传感器读数?

    如果您对每种类型的传感器都有一个类,其中包含了如何与该传感器通信的普通细节,那么这通常被认为是好的设计(封装等)。但这取决于,真的。细节决定成败。请注意,无论如何,Arduino 或 Adafruit 传感器库已经这样做了——它们倾向于提供一个漂亮、简单的界面,您可以在不了解其工作细节的情况下使用该界面。不要费心包装那些(除非你有明确的目的)。

    【讨论】:

    • 非常感谢!这是一个非常有用的答案,我将完全检查 FreeRTOS 书!关于为每个传感器创建一个类,我选择这样做是因为我知道库已经提供了非常简单的接口,但与 bme280 传感器不同,其他传感器需要更长的设置和使用时间,所以我希望我的“主”代码尽可能干净.我只是想知道项目的这种结构是否会影响传感器读数。到目前为止,我只在使用 bme280 传感器时遇到了这个问题。
    • 项目结构不会导致错误。编码过程中的错误会导致错误 :) 或接线不良,或电源不良,或其他任何原因。
    猜你喜欢
    • 2018-07-23
    • 1970-01-01
    • 2013-08-24
    • 1970-01-01
    • 2010-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-13
    相关资源
    最近更新 更多