Repo for ESP32 Weather Station Development
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

224 lines
6.6KB

  1. #include "bme280.h"
  2. #include "bme280_defs.h"
  3. #include "driver/i2c.h"
  4. #include <u8g2.h>
  5. #include "u8g2_esp32_hal.h"
  6. #include <esp_log.h>
  7. void i2c_setup()
  8. {
  9. printf("Setting up I²C driver... ");
  10. //i2c_driver_install(0, I2C_MODE_MASTER, 0, 0, 0);
  11. i2c_config_t config;
  12. config.mode = I2C_MODE_MASTER;
  13. config.sda_io_num = 18;
  14. config.sda_pullup_en = GPIO_PULLUP_ENABLE;
  15. config.scl_io_num = 19;
  16. config.scl_pullup_en = GPIO_PULLUP_ENABLE;
  17. config.master.clk_speed = 100000;
  18. i2c_param_config(I2C_NUM_0, &config);
  19. printf("Set driver parameters... ");
  20. esp_err_t err = i2c_driver_install(I2C_NUM_0, I2C_MODE_MASTER, 0, 0, 0);
  21. if (err == ESP_OK)
  22. printf("Driver installed!\n");
  23. else if (err == ESP_ERR_INVALID_ARG)
  24. printf("Driver install failed, invalid arguments!\n");
  25. else
  26. printf("Driver install failed!\n");
  27. }
  28. void i2c_detect()
  29. {
  30. printf("Scanning I²C bus:\n");
  31. uint8_t address;
  32. printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\r\n");
  33. for (int i = 0; i < 128; i += 16) {
  34. printf("%02x: ", i);
  35. for (int j = 0; j < 16; j++) {
  36. fflush(stdout);
  37. address = i + j;
  38. i2c_cmd_handle_t cmd = i2c_cmd_link_create();
  39. i2c_master_start(cmd);
  40. i2c_master_write_byte(cmd, (address << 1) | I2C_MASTER_WRITE, 0x1);
  41. i2c_master_stop(cmd);
  42. esp_err_t ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, 50 / portTICK_RATE_MS);
  43. i2c_cmd_link_delete(cmd);
  44. if (ret == ESP_OK) {
  45. printf("%02x ", address);
  46. } else if (ret == ESP_ERR_TIMEOUT) {
  47. printf("UU ");
  48. } else {
  49. printf("-- ");
  50. }
  51. }
  52. printf("\r\n");
  53. }
  54. }
  55. int8_t i2c_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *data, uint16_t len) {
  56. i2c_cmd_handle_t cmd = i2c_cmd_link_create();
  57. i2c_master_start(cmd);
  58. i2c_master_write_byte(cmd, dev_id << 1 | I2C_MASTER_WRITE, 1);
  59. i2c_master_write_byte(cmd, reg_addr, 1);
  60. i2c_master_start(cmd);
  61. i2c_master_write_byte(cmd, dev_id << 1 | I2C_MASTER_READ, 1);
  62. if (len > 1) {
  63. i2c_master_read(cmd, data, len - 1, I2C_MASTER_ACK);
  64. }
  65. i2c_master_read_byte(cmd, data + len - 1, I2C_MASTER_NACK);
  66. i2c_master_stop(cmd);
  67. i2c_master_cmd_begin(I2C_NUM_0, cmd, 500 / portTICK_RATE_MS);
  68. i2c_cmd_link_delete(cmd);
  69. return 0;
  70. }
  71. int8_t i2c_write(uint8_t dev_id, uint8_t reg_addr, uint8_t *data, uint16_t len) {
  72. //printf("Writing to bus: dev_id=%x, reg_addr=%x, data=%p, length=%u\n", dev_id, reg_addr, data, len);
  73. i2c_cmd_handle_t cmd = i2c_cmd_link_create();
  74. i2c_master_start(cmd);
  75. i2c_master_write_byte(cmd, (dev_id << 1) | I2C_MASTER_WRITE, 1);
  76. i2c_master_write_byte(cmd, reg_addr, 1);
  77. i2c_master_write(cmd, data, len, 1);
  78. i2c_master_stop(cmd);
  79. i2c_master_cmd_begin(I2C_NUM_0, cmd, 500 / portTICK_RATE_MS);
  80. i2c_cmd_link_delete(cmd);
  81. return 0;
  82. }
  83. void i2c_delay(uint32_t period) {
  84. vTaskDelay(period / portTICK_PERIOD_MS);
  85. }
  86. void i2c_shutdown()
  87. {
  88. printf("Shutting down I²C bus... ");
  89. esp_err_t err = i2c_driver_delete(I2C_NUM_0);
  90. if (err == ESP_ERR_INVALID_ARG)
  91. printf("Failed, invalid arguments!\n");
  92. else
  93. printf("Success!\n");
  94. }
  95. void read_sensor(struct bme280_dev* dev, int32_t* temp, uint32_t* pressure, uint32_t* humidity) {
  96. uint8_t settings_sel;
  97. uint32_t req_delay;
  98. struct bme280_data comp_data;
  99. /* Recommended mode of operation: Indoor navigation */
  100. dev->settings.osr_h = BME280_OVERSAMPLING_1X;
  101. dev->settings.osr_p = BME280_OVERSAMPLING_16X;
  102. dev->settings.osr_t = BME280_OVERSAMPLING_16X;
  103. dev->settings.filter = BME280_FILTER_COEFF_16;
  104. settings_sel = BME280_OSR_PRESS_SEL | BME280_OSR_TEMP_SEL | BME280_OSR_HUM_SEL | BME280_FILTER_SEL;
  105. bme280_set_sensor_settings(settings_sel, dev);
  106. /*Calculate the minimum delay required between consecutive measurement based upon the sensor enabled
  107. * and the oversampling configuration. */
  108. req_delay = 12*bme280_cal_meas_delay(&(dev->settings));
  109. printf("req_delay=%i\r\n", req_delay);
  110. /* Continuously stream sensor data */
  111. bme280_set_sensor_mode(BME280_FORCED_MODE, dev);
  112. /* Wait for the measurement to complete and print data @25Hz */
  113. dev->delay_ms(req_delay / portTICK_PERIOD_MS);
  114. bme280_get_sensor_data(BME280_ALL, &comp_data, dev);
  115. *temp = comp_data.temperature;
  116. *pressure = comp_data.pressure;
  117. *humidity = comp_data.humidity;
  118. }
  119. void print_data(u8g2_t* u8g2, int32_t temp, uint32_t pressure, uint32_t humidity) {
  120. int32_t temp1 = temp / 100;
  121. int32_t temp2 = (abs(temp) % 100) / 10;
  122. uint32_t press1 = pressure / 100;
  123. uint32_t humid1 = humidity / 1024;
  124. uint32_t humid2 = (humidity - humid1*1024) * 10 / 1024;
  125. //temp1 = 12;
  126. //temp2 = 3;
  127. int32_t temp3 = -1*temp1;
  128. int32_t temp4 = temp2;
  129. //press1 = 9999;
  130. //humid1 = 13;
  131. //humid2 = 4;
  132. char temp1str[31];
  133. char temp1str2[32];
  134. sprintf(temp1str, "%d,%d", temp1, temp2);
  135. if (temp1 < 10) {
  136. sprintf(temp1str2, " %s", temp1str);
  137. } else {
  138. sprintf(temp1str2, "%s", temp1str);
  139. }
  140. char temp2str[31];
  141. char temp2str2[33];
  142. sprintf(temp2str, "%d,%d", temp3, temp4);
  143. uint8_t spaces = 0;
  144. if (temp3 > 0)
  145. spaces++;
  146. if (abs(temp3) < 10)
  147. spaces++;
  148. if (spaces == 2)
  149. sprintf(temp2str2, " %s", temp2str);
  150. else if (spaces == 1)
  151. sprintf(temp2str2, " %s", temp2str);
  152. else {
  153. sprintf(temp2str2, "%s", temp2str);
  154. }
  155. char tempstr[70];
  156. sprintf(tempstr, "%s %s °C", temp1str2, temp2str2);
  157. u8g2_ClearBuffer(u8g2);
  158. char pressstr[27];
  159. char humidstr[27];
  160. sprintf(pressstr, "%d %d hPa", press1, press1);
  161. sprintf(humidstr, "%d,%d %d,%d %%", humid1, humid2, humid1, humid2);
  162. u8g2_SetFont(u8g2, u8g2_font_profont17_mf);
  163. int8_t fontheight = u8g2_GetAscent(u8g2);
  164. int8_t fontmargin = abs(u8g2_GetDescent(u8g2))+2;
  165. u8g2_DrawStr(u8g2, 0, fontheight, " IN OUT ");
  166. u8g2_DrawStr(u8g2, 0, 2*fontheight + fontmargin, tempstr);
  167. u8g2_DrawStr(u8g2, 0, 3*fontheight + 2*fontmargin, humidstr);
  168. u8g2_DrawStr(u8g2, 0, 4*fontheight + 3*fontmargin, pressstr);
  169. u8g2_SendBuffer(u8g2);
  170. }
  171. void app_main(void)
  172. {
  173. int32_t temp = 0;
  174. uint32_t pressure = 0;
  175. uint32_t humidity = 0;
  176. // INIT SENSOR
  177. i2c_setup();
  178. struct bme280_dev dev;
  179. dev.dev_id = 0x76;
  180. dev.intf = BME280_I2C_INTF;
  181. dev.read = i2c_read;
  182. dev.write = i2c_write;
  183. dev.delay_ms = i2c_delay;
  184. bme280_init(&dev);
  185. // INIT DISPLAY
  186. u8g2_esp32_hal_t u8g2_esp32_hal = U8G2_ESP32_HAL_DEFAULT;
  187. u8g2_esp32_hal.sda = 18;
  188. u8g2_esp32_hal.scl = 19;
  189. u8g2_esp32_hal_init(u8g2_esp32_hal);
  190. u8g2_t u8g2;
  191. u8g2_Setup_ssd1306_i2c_128x64_vcomh0_f(&u8g2, U8G2_R0, u8g2_esp32_i2c_byte_cb,
  192. u8g2_esp32_gpio_and_delay_cb);
  193. u8x8_SetI2CAddress(&u8g2.u8x8,0x3C << 1);
  194. u8g2_InitDisplay(&u8g2); // send init sequence to the display, display is in sleep mode after this,
  195. u8g2_SetPowerSave(&u8g2, 0); // wake up display
  196. while (1) {
  197. read_sensor(&dev, &temp, &pressure, &humidity);
  198. printf("%i °c, %i hPa, %i %%\r\n", temp, pressure, humidity);
  199. print_data(&u8g2, temp, pressure, humidity);
  200. vTaskDelay(250 / portTICK_PERIOD_MS);
  201. }
  202. }