【问题标题】:Program design architecture for sensors application in embedded device嵌入式设备中传感器应用的程序设计架构
【发布时间】:2017-11-03 23:15:44
【问题描述】:

我不是 C++ 专家,因为我来自电子背景。

我正在尝试制作一个 Arduino 程序,允许任何人使用标准格式轻松地将传感器添加到 Arduino 设备。

我想为每个传感器创建一个 HAL,为此我创建了一个名为 Sensor 的类,它是每个传感器的基类。用户必须创建一个继承自 Sensor 类的子类。例如,这个子类称为Sensor_2(2 是 ID),它实现的功能如下:

uint16_t getID( void );
uint8_t getAvailableChannels( void ); 
void sampleChannel( uint8_t aChannel, uint8_t *aDataSize, uint8_t aDataBuffer[] );

这个类是调用它自己的依赖于传感器的传感器库的类。

这样做,我可以以标准方式对每个传感器进行采样,而无需重写每个传感器库。

我不知道这是否是这样做的方法,但我想不出更好的方法。

我已尝试使用以下代码来实现:

传感器.h

#ifndef SENSOR_H
#define SENSOR_H

#include "Arduino.h"

class Sensor
{
public:
  Sensor();  
  virtual uint16_t getID( void );
  virtual uint8_t getAvailableChannels( void ); 
  virtual void sampleChannel( uint8_t channel, uint8_t dataSize, uint8_t dataBuffer[]);
};

#endif

Sensor_2.h

#ifndef Sensor_2_H
#define Sensor_2_H

#include "Arduino.h"

#include "../../Sensor.h"

#define ID 2
#define CHANNELS 1
class Sensor_2: public Sensor
{
public:
  Sensor_2 ( void  );  
  virtual uint16_t getID( void );
  virtual uint8_t getAvailableChannels( void ); 
  virtual void sampleChannel( uint8_t aChannel, uint8_t *aDataSize, uint8_t aDataBuffer[] );
};

#endif 

Sensor_2.cpp

#include "Sensor_2.h"

Sensor_2::Sensor_2( void )
{

}

uint16_t Sensor_2::getID( void )
{
    return (ID);    
}

uint8_t Sensor_2::getAvailableChannels( void )
{
    return (CHANNELS);    
} 

void sampleChannel( uint8_t aChannel, uint8_t *aDataSize, uint8_t aDataBuffer[] )
{
    aDataSize = 1;
    aDataBuffer[0] = hallRead();    
}

main.cpp

#include <Logger.h>
#include "ComHandler.h"    
#include "./Sensors/Sensor_2/Sensor_2.h"


ComHandler comHandler;

SensorManager* sensorManager = SensorManager::getInstance();

void setup()
{
  Serial.begin(115200);

  Logger::setLogLevel(Logger::WARNING);

  Sensor_2 sensorHall = new Sensor_2;

  sensorManager->addSensor(sensorHall);     
}

void loop()
{
    uint8_t* datasize;
    uint16_t buffer[4];
    comHandler.checkForData();
    sensorManager.getAvailableSensors()[0].sampleChannel(0,dataSize, buffer);

}

问题是在尝试编译时出现此错误:

conversion from 'Sensor_2*' to non-scalar type 'Sensor_2' requested
   Sensor_2 sensorHall = new Sensor_2;
                         ^

如果不是:

Sensor_2 sensorHall = new Sensor_2; 

我用:

Sensor_2 sensorHall; 

我明白了:

sketch/Sensor.cpp.o:(.literal._ZN6SensorC2Ev+0x0): undefined reference to `vtable for Sensor'
sketch/Winja.ino.cpp.o:(.literal._Z5setupv+0x10): undefined reference to `Sensor_2::Sensor_2()'
sketch/Winja.ino.cpp.o: In function `setup()':

您认为这是解决我的问题的好方法吗?如果是这样,我该如何解决我的错误?

【问题讨论】:

    标签: c++ architecture arduino


    【解决方案1】:

    如果我理解这个问题,这里有两个问题(一个是阻塞,另一个不是)。

    至于最简单的问题,Sensor_2 sensorHall = new Sensor_2; 无效,因为new 关键字会生成一个指向对象的指针。您有两种方法来生成对象并将其传递给传感器管理器(我假设传感器管理器接受指向传感器的指针):

    // Solution 1
    Sensor_2 *sensorHall = new Sensor_2;
    sensorManager->addSensor(sensorHall);
    
    // Solution 2
    Sensor_2 sensorHall;
    sensorManager->addSensor(&sensorHall);
    

    但是请注意,如果您使用解决方案 2,则必须将传感器定义放在函数之外。例如,如果你写

    void setup() {
      Sensor_2 sensorHall;
      sensorManager->addSensor(&sensorHall);
    }
    

    那么在您退出setup 后,传感器对象将被销毁。为了避免这种情况,写

    Sensor_2 sensorHall;
    void setup() {
      sensorManager->addSensor(&sensorHall);
    }
    

    至于主要问题,我认为 arduino 不会在主草图文件夹之外编译源文件(并且它不会递归,因此不会扫描子文件夹)。

    但是,您尝试做的通常是通过实现库来完成。您可以找到不同的库和资源来了解库的工作原理(例如,arduino 网站上有一个library tutorial)。您必须在库文件夹中创建一个文件夹,然后放入源文件中(在这种情况下,您可以使用子文件夹);编译将成功。这样您就无需在以后的项目中复制这些文件:它们已经存在了。

    如果您不想共享它们,但仍想将它们放在单独的文件夹中,IIRC 您可以创建一个名为 src 的特殊文件夹并将源文件放在那里(同样,不是在子文件夹中)。 src 文件夹在编译时与草图文件夹合并。

    我的建议:把它变成一个图书馆。完全可重复使用,易于维护,甚至有点突出显示...

    【讨论】:

    • 感谢您的所有时间。我会试试的。我不认为我想让它成为一个库,因为它非常针对我的问题。您如何看待我想要实现的方式?你会用其他方式吗?
    • @Twistx77 好吧,如果您正在努力使其“通用”,以便可以使用许多不同的传感器,那么这正是发明库的原因。即使,就目前而言,它只是一个使用它们的项目。至于实现,不,我认为您以正确的方式完成了工作(定义了一个通用接口和一种识别不同成员的方法)。在我的项目中,我通常使用枚举而不是数字 ID 来识别孩子,所以它更“用户友好”
    • 此外,我不知道您的具体任务是什么,但我通常更喜欢为孩子们安排一些特定的成员。例如,我想要一个通用的sampleChannel,它返回一个字节数组,但我还想要一个更具体的getDistance 用于超声波传感器,getTemperature 用于温度或setSampleRate 用于ADC,所以如果我知道SensorManager的第三个元素是温度传感器我可以投它然后直接得到物理量(所以转换是在类中进行的,而不是在main中)
    • 感谢您的洞察力。我将尝试向您介绍我正在尝试完成的工作。我正在尝试制作一个能够连接到几乎任何传感器的电路板。它有 4 个连接器,它们都具有 I2C 总线,其中两个还具有 ADC 输入和数字 I/O、DAC 和一个 SPI。想法是让任何人都可以为我正在使用的连接器类型制作电路板,然后简单地编写在主应用程序和传感器库之间接口的 Sensor_X 类(当然更具体)。主应用程序几乎可以与传感器交互
    • 不修改。此外,通过制作基于文本的文件,它将能够与计算机/移动软件连接,告诉软件 ID、传感器的范围、转换操作(ADC 读数到温度),它还提供了一种方法将其配置在文本文件中所有参数的位置,这样您就不必修改软件或固件中的主应用程序。通过该软件,您将能够仅向设备询问可用传感器的 ID,并且该软件将在文本文件中包含与相关传感器交互所需的所有数据。
    猜你喜欢
    • 2011-01-14
    • 2010-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-05
    • 2021-07-14
    • 2023-03-25
    • 1970-01-01
    相关资源
    最近更新 更多