mirror of
https://github.com/airgradienthq/arduino.git
synced 2025-07-25 22:47:16 +02:00
v1.0.0
This commit is contained in:
BIN
AirGradient/.DS_Store
vendored
Normal file
BIN
AirGradient/.DS_Store
vendored
Normal file
Binary file not shown.
833
AirGradient/AirGradient.cpp
Normal file
833
AirGradient/AirGradient.cpp
Normal file
@ -0,0 +1,833 @@
|
|||||||
|
/*
|
||||||
|
Test.h - Test library for Wiring - implementation
|
||||||
|
Copyright (c) 2006 John Doe. All right reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// include this library's description file
|
||||||
|
#include "AirGradient.h"
|
||||||
|
|
||||||
|
// include description files for other libraries used (if any)
|
||||||
|
#include <SoftwareSerial.h>
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include <Wire.h>
|
||||||
|
|
||||||
|
|
||||||
|
// Constructor /////////////////////////////////////////////////////////////////
|
||||||
|
// Function that handles the creation and setup of instances
|
||||||
|
|
||||||
|
const int MHZ14A = 14;
|
||||||
|
const int MHZ19B = 19; // this one we use for AQI whatever
|
||||||
|
|
||||||
|
const int MHZ14A_PREHEATING_TIME = 3 * 60 * 1000;
|
||||||
|
const int MHZ19B_PREHEATING_TIME = 3 * 60 * 1000;
|
||||||
|
|
||||||
|
const int MHZ14A_RESPONSE_TIME = 60 * 1000;
|
||||||
|
const int MHZ19B_RESPONSE_TIME = 120 * 1000;
|
||||||
|
|
||||||
|
const int STATUS_NO_RESPONSE = -2;
|
||||||
|
const int STATUS_CHECKSUM_MISMATCH = -3;
|
||||||
|
const int STATUS_INCOMPLETE = -4;
|
||||||
|
const int STATUS_NOT_READY = -5;
|
||||||
|
const int STATUS_PWM_NOT_CONFIGURED = -6;
|
||||||
|
const int STATUS_serial_MHZ19_NOT_CONFIGURED = -7;
|
||||||
|
|
||||||
|
unsigned long lastRequest = 0;
|
||||||
|
|
||||||
|
bool SerialConfigured = true;
|
||||||
|
bool PwmConfigured = true;
|
||||||
|
|
||||||
|
AirGradient::AirGradient(bool displayMsg,int baudRate)
|
||||||
|
{
|
||||||
|
_debugMsg = displayMsg;
|
||||||
|
Wire.begin();
|
||||||
|
Serial.begin(baudRate);
|
||||||
|
if (_debugMsg) {
|
||||||
|
Serial.println("AirGradiant Library instantiated successfully.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public Methods //////////////////////////////////////////////////////////////
|
||||||
|
// Functions available in Wiring sketches, this library, and other libraries
|
||||||
|
|
||||||
|
|
||||||
|
void AirGradient::PMS_Init(){
|
||||||
|
if (_debugMsg) {
|
||||||
|
Serial.println("Initializing PMS...");
|
||||||
|
}
|
||||||
|
PMS_Init(5,6);
|
||||||
|
}
|
||||||
|
void AirGradient::PMS_Init(int rx_pin,int tx_pin){
|
||||||
|
PMS_Init(rx_pin,tx_pin,9600);
|
||||||
|
}
|
||||||
|
void AirGradient::PMS_Init(int rx_pin,int tx_pin,int baudRate){
|
||||||
|
_SoftSerial_PMS = new SoftwareSerial(rx_pin,tx_pin);
|
||||||
|
PMS(*_SoftSerial_PMS);
|
||||||
|
_SoftSerial_PMS->begin(baudRate);
|
||||||
|
|
||||||
|
if(getPM2() <= 0){
|
||||||
|
|
||||||
|
if (_debugMsg) {
|
||||||
|
Serial.println("PMS Sensor Failed to Initialize ");
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
Serial.println("PMS Successfully Initialized. Heating up for 10s");
|
||||||
|
delay(10000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int AirGradient::getPM2(){
|
||||||
|
int pm02;
|
||||||
|
DATA data;
|
||||||
|
requestRead();
|
||||||
|
if (readUntil(data)) {
|
||||||
|
pm02 = data.PM_AE_UG_2_5;
|
||||||
|
return pm02;
|
||||||
|
} else {
|
||||||
|
//Serial.println("no PMS data");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Private Methods /////////////////////////////////////////////////////////////
|
||||||
|
// Functions only available to other functions in this library
|
||||||
|
|
||||||
|
//START PMS FUNCTIONS //
|
||||||
|
|
||||||
|
void AirGradient::PMS(Stream& stream)
|
||||||
|
{
|
||||||
|
this->_stream = &stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Standby mode. For low power consumption and prolong the life of the sensor.
|
||||||
|
void AirGradient::sleep()
|
||||||
|
{
|
||||||
|
uint8_t command[] = { 0x42, 0x4D, 0xE4, 0x00, 0x00, 0x01, 0x73 };
|
||||||
|
_stream->write(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Operating mode. Stable data should be got at least 30 seconds after the sensor wakeup from the sleep mode because of the fan's performance.
|
||||||
|
void AirGradient::wakeUp()
|
||||||
|
{
|
||||||
|
uint8_t command[] = { 0x42, 0x4D, 0xE4, 0x00, 0x01, 0x01, 0x74 };
|
||||||
|
_stream->write(command, sizeof(command));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Active mode. Default mode after power up. In this mode sensor would send serial data to the host automatically.
|
||||||
|
void AirGradient::activeMode()
|
||||||
|
{
|
||||||
|
|
||||||
|
uint8_t command[] = { 0x42, 0x4D, 0xE1, 0x00, 0x01, 0x01, 0x71 };
|
||||||
|
_stream->write(command, sizeof(command));
|
||||||
|
_mode = MODE_ACTIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Passive mode. In this mode sensor would send serial data to the host only for request.
|
||||||
|
void AirGradient::passiveMode()
|
||||||
|
{
|
||||||
|
uint8_t command[] = { 0x42, 0x4D, 0xE1, 0x00, 0x00, 0x01, 0x70 };
|
||||||
|
_stream->write(command, sizeof(command));
|
||||||
|
_mode = MODE_PASSIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Request read in Passive Mode.
|
||||||
|
void AirGradient::requestRead()
|
||||||
|
{
|
||||||
|
if (_mode == MODE_PASSIVE)
|
||||||
|
{
|
||||||
|
uint8_t command[] = { 0x42, 0x4D, 0xE2, 0x00, 0x00, 0x01, 0x71 };
|
||||||
|
_stream->write(command, sizeof(command));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Non-blocking function for parse response.
|
||||||
|
bool AirGradient::read_PMS(DATA& data)
|
||||||
|
{
|
||||||
|
_data = &data;
|
||||||
|
loop();
|
||||||
|
|
||||||
|
return _PMSstatus == STATUS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Blocking function for parse response. Default timeout is 1s.
|
||||||
|
bool AirGradient::readUntil(DATA& data, uint16_t timeout)
|
||||||
|
{
|
||||||
|
_data = &data;
|
||||||
|
uint32_t start = millis();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
loop();
|
||||||
|
if (_PMSstatus == STATUS_OK) break;
|
||||||
|
} while (millis() - start < timeout);
|
||||||
|
|
||||||
|
return _PMSstatus == STATUS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AirGradient::loop()
|
||||||
|
{
|
||||||
|
_PMSstatus = STATUS_WAITING;
|
||||||
|
if (_stream->available())
|
||||||
|
{
|
||||||
|
uint8_t ch = _stream->read();
|
||||||
|
|
||||||
|
switch (_index)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
if (ch != 0x42)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_calculatedChecksum = ch;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
if (ch != 0x4D)
|
||||||
|
{
|
||||||
|
_index = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_calculatedChecksum += ch;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
_calculatedChecksum += ch;
|
||||||
|
_frameLen = ch << 8;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
_frameLen |= ch;
|
||||||
|
// Unsupported sensor, different frame length, transmission error e.t.c.
|
||||||
|
if (_frameLen != 2 * 9 + 2 && _frameLen != 2 * 13 + 2)
|
||||||
|
{
|
||||||
|
_index = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_calculatedChecksum += ch;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (_index == _frameLen + 2)
|
||||||
|
{
|
||||||
|
_checksum = ch << 8;
|
||||||
|
}
|
||||||
|
else if (_index == _frameLen + 2 + 1)
|
||||||
|
{
|
||||||
|
_checksum |= ch;
|
||||||
|
|
||||||
|
if (_calculatedChecksum == _checksum)
|
||||||
|
{
|
||||||
|
_PMSstatus = STATUS_OK;
|
||||||
|
|
||||||
|
// Standard Particles, CF=1.
|
||||||
|
_data->PM_SP_UG_1_0 = makeWord(_payload[0], _payload[1]);
|
||||||
|
_data->PM_SP_UG_2_5 = makeWord(_payload[2], _payload[3]);
|
||||||
|
_data->PM_SP_UG_10_0 = makeWord(_payload[4], _payload[5]);
|
||||||
|
|
||||||
|
// Atmospheric Environment.
|
||||||
|
_data->PM_AE_UG_1_0 = makeWord(_payload[6], _payload[7]);
|
||||||
|
_data->PM_AE_UG_2_5 = makeWord(_payload[8], _payload[9]);
|
||||||
|
_data->PM_AE_UG_10_0 = makeWord(_payload[10], _payload[11]);
|
||||||
|
}
|
||||||
|
|
||||||
|
_index = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_calculatedChecksum += ch;
|
||||||
|
uint8_t payloadIndex = _index - 4;
|
||||||
|
|
||||||
|
// Payload is common to all sensors (first 2x6 bytes).
|
||||||
|
if (payloadIndex < sizeof(_payload))
|
||||||
|
{
|
||||||
|
_payload[payloadIndex] = ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
_index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//END PMS FUNCTIONS //
|
||||||
|
|
||||||
|
//START TMP_RH FUNCTIONS//
|
||||||
|
uint32_t AirGradient::getTemp(){
|
||||||
|
TMP_RH result = periodicFetchData();
|
||||||
|
return result.t;
|
||||||
|
}
|
||||||
|
int AirGradient::getRhum(){
|
||||||
|
TMP_RH result = periodicFetchData();
|
||||||
|
return result.rh;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TMP_RH_ErrorCode AirGradient::TMP_RH_Init(uint8_t address) {
|
||||||
|
if (_debugMsg) {
|
||||||
|
Serial.println("Initializing TMP_RH...");
|
||||||
|
}
|
||||||
|
TMP_RH_ErrorCode error = SHT3XD_NO_ERROR;
|
||||||
|
_address = address;
|
||||||
|
periodicStart(SHT3XD_REPEATABILITY_HIGH, SHT3XD_FREQUENCY_10HZ);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
TMP_RH_ErrorCode AirGradient::reset()
|
||||||
|
{
|
||||||
|
return softReset();
|
||||||
|
}
|
||||||
|
|
||||||
|
TMP_RH AirGradient::periodicFetchData() //
|
||||||
|
{
|
||||||
|
TMP_RH_ErrorCode error = writeCommand(SHT3XD_CMD_FETCH_DATA);
|
||||||
|
if (error == SHT3XD_NO_ERROR)
|
||||||
|
return readTemperatureAndHumidity();
|
||||||
|
else
|
||||||
|
returnError(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
TMP_RH_ErrorCode AirGradient::periodicStop() {
|
||||||
|
return writeCommand(SHT3XD_CMD_STOP_PERIODIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
TMP_RH_ErrorCode AirGradient::periodicStart(TMP_RH_Repeatability repeatability, TMP_RH_Frequency frequency) //
|
||||||
|
{
|
||||||
|
TMP_RH_ErrorCode error;
|
||||||
|
|
||||||
|
switch (repeatability)
|
||||||
|
{
|
||||||
|
case SHT3XD_REPEATABILITY_LOW:
|
||||||
|
switch (frequency)
|
||||||
|
{
|
||||||
|
case SHT3XD_FREQUENCY_HZ5:
|
||||||
|
error = writeCommand(SHT3XD_CMD_PERIODIC_HALF_L);
|
||||||
|
break;
|
||||||
|
case SHT3XD_FREQUENCY_1HZ:
|
||||||
|
error = writeCommand(SHT3XD_CMD_PERIODIC_1_L);
|
||||||
|
break;
|
||||||
|
case SHT3XD_FREQUENCY_2HZ:
|
||||||
|
error = writeCommand(SHT3XD_CMD_PERIODIC_2_L);
|
||||||
|
break;
|
||||||
|
case SHT3XD_FREQUENCY_4HZ:
|
||||||
|
error = writeCommand(SHT3XD_CMD_PERIODIC_4_L);
|
||||||
|
break;
|
||||||
|
case SHT3XD_FREQUENCY_10HZ:
|
||||||
|
error = writeCommand(SHT3XD_CMD_PERIODIC_10_L);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error = SHT3XD_PARAM_WRONG_FREQUENCY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SHT3XD_REPEATABILITY_MEDIUM:
|
||||||
|
switch (frequency)
|
||||||
|
{
|
||||||
|
case SHT3XD_FREQUENCY_HZ5:
|
||||||
|
error = writeCommand(SHT3XD_CMD_PERIODIC_HALF_M);
|
||||||
|
break;
|
||||||
|
case SHT3XD_FREQUENCY_1HZ:
|
||||||
|
error = writeCommand(SHT3XD_CMD_PERIODIC_1_M);
|
||||||
|
break;
|
||||||
|
case SHT3XD_FREQUENCY_2HZ:
|
||||||
|
error = writeCommand(SHT3XD_CMD_PERIODIC_2_M);
|
||||||
|
break;
|
||||||
|
case SHT3XD_FREQUENCY_4HZ:
|
||||||
|
error = writeCommand(SHT3XD_CMD_PERIODIC_4_M);
|
||||||
|
break;
|
||||||
|
case SHT3XD_FREQUENCY_10HZ:
|
||||||
|
error = writeCommand(SHT3XD_CMD_PERIODIC_10_M);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error = SHT3XD_PARAM_WRONG_FREQUENCY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SHT3XD_REPEATABILITY_HIGH:
|
||||||
|
switch (frequency)
|
||||||
|
{
|
||||||
|
case SHT3XD_FREQUENCY_HZ5:
|
||||||
|
error = writeCommand(SHT3XD_CMD_PERIODIC_HALF_H);
|
||||||
|
break;
|
||||||
|
case SHT3XD_FREQUENCY_1HZ:
|
||||||
|
error = writeCommand(SHT3XD_CMD_PERIODIC_1_H);
|
||||||
|
break;
|
||||||
|
case SHT3XD_FREQUENCY_2HZ:
|
||||||
|
error = writeCommand(SHT3XD_CMD_PERIODIC_2_H);
|
||||||
|
break;
|
||||||
|
case SHT3XD_FREQUENCY_4HZ:
|
||||||
|
error = writeCommand(SHT3XD_CMD_PERIODIC_4_H);
|
||||||
|
break;
|
||||||
|
case SHT3XD_FREQUENCY_10HZ:
|
||||||
|
error = writeCommand(SHT3XD_CMD_PERIODIC_10_H);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error = SHT3XD_PARAM_WRONG_FREQUENCY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error = SHT3XD_PARAM_WRONG_REPEATABILITY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
delay(100);
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TMP_RH_ErrorCode AirGradient::writeCommand(TMP_RH_Commands command)
|
||||||
|
{
|
||||||
|
Wire.beginTransmission(_address);
|
||||||
|
Wire.write(command >> 8);
|
||||||
|
Wire.write(command & 0xFF);
|
||||||
|
return (TMP_RH_ErrorCode)(-10 * Wire.endTransmission());
|
||||||
|
}
|
||||||
|
|
||||||
|
TMP_RH_ErrorCode AirGradient::softReset() {
|
||||||
|
return writeCommand(SHT3XD_CMD_SOFT_RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t AirGradient::readSerialNumber()
|
||||||
|
{
|
||||||
|
uint32_t result = SHT3XD_NO_ERROR;
|
||||||
|
uint16_t buf[2];
|
||||||
|
|
||||||
|
if (writeCommand(SHT3XD_CMD_READ_SERIAL_NUMBER) == SHT3XD_NO_ERROR) {
|
||||||
|
if (read_TMP_RH(buf, 2) == SHT3XD_NO_ERROR) {
|
||||||
|
result = (buf[0] << 16) | buf[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(writeCommand(SHT3XD_CMD_READ_SERIAL_NUMBER) != SHT3XD_NO_ERROR){
|
||||||
|
if (_debugMsg) {
|
||||||
|
Serial.println("TMP_RH Failed to Initialize.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
uint32_t AirGradient::testTMP_RH()
|
||||||
|
{
|
||||||
|
uint32_t result = SHT3XD_NO_ERROR;
|
||||||
|
uint16_t buf[2];
|
||||||
|
|
||||||
|
if (writeCommand(SHT3XD_CMD_READ_SERIAL_NUMBER) == SHT3XD_NO_ERROR) {
|
||||||
|
if (read_TMP_RH(buf, 2) == SHT3XD_NO_ERROR) {
|
||||||
|
result = (buf[0] << 16) | buf[1];
|
||||||
|
}
|
||||||
|
if (_debugMsg) {
|
||||||
|
Serial.print("TMP_RH successfully initialized with serial number: ");
|
||||||
|
Serial.println(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(writeCommand(SHT3XD_CMD_READ_SERIAL_NUMBER) != SHT3XD_NO_ERROR){
|
||||||
|
if (_debugMsg) {
|
||||||
|
Serial.println("TMP_RH Failed to Initialize.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
TMP_RH_ErrorCode AirGradient::clearAll() {
|
||||||
|
return writeCommand(SHT3XD_CMD_CLEAR_STATUS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TMP_RH AirGradient::readTemperatureAndHumidity()//
|
||||||
|
{
|
||||||
|
TMP_RH result;
|
||||||
|
|
||||||
|
result.t = 0;
|
||||||
|
result.rh = 0;
|
||||||
|
|
||||||
|
TMP_RH_ErrorCode error;
|
||||||
|
uint16_t buf[2];
|
||||||
|
|
||||||
|
if (error == SHT3XD_NO_ERROR)
|
||||||
|
error = read_TMP_RH(buf, 2);
|
||||||
|
|
||||||
|
if (error == SHT3XD_NO_ERROR) {
|
||||||
|
result.t = calculateTemperature(buf[0]);
|
||||||
|
result.rh = calculateHumidity(buf[1]);
|
||||||
|
}
|
||||||
|
result.error = error;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
TMP_RH_ErrorCode AirGradient::read_TMP_RH(uint16_t* data, uint8_t numOfPair)//
|
||||||
|
{
|
||||||
|
uint8_t buf[2];
|
||||||
|
uint8_t checksum;
|
||||||
|
|
||||||
|
const uint8_t numOfBytes = numOfPair * 3;
|
||||||
|
Wire.requestFrom(_address, numOfBytes);
|
||||||
|
|
||||||
|
int counter = 0;
|
||||||
|
|
||||||
|
for (counter = 0; counter < numOfPair; counter++) {
|
||||||
|
Wire.readBytes(buf, (uint8_t)2);
|
||||||
|
checksum = Wire.read();
|
||||||
|
|
||||||
|
if (checkCrc(buf, checksum) != 0)
|
||||||
|
return SHT3XD_CRC_ERROR;
|
||||||
|
|
||||||
|
data[counter] = (buf[0] << 8) | buf[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
return SHT3XD_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t AirGradient::checkCrc(uint8_t data[], uint8_t checksum)//
|
||||||
|
{
|
||||||
|
return calculateCrc(data) != checksum;
|
||||||
|
}
|
||||||
|
|
||||||
|
float AirGradient::calculateTemperature(uint16_t rawValue)//
|
||||||
|
{
|
||||||
|
return 175.0f * (float)rawValue / 65535.0f - 45.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float AirGradient::calculateHumidity(uint16_t rawValue)//
|
||||||
|
{
|
||||||
|
return 100.0f * rawValue / 65535.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t AirGradient::calculateCrc(uint8_t data[])
|
||||||
|
{
|
||||||
|
uint8_t bit;
|
||||||
|
uint8_t crc = 0xFF;
|
||||||
|
uint8_t dataCounter = 0;
|
||||||
|
|
||||||
|
for (; dataCounter < 2; dataCounter++)
|
||||||
|
{
|
||||||
|
crc ^= (data[dataCounter]);
|
||||||
|
for (bit = 8; bit > 0; --bit)
|
||||||
|
{
|
||||||
|
if (crc & 0x80)
|
||||||
|
crc = (crc << 1) ^ 0x131;
|
||||||
|
else
|
||||||
|
crc = (crc << 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
TMP_RH AirGradient::returnError(TMP_RH_ErrorCode error) {
|
||||||
|
TMP_RH result;
|
||||||
|
result.t = NULL;
|
||||||
|
result.rh = NULL;
|
||||||
|
result.error = error;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
//END TMP_RH FUNCTIONS //
|
||||||
|
|
||||||
|
//START C02 FUNCTIONS //
|
||||||
|
void AirGradient::C02_Init(){
|
||||||
|
C02_Init(4,3);
|
||||||
|
}
|
||||||
|
void AirGradient::C02_Init(int rx_pin,int tx_pin){
|
||||||
|
C02_Init(rx_pin,tx_pin,9600);
|
||||||
|
|
||||||
|
}
|
||||||
|
void AirGradient::C02_Init(int rx_pin,int tx_pin,int baudRate){
|
||||||
|
if (_debugMsg) {
|
||||||
|
Serial.println("Initializing C02...");
|
||||||
|
}
|
||||||
|
_SoftSerial_C02 = new SoftwareSerial(rx_pin,tx_pin);
|
||||||
|
_SoftSerial_C02->begin(baudRate);
|
||||||
|
|
||||||
|
if(getC02() == -1){
|
||||||
|
if (_debugMsg) {
|
||||||
|
Serial.println("C02 Sensor Failed to Initialize ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
Serial.println("C02 Successfully Initialized. Heating up for 10s");
|
||||||
|
delay(10000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int AirGradient::getC02(int retryLimit) {
|
||||||
|
int ctr = 0;
|
||||||
|
int result_c02 = 0;
|
||||||
|
while(result_c02 == -1){
|
||||||
|
result_c02 = get_C02_values();
|
||||||
|
if(ctr == retryLimit){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ctr++;
|
||||||
|
}
|
||||||
|
return result_c02;
|
||||||
|
}
|
||||||
|
int AirGradient::get_C02_values(){
|
||||||
|
int retry = 0;
|
||||||
|
CO2_READ_RESULT result;
|
||||||
|
const byte C02Command[] = {0xFE, 0X44, 0X00, 0X08, 0X02, 0X9F, 0X25};
|
||||||
|
byte C02Response[] = {0,0,0,0,0,0,0};
|
||||||
|
|
||||||
|
while(!(_SoftSerial_C02->available())) {
|
||||||
|
retry++;
|
||||||
|
// keep sending request until we start to get a response
|
||||||
|
_SoftSerial_C02->write(C02Command, 7);
|
||||||
|
delay(50);
|
||||||
|
if (retry > 10) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int timeout = 0;
|
||||||
|
|
||||||
|
while (_SoftSerial_C02->available() < 7) {
|
||||||
|
timeout++;
|
||||||
|
if (timeout > 10) {
|
||||||
|
while(_SoftSerial_C02->available())
|
||||||
|
_SoftSerial_C02->read();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
delay(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i=0; i < 7; i++) {
|
||||||
|
int byte = _SoftSerial_C02->read();
|
||||||
|
if (byte == -1) {
|
||||||
|
result.success = false;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
C02Response[i] = byte;
|
||||||
|
}
|
||||||
|
int valMultiplier = 1;
|
||||||
|
int high = C02Response[3];
|
||||||
|
int low = C02Response[4];
|
||||||
|
unsigned long val = high*256 + low;
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
//END C02 FUNCTIONS //
|
||||||
|
|
||||||
|
//START MHZ19 FUNCTIONS //
|
||||||
|
void AirGradient::MHZ19_Init(uint8_t type) {
|
||||||
|
MHZ19_Init(9,10,type);
|
||||||
|
}
|
||||||
|
void AirGradient::MHZ19_Init(int rx_pin,int tx_pin, uint8_t type) {
|
||||||
|
MHZ19_Init(rx_pin,tx_pin,9600,type);
|
||||||
|
}
|
||||||
|
void AirGradient::MHZ19_Init(int rx_pin,int tx_pin, int baudRate, uint8_t type) {
|
||||||
|
if (_debugMsg) {
|
||||||
|
Serial.println("Initializing MHZ19...");
|
||||||
|
}
|
||||||
|
_SoftSerial_MHZ19 = new SoftwareSerial(rx_pin,tx_pin);
|
||||||
|
_SoftSerial_MHZ19->begin(baudRate);
|
||||||
|
|
||||||
|
if(getC02() == -1){
|
||||||
|
if (_debugMsg) {
|
||||||
|
Serial.println("MHZ19 Sensor Failed to Initialize ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
Serial.println("MHZ19 Successfully Initialized. Heating up for 10s");
|
||||||
|
delay(10000);
|
||||||
|
}
|
||||||
|
|
||||||
|
_type_MHZ19 = type;
|
||||||
|
|
||||||
|
PwmConfigured = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables or disables the debug mode (more logging).
|
||||||
|
*/
|
||||||
|
void AirGradient::setDebug_MHZ19(bool enable) {
|
||||||
|
debug_MHZ19 = enable;
|
||||||
|
if (debug_MHZ19) {
|
||||||
|
Serial.println(F("MHZ: debug mode ENABLED"));
|
||||||
|
} else {
|
||||||
|
Serial.println(F("MHZ: debug mode DISABLED"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AirGradient::isPreHeating_MHZ19() {
|
||||||
|
if (_type_MHZ19 == MHZ14A) {
|
||||||
|
return millis() < (MHZ14A_PREHEATING_TIME);
|
||||||
|
} else if (_type_MHZ19 == MHZ19B) {
|
||||||
|
return millis() < (MHZ19B_PREHEATING_TIME);
|
||||||
|
} else {
|
||||||
|
Serial.println(F("MHZ::isPreheating_MHZ19() => UNKNOWN SENSOR"));
|
||||||
|
return false;
|
||||||
|
}//
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AirGradient::isReady_MHZ19() {
|
||||||
|
if (isPreHeating_MHZ19()) return false;
|
||||||
|
if (_type_MHZ19 == MHZ14A)
|
||||||
|
return lastRequest < millis() - MHZ14A_RESPONSE_TIME;
|
||||||
|
else if (_type_MHZ19 == MHZ19B)
|
||||||
|
return lastRequest < millis() - MHZ19B_RESPONSE_TIME;
|
||||||
|
else {
|
||||||
|
Serial.print(F("MHZ::isReady_MHZ19() => UNKNOWN SENSOR \""));
|
||||||
|
Serial.print(_type_MHZ19);
|
||||||
|
Serial.println(F("\""));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int AirGradient::readMHZ19() {
|
||||||
|
|
||||||
|
int firstRead = readInternal_MHZ19();
|
||||||
|
int secondRead = readInternal_MHZ19();
|
||||||
|
|
||||||
|
if (abs(secondRead - firstRead) > 50) {
|
||||||
|
// we arrive here sometimes when the CO2 sensor is not connected
|
||||||
|
// could possibly also be fixed with a pull-up resistor on Rx but if we forget this then ...
|
||||||
|
Serial.println("MHZ::read() inconsistent values");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.println("MHZ::read(1) " + String(firstRead));
|
||||||
|
Serial.println("MHZ::read(2) " + String(secondRead));
|
||||||
|
|
||||||
|
// TODO: return average?
|
||||||
|
return secondRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
int AirGradient::readInternal_MHZ19() {
|
||||||
|
if (!SerialConfigured) {
|
||||||
|
if (debug_MHZ19) Serial.println(F("-- serial is not configured"));
|
||||||
|
return STATUS_serial_MHZ19_NOT_CONFIGURED;
|
||||||
|
}
|
||||||
|
// if (!isReady_MHZ19()) return STATUS_NOT_READY;
|
||||||
|
if (debug_MHZ19) Serial.println(F("-- read CO2 uart ---"));
|
||||||
|
byte cmd[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79};
|
||||||
|
unsigned char response[9]; // for answer
|
||||||
|
|
||||||
|
if (debug_MHZ19) Serial.print(F(" >> Sending CO2 request"));
|
||||||
|
_SoftSerial_MHZ19->write(cmd, 9); // request PPM CO2
|
||||||
|
lastRequest = millis();
|
||||||
|
|
||||||
|
// clear the buffer
|
||||||
|
memset(response, 0, 9);
|
||||||
|
|
||||||
|
int waited = 0;
|
||||||
|
while (_SoftSerial_MHZ19->available() == 0) {
|
||||||
|
if (debug_MHZ19) Serial.print(".");
|
||||||
|
delay(100); // wait a short moment to avoid false reading
|
||||||
|
if (waited++ > 10) {
|
||||||
|
if (debug_MHZ19) Serial.println(F("No response after 10 seconds"));
|
||||||
|
_SoftSerial_MHZ19->flush();
|
||||||
|
return STATUS_NO_RESPONSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (debug_MHZ19) Serial.println();
|
||||||
|
|
||||||
|
// The serial stream can get out of sync. The response starts with 0xff, try
|
||||||
|
// to resync.
|
||||||
|
// TODO: I think this might be wrong any only happens during initialization?
|
||||||
|
boolean skip = false;
|
||||||
|
while (_SoftSerial_MHZ19->available() > 0 && (unsigned char)_SoftSerial_MHZ19->peek() != 0xFF) {
|
||||||
|
if (!skip) {
|
||||||
|
Serial.print(F("MHZ: - skipping unexpected readings:"));
|
||||||
|
skip = true;
|
||||||
|
}
|
||||||
|
Serial.print(" ");
|
||||||
|
Serial.print(_SoftSerial_MHZ19->peek(), HEX);
|
||||||
|
_SoftSerial_MHZ19->read();
|
||||||
|
}
|
||||||
|
if (skip) Serial.println();
|
||||||
|
|
||||||
|
if (_SoftSerial_MHZ19->available() > 0) {
|
||||||
|
int count = _SoftSerial_MHZ19->readBytes(response, 9);
|
||||||
|
if (count < 9) {
|
||||||
|
_SoftSerial_MHZ19->flush();
|
||||||
|
return STATUS_INCOMPLETE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_SoftSerial_MHZ19->flush();
|
||||||
|
return STATUS_INCOMPLETE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug_MHZ19) {
|
||||||
|
// print out the response in hexa
|
||||||
|
Serial.print(F(" << "));
|
||||||
|
for (int i = 0; i < 9; i++) {
|
||||||
|
Serial.print(response[i], HEX);
|
||||||
|
Serial.print(F(" "));
|
||||||
|
}
|
||||||
|
Serial.println(F(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
// checksum
|
||||||
|
byte check = getCheckSum_MHZ19(response);
|
||||||
|
if (response[8] != check) {
|
||||||
|
Serial.println(F("MHZ: Checksum not OK!"));
|
||||||
|
Serial.print(F("MHZ: Received: "));
|
||||||
|
Serial.println(response[8], HEX);
|
||||||
|
Serial.print(F("MHZ: Should be: "));
|
||||||
|
Serial.println(check, HEX);
|
||||||
|
temperature_MHZ19 = STATUS_CHECKSUM_MISMATCH;
|
||||||
|
_SoftSerial_MHZ19->flush();
|
||||||
|
return STATUS_CHECKSUM_MISMATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ppm_uart = 256 * (unsigned int)response[2] + (unsigned int)response[3];
|
||||||
|
|
||||||
|
temperature_MHZ19 = response[4] - 44; // - 40;
|
||||||
|
|
||||||
|
byte status = response[5];
|
||||||
|
if (debug_MHZ19) {
|
||||||
|
Serial.print(F(" # PPM UART: "));
|
||||||
|
Serial.println(ppm_uart);
|
||||||
|
Serial.print(F(" # temperature_MHZ19? "));
|
||||||
|
Serial.println(temperature_MHZ19);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is always 0 for version 14a and 19b
|
||||||
|
// Version 19a?: status != 0x40
|
||||||
|
if (debug_MHZ19 && status != 0) {
|
||||||
|
Serial.print(F(" ! Status maybe not OK ! "));
|
||||||
|
Serial.println(status, HEX);
|
||||||
|
} else if (debug_MHZ19) {
|
||||||
|
Serial.print(F(" Status OK: "));
|
||||||
|
Serial.println(status, HEX);
|
||||||
|
}
|
||||||
|
|
||||||
|
_SoftSerial_MHZ19->flush();
|
||||||
|
return ppm_uart;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
byte AirGradient::getCheckSum_MHZ19(byte* packet) {
|
||||||
|
if (!SerialConfigured) {
|
||||||
|
if (debug_MHZ19) Serial.println(F("-- serial is not configured"));
|
||||||
|
return STATUS_serial_MHZ19_NOT_CONFIGURED;
|
||||||
|
}
|
||||||
|
if (debug_MHZ19) Serial.println(F(" getCheckSum_MHZ19()"));
|
||||||
|
byte i;
|
||||||
|
unsigned char checksum = 0;
|
||||||
|
for (i = 1; i < 8; i++) {
|
||||||
|
checksum += packet[i];
|
||||||
|
}
|
||||||
|
checksum = 0xff - checksum;
|
||||||
|
checksum += 1;
|
||||||
|
return checksum;
|
||||||
|
}
|
||||||
|
|
||||||
|
//END MHZ19 FUNCTIONS //
|
300
AirGradient/AirGradient.h
Normal file
300
AirGradient/AirGradient.h
Normal file
@ -0,0 +1,300 @@
|
|||||||
|
/*
|
||||||
|
Test.h - Test library for Wiring - description
|
||||||
|
Copyright (c) 2006 John Doe. All right reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// ensure this library description is only included once
|
||||||
|
#ifndef AirGradient_h
|
||||||
|
#define AirGradient_h
|
||||||
|
|
||||||
|
#include <SoftwareSerial.h>
|
||||||
|
#include <Print.h>
|
||||||
|
#include "Stream.h"
|
||||||
|
//MHZ19 CONSTANTS START
|
||||||
|
// types of sensors.
|
||||||
|
extern const int MHZ14A;
|
||||||
|
extern const int MHZ19B;
|
||||||
|
|
||||||
|
// status codes
|
||||||
|
extern const int STATUS_NO_RESPONSE;
|
||||||
|
extern const int STATUS_CHECKSUM_MISMATCH;
|
||||||
|
extern const int STATUS_INCOMPLETE;
|
||||||
|
extern const int STATUS_NOT_READY;
|
||||||
|
//MHZ19 CONSTANTS END
|
||||||
|
|
||||||
|
//ENUMS AND STRUCT FOR TMP_RH START
|
||||||
|
typedef enum {
|
||||||
|
SHT3XD_CMD_READ_SERIAL_NUMBER = 0x3780,
|
||||||
|
|
||||||
|
SHT3XD_CMD_READ_STATUS = 0xF32D,
|
||||||
|
SHT3XD_CMD_CLEAR_STATUS = 0x3041,
|
||||||
|
|
||||||
|
SHT3XD_CMD_HEATER_ENABLE = 0x306D,
|
||||||
|
SHT3XD_CMD_HEATER_DISABLE = 0x3066,
|
||||||
|
|
||||||
|
SHT3XD_CMD_SOFT_RESET = 0x30A2,
|
||||||
|
|
||||||
|
SHT3XD_CMD_CLOCK_STRETCH_H = 0x2C06,
|
||||||
|
SHT3XD_CMD_CLOCK_STRETCH_M = 0x2C0D,
|
||||||
|
SHT3XD_CMD_CLOCK_STRETCH_L = 0x2C10,
|
||||||
|
|
||||||
|
SHT3XD_CMD_POLLING_H = 0x2400,
|
||||||
|
SHT3XD_CMD_POLLING_M = 0x240B,
|
||||||
|
SHT3XD_CMD_POLLING_L = 0x2416,
|
||||||
|
|
||||||
|
SHT3XD_CMD_ART = 0x2B32,
|
||||||
|
|
||||||
|
SHT3XD_CMD_PERIODIC_HALF_H = 0x2032,
|
||||||
|
SHT3XD_CMD_PERIODIC_HALF_M = 0x2024,
|
||||||
|
SHT3XD_CMD_PERIODIC_HALF_L = 0x202F,
|
||||||
|
SHT3XD_CMD_PERIODIC_1_H = 0x2130,
|
||||||
|
SHT3XD_CMD_PERIODIC_1_M = 0x2126,
|
||||||
|
SHT3XD_CMD_PERIODIC_1_L = 0x212D,
|
||||||
|
SHT3XD_CMD_PERIODIC_2_H = 0x2236,
|
||||||
|
SHT3XD_CMD_PERIODIC_2_M = 0x2220,
|
||||||
|
SHT3XD_CMD_PERIODIC_2_L = 0x222B,
|
||||||
|
SHT3XD_CMD_PERIODIC_4_H = 0x2334,
|
||||||
|
SHT3XD_CMD_PERIODIC_4_M = 0x2322,
|
||||||
|
SHT3XD_CMD_PERIODIC_4_L = 0x2329,
|
||||||
|
SHT3XD_CMD_PERIODIC_10_H = 0x2737,
|
||||||
|
SHT3XD_CMD_PERIODIC_10_M = 0x2721,
|
||||||
|
SHT3XD_CMD_PERIODIC_10_L = 0x272A,
|
||||||
|
|
||||||
|
SHT3XD_CMD_FETCH_DATA = 0xE000,
|
||||||
|
SHT3XD_CMD_STOP_PERIODIC = 0x3093,
|
||||||
|
|
||||||
|
SHT3XD_CMD_READ_ALR_LIMIT_LS = 0xE102,
|
||||||
|
SHT3XD_CMD_READ_ALR_LIMIT_LC = 0xE109,
|
||||||
|
SHT3XD_CMD_READ_ALR_LIMIT_HS = 0xE11F,
|
||||||
|
SHT3XD_CMD_READ_ALR_LIMIT_HC = 0xE114,
|
||||||
|
|
||||||
|
SHT3XD_CMD_WRITE_ALR_LIMIT_HS = 0x611D,
|
||||||
|
SHT3XD_CMD_WRITE_ALR_LIMIT_HC = 0x6116,
|
||||||
|
SHT3XD_CMD_WRITE_ALR_LIMIT_LC = 0x610B,
|
||||||
|
SHT3XD_CMD_WRITE_ALR_LIMIT_LS = 0x6100,
|
||||||
|
|
||||||
|
SHT3XD_CMD_NO_SLEEP = 0x303E,
|
||||||
|
} TMP_RH_Commands;
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SHT3XD_REPEATABILITY_HIGH,
|
||||||
|
SHT3XD_REPEATABILITY_MEDIUM,
|
||||||
|
SHT3XD_REPEATABILITY_LOW,
|
||||||
|
} TMP_RH_Repeatability;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SHT3XD_MODE_CLOCK_STRETCH,
|
||||||
|
SHT3XD_MODE_POLLING,
|
||||||
|
} TMP_RH_Mode;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SHT3XD_FREQUENCY_HZ5,
|
||||||
|
SHT3XD_FREQUENCY_1HZ,
|
||||||
|
SHT3XD_FREQUENCY_2HZ,
|
||||||
|
SHT3XD_FREQUENCY_4HZ,
|
||||||
|
SHT3XD_FREQUENCY_10HZ
|
||||||
|
} TMP_RH_Frequency;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SHT3XD_NO_ERROR = 0,
|
||||||
|
|
||||||
|
SHT3XD_CRC_ERROR = -101,
|
||||||
|
SHT3XD_TIMEOUT_ERROR = -102,
|
||||||
|
|
||||||
|
SHT3XD_PARAM_WRONG_MODE = -501,
|
||||||
|
SHT3XD_PARAM_WRONG_REPEATABILITY = -502,
|
||||||
|
SHT3XD_PARAM_WRONG_FREQUENCY = -503,
|
||||||
|
SHT3XD_PARAM_WRONG_ALERT = -504,
|
||||||
|
|
||||||
|
// Wire I2C translated error codes
|
||||||
|
SHT3XD_WIRE_I2C_DATA_TOO_LOG = -10,
|
||||||
|
SHT3XD_WIRE_I2C_RECEIVED_NACK_ON_ADDRESS = -20,
|
||||||
|
SHT3XD_WIRE_I2C_RECEIVED_NACK_ON_DATA = -30,
|
||||||
|
SHT3XD_WIRE_I2C_UNKNOW_ERROR = -40
|
||||||
|
} TMP_RH_ErrorCode;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
uint16_t rawData;
|
||||||
|
struct {
|
||||||
|
uint8_t WriteDataChecksumStatus : 1;
|
||||||
|
uint8_t CommandStatus : 1;
|
||||||
|
uint8_t Reserved0 : 2;
|
||||||
|
uint8_t SystemResetDetected : 1;
|
||||||
|
uint8_t Reserved1 : 5;
|
||||||
|
uint8_t T_TrackingAlert : 1;
|
||||||
|
uint8_t RH_TrackingAlert : 1;
|
||||||
|
uint8_t Reserved2 : 1;
|
||||||
|
uint8_t HeaterStatus : 1;
|
||||||
|
uint8_t Reserved3 : 1;
|
||||||
|
uint8_t AlertPending : 1;
|
||||||
|
};
|
||||||
|
} TMP_RH_RegisterStatus;
|
||||||
|
|
||||||
|
struct TMP_RH {
|
||||||
|
float t;
|
||||||
|
int rh;
|
||||||
|
TMP_RH_ErrorCode error;
|
||||||
|
};
|
||||||
|
// ENUMS AND STRUCTS FOR TMP_RH END
|
||||||
|
|
||||||
|
//ENUMS STRUCTS FOR C02 START
|
||||||
|
struct CO2_READ_RESULT {
|
||||||
|
int co2 = -1;
|
||||||
|
bool success = false;
|
||||||
|
};
|
||||||
|
//ENUMS STRUCTS FOR C02 END
|
||||||
|
|
||||||
|
// library interface description
|
||||||
|
class AirGradient
|
||||||
|
{
|
||||||
|
// user-accessible "public" interface
|
||||||
|
public:
|
||||||
|
AirGradient(bool displayMsg=false,int baudRate=9600);
|
||||||
|
//void begin(int baudRate=9600);
|
||||||
|
|
||||||
|
static void setOutput(Print& debugOut, bool verbose = true);
|
||||||
|
|
||||||
|
void beginC02(void);
|
||||||
|
void beginC02(int,int);
|
||||||
|
void PMS_Init(void);
|
||||||
|
void PMS_Init(int,int);
|
||||||
|
void PMS_Init(int,int,int);
|
||||||
|
|
||||||
|
bool _debugMsg;
|
||||||
|
|
||||||
|
|
||||||
|
//PMS VARIABLES PUBLIC_START
|
||||||
|
static const uint16_t SINGLE_RESPONSE_TIME = 1000;
|
||||||
|
static const uint16_t TOTAL_RESPONSE_TIME = 1000 * 10;
|
||||||
|
static const uint16_t STEADY_RESPONSE_TIME = 1000 * 30;
|
||||||
|
|
||||||
|
static const uint16_t BAUD_RATE = 9600;
|
||||||
|
|
||||||
|
struct DATA {
|
||||||
|
// Standard Particles, CF=1
|
||||||
|
uint16_t PM_SP_UG_1_0;
|
||||||
|
uint16_t PM_SP_UG_2_5;
|
||||||
|
uint16_t PM_SP_UG_10_0;
|
||||||
|
|
||||||
|
// Atmospheric environment
|
||||||
|
uint16_t PM_AE_UG_1_0;
|
||||||
|
uint16_t PM_AE_UG_2_5;
|
||||||
|
uint16_t PM_AE_UG_10_0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void PMS(Stream&);
|
||||||
|
void sleep();
|
||||||
|
void wakeUp();
|
||||||
|
void activeMode();
|
||||||
|
void passiveMode();
|
||||||
|
|
||||||
|
void requestRead();
|
||||||
|
bool read_PMS(DATA& data);
|
||||||
|
bool readUntil(DATA& data, uint16_t timeout = SINGLE_RESPONSE_TIME);
|
||||||
|
int getPM2();
|
||||||
|
|
||||||
|
//PMS VARIABLES PUBLIC_END
|
||||||
|
|
||||||
|
//TMP_RH VARIABLES PUBLIC START
|
||||||
|
void ClosedCube_TMP_RH();
|
||||||
|
uint32_t getTemp();
|
||||||
|
int getRhum();
|
||||||
|
TMP_RH_ErrorCode TMP_RH_Init(uint8_t address);
|
||||||
|
TMP_RH_ErrorCode clearAll();
|
||||||
|
|
||||||
|
TMP_RH_ErrorCode softReset();
|
||||||
|
TMP_RH_ErrorCode reset(); // same as softReset
|
||||||
|
|
||||||
|
uint32_t readSerialNumber();
|
||||||
|
uint32_t testTMP_RH();
|
||||||
|
|
||||||
|
TMP_RH_ErrorCode periodicStart(TMP_RH_Repeatability repeatability, TMP_RH_Frequency frequency);
|
||||||
|
TMP_RH periodicFetchData();
|
||||||
|
TMP_RH_ErrorCode periodicStop();
|
||||||
|
|
||||||
|
//TMP_RH VARIABLES PUBLIC END
|
||||||
|
|
||||||
|
//C02 VARIABLES PUBLIC START
|
||||||
|
void C02_Init();
|
||||||
|
void C02_Init(int,int);
|
||||||
|
void C02_Init(int,int,int);
|
||||||
|
int getC02(int retryLimit = 5);
|
||||||
|
int get_C02_values();
|
||||||
|
SoftwareSerial *_SoftSerial_C02;
|
||||||
|
|
||||||
|
//CO2 VARIABLES PUBLIC END
|
||||||
|
|
||||||
|
//MHZ19 VARIABLES PUBLIC START
|
||||||
|
void MHZ19_Init(uint8_t);
|
||||||
|
void MHZ19_Init(int,int,uint8_t);
|
||||||
|
void MHZ19_Init(int,int,int,uint8_t);
|
||||||
|
void setDebug_MHZ19(bool enable);
|
||||||
|
bool isPreHeating_MHZ19();
|
||||||
|
bool isReady_MHZ19();
|
||||||
|
|
||||||
|
int readMHZ19();
|
||||||
|
|
||||||
|
//MHZ19 VARIABLES PUBLIC END
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// library-accessible "private" interface
|
||||||
|
private:
|
||||||
|
int value;
|
||||||
|
|
||||||
|
|
||||||
|
//PMS VARIABLES PRIVATE START
|
||||||
|
enum STATUS { STATUS_WAITING, STATUS_OK };
|
||||||
|
enum MODE { MODE_ACTIVE, MODE_PASSIVE };
|
||||||
|
|
||||||
|
uint8_t _payload[12];
|
||||||
|
Stream* _stream;
|
||||||
|
DATA* _data;
|
||||||
|
STATUS _PMSstatus;
|
||||||
|
MODE _mode = MODE_ACTIVE;
|
||||||
|
|
||||||
|
uint8_t _index = 0;
|
||||||
|
uint16_t _frameLen;
|
||||||
|
uint16_t _checksum;
|
||||||
|
uint16_t _calculatedChecksum;
|
||||||
|
SoftwareSerial *_SoftSerial_PMS;
|
||||||
|
void loop();
|
||||||
|
//PMS VARIABLES PRIVATE END
|
||||||
|
|
||||||
|
//TMP_RH VARIABLES PRIVATE START
|
||||||
|
uint8_t _address;
|
||||||
|
TMP_RH_RegisterStatus _status;
|
||||||
|
|
||||||
|
TMP_RH_ErrorCode writeCommand(TMP_RH_Commands command);
|
||||||
|
TMP_RH_ErrorCode writeAlertData(TMP_RH_Commands command, float temperature, float humidity);
|
||||||
|
|
||||||
|
uint8_t checkCrc(uint8_t data[], uint8_t checksum);
|
||||||
|
uint8_t calculateCrc(uint8_t data[]);
|
||||||
|
|
||||||
|
float calculateHumidity(uint16_t rawValue);
|
||||||
|
float calculateTemperature(uint16_t rawValue);
|
||||||
|
|
||||||
|
TMP_RH readTemperatureAndHumidity();
|
||||||
|
TMP_RH_ErrorCode read_TMP_RH(uint16_t* data, uint8_t numOfPair);
|
||||||
|
|
||||||
|
TMP_RH returnError(TMP_RH_ErrorCode command);
|
||||||
|
//TMP_RH VARIABLES PRIVATE END
|
||||||
|
|
||||||
|
//MHZ19 VARABLES PUBLIC START
|
||||||
|
|
||||||
|
int readInternal_MHZ19();
|
||||||
|
|
||||||
|
uint8_t _type_MHZ19, temperature_MHZ19;
|
||||||
|
boolean debug_MHZ19 = false;
|
||||||
|
|
||||||
|
Stream * _serial_MHZ19;
|
||||||
|
SoftwareSerial *_SoftSerial_MHZ19;
|
||||||
|
byte getCheckSum_MHZ19(byte *packet);
|
||||||
|
//MHZ19 VARABLES PUBLIC END
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
21
AirGradient/LICENSE.md
Normal file
21
AirGradient/LICENSE.md
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2020 AirGradient
|
||||||
|
|
||||||
|
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.
|
8
AirGradient/README.md
Normal file
8
AirGradient/README.md
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
AirGradient Arduino Library for ESP8266 (Wemos D1 MINI)
|
||||||
|
=====================================================================================================
|
||||||
|
|
||||||
|
Build your own low cost air quality sensor with optional display measuring PM2.5, CO2, Temperature and Humidity.
|
||||||
|
|
||||||
|
This library makes it easy to read the sensor data from the Plantower PMS5003 PM2.5 sensor, the Senseair S8 and the SHT30/31 Temperature and Humidity sensor. Visit our blog for detailed build instructions and PCB layout.
|
||||||
|
|
||||||
|
https://www.airgradient.com/blog/
|
BIN
AirGradient/examples/.DS_Store
vendored
Normal file
BIN
AirGradient/examples/.DS_Store
vendored
Normal file
Binary file not shown.
BIN
AirGradient/examples/C02_PM_SHT/.DS_Store
vendored
Normal file
BIN
AirGradient/examples/C02_PM_SHT/.DS_Store
vendored
Normal file
Binary file not shown.
27
AirGradient/examples/C02_PM_SHT/C02_PM_SHT.ino
Normal file
27
AirGradient/examples/C02_PM_SHT/C02_PM_SHT.ino
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#include <AirGradient.h>
|
||||||
|
AirGradient ag = AirGradient();
|
||||||
|
|
||||||
|
void setup(){
|
||||||
|
Serial.begin(9600);
|
||||||
|
ag.PMS_Init();
|
||||||
|
ag.C02_Init();
|
||||||
|
ag.TMP_RH_Init(0x44); //check for SHT sensor with address 0x44
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop(){
|
||||||
|
|
||||||
|
int PM2 = ag.getPM2();
|
||||||
|
Serial.print("PM2: ");
|
||||||
|
Serial.println(PM2);
|
||||||
|
|
||||||
|
int CO2 = ag.getC02();
|
||||||
|
Serial.print("C02: ");
|
||||||
|
Serial.println(CO2);
|
||||||
|
|
||||||
|
TMP_RH result = ag.periodicFetchData();
|
||||||
|
Serial.print("Humidity: ");
|
||||||
|
Serial.print(result.rh);
|
||||||
|
Serial.print(" Temperature: ");
|
||||||
|
Serial.println(result.t);
|
||||||
|
delay(5000);
|
||||||
|
}
|
41
AirGradient/examples/C02_PM_SHT_OLED/C02_PM_SHT_OLED.ino
Normal file
41
AirGradient/examples/C02_PM_SHT_OLED/C02_PM_SHT_OLED.ino
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#include <AirGradient.h>
|
||||||
|
#include <Adafruit_GFX.h>
|
||||||
|
#include <Adafruit_SSD1306.h>
|
||||||
|
|
||||||
|
AirGradient ag = AirGradient();
|
||||||
|
#define OLED_RESET 0
|
||||||
|
Adafruit_SSD1306 display(OLED_RESET);
|
||||||
|
|
||||||
|
void setup(){
|
||||||
|
Serial.begin(9600);
|
||||||
|
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
|
||||||
|
ag.PMS_Init();
|
||||||
|
ag.C02_Init();
|
||||||
|
ag.TMP_RH_Init(0x44); //check for SHT sensor with address 0x44
|
||||||
|
showTextRectangle("Init", String(ESP.getChipId(),HEX),"AirGradient");
|
||||||
|
delay(2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop(){
|
||||||
|
int PM2 = ag.getPM2();
|
||||||
|
int CO2 = ag.getC02();
|
||||||
|
TMP_RH result = ag.periodicFetchData();
|
||||||
|
showTextRectangle(String(result.t)+"c "+String(result.rh)+"%", "PM2: "+ String(PM2), "CO2: "+String(CO2)+"");
|
||||||
|
delay(5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// DISPLAY
|
||||||
|
void showTextRectangle(String ln1, String ln2, String ln3) {
|
||||||
|
display.clearDisplay();
|
||||||
|
display.setTextColor(WHITE);
|
||||||
|
display.setTextSize(1);
|
||||||
|
display.setCursor(32,8);
|
||||||
|
display.println(ln1);
|
||||||
|
display.setTextSize(1);
|
||||||
|
display.setCursor(32,16);
|
||||||
|
display.println(ln2);
|
||||||
|
display.setTextSize(1);
|
||||||
|
display.setCursor(32,24);
|
||||||
|
display.println(ln3);
|
||||||
|
display.display();
|
||||||
|
}
|
@ -0,0 +1,77 @@
|
|||||||
|
#include <AirGradient.h>
|
||||||
|
#include <Adafruit_GFX.h>
|
||||||
|
#include <Adafruit_SSD1306.h>
|
||||||
|
#include <WiFiManager.h>
|
||||||
|
#include <ESP8266WiFi.h>
|
||||||
|
#include <ESP8266HTTPClient.h>
|
||||||
|
|
||||||
|
AirGradient ag = AirGradient();
|
||||||
|
#define OLED_RESET 0
|
||||||
|
Adafruit_SSD1306 display(OLED_RESET);
|
||||||
|
|
||||||
|
String APIROOT = "http://hw.airgradient.com/";
|
||||||
|
|
||||||
|
void setup(){
|
||||||
|
Serial.begin(9600);
|
||||||
|
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
|
||||||
|
ag.PMS_Init();
|
||||||
|
ag.C02_Init();
|
||||||
|
ag.TMP_RH_Init(0x44); //check for SHT sensor with address 0x44
|
||||||
|
showTextRectangle("Init", String(ESP.getChipId(),HEX),"AirGradient");
|
||||||
|
connectToWifi();
|
||||||
|
delay(2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop(){
|
||||||
|
int PM2 = ag.getPM2();
|
||||||
|
int CO2 = ag.getC02();
|
||||||
|
TMP_RH result = ag.periodicFetchData();
|
||||||
|
showTextRectangle(String(result.t)+"c "+String(result.rh)+"%", "PM2: "+ String(PM2), "CO2: "+String(CO2)+"");
|
||||||
|
|
||||||
|
// send payload
|
||||||
|
String payload = "{\"pm02\":" + String(PM2) + ",\"wifi\":" + String(WiFi.RSSI()) + ",\"rco2\":" + String(CO2) + ",\"atmp\":" + String(result.t) + ",\"rhum\":" + String(result.rh) + "}";
|
||||||
|
Serial.println(payload);
|
||||||
|
String POSTURL = APIROOT + "sensors/airgradient:" + String(ESP.getChipId(),HEX) + "/measures";
|
||||||
|
Serial.println(POSTURL);
|
||||||
|
HTTPClient http;
|
||||||
|
http.begin(POSTURL);
|
||||||
|
http.addHeader("content-type", "application/json");
|
||||||
|
int httpCode = http.POST(payload);
|
||||||
|
String response = http.getString();
|
||||||
|
Serial.println(httpCode);
|
||||||
|
Serial.println(response);
|
||||||
|
http.end();
|
||||||
|
|
||||||
|
delay(15000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// DISPLAY
|
||||||
|
void showTextRectangle(String ln1, String ln2, String ln3) {
|
||||||
|
display.clearDisplay();
|
||||||
|
display.setTextColor(WHITE);
|
||||||
|
display.setTextSize(1);
|
||||||
|
display.setCursor(32,8);
|
||||||
|
display.println(ln1);
|
||||||
|
display.setTextSize(1);
|
||||||
|
display.setCursor(32,16);
|
||||||
|
display.println(ln2);
|
||||||
|
display.setTextSize(1);
|
||||||
|
display.setCursor(32,24);
|
||||||
|
display.println(ln3);
|
||||||
|
display.display();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wifi Manager
|
||||||
|
void connectToWifi(){
|
||||||
|
WiFiManager wifiManager;
|
||||||
|
//chWiFi.disconnect(); //to delete previous saved hotspot
|
||||||
|
String HOTSPOT = "AIRGRADIENT-"+String(ESP.getChipId(),HEX);
|
||||||
|
wifiManager.setTimeout(120);
|
||||||
|
if(!wifiManager.autoConnect((const char*)HOTSPOT.c_str())) {
|
||||||
|
//Serial.println("failed to connect and hit timeout");
|
||||||
|
delay(3000);
|
||||||
|
ESP.restart();
|
||||||
|
delay(5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
16
AirGradient/examples/C02_Test/C02_Test.ino
Normal file
16
AirGradient/examples/C02_Test/C02_Test.ino
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#include <AirGradient.h>
|
||||||
|
AirGradient ag = AirGradient();
|
||||||
|
|
||||||
|
void setup(){
|
||||||
|
Serial.begin(9600);
|
||||||
|
ag.C02_Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop(){
|
||||||
|
|
||||||
|
int CO2 = ag.getC02();
|
||||||
|
Serial.print("C02: ");
|
||||||
|
Serial.println(CO2);
|
||||||
|
|
||||||
|
delay(5000);
|
||||||
|
}
|
16
AirGradient/examples/MHZ19_Test/MHZ19_Test.ino
Normal file
16
AirGradient/examples/MHZ19_Test/MHZ19_Test.ino
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#include <AirGradient.h>
|
||||||
|
AirGradient ag = AirGradient();
|
||||||
|
|
||||||
|
void setup(){
|
||||||
|
Serial.begin(9600);
|
||||||
|
ag.MHZ19_Init(MHZ19B);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop(){
|
||||||
|
|
||||||
|
int MHZ19_C02 = ag.readMHZ19();
|
||||||
|
Serial.print("C02: ");
|
||||||
|
Serial.println(MHZ19_C02);
|
||||||
|
|
||||||
|
delay(5000);
|
||||||
|
}
|
16
AirGradient/examples/PM2_Test/PM2_Test.ino
Normal file
16
AirGradient/examples/PM2_Test/PM2_Test.ino
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#include <AirGradient.h>
|
||||||
|
AirGradient ag = AirGradient();
|
||||||
|
|
||||||
|
void setup(){
|
||||||
|
Serial.begin(9600);
|
||||||
|
ag.PMS_Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop(){
|
||||||
|
|
||||||
|
int PM2 = ag.getPM2();
|
||||||
|
Serial.print("PM2: ");
|
||||||
|
Serial.println(PM2);
|
||||||
|
|
||||||
|
delay(5000);
|
||||||
|
}
|
16
AirGradient/examples/TMP_RH_Test/TMP_RH_Test.ino
Normal file
16
AirGradient/examples/TMP_RH_Test/TMP_RH_Test.ino
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#include <AirGradient.h>
|
||||||
|
AirGradient ag = AirGradient();
|
||||||
|
|
||||||
|
void setup(){
|
||||||
|
Serial.begin(9600);
|
||||||
|
ag.TMP_RH_Init(0x44); //check for SHT sensor with address 0x44
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop(){
|
||||||
|
TMP_RH result = ag.periodicFetchData();
|
||||||
|
Serial.print("Humidity: ");
|
||||||
|
Serial.print(result.rh);
|
||||||
|
Serial.print(" Temperature: ");
|
||||||
|
Serial.println(result.t);
|
||||||
|
delay(5000);
|
||||||
|
}
|
65
AirGradient/keywords.txt
Normal file
65
AirGradient/keywords.txt
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
#######################################
|
||||||
|
# Syntax Coloring Map For AirGradient
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Datatypes (KEYWORD1)
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
AirGradient KEYWORD1
|
||||||
|
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Methods and Functions (KEYWORD2)
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
setOutput KEYWORD2
|
||||||
|
beginC02 KEYWORD2
|
||||||
|
PMS_Init KEYWORD2
|
||||||
|
PMS KEYWORD2
|
||||||
|
sleep KEYWORD2
|
||||||
|
wakeUp KEYWORD2
|
||||||
|
activeMode KEYWORD2
|
||||||
|
passiveMode KEYWORD2
|
||||||
|
requestRead KEYWORD2
|
||||||
|
read_PMS KEYWORD2
|
||||||
|
readUntil KEYWORD2
|
||||||
|
getPM2 KEYWORD2
|
||||||
|
|
||||||
|
|
||||||
|
ClosedCube_TMP_RH KEYWORD2
|
||||||
|
getTemp KEYWORD2
|
||||||
|
getRhum KEYWORD2
|
||||||
|
TMP_RH_Init KEYWORD2
|
||||||
|
clearAll KEYWORD2
|
||||||
|
softReset KEYWORD2
|
||||||
|
reset KEYWORD2
|
||||||
|
readSerialNumber KEYWORD2
|
||||||
|
testTMP_RH KEYWORD2
|
||||||
|
periodicStart KEYWORD2
|
||||||
|
periodicFetchData KEYWORD2
|
||||||
|
periodicStop KEYWORD2
|
||||||
|
|
||||||
|
|
||||||
|
C02_Init KEYWORD2
|
||||||
|
getC02 KEYWORD2
|
||||||
|
get_C02_values KEYWORD2
|
||||||
|
|
||||||
|
|
||||||
|
MHZ19_Init KEYWORD2
|
||||||
|
setDebug_MHZ19 KEYWORD2
|
||||||
|
isPreHeating_MHZ19 KEYWORD2
|
||||||
|
readMHZ19 KEYWORD2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Instances (KEYWORD2)
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Constants (LITERAL1)
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
MHZ14A LITERAL1
|
||||||
|
MHZ19B LITERAL1
|
9
AirGradient/library.properties
Normal file
9
AirGradient/library.properties
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
name=AirGradient Air Quality Sensor
|
||||||
|
version=1.0.0
|
||||||
|
author=AirGradient <support@airgradient.com>
|
||||||
|
maintainer=AirGradient <support@airgradient.com>
|
||||||
|
sentence=ESP8266 library for an air quality sensor featuring PM2.5, CO2, Temperature and Humidity with OLED display.
|
||||||
|
paragraph=The library is very robust and works with the Plantower PMS5003 particle sensor, the Senseair S8 CO2 sensor and the SHT30/31 sensor for humidity and temperature. You can also connect an OLED display or send the air quality data to the AirGradient platform or any other backend.
|
||||||
|
category=Sensors
|
||||||
|
url=https://github.com/airgradienthq/arduino
|
||||||
|
architectures=*
|
39
AirGradient/readme.txt
Normal file
39
AirGradient/readme.txt
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
This is an example C++ library for Arduino 0004+, based on one created by
|
||||||
|
Nicholas Zambetti for Wiring 0006+
|
||||||
|
|
||||||
|
Installation
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
To install this library, just place this entire folder as a subfolder in your
|
||||||
|
Arduino/lib/targets/libraries folder.
|
||||||
|
|
||||||
|
When installed, this library should look like:
|
||||||
|
|
||||||
|
Arduino/lib/targets/libraries/Test (this library's folder)
|
||||||
|
Arduino/lib/targets/libraries/Test/Test.cpp (the library implementation file)
|
||||||
|
Arduino/lib/targets/libraries/Test/Test.h (the library description file)
|
||||||
|
Arduino/lib/targets/libraries/Test/keywords.txt (the syntax coloring file)
|
||||||
|
Arduino/lib/targets/libraries/Test/examples (the examples in the "open" menu)
|
||||||
|
Arduino/lib/targets/libraries/Test/readme.txt (this file)
|
||||||
|
|
||||||
|
Building
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
After this library is installed, you just have to start the Arduino application.
|
||||||
|
You may see a few warning messages as it's built.
|
||||||
|
|
||||||
|
To use this library in a sketch, go to the Sketch | Import Library menu and
|
||||||
|
select Test. This will add a corresponding line to the top of your sketch:
|
||||||
|
#include <Test.h>
|
||||||
|
|
||||||
|
To stop using this library, delete that line from your sketch.
|
||||||
|
|
||||||
|
Geeky information:
|
||||||
|
After a successful build of this library, a new file named "Test.o" will appear
|
||||||
|
in "Arduino/lib/targets/libraries/Test". This file is the built/compiled library
|
||||||
|
code.
|
||||||
|
|
||||||
|
If you choose to modify the code for this library (i.e. "Test.cpp" or "Test.h"),
|
||||||
|
then you must first 'unbuild' this library by deleting the "Test.o" file. The
|
||||||
|
new "Test.o" with your code will appear after the next press of "verify"
|
||||||
|
|
Reference in New Issue
Block a user