我不是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[] );
这个类调用自己的传感器库,该库依赖于传感器。
通过这种方式,我可以以标准的方式对每个传感器进行采样,而无需重写每个传感器库。
我不知道这是不是办法,但我想不出比这更好的办法了。
我尝试用以下代码来实现它:
Sensor.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
传感器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()':
你认为这是解决我问题的好方法吗?如果是,我该如何修复我的错误?
如果我理解这个问题,这里有两个问题(一个是阻塞,另一个不是)。
对于最简单的问题,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);
}
那么在您退出CCD_ 6之后,传感器对象将被破坏。为了避免这种情况,写入
Sensor_2 sensorHall;
void setup() {
sensorManager->addSensor(&sensorHall);
}
至于主要问题,我认为arduino不会编译主草图文件夹之外的源文件(而且它不会递归,所以不会扫描子文件夹)。
然而,您试图做的事情通常是通过实现库来完成的。你可以找到不同的库和资源来了解库是如何工作的(例如,arduino网站上有一个库教程)。你必须在库文件夹中创建一个文件夹,然后放在源文件中(在这种情况下,你可以使用子文件夹);汇编将会成功。这样,您就不需要在未来的项目中复制这些文件:它们已经存在了。
如果你不想让它们共享,但仍然想把它们放在一个单独的文件夹中,IIRC你可以制作一个名为src的特殊文件夹,并把源文件放在那里(同样,不是放在子文件夹中)。编译时,src文件夹将与草图文件夹合并。
我的建议是:把它变成一个图书馆。完全可重复使用,易于维护,甚至有点突出显示。。。