Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | /* * Copyright (c) 2017 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ /* sensor pms7003.c - Driver for plantower PMS7003 sensor * PMS7003 product: http://www.plantower.com/en/content/?110.html * PMS7003 spec: http://aqicn.org/air/view/sensor/spec/pms7003.pdf */ #include <errno.h> #include <arch/cpu.h> #include <init.h> #include <kernel.h> #include <sensor.h> #include <stdlib.h> #include <string.h> #include <uart.h> #include <logging/log.h> #define LOG_LEVEL CONFIG_SENSOR_LOG_LEVEL LOG_MODULE_REGISTER(PMS7003); /* wait serial output with 1000ms timeout */ #define CFG_PMS7003_SERIAL_TIMEOUT 1000 struct pms7003_data { struct device *uart_dev; u16_t pm_1_0; u16_t pm_2_5; u16_t pm_10; }; /** * @brief wait for an array data from uart device with a timeout * * @param dev the uart device * @param data the data array to be matched * @param len the data array len * @param timeout the timeout in milliseconds * @return 0 if success; -ETIME if timeout */ static int uart_wait_for(struct device *dev, u8_t *data, int len, int timeout) { int matched_size = 0; s64_t timeout_time = k_uptime_get() + K_MSEC(timeout); while (1) { u8_t c; if (k_uptime_get() > timeout_time) { return -ETIME; } if (uart_poll_in(dev, &c) == 0) { if (c == data[matched_size]) { matched_size++; if (matched_size == len) { break; } } else if (c == data[0]) { matched_size = 1; } else { matched_size = 0; } } } return 0; } /** * @brief read bytes from uart * * @param data the data buffer * @param len the data len * @param timeout the timeout in milliseconds * @return 0 if success; -ETIME if timeout */ static int uart_read_bytes(struct device *dev, u8_t *data, int len, int timeout) { int read_size = 0; s64_t timeout_time = k_uptime_get() + K_MSEC(timeout); while (1) { u8_t c; if (k_uptime_get() > timeout_time) { return -ETIME; } if (uart_poll_in(dev, &c) == 0) { data[read_size++] = c; if (read_size == len) { break; } } } return 0; } static int pms7003_sample_fetch(struct device *dev, enum sensor_channel chan) { struct pms7003_data *drv_data = dev->driver_data; /* sample output */ /* 42 4D 00 1C 00 01 00 01 00 01 00 01 00 01 00 01 01 92 * 00 4E 00 03 00 00 00 00 00 00 71 00 02 06 */ u8_t pms7003_start_bytes[] = {0x42, 0x4d}; u8_t pms7003_receive_buffer[30]; if (uart_wait_for(drv_data->uart_dev, pms7003_start_bytes, sizeof(pms7003_start_bytes), CFG_PMS7003_SERIAL_TIMEOUT) < 0) { LOG_WRN("waiting for start bytes is timeout"); return -ETIME; } if (uart_read_bytes(drv_data->uart_dev, pms7003_receive_buffer, 30, CFG_PMS7003_SERIAL_TIMEOUT) < 0) { return -ETIME; } drv_data->pm_1_0 = (pms7003_receive_buffer[8] << 8) + pms7003_receive_buffer[9]; drv_data->pm_2_5 = (pms7003_receive_buffer[10] << 8) + pms7003_receive_buffer[11]; drv_data->pm_10 = (pms7003_receive_buffer[12] << 8) + pms7003_receive_buffer[13]; LOG_DBG("pm1.0 = %d", drv_data->pm_1_0); LOG_DBG("pm2.5 = %d", drv_data->pm_2_5); LOG_DBG("pm10 = %d", drv_data->pm_10); return 0; } static int pms7003_channel_get(struct device *dev, enum sensor_channel chan, struct sensor_value *val) { struct pms7003_data *drv_data = dev->driver_data; if (chan == SENSOR_CHAN_PM_1_0) { val->val1 = drv_data->pm_1_0; val->val2 = 0; } else if (chan == SENSOR_CHAN_PM_2_5) { val->val1 = drv_data->pm_2_5; val->val2 = 0; } else if (chan == SENSOR_CHAN_PM_10) { val->val1 = drv_data->pm_10; val->val2 = 0; } else { return -EINVAL; } return 0; } static const struct sensor_driver_api pms7003_api = { .sample_fetch = &pms7003_sample_fetch, .channel_get = &pms7003_channel_get, }; static int pms7003_init(struct device *dev) { struct pms7003_data *drv_data = dev->driver_data; drv_data->uart_dev = device_get_binding(CONFIG_PMS7003_UART_DEVICE); if (!drv_data->uart_dev) { LOG_DBG("uart device is not found: %s", CONFIG_PMS7003_UART_DEVICE); return -EINVAL; } return 0; } static struct pms7003_data pms7003_data; DEVICE_AND_API_INIT(gts_dev, CONFIG_PMS7003_DRIVER_NAME, &pms7003_init, &pms7003_data, NULL, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, &pms7003_api); |