概述
在本 wiki 中,我们将介绍如何向 SenseCAP S2110 传感器构建器中添加更多 Grove 模块,并列出所有支持的模块。
将 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();
}
新传感器的 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) | 温度 | 0x0004 | 04 | 
| 湿度 | 0x0006 | 06 | |
| CO2 | 0x0008 | 08 | |
| Grove - Light Sensor v1.2 | 光照 | 0x000A | 10 | 
| Grove - Flame Sensor | 火焰 | 0x000C | 12 | 
| Grove - Oxygen Sensor (MIX8410) | 氧气 | 0x000E | 14 | 
| Grove - Sunlight sensor (SI1151) | 光照强度 | 0x0010 | 16 | 
| 可见光 | 0x0012 | 18 | |
| 紫外线 | 0x0014 | 20 | |
| Grove Temperature and Barometer Sensor (BMP280) | 气压温度 | 0x0016 | 22 | 
| 大气压力 | 0x0018 | 24 | |
| 高度 | 0x001A | 26 | |
| Grove - Temperature Humidity Pressure Gas Sensor(BME680) | 温度 | 0x001C | 28 | 
| 大气压力 | 0x001E | 30 | |
| 湿度 | 0x0020 | 32 | |
| 空气质量(VOC) | 0x0022 | 34 | |
| Grove - Gas Sensor V2(Multichannel) | N02 | 0x0024 | 36 | 
| C2H50H | 0x0026 | 38 | |
| VOC | 0x0028 | 40 | |
| CO | 0x002A | 42 | |
| Grove - UV Sensor | 紫外线强度 | 0x002C | 44 | 
| Grove - Turbidity Sensor Meter V1.0 | 浊度 | 0x002E | 46 | 
| Grove - TDS Sensor | TDS | 0x0030 | 48 | 
| Grove - Ultrasonic Ranger | 距离 | 0x0032 | 50 | 
3. 硬件连接知识
将传感器的 SIG(信号)引脚连接到任何微控制器的模拟引脚之一,为 VCC 提供 5V-3.3V 电源,并将 GND 连接到微控制器的地线。
Grove 传感器配有一个安装在其上的电位器,允许用户微调增益,使其可调节以适应不同的输入电压。它有助于改变传感器的灵敏度。

4. 从上述步骤中,我们可以获得 Grove 交流传感器的库:
按照上述步骤,我们有了应用 Grove 交流传感器的库。
#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				//here pin A2 is used
#define ADC_BITS 12					//depends on microcontroller to microcontroller
#define Calibration_Value 523.56	//depends on the calibration result
#define Phase_Shift 1.7 			//depends on the calibration result
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;			//Number of AC Cycles you want to measure
unsigned int timeout = 500;			//Timeout 
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,为了获得准确的校准值,我们需要进行简单的数学计算,使用以下公式。
- 步骤 3:找到 x 的值,并在程序中用它替换 Calibration_Value,然后将程序刷写到微控制器。
您可以根据您的配置更改其他参数,如 Phase_Shift、交流周期数和超时,或保持默认设置。
参考
- 您可以参考 Grove AC-Voltage Sensor Library 获取更多信息。
- 有关计算的更多详细信息可以在这里找到
SenseCAP S2110 Sensor Builder 支持的 Grove 模块列表
目前,SenseCAP S2110 Sensor Builder 开箱即用地支持以下 Grove 模块,可与 SenseCAP Data Logger 通信并通过 LoRa 将传感器数据发送到 SenseCAP 平台。
- Grove - 温度和气压传感器 (BMP280)
- Grove - 氧气传感器 (MIX8410)
- Grove - CO2 & 温度 & 湿度传感器 - SCD41
- Grove - 日光传感器 - SI1151
- Grove - 光线传感器 v1.2 - LS06-S 光电晶体管
- Grove - 火焰传感器
- Grove - 气体传感器(BME680)
- Grove - 多通道气体传感器 v2
- Grove - TDS 传感器/仪表用于水质检测(总溶解固体)
- Grove - UV 传感器
- Grove - 超声波距离传感器
- Grove - 浊度传感器
- Grove - 闪电传感器
- Grove - ±5A DC/AC 电流传感器 (ACS70331)
✨ 贡献者项目
- 本项目由 Seeed Studio 贡献者项目支持。
- 感谢 Mohammed Adnan Khan 的努力,您的工作将会被展示。
技术支持与产品讨论
感谢您选择我们的产品!我们在这里为您提供不同的支持,以确保您使用我们产品的体验尽可能顺畅。我们提供多种沟通渠道,以满足不同的偏好和需求。