Skip to content

Instantly share code, notes, and snippets.

@neosarchizo
Created March 3, 2022 07:53
Show Gist options
  • Save neosarchizo/ab0061c8a287ba907c1f6c3cd701cb7d to your computer and use it in GitHub Desktop.
Save neosarchizo/ab0061c8a287ba907c1f6c3cd701cb7d to your computer and use it in GitHub Desktop.
[Arduino] PM2008 packet
#include "packet.h"
void PACKET_generate(uint8_t cmd, uint8_t length, uint8_t *data) {
// STX
*data = PACKET_STX;
// LEN
*(data + PACKET_POS_LEN) = length - 2;
// CMD
*(data + 2) = cmd;
// CS : STX ^ LEN ^ CMD ^ D...
*(data + length - 2) = *data;
for (uint8_t i = 1; i < length - 2; ++i) {
*(data + length - 2) ^= *(data + i);
}
*(data + length - 1) = PACKET_ETX;
}
bool PACKET_check(uint8_t length, uint8_t *data) {
// STX
if (*data != PACKET_STX) {
return false;
}
// ETX
if (*(data + length - 1) != PACKET_ETX) {
return false;
}
// LEN
if (*(data + 1) + 2 != length) {
return false;
}
// CMD
switch (*(data + 2)) {
case PACKET_CMD_GET_PM2008:
break;
default:
return false;
}
// CS
uint8_t cs = *data;
for (uint8_t i = 1; i < length - 2; ++i) {
cs ^= *(data + i);
}
if (cs != *(data + length - 2)) {
return false;
}
return true;
}
uint8_t PACKET_getDataLength(uint8_t *data) {
return *(data + PACKET_POS_LEN) - 3;
}
uint8_t PACKET_getCmd(uint8_t *data) {
return *(data + PACKET_POS_CMD);
}
void PACKET_getData(uint8_t *src, uint8_t length, uint8_t *dst) {
for (uint8_t i = 0; i < length; ++i) {
*(dst + i) = *(src + PACKET_POS_DAT + i);
}
}
#ifndef PACKET_H__
#define PACKET_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h>
#include <stdbool.h>
#define PACKET_STX 0xAB
#define PACKET_ETX 0x7D
#define PACKET_CMD_GET_PM2008 0
// CM1106
// AM1008W-K
#define PACKET_POS_LEN 1
#define PACKET_POS_CMD 2
#define PACKET_POS_DAT 3
extern void PACKET_generate(uint8_t cmd, uint8_t length, uint8_t *data);
extern bool PACKET_check(uint8_t length, uint8_t *data);
extern uint8_t PACKET_getDataLength(uint8_t *data);
extern uint8_t PACKET_getCmd(uint8_t *data);
extern void PACKET_getData(uint8_t *src, uint8_t length, uint8_t *dst);
#ifdef __cplusplus
}
#endif
#endif // PACKET_H__
#include <pm2008_i2c.h>
#include "packet.h"
PM2008_I2C pm2008_i2c;
static uint8_t txBuffer[256];
static uint8_t rxBuffer[256];
static volatile uint8_t idxBuffer = 0;
static volatile uint8_t rearLength = 0;
static uint8_t data[256];
void setup() {
pm2008_i2c.begin();
Serial.begin(9600);
pm2008_i2c.command();
delay(1000);
}
void loop() {
if (Serial.available()) {
uint8_t b = Serial.read();
switch (idxBuffer) {
case 0: {
if (b != PACKET_STX) {
break;
}
rxBuffer[idxBuffer++] = b;
break;
}
case 1: { // LEN
// (STX), (LEN), CMD, DAT, CS, ETX
// Total length = LEN + 2
if (b < 3) {
idxBuffer = 0;
break;
}
rxBuffer[idxBuffer++] = b;
rearLength = b; // buffer[PACKET_POS_LEN]
break;
}
case 2: { // CMD
if (b != PACKET_CMD_GET_PM2008 ) {
idxBuffer = 0;
break;
}
rxBuffer[idxBuffer++] = b;
break;
}
default: {
// DAT, CS, ETX
rxBuffer[idxBuffer++] = b;
if (idxBuffer >= rearLength + 2) {
idxBuffer = 0;
if (b != PACKET_ETX) {
break;
}
if (!PACKET_check(rearLength + 2, rxBuffer)) {
break;
}
uint8_t dataLength = PACKET_getDataLength(rxBuffer);
uint8_t cmd = PACKET_getCmd(rxBuffer);
if ( dataLength > 0 ) {
PACKET_getData(rxBuffer, dataLength, data);
}
switch (cmd) {
case PACKET_CMD_GET_PM2008: {
// length = 0
uint8_t ret = pm2008_i2c.read();
// D0 : error ( 0 : none, 1 : wrong)
if (ret != 0 ) {
txBuffer[PACKET_POS_DAT] = 1;
PACKET_generate(PACKET_CMD_GET_PM2008, 6, txBuffer);
Serial.write(txBuffer, 6);
break;
}
// parsing
// D0 : 0
// D1 ~
txBuffer[PACKET_POS_DAT] = 0;
// GRIMM
txBuffer[PACKET_POS_DAT + 1] = pm2008_i2c.pm1p0_grimm & 0xff;
txBuffer[PACKET_POS_DAT + 2] = (pm2008_i2c.pm1p0_grimm >> 8) & 0xff;
txBuffer[PACKET_POS_DAT + 3] = pm2008_i2c.pm2p5_grimm & 0xff;
txBuffer[PACKET_POS_DAT + 4] = (pm2008_i2c.pm2p5_grimm >> 8) & 0xff;
txBuffer[PACKET_POS_DAT + 5] = pm2008_i2c.pm10_grimm & 0xff;
txBuffer[PACKET_POS_DAT + 6] = (pm2008_i2c.pm10_grimm >> 8) & 0xff;
// TSI
txBuffer[PACKET_POS_DAT + 7] = pm2008_i2c.pm1p0_tsi & 0xff;
txBuffer[PACKET_POS_DAT + 8] = (pm2008_i2c.pm1p0_tsi >> 8) & 0xff;
txBuffer[PACKET_POS_DAT + 9] = pm2008_i2c.pm2p5_tsi & 0xff;
txBuffer[PACKET_POS_DAT + 10] = (pm2008_i2c.pm2p5_tsi >> 8) & 0xff;
txBuffer[PACKET_POS_DAT + 11] = pm2008_i2c.pm10_tsi & 0xff;
txBuffer[PACKET_POS_DAT + 12] = (pm2008_i2c.pm10_tsi >> 8) & 0xff;
// size
txBuffer[PACKET_POS_DAT + 13] = pm2008_i2c.number_of_0p3_um & 0xff;
txBuffer[PACKET_POS_DAT + 14] = (pm2008_i2c.number_of_0p3_um >> 8) & 0xff;
txBuffer[PACKET_POS_DAT + 15] = pm2008_i2c.number_of_0p5_um & 0xff;
txBuffer[PACKET_POS_DAT + 16] = (pm2008_i2c.number_of_0p5_um >> 8) & 0xff;
txBuffer[PACKET_POS_DAT + 17] = pm2008_i2c.number_of_1_um & 0xff;
txBuffer[PACKET_POS_DAT + 18] = (pm2008_i2c.number_of_1_um >> 8) & 0xff;
txBuffer[PACKET_POS_DAT + 19] = pm2008_i2c.number_of_2p5_um & 0xff;
txBuffer[PACKET_POS_DAT + 20] = (pm2008_i2c.number_of_2p5_um >> 8) & 0xff;
txBuffer[PACKET_POS_DAT + 21] = pm2008_i2c.number_of_5_um & 0xff;
txBuffer[PACKET_POS_DAT + 22] = (pm2008_i2c.number_of_5_um >> 8) & 0xff;
txBuffer[PACKET_POS_DAT + 23] = pm2008_i2c.number_of_10_um & 0xff;
txBuffer[PACKET_POS_DAT + 24] = (pm2008_i2c.number_of_10_um >> 8) & 0xff;
PACKET_generate(PACKET_CMD_GET_PM2008, 30, txBuffer);
Serial.write(txBuffer, 30);
break;
}
default:
break;
}
}
break;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment