Skip to main content

概述

在本 wiki 中,我们将介绍如何将更多 Grove 模块添加到 SenseCAP S2110 传感器构建器中,并列出所有支持的模块。

将 Grove - ±5A DC/AC 电流传感器 (ACS70331) 添加到构建器并应用

1. 使用 GitHub 源代码构建新库

这里的内容位于我们维护代码的 GitHub 上。

  • 步骤 1:src\sensor 文件夹中为新传感器添加一个 sensorNew.hpp 文件。

  • 步骤 2: 定义传感器类并实现 init()sample() 函数。

传感器类应该继承自 sensorClass 类,并实现 init()sample() 函数。 init() 函数用于初始化传感器,然后返回用于 Modbus 通信的寄存器偏移值。 sample() 函数用于读取传感器数据,当数据有效时返回 true,当数据无效时返回 false。

  • 步骤 3: 包含 sensorNEW.hpp 文件并调用它。

src\sensor\sensorBuilder.hpp 文件中添加 #include "sensorNew.hpp" 行。 在 sensorBuilder.ino 文件的 setup() 函数中,创建新的传感器类对象并调用 SensorBuilder.addSensor() 函数,将其作为参数传入。

参考以下代码:

void setup()
{
Serial.begin(9600);
SensorBuilder.check_grove();

/* sensor list */
sensorUltrasonic *ultrasonic = new sensorUltrasonic();
SensorBuilder.addSensor(ultrasonic);

// add new sensor to sensor list
sensorNew *newSensor = new sensorNew();
SensorBuilder.addSensor(newSensor);

SensorBuilder.begin();
}
note

新传感器的 Modbus 寄存器地址将从 0x0034 开始,每个测量值的寄存器位宽为 32,因此两个相邻测量值之间的寄存器地址偏移量为 2。

2. Modbus 寄存器表知识

Modbus 寄存器地址 0x0000 到 0x0003 保留用于存储模块系统信息,其中 0x0000 是 modbus 地址,默认值为 1,最大值为 247,0x0001 是串口波特率,默认值为 96(对应 9600),0x0002 到 0x0003 用于软件版本。

Grove 传感器名称寄存器名称寄存器地址
(十六进制)
寄存器地址
(十进制)
Grove - CO2 & Temperature & Humidity Sensor (SCD41)温度0x000404
湿度0x000606
CO20x000808
Grove - Light Sensor v1.2光照0x000A10
Grove - Flame Sensor火焰0x000C12
Grove - Oxygen Sensor (MIX8410)氧气0x000E14
Grove - Sunlight sensor (SI1151)光照强度0x001016
可见光0x001218
紫外线0x001420
Grove Temperature and Barometer Sensor (BMP280)气压温度0x001622
大气压力0x001824
高度0x001A26
Grove - Temperature Humidity Pressure Gas Sensor(BME680)温度0x001C28
大气压力0x001E30
湿度0x002032
空气质量(VOC)0x002234
Grove - Gas Sensor V2(Multichannel)N020x002436
C2H50H0x002638
VOC0x002840
CO0x002A42
Grove - UV Sensor紫外线强度0x002C44
Grove - Turbidity Sensor Meter V1.0浊度0x002E46
Grove - TDS SensorTDS0x003048
Grove - Ultrasonic Ranger距离0x003250

3. 硬件连接知识

将传感器的 SIG(信号)引脚连接到任何微控制器的模拟引脚之一,为 VCC 提供 5V-3.3V 电源,将 GND 连接到微控制器的地线。

Grove 传感器配有一个安装在其上的电位器,允许用户微调增益,使其可调节以适应不同的输入电压。它有助于改变传感器的灵敏度。

4. 从上述步骤中,我们可以获得 Grove AC 传感器的库:

按照上述步骤,我们有了应用 Grove AC 传感器的库。

#ifndef _SENSOR_AC_H
#define _SENSOR_AC_H

#include "sensorClass.hpp"

#define AC_ADC_PIN A2
#define ADC_BITS 12
#define ADC_COUNTS (1<<ADC_BITS)

class sensorAC : public sensorClass
{
public:
sensorAC(): sensorClass("AC"){};
~sensorAC(){};

uint16_t init(uint16_t reg, bool i2c_available);
bool connected();
bool sample();

enum
{
AC = 0,
MAX
};
private:
double voltCal = 523.56;
double phaseCal = 1.7;
unsigned int cycles = 20;
unsigned int timeout = 2000;
int SupplyVoltage = 3300;
int sampleV;
double lastFilteredV,filteredV;
double offsetV = ADC_COUNTS >> 1;
double phaseShiftedV;
double sqV,sumV;
int startV;
boolean lastVCross,checkVCross;
};

uint16_t sensorAC::init(uint16_t reg, bool i2c_available){
uint16_t t_reg = reg;

for (uint16_t i = 0; i < sensorAC::MAX; i++)
{
sensorClass::reg_t value;
value.addr = t_reg;
value.type = sensorClass::regType_t::REG_TYPE_S32_ABCD;
value.value.s32 = 0;
t_reg += sensorClass::valueLength(value.type);
m_valueVector.emplace_back(value);
}

_connected = i2c_available ? false : true;
//_connected = true;
return t_reg - reg;
}

bool sensorAC::sample()
{

GROVE_SWITCH_ADC;
pinMode(AC_ADC_PIN, INPUT);

unsigned int crossCount = 0;
unsigned int numberOfSamples = 0;

unsigned long start = millis();

while(1){
int startV = analogRead(AC_ADC_PIN);
if((startV<(ADC_COUNTS*0.51)) && (startV>(ADC_COUNTS*0.49)))
break;
if((millis()-start)>timeout)
break;
}

start = millis();

while((crossCount<cycles) && ((millis()-start)<timeout))
{
numberOfSamples++;
lastFilteredV = filteredV;

sampleV = analogRead(AC_ADC_PIN);
offsetV = offsetV + ((sampleV - offsetV)/ADC_COUNTS);
filteredV = sampleV - offsetV;

sqV = filteredV * filteredV;
sumV += sqV;

phaseShiftedV = lastFilteredV + phaseCal * (filteredV - lastFilteredV);

lastVCross = checkVCross;
if(sampleV>startV)
checkVCross = true;
else
checkVCross = false;
if(numberOfSamples == 1)
lastVCross = checkVCross;
if(lastVCross !=checkVCross)
crossCount++;
}

double V_RATIO = voltCal * ((SupplyVoltage/1000.0)/(ADC_COUNTS));
float value = V_RATIO * sqrt(sumV/numberOfSamples);
m_valueVector[AC].value.s32 = value * SCALE;
//Serial.println(value);
sumV = 0;

return true;
}

bool sensorAC::connected()
{
return _connected;
}

#endif

5. 使用 Arduino 编程进行首次测试

该程序需要一些参数,这些参数需要在运行程序之前进行初始化。这确保程序与传感器正确运行并获得准确的数值。

首先将程序烧录到微控制器中,然后校准参数以适配读数。

#define AC_ADC_PIN A2				//这里使用引脚 A2
#define ADC_BITS 12 //取决于微控制器
#define Calibration_Value 523.56 //取决于校准结果
#define Phase_Shift 1.7 //取决于校准结果

void setup() {
Serial.begin(115200);
pinMode(AC_ADC_PIN, INPUT);
}

int ADC_COUNTS = (1<<ADC_BITS);
double voltCal = Calibration_Value;
double phaseCal = Phase_Shift;
unsigned int cycles = 10; //要测量的交流周期数
unsigned int timeout = 500; //超时时间
int SupplyVoltage = 3300;
int sampleV;
double lastFilteredV,filteredV;
double offsetV = ADC_COUNTS >> 1;
double phaseShiftedV;
double sqV,sumV;
int startV;
boolean lastVCross,checkVCross;

void loop() {
unsigned int crossCount = 0;
unsigned int numberOfSamples = 0;

unsigned long start = millis();

while(1){
int startV = analogRead(AC_ADC_PIN);
if((startV<(ADC_COUNTS*0.51)) && (startV>(ADC_COUNTS*0.49)))
break;
if((millis()-start)>timeout)
break;
}

start = millis();

while((crossCount<cycles) && ((millis()-start)<timeout))
{
numberOfSamples++;
lastFilteredV = filteredV;

sampleV = analogRead(AC_ADC_PIN);
offsetV = offsetV + ((sampleV - offsetV)/ADC_COUNTS);
filteredV = sampleV - offsetV;

sqV = filteredV * filteredV;
sumV += sqV;

phaseShiftedV = lastFilteredV + phaseCal * (filteredV - lastFilteredV);

lastVCross = checkVCross;
if(sampleV>startV)
checkVCross = true;
else
checkVCross = false;
if(numberOfSamples == 1)
lastVCross = checkVCross;
if(lastVCross !=checkVCross)
crossCount++;
}

double V_RATIO = voltCal * ((SupplyVoltage/1000.0)/(ADC_COUNTS));
float value = V_RATIO * sqrt(sumV/numberOfSamples);
Serial.println(value);
sumV = 0;

}

6. 获取校准值

最初模拟引脚设置为 A2 引脚,可以根据您的需求使用 AC_ADC_PIN 参数进行更改。 每次更改电压源时都需要更改 Calibration_Value 和 Phase_Shift 值,因为交流电压因国家而异,有时甚至因插座而异。

程序将传感器值输出到串行监视器。您也可以打开串行绘图仪查看电压与时间的图表。

  • 步骤 1:使用万用表测量交流电压并记录下来。
  • 步骤 2:同样记录串行监视器中显示的电压。

在我的情况下,万用表的读数是 220V RMS 电压,而传感器在串行监视器上显示 718.87V,为了获得准确的校准值,我们需要进行简单的数学计算,使用以下公式。

Mains Voltage / x = Sensor voltage / Initial Calibration

  • 步骤 3:找到 x 的值,并在程序中用它替换 Calibration_Value,然后将程序刷写到微控制器。

x = (mains voltage × initial calibration) / Sensor voltage 您可以根据您的配置更改其他参数,如 Phase_Shift、交流周期数和超时,或保持默认值。

参考

SenseCAP S2110 Sensor Builder 支持的 Grove 模块列表

目前,SenseCAP S2110 Sensor Builder 开箱即用地支持以下 Grove 模块,可与 SenseCAP Data Logger 通信并通过 LoRa 将传感器数据发送到 SenseCAP 平台。

✨ 贡献者项目

技术支持与产品讨论

感谢您选择我们的产品!我们在这里为您提供不同的支持,以确保您使用我们产品的体验尽可能顺畅。我们提供多种沟通渠道,以满足不同的偏好和需求。

Loading Comments...