Merge pull request #6843 from climberhunt/pr_hpma115s0

add support for Honeywell HPMA115S0 particle sensor
This commit is contained in:
Theo Arends 2019-11-06 13:53:28 +01:00 committed by GitHub
commit 2c04785119
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 570 additions and 0 deletions

7
lib/HPMA115S0/LICENSE.md Normal file
View File

@ -0,0 +1,7 @@
Copyright 2017 Felix Galindo
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

2
lib/HPMA115S0/README.md Normal file
View File

@ -0,0 +1,2 @@
# HPMA115S0
Library for Honeywell's Particle Sensor (HPMA115S0-XXX)

View File

@ -0,0 +1,34 @@
/**
* @file example.ino
* @author Felix Galindo
* @date June 2017
* @brief Example using HPMA115S0 sensor library on a Feather 32u4
* @license MIT
*/
#include <HPMA115S0.h>
#include <SoftwareSerial.h>
//Create an instance of software serial
SoftwareSerial hpmaSerial(10, 11); // Feather TX, Feather RX
//Create an instance of the hpma115S0 library
HPMA115S0 hpma115S0(hpmaSerial);
void setup() {
Serial.begin(57600);
hpmaSerial.begin(9600);
delay(5000);
Serial.println("Starting...");
hpma115S0.Init();
hpma115S0.StartParticleMeasurement();
}
void loop() {
unsigned int pm2_5, pm10;
if (hpma115S0.ReadParticleMeasurement(&pm2_5, &pm10)) {
Serial.println("PM 2.5: " + String(pm2_5) + " ug/m3" );
Serial.println("PM 10: " + String(pm10) + " ug/m3" );
}
delay(1000);
}

View File

@ -0,0 +1,9 @@
name=HPMA115S0 Arduino Library
version=1.0.0
author=Felix Galindo
maintainer=Felix Galindo
sentence=A library for Honeywell HPMA115S0 Particle Sensor
paragraph=Supports the HPMA115S0
category=Sensors
url=https://github.com/felixgalindo/HPMA115S0.git
architectures=*

View File

@ -0,0 +1,190 @@
/**
* @file HPMA115S0.cpp
* @author Felix Galindo
* @date June 2017
* @brief Arduino Library for Honeywell's Particle Sensor (HPMA115S0-XXX)
* @license MIT
*/
#include "Arduino.h"
#include "hpma115S0.h"
extern "C" {
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
}
/**
* @brief Constructor for HPMA115S0 class
* @param a Stream ({Software/Hardware}Serial) object.
* @note The serial stream should be already initialized
* @return void
*/
HPMA115S0::HPMA115S0(Stream& serial):
_serial(serial)
{
_serial.setTimeout(100);
}
/**
* @brief Function that initializes sensor
* @return a String containing sensor response
*/
void HPMA115S0::Init() {
//Serial.println("PS- Initializing...");
delay(100);
StartParticleMeasurement();
delay(100);
DisableAutoSend();
}
/**
* @brief Function that sends serial command to sensor
* @param a unsigned char * containing the command
* @param size of buffer
* @return void
*/
void HPMA115S0::SendCmd(unsigned char * cmdBuf, unsigned int cmdSize) {
//Clear RX
while (_serial.available())
_serial.read();
//Send command
//Serial.print("PS- Sending cmd: ");
unsigned int index = 0;
for (index = 0; index < cmdSize; index++) {
//Serial.print(cmdBuf[index], HEX);
//Serial.print(" ");
_serial.write(cmdBuf[index]);
}
//Serial.println("");
return;
}
/**
* @brief Function that reads command response from sensor
* @param Buffer to store data in
* @param Buffer size
* @param Expected command type
* @return returns number of bytes read from sensor
*/
int HPMA115S0::ReadCmdResp(unsigned char * dataBuf, unsigned int dataBufSize, unsigned int cmdType) {
static unsigned char respBuf[HPM_MAX_RESP_SIZE];
static unsigned int respIdx = 0;
static unsigned int calChecksum = 0;
//Read response
respIdx = 0;
calChecksum = 0;
memset(respBuf, 0, sizeof(respBuf));
_serial.setTimeout(100);
//Serial.println("PS- Waiting for cmd resp...");
if (_serial.readStringUntil(HPM_CMD_RESP_HEAD)) {
delay(1); //wait for the rest of the bytes to arrive
respBuf[HPM_HEAD_IDX] = HPM_CMD_RESP_HEAD;
respBuf[HPM_LEN_IDX] = _serial.read(); //Read the command length
//Ensure buffers are big enough
if (respBuf[HPM_LEN_IDX] && ((respBuf[HPM_LEN_IDX] + 1) <= sizeof(respBuf) - 2) && (respBuf[HPM_LEN_IDX] - 1) <= dataBufSize ) {
if (_serial.readBytes(&respBuf[HPM_CMD_IDX], respBuf[HPM_LEN_IDX] + 1) == (respBuf[HPM_LEN_IDX] + 1)) { //read respBuf[HPM_LEN_IDX] num of bytes + calChecksum byte
if (respBuf[HPM_CMD_IDX] == cmdType) { //check if CMD type matches
//Calculate and validate checksum
for (respIdx = 0; respIdx < (2 + respBuf[HPM_LEN_IDX]); respIdx++) {
calChecksum += respBuf[respIdx];
}
calChecksum = (65536 - calChecksum) % 256;
if (calChecksum == respBuf[2 + respBuf[HPM_LEN_IDX]]) {
//Serial.println("PS- Received valid data!!!");
memset(dataBuf, 0, dataBufSize);
memcpy(dataBuf, &respBuf[HPM_DATA_START_IDX], respBuf[HPM_LEN_IDX] - 1);
return (respBuf[HPM_LEN_IDX] - 1);
}
}
}
}
}
return false;
}
/**
* @brief Function that sends a read command to sensor
* @return returns true if valid measurements were read from sensor
*/
boolean HPMA115S0::ReadParticleMeasurement(unsigned int * pm2_5, unsigned int * pm10) {
unsigned char cmdBuf[] = {0x68, 0x01, 0x04, 0x93};
static unsigned char dataBuf[HPM_READ_PARTICLE_MEASURMENT_LEN - 1];
//Serial.println("PS- Reading Particle Measurements..." );
//Send command
SendCmd(cmdBuf, 4);
//Read response
if (ReadCmdResp(dataBuf, sizeof(dataBuf), READ_PARTICLE_MEASURMENT) == (HPM_READ_PARTICLE_MEASURMENT_LEN - 1)) {
_pm2_5 = dataBuf[0] * 256 + dataBuf[1];
_pm10 = dataBuf[2] * 256 + dataBuf[3];
*pm2_5 = _pm2_5;
*pm10 = _pm10;
// Serial.println("PS- PM 2.5: " + String(_pm2_5) + " ug/m3" );
// Serial.println("PS- PM 10: " + String(_pm10) + " ug/m3" );
return true;
}
return false;
}
/**
* @brief Function that starts sensor measurement
* @return void
*/
void HPMA115S0::StartParticleMeasurement() {
unsigned char cmd[] = {0x68, 0x01, 0x01, 0x96};
SendCmd(cmd, 4);
}
/**
* @brief Function that stops sensor measurement
* @return void
*/
void HPMA115S0::StopParticleMeasurement() {
unsigned char cmd[] = {0x68, 0x01, 0x02, 0x95};
SendCmd(cmd, 4);
}
/**
* @brief Function that enables auto send
* @return void
*/
void HPMA115S0::EnableAutoSend() {
unsigned char cmd[] = {0x68, 0x01, 0x40, 0x57};
SendCmd(cmd, 4);
}
/**
* @brief Function that stops auto send
* @return void
*/
void HPMA115S0::DisableAutoSend() {
unsigned char cmd[] = {0x68, 0x01, 0x20, 0x77};
SendCmd(cmd, 4);
}
/**
* @brief Function that returns the latest PM 2.5 reading
* @note Sensor reports new reading ~ every 1 sec.
* @return PM 2.5 reading (unsigned int)
*/
unsigned int HPMA115S0::GetPM2_5() {
return _pm2_5;
}
/**
* @brief Function that returns the latest PM 10 reading
* @note Sensor reports new reading ~ every 1 sec.
* @return PM 10 reading (unsigned int)
*/
unsigned int HPMA115S0::GetPM10() {
return _pm10;
}

View File

@ -0,0 +1,123 @@
/**
*
* @file HPMA115S0.h
* @author Felix A. Galindo
* @date June 2017
* @brief Arduino Library for Honeywell's Particle Sensor (HPMA115S0-XXX)
*
*/
#ifndef HPMA115S0_H
#define HPMA115S0_H
#include "Arduino.h"
#define HPM_CMD_RESP_HEAD 0x40
#define HPM_MAX_RESP_SIZE 8 // max command response size is 8 bytes
#define HPM_READ_PARTICLE_MEASURMENT_LEN 5
enum CMD_TYPE_T {
READ_PARTICLE_MEASURMENT = 0x04,
START_PARTICLE_MEASURMENT = 0x01,
STOP_PARTICLE_MEASURMENT = 0x02,
SET_ADJUSTMENT_COEFFICIENT = 0x08,
READ_ADJUSTMENT_COEFFICIENT = 0x08,
STOP_AUTO_SEND = 0x20,
ENABLE_AUTO_SEND = 0x40,
};
enum HPM_PACKET_T {
HPM_HEAD_IDX,
HPM_LEN_IDX,
HPM_CMD_IDX,
HPM_DATA_START_IDX
};
class HPMA115S0
{
public:
/**
* @brief Constructor for HPMA115S0 class
* @param a Stream ({Software/Hardware}Serial) object.
* @note The serial stream should be already initialized
* @return void
*/
HPMA115S0(Stream& serial);
/**
* @brief Function that initializes sensor
* @return a String containing sensor response
*/
void Init();
/**
* @brief Function that sends a read command to sensor
* @return returns true if valid measurements were read from sensor
*/boolean ReadParticleMeasurement(unsigned int * pm2_5, unsigned int * pm10)
;
/**
* @brief Function that starts sensor measurement
* @return void
*/
void StartParticleMeasurement();
/**
* @brief Function that stops sensor measurement
* @return void
*/
void StopParticleMeasurement();
/**
* @brief Function that enables auto send
* @return void
*/
void EnableAutoSend();
/**
* @brief Function that stops auto send
* @return void
*/
void DisableAutoSend();
/**
* @brief Function that returns the latest PM 2.5 reading
* @note Sensor reports new reading ~ every 1 sec.
* @return PM 2.5 reading (unsigned int)
*/
unsigned int GetPM2_5();
/**
* @brief Function that returns the latest PM 10 reading
* @note Sensor reports new reading ~ every 1 sec.
* @return PM 10 reading (unsigned int)
*/
unsigned int GetPM10();
private:
Stream& _serial;
//Latest PM 2.5 reading
unsigned int _pm2_5 = 0;
//Latest PM 10 reading
unsigned int _pm10 = 0;
/**
* @brief Function that sends serial command to sensor
* @param a char * containing the command
* @param size of buffer
* @return void
*/
void SendCmd(unsigned char * command, unsigned int size);
/**
* @brief Function that reads command response from sensor
* @param Buffer to store data in
* @param Buffer size
* @param Expected command type
* @return returns number of bytes read from sensor
*/
int ReadCmdResp(unsigned char * dataBuf, unsigned int dataBufSize, unsigned int cmdType);
};
#endif

View File

@ -548,6 +548,8 @@
#define D_SENSOR_PMS5003 "PMS5003"
#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_HPMA_RX "HPMA Rx"
#define D_SENSOR_HPMA_TX "HPMA Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -548,6 +548,8 @@
#define D_SENSOR_PMS5003 "PMS5003"
#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_HPMA_RX "HPMA Rx"
#define D_SENSOR_HPMA_TX "HPMA Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -548,6 +548,8 @@
#define D_SENSOR_PMS5003 "PMS5003"
#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_HPMA_RX "HPMA Rx"
#define D_SENSOR_HPMA_TX "HPMA Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -548,6 +548,8 @@
#define D_SENSOR_PMS5003 "PMS5003"
#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_HPMA_RX "HPMA Rx"
#define D_SENSOR_HPMA_TX "HPMA Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -548,6 +548,8 @@
#define D_SENSOR_PMS5003 "PMS5003"
#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_HPMA_RX "HPMA Rx"
#define D_SENSOR_HPMA_TX "HPMA Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -1,6 +1,8 @@
/*
es-ES.h - localization for Spanish - Spain for Tasmota
#define D_SENSOR_HPMA_RX "HPMA Rx"
#define D_SENSOR_HPMA_RX "HPMA Rx"
Copyright (C) 2019 Adrian Scillato
This program is free software: you can redistribute it and/or modify
@ -548,6 +550,8 @@
#define D_SENSOR_PMS5003 "PMS5003"
#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_HPMA_RX "HPMA Rx"
#define D_SENSOR_HPMA_TX "HPMA Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -548,6 +548,8 @@
#define D_SENSOR_PMS5003 "PMS5003"
#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_HPMA_RX "HPMA Rx"
#define D_SENSOR_HPMA_TX "HPMA Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -548,6 +548,8 @@
#define D_SENSOR_PMS5003 "PMS5003"
#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_HPMA_RX "HPMA Rx"
#define D_SENSOR_HPMA_TX "HPMA Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -548,6 +548,8 @@
#define D_SENSOR_PMS5003 "PMS5003"
#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_HPMA_RX "HPMA Rx"
#define D_SENSOR_HPMA_TX "HPMA Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -548,6 +548,8 @@
#define D_SENSOR_PMS5003 "PMS5003"
#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_HPMA_RX "HPMA Rx"
#define D_SENSOR_HPMA_TX "HPMA Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -548,6 +548,8 @@
#define D_SENSOR_PMS5003 "PMS5003"
#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_HPMA_RX "HPMA Rx"
#define D_SENSOR_HPMA_TX "HPMA Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -548,6 +548,8 @@
#define D_SENSOR_PMS5003 "PMS5003"
#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_HPMA_RX "HPMA Rx"
#define D_SENSOR_HPMA_TX "HPMA Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -548,6 +548,8 @@
#define D_SENSOR_PMS5003 "PMS5003"
#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_HPMA_RX "HPMA Rx"
#define D_SENSOR_HPMA_TX "HPMA Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -548,6 +548,8 @@
#define D_SENSOR_PMS5003 "PMS5003"
#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_HPMA_RX "HPMA Rx"
#define D_SENSOR_HPMA_TX "HPMA Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -548,6 +548,8 @@
#define D_SENSOR_PMS5003 "PMS5003"
#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_HPMA_RX "HPMA Rx"
#define D_SENSOR_HPMA_TX "HPMA Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -548,6 +548,8 @@
#define D_SENSOR_PMS5003 "PMS5003"
#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_HPMA_RX "HPMA Rx"
#define D_SENSOR_HPMA_TX "HPMA Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -548,6 +548,8 @@
#define D_SENSOR_PMS5003 "PMS5003"
#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_HPMA_RX "HPMA Rx"
#define D_SENSOR_HPMA_TX "HPMA Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -548,6 +548,8 @@
#define D_SENSOR_PMS5003 "PMS5003"
#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_HPMA_RX "HPMA Rx"
#define D_SENSOR_HPMA_TX "HPMA Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -548,6 +548,8 @@
#define D_SENSOR_PMS5003 "PMS5003"
#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_HPMA_RX "HPMA Rx"
#define D_SENSOR_HPMA_TX "HPMA Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -548,6 +548,8 @@
#define D_SENSOR_PMS5003 "PMS5003"
#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_HPMA_RX "HPMA Rx"
#define D_SENSOR_HPMA_TX "HPMA Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -548,6 +548,8 @@
#define D_SENSOR_PMS5003 "PMS5003"
#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_HPMA_RX "HPMA Rx"
#define D_SENSOR_HPMA_TX "HPMA Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -548,6 +548,8 @@
#define D_SENSOR_PMS5003 "PMS5003"
#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_HPMA_RX "HPMA Rx"
#define D_SENSOR_HPMA_TX "HPMA Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -456,6 +456,7 @@
//#define PMS_MODEL_PMS3003 // Enable support of PMS3003 instead of PMS5003/PMS7003 (needs the USE_PMS5003 above)
#define USE_NOVA_SDS // Add support for SDS011 and SDS021 particle concentration sensor (+1k5 code)
#define STARTING_OFFSET 30 // Turn on NovaSDS XX-seconds before tele_period is reached
#define USE_HPMA // Add support for Honeywell HPMA115S0 particle concentration sensor
#define USE_SERIAL_BRIDGE // Add support for software Serial Bridge (+0k8 code)
//#define USE_MP3_PLAYER // Use of the DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop
#define MP3_VOLUME 10 // Set the startup volume on init, the range can be 0..30(max)

View File

@ -170,6 +170,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c
#define USE_PMS5003 // Add support for PMS5003 and PMS7003 particle concentration sensor (+1k3 code)
//#define PMS_MODEL_PMS3003 // Enable support of PMS3003 instead of PMS5003/PMS7003 (needs the USE_PMS5003 above)
#define USE_NOVA_SDS // Add support for SDS011 and SDS021 particle concentration sensor (+0k7 code)
#define USE_HPMA // Add support for Honeywell HPMA115S0 particle concentration sensor
#define USE_SERIAL_BRIDGE // Add support for software Serial Bridge (+0k8 code)
#define USE_MP3_PLAYER // Use of the DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop
#define MP3_VOLUME 10 // Set the startup volume on init, the range can be 0..30(max)
@ -365,6 +366,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c
#undef USE_SENSEAIR // Disable support for SenseAir K30, K70 and S8 CO2 sensor
#undef USE_PMS5003 // Disable support for PMS5003 and PMS7003 particle concentration sensor
#undef USE_NOVA_SDS // Disable support for SDS011 and SDS021 particle concentration sensor
#undef USE_HPMA // Disable support for Honeywell HPMA115S0 particle concentration sensor
#undef USE_SERIAL_BRIDGE // Disable support for software Serial Bridge
#undef USE_MP3_PLAYER // Disable DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop
#undef USE_AZ7798 // Disable support for AZ-Instrument 7798 CO2 datalogger
@ -452,6 +454,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c
#undef USE_SENSEAIR // Disable support for SenseAir K30, K70 and S8 CO2 sensor
#undef USE_PMS5003 // Disable support for PMS5003 and PMS7003 particle concentration sensor
#undef USE_NOVA_SDS // Disable support for SDS011 and SDS021 particle concentration sensor
#undef USE_HPMA // Disable support for Honeywell HPMA115S0 particle concentration sensor
#undef USE_SERIAL_BRIDGE // Disable support for software Serial Bridge
#undef USE_MP3_PLAYER // Disable DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop
#undef USE_AZ7798 // Disable support for AZ-Instrument 7798 CO2 datalogger
@ -553,6 +556,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c
#undef USE_SENSEAIR // Disable support for SenseAir K30, K70 and S8 CO2 sensor
#undef USE_PMS5003 // Disable support for PMS5003 and PMS7003 particle concentration sensor
#undef USE_NOVA_SDS // Disable support for SDS011 and SDS021 particle concentration sensor
#undef USE_HPMA // Disable support for Honeywell HPMA115S0 particle concentration sensor
#undef USE_SERIAL_BRIDGE // Disable support for software Serial Bridge
#undef USE_MP3_PLAYER // Disable DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop
#undef USE_AZ7798 // Disable support for AZ-Instrument 7798 CO2 datalogger

View File

@ -212,6 +212,8 @@ enum UserSelectablePins {
GPIO_TASMOTASLAVE_RXD, // Slave RX
GPIO_TASMOTASLAVE_RST, // Slave Reset Pin
GPIO_TASMOTASLAVE_RST_INV, // Slave Reset Inverted
GPIO_HPMA_RX, // Honeywell HPMA115S0 Serial interface
GPIO_HPMA_TX, // Honeywell HPMA115S0 Serial interface
GPIO_SENSOR_END };
// Programmer selectable GPIO functionality
@ -291,6 +293,7 @@ const char kSensorNames[] PROGMEM =
D_SENSOR_SM2135_CLK "|" D_SENSOR_SM2135_DAT "|"
D_SENSOR_DEEPSLEEP "|" D_SENSOR_EXS_ENABLE "|"
D_SENSOR_SLAVE_TX "|" D_SENSOR_SLAVE_RX "|" D_SENSOR_SLAVE_RESET "|" D_SENSOR_SLAVE_RESET "i|"
D_SENSOR_HPMA_RX "|" D_SENSOR_HPMA_TX "|"
;
const char kSensorNamesFixed[] PROGMEM =
@ -686,6 +689,10 @@ const uint8_t kGpioNiceList[] PROGMEM = {
GPIO_SDS0X1_TX, // Nova Fitness SDS011 Serial interface
GPIO_SDS0X1_RX, // Nova Fitness SDS011 Serial interface
#endif
#ifdef USE_HPMA
GPIO_HPMA_TX, // Honeywell HPMA115S0 Serial interface
GPIO_HPMA_RX, // Honeywell HPMA115S0 Serial interface
#endif
#ifdef USE_PMS5003
GPIO_PMS5003, // Plantower PMS5003 Serial interface
#endif

147
tasmota/xsns_56_hpma.ino Normal file
View File

@ -0,0 +1,147 @@
/*
xsns_56_hpma.ino - Honeywell HPMA115S0 particle concentration sensor support for Tasmota
Copyright (C) 2019 Theo Arends
Copyright (C) 2019 David Hunt
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef USE_HPMA
/*********************************************************************************************\
* Honeywell HPMA115S0 particle concentration sensor
* For background information see
* https://sensing.honeywell.com/hpma115s0-xxx-particulate-matter-sensors
* For protocol specification see
* https://sensing.honeywell.com/honeywell-sensing-hpm-series-particle-sensors-datasheet-32322550-e-en.pdf
*
\*********************************************************************************************/
#define XSNS_56 56
#include <hpma115S0.h>
#include <TasmotaSerial.h>
TasmotaSerial *HpmaSerial;
HPMA115S0 *hpma115S0;
uint8_t hpma_type = 1;
uint8_t hpma_valid = 0;
struct hpmadata {
unsigned int pm10;
unsigned int pm2_5;
} hpma_data;
/*********************************************************************************************/
void HpmaSecond(void) // Every second
{
unsigned int pm2_5, pm10;
/*
* Sensor sends data every second, so we just read it and update the structure.
*/
if (hpma115S0->ReadParticleMeasurement(&pm2_5, &pm10)) {
hpma_data.pm2_5 = pm2_5;
hpma_data.pm10 = pm10;
hpma_valid = 1;
}
}
void HpmaInit(void)
{
hpma_type = 0;
Serial.println("SDS init");
if (pin[GPIO_HPMA_RX] < 99 && pin[GPIO_HPMA_TX] < 99) {
HpmaSerial = new TasmotaSerial(pin[GPIO_HPMA_RX], pin[GPIO_HPMA_TX], 1);
hpma115S0 = new HPMA115S0(*HpmaSerial);
if (HpmaSerial->begin(9600)) {
if (HpmaSerial->hardwareSerial()) {
ClaimSerial();
}
hpma_type = 1;
hpma115S0->Init();
hpma115S0->StartParticleMeasurement();
}
}
}
#ifdef USE_WEBSERVER
const char HTTP_HPMA_SNS[] PROGMEM =
"{s}HPMA " D_ENVIRONMENTAL_CONCENTRATION "2.5 " D_UNIT_MICROMETER "{m}%s " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}"
"{s}HPMA " D_ENVIRONMENTAL_CONCENTRATION "10 " D_UNIT_MICROMETER "{m}%s " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
#endif // USE_WEBSERVER
void HpmaShow(bool json)
{
if (hpma_valid) {
char pm10[33];
snprintf_P(pm10, 33, PSTR("%d"), hpma_data.pm10);
char pm2_5[33];
snprintf_P(pm2_5, 33, PSTR("%d"), hpma_data.pm2_5);
if (json) {
ResponseAppend_P(PSTR(",\"HPMA\":{\"PM2.5\":%d,\"PM10\":%d}"), hpma_data.pm2_5, hpma_data.pm10);
#ifdef USE_DOMOTICZ
if (0 == tele_period) {
DomoticzSensor(DZ_VOLTAGE, pm2_5); // PM2.5
DomoticzSensor(DZ_CURRENT, pm10); // PM10
}
#endif // USE_DOMOTICZ
#ifdef USE_WEBSERVER
} else {
WSContentSend_PD(HTTP_HPMA_SNS, pm2_5, pm10);
#endif // USE_WEBSERVER
}
}
}
/*********************************************************************************************\
* Interface
\*********************************************************************************************/
bool Xsns56(uint8_t function)
{
bool result = false;
if (hpma_type) {
switch (function) {
case FUNC_INIT:
HpmaInit();
break;
case FUNC_EVERY_SECOND:
HpmaSecond();
break;
case FUNC_COMMAND_SENSOR:
if (XSNS_56 == XdrvMailbox.index) {
return true;
}
break;
case FUNC_JSON_APPEND:
HpmaShow(1);
break;
#ifdef USE_WEBSERVER
case FUNC_WEB_SENSOR:
HpmaShow(0);
break;
#endif // USE_WEBSERVER
}
}
return result;
}
#endif // USE_HPMA