136 lines
6.1 KiB
C
136 lines
6.1 KiB
C
#ifndef MPS_SENSOR_H
|
|
#define MPS_SENSOR_H
|
|
|
|
#pragma once
|
|
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include "config.h"
|
|
|
|
// =====================================================
|
|
// MPS SENSOR COMMAND IDs
|
|
// =====================================================
|
|
#define MPS_CMD_ANSWER 0x01 // Returns a complete answer in one read
|
|
#define MPS_CMD_CONC 0x03 // Returns flammable gas concentration [%LEL]
|
|
#define MPS_CMD_ID 0x04 // Returns flammable gas ID
|
|
#define MPS_CMD_TEMP 0x21 // Returns ambient temperature (C)
|
|
#define MPS_CMD_PRES 0x22 // Returns ambient pressure (kPa)
|
|
#define MPS_CMD_REL_HUM 0x23 // Returns ambient relative humidity (%RH)
|
|
#define MPS_CMD_ABS_HUM 0x24 // Returns ambient absolute humidity (g/m3)
|
|
#define MPS_CMD_STATUS 0x41 // Returns MPS status code
|
|
#define MPS_CMD_VERSION 0x42 // Returns SW / HW / protocol versions
|
|
#define MPS_CMD_SENSOR_INFO 0x43 // Returns sensor serial number and info
|
|
#define MPS_CMD_MEAS 0x61 // Sets sensing mode and concentration unit
|
|
#define MPS_CMD_RESET 0x62 // Soft reset — clears all data and states
|
|
|
|
// =====================================================
|
|
// MPS MEASUREMENT MODE (payload for MPS_CMD_MEAS)
|
|
// =====================================================
|
|
// CONFIRMED from NevadaNano MPS 5.0 User Manual, Table 12.
|
|
// Only two modes are documented; there is no "idle" or "single" mode.
|
|
#define MPS_MEAS_MODE_CONT 0x2 // MPS_CONT — continuous autonomous mode
|
|
#define MPS_MEAS_MODE_STOP 0x3 // MPS_STOP — stop measurement
|
|
|
|
// CONFIRMED from User Manual, Table 11.
|
|
#define MPS_CONC_UNIT_LEL_ISO 0x0 // %LEL per ISO 10156
|
|
#define MPS_CONC_UNIT_LEL_IEC 0x2 // %LEL per IEC 60079-20-1
|
|
|
|
// =====================================================
|
|
// MPS STATUS CODES
|
|
// =====================================================
|
|
#define MPS_STATUS_OK 0x00
|
|
#define MPS_STATUS_CRC_FAILED 0x01
|
|
#define MPS_STATUS_BAD_PARAMETER 0x02
|
|
#define MPS_STATUS_EXECUTION_FAILED 0x03
|
|
#define MPS_STATUS_NO_MEMORY 0x04
|
|
#define MPS_STATUS_UNKNOWN_COMMAND 0x05
|
|
#define MPS_STATUS_INCOMPLETE_COMMAND 0x07
|
|
#define MPS_STATUS_HW_ERR_AO 0x20
|
|
#define MPS_STATUS_HW_ERR_VDD 0x21
|
|
#define MPS_STATUS_HW_ERR_VREF 0x22
|
|
#define MPS_STATUS_HW_ENV_XCD_RANGE 0x23
|
|
#define MPS_STATUS_HW_ENV_SNSR_MALFUNCTION 0x24
|
|
#define MPS_STATUS_HW_ERR_MCU 0x25
|
|
#define MPS_STATUS_SENSOR_INITIALIZATION 0x26
|
|
#define MPS_STATUS_SENSOR_STARTUP 0x27
|
|
#define MPS_STATUS_SENSOR_NEGATIVE 0x30
|
|
#define MPS_STATUS_CONDENSATION_DETECTED 0x31
|
|
#define MPS_STATUS_HW_SENSOR_MALFUNCTION 0x32
|
|
#define MPS_STATUS_GAS_DETECTED_DURING_STARTUP 0x33
|
|
#define MPS_STATUS_SLOW_GAS_ACCUMULATION 0x34
|
|
#define MPS_STATUS_BREATH_OR_HUMIDITY_SURGE 0x35
|
|
#define MPS_STATUS_WATCHDOG_MCU_RESET 0x36
|
|
#define MPS_STATUS_HW_ERR_WATCHDOG 0x37
|
|
#define MPS_STATUS_HW_ERR_DAC_ADC_XCD_RANGE 0x38
|
|
|
|
// =====================================================
|
|
// ALARM LEVELS
|
|
// =====================================================
|
|
typedef enum {
|
|
MPS_ALARM_NONE = 0,
|
|
MPS_ALARM_WARNING = 1,
|
|
MPS_ALARM_ALARM = 2,
|
|
MPS_ALARM_HIGH = 3
|
|
} MpsAlarmLevel_t;
|
|
|
|
// =====================================================
|
|
// PACKET STRUCTURES
|
|
// =====================================================
|
|
// CONFIRMED from NevadaNano MPS 5.0 User Manual, Tables 2 & 3.
|
|
// All multi-byte integers are Little-Endian on the wire.
|
|
//
|
|
// Request header (8 bytes): CmdID(2) + Length(2) + Reserved(2) + Checksum(2)
|
|
// Reply header (6 bytes): CmdID(1) + Status(1) + Length(2) + Checksum(2)
|
|
//
|
|
// NOTE: CmdID in the REQUEST is 2 bytes (high byte always 0x00) for alignment,
|
|
// even though only 1 byte is meaningful. This differs from the REPLY, where
|
|
// CmdID is 1 byte. Mixing these up breaks the CRC and the sensor will return
|
|
// CRC_FAILED (0x01) or simply not respond as expected.
|
|
typedef struct __attribute__((packed)) {
|
|
uint16_t cmdID; // Command ID, low byte significant, high byte = 0x00
|
|
uint16_t length; // Payload length in bytes (0 if no payload)
|
|
uint16_t reserved; // Reserved for future use, zero-filled
|
|
uint16_t checksum; // CRC-16/CCITT over entire packet (this field zeroed during calc)
|
|
uint8_t payload[MPS_PACKET_MAX_PAYLOAD];
|
|
} MpsRequest_t;
|
|
|
|
typedef struct __attribute__((packed)) {
|
|
uint8_t cmdID; // Echo of command ID (1 byte in replies)
|
|
uint8_t status; // MPS_STATUS_* code
|
|
uint16_t length; // Payload length in bytes (0 if no payload)
|
|
uint16_t checksum; // CRC-16/CCITT over entire packet (this field zeroed during calc)
|
|
uint8_t payload[MPS_PACKET_MAX_PAYLOAD];
|
|
} MpsReply_t;
|
|
|
|
// =====================================================
|
|
// SENSOR DATA
|
|
// =====================================================
|
|
typedef struct {
|
|
uint32_t cycle_count; // Measurement cycle number; compare to detect repeats
|
|
float concentration_lel;
|
|
uint8_t gas_id;
|
|
float temperature_c;
|
|
float pressure_kpa;
|
|
float rel_humidity_pct;
|
|
float abs_humidity_gm3;
|
|
uint8_t sensor_status;
|
|
MpsAlarmLevel_t alarm_level;
|
|
bool data_valid;
|
|
} MpsSensorData_t;
|
|
|
|
// =====================================================
|
|
// FUNCTION DECLARATIONS
|
|
// =====================================================
|
|
bool MPS_Init(void);
|
|
bool MPS_Reset(void);
|
|
bool MPS_SetMeasurementMode(uint8_t mode, uint8_t unit);
|
|
bool MPS_ReadStatus(uint8_t *status);
|
|
bool MPS_ReadAll(MpsSensorData_t *data);
|
|
bool MPS_ReadConcentration(float *conc_lel);
|
|
bool MPS_ReadEnvironmental(MpsSensorData_t *data);
|
|
void MPS_EvaluateAlarm(MpsSensorData_t *data);
|
|
const char *MPS_StatusString(uint8_t status);
|
|
uint16_t MPS_ComputeCRC(const uint8_t *data, uint16_t len);
|
|
|
|
#endif // MPS_SENSOR_H
|