kopia lustrzana https://github.com/pimoroni/pimoroni-pico
Merge pull request #389 from pimoroni/driver/pms5003
PMS5003: Basic PMS5003 active-mode only driver.pull/391/head
commit
e439d9bcd1
|
@ -34,3 +34,4 @@ add_subdirectory(encoder)
|
|||
add_subdirectory(motor)
|
||||
add_subdirectory(vl53l5cx)
|
||||
add_subdirectory(pcf85063a)
|
||||
add_subdirectory(pms5003)
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
include(pms5003.cmake)
|
|
@ -0,0 +1,10 @@
|
|||
set(DRIVER_NAME pms5003)
|
||||
add_library(${DRIVER_NAME} INTERFACE)
|
||||
|
||||
target_sources(${DRIVER_NAME} INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR}/${DRIVER_NAME}.cpp)
|
||||
|
||||
target_include_directories(${DRIVER_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(${DRIVER_NAME} INTERFACE pico_stdlib hardware_uart hardware_gpio)
|
|
@ -0,0 +1,114 @@
|
|||
#include "pico/stdlib.h"
|
||||
#include "hardware/uart.h"
|
||||
#include <cstring>
|
||||
|
||||
constexpr char PMS5003_SOF[] = "\x42\x4d";
|
||||
constexpr uint16_t PMS5003_SOFU = 0x424d;
|
||||
constexpr char PMS5003_CMD_MODE_PASSIVE[] = "\xe1\x00\x00";
|
||||
constexpr char PMS5003_CMD_MODE_ACTIVE[] = "\xe1\x00\x01";
|
||||
constexpr char PMS5003_CMD_READ[] = "\xe2\x00\x00";
|
||||
constexpr char PMS5003_CMD_SLEEP[] = "\xe4\x00\x00";
|
||||
constexpr char PMS5003_CMD_WAKEUP[] = "\xe4\x00\x01";
|
||||
|
||||
constexpr uint PMS5003_MAX_RESET_TIME = 20000;
|
||||
constexpr uint PMS5003_MAX_RESP_TIME = 5000;
|
||||
constexpr uint PMS5003_MIN_CMD_INTERVAL = 100;
|
||||
|
||||
|
||||
class PMS5003 {
|
||||
public:
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct alignas(1) response_data {
|
||||
uint16_t pm_1_0;
|
||||
uint16_t pm_2_5;
|
||||
uint16_t pm_10;
|
||||
uint16_t pm_1_0_ao;
|
||||
uint16_t pm_2_5_ao;
|
||||
uint16_t pm_10_ao;
|
||||
uint16_t pm_0_3_1l;
|
||||
uint16_t pm_0_5_1l;
|
||||
uint16_t pm_1_0_1l;
|
||||
uint16_t pm_2_5_1l;
|
||||
uint16_t pm_5_1l;
|
||||
uint16_t pm_10_1l;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
PMS5003(uart_inst_t *uart, uint pin_tx, uint pin_rx,
|
||||
uint pin_reset, uint pin_enable)
|
||||
: uart(uart),
|
||||
pin_tx(pin_tx),
|
||||
pin_rx(pin_rx),
|
||||
pin_reset(pin_reset),
|
||||
pin_enable(pin_enable) {
|
||||
uart_init(uart, 9600);
|
||||
gpio_init(pin_tx);gpio_set_function(pin_tx, GPIO_FUNC_UART);
|
||||
gpio_init(pin_rx);gpio_set_function(pin_rx, GPIO_FUNC_UART);
|
||||
gpio_init(pin_reset);gpio_set_function(pin_reset, GPIO_FUNC_SIO);gpio_set_dir(pin_reset, GPIO_OUT);gpio_put(pin_reset, false);
|
||||
gpio_init(pin_enable);gpio_set_function(pin_enable, GPIO_FUNC_SIO);gpio_set_dir(pin_enable, GPIO_OUT);gpio_put(pin_enable, true);
|
||||
|
||||
reset();
|
||||
};
|
||||
~PMS5003() {};
|
||||
|
||||
void reset() {
|
||||
sleep_ms(100);
|
||||
gpio_put(pin_reset, false);
|
||||
reset_input_buffer();
|
||||
sleep_ms(100);
|
||||
gpio_put(pin_reset, true);
|
||||
};
|
||||
|
||||
bool read(response_data &data) {
|
||||
reset_input_buffer();
|
||||
|
||||
// Read the 32 byte transaction - SOF + Size + Data + CRC
|
||||
uart_read_blocking(uart, buffer, 32);
|
||||
|
||||
// test the checksum matches, if not quit early with a false return value
|
||||
uint16_t checksum = (buffer[30] << 8) | buffer[31];
|
||||
uint16_t compare = 0;
|
||||
for(int i = 0; i < 30; i++) {
|
||||
compare += buffer[i];
|
||||
}
|
||||
|
||||
if(compare != checksum) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copy the data into the result struct
|
||||
memcpy(&data, buffer + 4, sizeof(data));
|
||||
|
||||
// Byteswap the results
|
||||
data.pm_1_0 = __builtin_bswap16(data.pm_1_0);
|
||||
data.pm_2_5 = __builtin_bswap16(data.pm_2_5);
|
||||
data.pm_10 = __builtin_bswap16(data.pm_10);
|
||||
data.pm_1_0_ao = __builtin_bswap16(data.pm_1_0_ao);
|
||||
data.pm_2_5_ao = __builtin_bswap16(data.pm_2_5_ao);
|
||||
data.pm_10_ao = __builtin_bswap16(data.pm_10_ao);
|
||||
data.pm_0_3_1l = __builtin_bswap16(data.pm_0_3_1l);
|
||||
data.pm_0_5_1l = __builtin_bswap16(data.pm_0_5_1l);
|
||||
data.pm_1_0_1l = __builtin_bswap16(data.pm_1_0_1l);
|
||||
data.pm_2_5_1l = __builtin_bswap16(data.pm_2_5_1l);
|
||||
data.pm_5_1l = __builtin_bswap16(data.pm_5_1l);
|
||||
data.pm_10_1l = __builtin_bswap16(data.pm_10_1l);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
uart_inst_t *uart;
|
||||
uint pin_tx;
|
||||
uint pin_rx;
|
||||
uint pin_reset;
|
||||
uint pin_enable;
|
||||
|
||||
uint8_t buffer[64];
|
||||
|
||||
void reset_input_buffer() {
|
||||
while(uart_is_readable(uart)) {
|
||||
uart_getc(uart);
|
||||
}
|
||||
};
|
||||
};
|
|
@ -22,6 +22,7 @@ add_subdirectory(breakout_bh1745)
|
|||
add_subdirectory(breakout_icp10125)
|
||||
add_subdirectory(breakout_scd41)
|
||||
add_subdirectory(breakout_vl53l5cx)
|
||||
add_subdirectory(breakout_pms5003)
|
||||
|
||||
add_subdirectory(pico_display)
|
||||
add_subdirectory(pico_display_2)
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
set(OUTPUT_NAME pms5003_demo)
|
||||
|
||||
add_executable(
|
||||
${OUTPUT_NAME}
|
||||
pms5003_demo.cpp
|
||||
)
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(${OUTPUT_NAME} pico_stdlib pms5003)
|
||||
|
||||
# create map/bin/hex file etc.
|
||||
pico_add_extra_outputs(${OUTPUT_NAME})
|
|
@ -0,0 +1,40 @@
|
|||
#include <stdio.h>
|
||||
#include "pico/stdlib.h"
|
||||
#include "common/pimoroni_common.hpp"
|
||||
#include "hardware/uart.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "pms5003.hpp"
|
||||
|
||||
using namespace pimoroni;
|
||||
|
||||
|
||||
PMS5003 pms5003(uart1, 8, 9, 2, 3);
|
||||
PMS5003::response_data data;
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
|
||||
while(true){
|
||||
bool result = pms5003.read(data);
|
||||
if(result){
|
||||
printf("%04x ", data.pm_1_0); // PM1.0 ug/m3 (ultrafine particles)
|
||||
printf("%04x ", data.pm_2_5); // PM2.5 ug/m3 (combustion particles, organic compounds, metals)
|
||||
printf("%04x ", data.pm_10); // PM10 ug/m3 (dust, pollen, mould spores)
|
||||
printf("%04x ", data.pm_1_0_ao); // PM 1.0 under atmospheric environment
|
||||
printf("%04x ", data.pm_2_5_ao); // PM 2.5 under atmospheric environment
|
||||
printf("%04x ", data.pm_10_ao); // PM 10 under atmospheric environment
|
||||
printf("%04x ", data.pm_0_3_1l); // PM 0.3 in 0.1L of air
|
||||
printf("%04x ", data.pm_0_5_1l); // PM 0.5 in 0.1L of air
|
||||
printf("%04x ", data.pm_1_0_1l); // PM 1.0 in 0.1L of air
|
||||
printf("%04x ", data.pm_2_5_1l); // PM 2.5 in 0.1L of air
|
||||
printf("%04x ", data.pm_5_1l); // PM 5 in 0.1L of air
|
||||
printf("%04x ", data.pm_10_1l); // PM 10 in 0.1L of air
|
||||
printf("\n");
|
||||
}
|
||||
sleep_ms(100);
|
||||
};
|
||||
|
||||
return 0;
|
||||
}
|
Ładowanie…
Reference in New Issue