Repo for ESP32 Weather Station Development
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

375 lignes
11KB

  1. #include "freertos/FreeRTOS.h"
  2. #include "esp_wifi.h"
  3. #include "esp_system.h"
  4. #include "esp_event.h"
  5. #include "esp_event_loop.h"
  6. #include "nvs_flash.h"
  7. #include "driver/gpio.h"
  8. #include "bme280.h"
  9. #include "driver/i2c.h"
  10. #define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
  11. #define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
  12. #define WRITE_BIT I2C_MASTER_WRITE /*!< I2C master write */
  13. #define READ_BIT I2C_MASTER_READ /*!< I2C master read */
  14. #define ACK_CHECK_EN 0x1 /*!< I2C master will check ack from slave*/
  15. #define ACK_CHECK_DIS 0x0 /*!< I2C master will not check ack from slave */
  16. #define ACK_VAL 0x0 /*!< I2C ack value */
  17. #define NACK_VAL 0x1 /*!< I2C nack value */
  18. static struct {
  19. struct arg_int *port;
  20. struct arg_int *freq;
  21. struct arg_int *sda;
  22. struct arg_int *scl;
  23. struct arg_end *end;
  24. } i2cconfig_args;
  25. static struct {
  26. struct arg_int *chip_address;
  27. struct arg_int *register_address;
  28. struct arg_int *data_length;
  29. struct arg_end *end;
  30. } i2cget_args;
  31. static struct {
  32. struct arg_int *chip_address;
  33. struct arg_int *register_address;
  34. struct arg_int *data;
  35. struct arg_end *end;
  36. } i2cset_args;
  37. static int do_i2cget_cmd(int argc, char **argv)
  38. {
  39. int nerrors = arg_parse(argc, argv, (void **)&i2cget_args);
  40. if (nerrors != 0) {
  41. arg_print_errors(stderr, i2cget_args.end, argv[0]);
  42. return 0;
  43. }
  44. /* Check chip address: "-c" option */
  45. int chip_addr = i2cget_args.chip_address->ival[0];
  46. /* Check register address: "-r" option */
  47. int data_addr = -1;
  48. if (i2cget_args.register_address->count) {
  49. data_addr = i2cget_args.register_address->ival[0];
  50. }
  51. /* Check data length: "-l" option */
  52. int len = 1;
  53. if (i2cget_args.data_length->count) {
  54. len = i2cget_args.data_length->ival[0];
  55. }
  56. uint8_t *data = malloc(len);
  57. i2c_master_driver_initialize();
  58. i2c_driver_install(i2c_port, I2C_MODE_MASTER, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
  59. i2c_cmd_handle_t cmd = i2c_cmd_link_create();
  60. i2c_master_start(cmd);
  61. if (data_addr != -1) {
  62. i2c_master_write_byte(cmd, chip_addr << 1 | WRITE_BIT, ACK_CHECK_EN);
  63. i2c_master_write_byte(cmd, data_addr, ACK_CHECK_EN);
  64. i2c_master_start(cmd);
  65. }
  66. i2c_master_write_byte(cmd, chip_addr << 1 | READ_BIT, ACK_CHECK_EN);
  67. if (len > 1) {
  68. i2c_master_read(cmd, data, len - 1, ACK_VAL);
  69. }
  70. i2c_master_read_byte(cmd, data + len - 1, NACK_VAL);
  71. i2c_master_stop(cmd);
  72. esp_err_t ret = i2c_master_cmd_begin(i2c_port, cmd, 1000 / portTICK_RATE_MS);
  73. i2c_cmd_link_delete(cmd);
  74. if (ret == ESP_OK) {
  75. for (int i = 0; i < len; i++) {
  76. printf("0x%02x ", data[i]);
  77. if ((i + 1) % 16 == 0) {
  78. printf("\r\n");
  79. }
  80. }
  81. if (len % 16) {
  82. printf("\r\n");
  83. }
  84. } else if (ret == ESP_ERR_TIMEOUT) {
  85. ESP_LOGW(TAG, "Bus is busy");
  86. } else {
  87. ESP_LOGW(TAG, "Read failed");
  88. }
  89. free(data);
  90. i2c_driver_delete(i2c_port);
  91. return 0;
  92. }
  93. static int do_i2cset_cmd(int argc, char **argv)
  94. {
  95. int nerrors = arg_parse(argc, argv, (void **)&i2cset_args);
  96. if (nerrors != 0) {
  97. arg_print_errors(stderr, i2cset_args.end, argv[0]);
  98. return 0;
  99. }
  100. /* Check chip address: "-c" option */
  101. int chip_addr = i2cset_args.chip_address->ival[0];
  102. /* Check register address: "-r" option */
  103. int data_addr = 0;
  104. if (i2cset_args.register_address->count) {
  105. data_addr = i2cset_args.register_address->ival[0];
  106. }
  107. /* Check data: "-d" option */
  108. int len = i2cset_args.data->count;
  109. i2c_master_driver_initialize();
  110. i2c_driver_install(i2c_port, I2C_MODE_MASTER, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
  111. i2c_cmd_handle_t cmd = i2c_cmd_link_create();
  112. i2c_master_start(cmd);
  113. i2c_master_write_byte(cmd, chip_addr << 1 | WRITE_BIT, ACK_CHECK_EN);
  114. if (i2cset_args.register_address->count) {
  115. i2c_master_write_byte(cmd, data_addr, ACK_CHECK_EN);
  116. }
  117. for (int i = 0; i < len; i++) {
  118. i2c_master_write_byte(cmd, i2cset_args.data->ival[i], ACK_CHECK_EN);
  119. }
  120. i2c_master_stop(cmd);
  121. esp_err_t ret = i2c_master_cmd_begin(i2c_port, cmd, 1000 / portTICK_RATE_MS);
  122. i2c_cmd_link_delete(cmd);
  123. if (ret == ESP_OK) {
  124. ESP_LOGI(TAG, "Write OK");
  125. } else if (ret == ESP_ERR_TIMEOUT) {
  126. ESP_LOGW(TAG, "Bus is busy");
  127. } else {
  128. ESP_LOGW(TAG, "Write Failed");
  129. }
  130. i2c_driver_delete(i2c_port);
  131. return 0;
  132. }
  133. static int do_i2cconfig_cmd(int argc, char **argv)
  134. {
  135. int nerrors = arg_parse(argc, argv, (void **)&i2cconfig_args);
  136. if (nerrors != 0) {
  137. arg_print_errors(stderr, i2cconfig_args.end, argv[0]);
  138. return 0;
  139. }
  140. /* Check "--port" option */
  141. if (i2cconfig_args.port->count) {
  142. if (i2c_get_port(i2cconfig_args.port->ival[0], &i2c_port) != ESP_OK) {
  143. return 1;
  144. }
  145. }
  146. /* Check "--freq" option */
  147. if (i2cconfig_args.freq->count) {
  148. i2c_frequency = i2cconfig_args.freq->ival[0];
  149. }
  150. /* Check "--sda" option */
  151. i2c_gpio_sda = i2cconfig_args.sda->ival[0];
  152. /* Check "--scl" option */
  153. i2c_gpio_scl = i2cconfig_args.scl->ival[0];
  154. return 0;
  155. }
  156. int fd;
  157. void user_delay_ms(uint32_t period);
  158. void print_sensor_data(struct bme280_data *comp_data);
  159. int8_t user_i2c_read(uint8_t id, uint8_t reg_addr, uint8_t *data, uint16_t len);
  160. int8_t user_i2c_write(uint8_t id, uint8_t reg_addr, uint8_t *data, uint16_t len);
  161. int8_t stream_sensor_data_forced_mode(struct bme280_dev *dev);
  162. /*!
  163. * @brief This function reading the sensor's registers through I2C bus.
  164. */
  165. int8_t user_i2c_read(uint8_t id, uint8_t reg_addr, uint8_t *data, uint16_t len)
  166. {
  167. write(fd, &reg_addr, 1);
  168. read(fd, data, len);
  169. return 0;
  170. }
  171. /*!
  172. * @brief This function provides the delay for required time (Microseconds) as per the input provided in some of the
  173. * APIs
  174. */
  175. void user_delay_ms(uint32_t period)
  176. {
  177. /* Milliseconds convert to microseconds */
  178. usleep(period * 1000);
  179. }
  180. /*!
  181. * @brief This function for writing the sensor's registers through I2C bus.
  182. */
  183. int8_t user_i2c_write(uint8_t id, uint8_t reg_addr, uint8_t *data, uint16_t len)
  184. {
  185. int8_t *buf;
  186. buf = malloc(len + 1);
  187. buf[0] = reg_addr;
  188. memcpy(buf + 1, data, len);
  189. if (write(fd, buf, len + 1) < len)
  190. {
  191. return BME280_E_COMM_FAIL;
  192. }
  193. free(buf);
  194. return BME280_OK;
  195. }
  196. /*!
  197. * @brief This API used to print the sensor temperature, pressure and humidity data.
  198. */
  199. void print_sensor_data(struct bme280_data *comp_data)
  200. {
  201. float temp, press, hum;
  202. #ifdef BME280_FLOAT_ENABLE
  203. temp = comp_data->temperature;
  204. press = 0.01 * comp_data->pressure;
  205. hum = comp_data->humidity;
  206. #else
  207. #ifdef BME280_64BIT_ENABLE
  208. temp = 0.01f * comp_data->temperature;
  209. press = 0.0001f * comp_data->pressure;
  210. hum = 1.0f / 1024.0f * comp_data->humidity;
  211. #else
  212. temp = 0.01f * comp_data->temperature;
  213. press = 0.01f * comp_data->pressure;
  214. hum = 1.0f / 1024.0f * comp_data->humidity;
  215. #endif
  216. #endif
  217. printf("%0.2lf deg C, %0.2lf hPa, %0.2lf%%\n", temp, press, hum);
  218. }
  219. /*!
  220. * @brief This API reads the sensor temperature, pressure and humidity data in forced mode.
  221. */
  222. int8_t stream_sensor_data_forced_mode(struct bme280_dev *dev)
  223. {
  224. /* Variable to define the result */
  225. int8_t rslt = BME280_OK;
  226. /* Variable to define the selecting sensors */
  227. uint8_t settings_sel = 0;
  228. /* Variable to store minimum wait time between consecutive measurement in force mode */
  229. uint32_t req_delay;
  230. /* Structure to get the pressure, temperature and humidity values */
  231. struct bme280_data comp_data;
  232. /* Recommended mode of operation: Indoor navigation */
  233. dev->settings.osr_h = BME280_OVERSAMPLING_1X;
  234. dev->settings.osr_p = BME280_OVERSAMPLING_16X;
  235. dev->settings.osr_t = BME280_OVERSAMPLING_2X;
  236. dev->settings.filter = BME280_FILTER_COEFF_16;
  237. settings_sel = BME280_OSR_PRESS_SEL | BME280_OSR_TEMP_SEL | BME280_OSR_HUM_SEL | BME280_FILTER_SEL;
  238. /* Set the sensor settings */
  239. rslt = bme280_set_sensor_settings(settings_sel, dev);
  240. if (rslt != BME280_OK)
  241. {
  242. fprintf(stderr, "Failed to set sensor settings (code %+d).", rslt);
  243. return rslt;
  244. }
  245. printf("Temperature, Pressure, Humidity\n");
  246. /*Calculate the minimum delay required between consecutive measurement based upon the sensor enabled
  247. * and the oversampling configuration. */
  248. req_delay = bme280_cal_meas_delay(&dev->settings);
  249. /* Continuously stream sensor data */
  250. while (1)
  251. {
  252. /* Set the sensor to forced mode */
  253. rslt = bme280_set_sensor_mode(BME280_FORCED_MODE, dev);
  254. if (rslt != BME280_OK)
  255. {
  256. fprintf(stderr, "Failed to set sensor mode (code %+d).", rslt);
  257. break;
  258. }
  259. /* Wait for the measurement to complete and print data */
  260. dev->delay_ms(req_delay);
  261. rslt = bme280_get_sensor_data(BME280_ALL, &comp_data, dev);
  262. if (rslt != BME280_OK)
  263. {
  264. fprintf(stderr, "Failed to get sensor data (code %+d).", rslt);
  265. break;
  266. }
  267. print_sensor_data(&comp_data);
  268. }
  269. return rslt;
  270. }
  271. static esp_err_t i2c_master_driver_initialize()
  272. {
  273. i2c_config_t conf = {
  274. .mode = I2C_MODE_MASTER,
  275. .sda_io_num = i2c_gpio_sda,
  276. .sda_pullup_en = GPIO_PULLUP_ENABLE,
  277. .scl_io_num = i2c_gpio_scl,
  278. .scl_pullup_en = GPIO_PULLUP_ENABLE,
  279. .master.clk_speed = i2c_frequency
  280. };
  281. return i2c_param_config(i2c_port, &conf);
  282. }
  283. void app_main(void)
  284. {
  285. struct bme280_dev dev;
  286. /* Variable to define the result */
  287. int8_t rslt = BME280_OK;
  288. /* Make sure to select BME280_I2C_ADDR_PRIM or BME280_I2C_ADDR_SEC as needed */
  289. dev.dev_id = BME280_I2C_ADDR_PRIM;
  290. /* dev.dev_id = BME280_I2C_ADDR_SEC; */
  291. dev.intf = BME280_I2C_INTF;
  292. dev.read = user_i2c_read;
  293. dev.write = user_i2c_write;
  294. dev.delay_ms = user_delay_ms;
  295. if ((fd = open(argv[1], O_RDWR)) < 0)
  296. {
  297. fprintf(stderr, "Failed to open the i2c bus %s\n", argv[1]);
  298. exit(1);
  299. }
  300. #ifdef __KERNEL__
  301. if (ioctl(fd, I2C_SLAVE, dev.dev_id) < 0)
  302. {
  303. fprintf(stderr, "Failed to acquire bus access and/or talk to slave.\n");
  304. exit(1);
  305. }
  306. #endif
  307. /* Initialize the bme280 */
  308. rslt = bme280_init(&dev);
  309. if (rslt != BME280_OK)
  310. {
  311. fprintf(stderr, "Failed to initialize the device (code %+d).\n", rslt);
  312. exit(1);
  313. }
  314. rslt = stream_sensor_data_forced_mode(&dev);
  315. if (rslt != BME280_OK)
  316. {
  317. fprintf(stderr, "Failed to stream sensor data (code %+d).\n", rslt);
  318. exit(1);
  319. }
  320. return ;
  321. }