#include "pms5003.h" #include "hardware/uart.h" #include "pico/stdlib.h" #include #include #include #include /** Lib for Plantower PMS5003 Particulate Matter (PM) Sensor Detects PM1, PM2.5, PM10 particulates Sourcces: - https://shop.pimoroni.com/products/pms5003-particulate-matter-sensor-with-cable - https://github.com/pimoroni/pms5003-python/blob/main/pms5003/__init__.py - https://github.com/vogelrh/pms5003c/tree/master - https://github.com/raspberrypi/pico-examples/blob/master/uart/hello_uart/hello_uart.c */ static uint8_t rx_buf[32] = {0}; static uint8_t rx_i = 0; static float last_pm1_reading = 0; static float last_pm2_5_reading = 0; static float last_pm10_reading = 0; static void extract_pm_values_from_rx_buf() { uint8_t pm1_low = rx_buf[9]; uint8_t pm1_high = rx_buf[10]; uint16_t pm1 = ((uint16_t)pm1_high << 8) | pm1_low; uint8_t pm2_5_low = rx_buf[11]; uint8_t pm2_5_high = rx_buf[12]; uint16_t pm2_5 = ((uint16_t)pm2_5_high << 8) | pm2_5_low; uint8_t pm10_low = rx_buf[13]; uint8_t pm10_high = rx_buf[14]; uint16_t pm10 = ((uint16_t)pm10_high << 8) | pm10_low; last_pm1_reading = (float)pm1; last_pm2_5_reading = (float)pm2_5; last_pm10_reading = (float)pm10; } static void on_uart_rx() { while (uart_is_readable(uart1)) { uint8_t ch = uart_getc(uart1); // start of a message if (ch == 0x42) { printf("pms5003 reading received\n"); rx_i = 0; } rx_buf[rx_i] = ch; rx_i++; // end of message if (rx_i == 31) { extract_pm_values_from_rx_buf(); } // guard if (rx_i > 32) { rx_i = 0; } } } static unsigned char pms5003_command_prefix[] = {0x42, 0x4D}; void pms5003_init(pms5003_config *new_config, uart_inst_t *uart, uint8_t tx_pin, uint8_t rx_pin, uint8_t enable_pin, uint8_t reset_pin) { gpio_set_function(tx_pin, UART_FUNCSEL_NUM(uart, tx_pin)); gpio_set_function(rx_pin, UART_FUNCSEL_NUM(uart, rx_pin)); uart_init(uart, 9600); uart_set_format(uart, 8, 1, UART_PARITY_NONE); irq_set_exclusive_handler(UART1_IRQ, on_uart_rx); irq_set_enabled(UART1_IRQ, true); uart_set_irq_enables(uart, true, false); // high level or suspending is normal working status, while low level is sleeping mode. gpio_init(enable_pin); gpio_set_dir(enable_pin, GPIO_OUT); gpio_put(enable_pin, 0); // low resets // gpio_init(reset_pin); // gpio_set_dir(reset_pin, GPIO_OUT); // gpio_set_pulls(enable_pin, true, false); // pull up // gpio_put(enable_pin, 1); new_config->uart = uart; new_config->enable_pin = enable_pin; new_config->reset_pin = reset_pin; } /** Reads should happen min of 30sec after waking the sensor */ pms5003_reading pms5003_read(pms5003_config *config) { pms5003_reading reading; reading.pm1 = last_pm1_reading; reading.pm2_5 = last_pm2_5_reading; reading.pm10 = last_pm10_reading; return reading; }