190 lines
5.9 KiB
C
190 lines
5.9 KiB
C
/*
|
||
* SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
|
||
*
|
||
* SPDX-License-Identifier: CC0-1.0
|
||
*/
|
||
|
||
#include <stdio.h>
|
||
#include <inttypes.h>
|
||
#include <time.h>
|
||
#include <string.h>
|
||
#include <sys/time.h>
|
||
|
||
#include "sdkconfig.h"
|
||
#include "freertos/FreeRTOS.h"
|
||
#include "freertos/task.h"
|
||
#include "esp_chip_info.h"
|
||
#include "esp_flash.h"
|
||
#include "esp_system.h"
|
||
#include "esp_timer.h"
|
||
#include "driver/gpio.h"
|
||
|
||
// Define the GPIO pin for the DHT11 data line
|
||
#define DHT11_GPIO 0
|
||
|
||
void read_dht11(uint8_t *humidity_int, uint8_t *humidity_dec,
|
||
int8_t *temperature_int, uint8_t *temperature_dec,
|
||
uint8_t *checksum) {
|
||
uint8_t data[5] = {0};
|
||
|
||
// Send start signal: pull the line low for 20ms
|
||
gpio_set_direction(DHT11_GPIO, GPIO_MODE_OUTPUT);
|
||
gpio_set_level(DHT11_GPIO, 0);
|
||
vTaskDelay(pdMS_TO_TICKS(20));
|
||
|
||
// Release the line and wait for sensor response
|
||
gpio_set_level(DHT11_GPIO, 1);
|
||
gpio_set_direction(DHT11_GPIO, GPIO_MODE_INPUT);
|
||
|
||
// Wait for the sensor to pull the line low (~20-40us)
|
||
while (gpio_get_level(DHT11_GPIO) == 1) {
|
||
vTaskDelay(pdMS_TO_TICKS(0.1));
|
||
}
|
||
|
||
// Wait for the sensor to pull the line high (~80us)
|
||
while (gpio_get_level(DHT11_GPIO) == 0) {
|
||
vTaskDelay(pdMS_TO_TICKS(0.1));
|
||
}
|
||
|
||
// Read 40 bits of data
|
||
for (int i = 0; i < 40; i++) {
|
||
// Wait for the start of the bit (low for ~50us)
|
||
while (gpio_get_level(DHT11_GPIO) == 1) {
|
||
vTaskDelay(pdMS_TO_TICKS(0.1));
|
||
}
|
||
while (gpio_get_level(DHT11_GPIO) == 0) {
|
||
vTaskDelay(pdMS_TO_TICKS(0.1));
|
||
}
|
||
|
||
// Measure the length of the high pulse
|
||
uint32_t pulse_start = esp_timer_get_time();
|
||
while (gpio_get_level(DHT11_GPIO) == 1) {
|
||
vTaskDelay(pdMS_TO_TICKS(0.1));
|
||
}
|
||
uint32_t pulse_end = esp_timer_get_time();
|
||
|
||
// Determine if the bit is 0 or 1
|
||
uint8_t bit = (pulse_end - pulse_start) > 50 ? 1 : 0;
|
||
data[i / 8] <<= 1;
|
||
data[i / 8] |= bit;
|
||
}
|
||
|
||
// Parse the data
|
||
*humidity_int = data[0];
|
||
*humidity_dec = data[1]; // Decimal part (0–9)
|
||
*temperature_int = (data[2] & 0x7F); // Remove sign bit (0–50)
|
||
*temperature_dec = data[3]; // Decimal part (0–9)
|
||
*checksum = data[4];
|
||
|
||
// Validate checksum
|
||
uint8_t sum = *humidity_int + *humidity_dec + *temperature_int + *temperature_dec;
|
||
if (sum != *checksum) {
|
||
printf("Checksum failed! Retrying...\n");
|
||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||
read_dht11(humidity_int, humidity_dec, temperature_int, temperature_dec, checksum);
|
||
}
|
||
}
|
||
|
||
|
||
void set_system_time_from_compiler() {
|
||
// Parse __DATE__: "Mmm dd yyyy"
|
||
char date[] = __DATE__;
|
||
char time[] = __TIME__;
|
||
|
||
struct tm tm = {0};
|
||
char month[4];
|
||
int day, year;
|
||
int hour, min, sec;
|
||
|
||
// Parse date
|
||
sscanf(date, "%3s %d %d", month, &day, &year);
|
||
|
||
// Parse time
|
||
sscanf(time, "%d:%d:%d", &hour, &min, &sec);
|
||
|
||
// Convert month abbreviation to number
|
||
const char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
|
||
for (int i = 0; i < 12; i++) {
|
||
if (strcmp(month, months[i]) == 0) {
|
||
tm.tm_mon = i;
|
||
break;
|
||
}
|
||
}
|
||
tm.tm_mday = day;
|
||
tm.tm_year = year - 1900; // Years since 1900
|
||
tm.tm_hour = hour;
|
||
tm.tm_min = min;
|
||
tm.tm_sec = sec;
|
||
tm.tm_isdst = -1; // Let system determine daylight saving time
|
||
|
||
// Set system time
|
||
struct timeval tv = { .tv_sec = mktime(&tm), .tv_usec = 0 };
|
||
settimeofday(&tv, NULL);
|
||
}
|
||
|
||
void print_current_time() {
|
||
time_t now;
|
||
struct tm timeinfo;
|
||
char strftime_buf[64];
|
||
|
||
time(&now);
|
||
localtime_r(&now, &timeinfo);
|
||
strftime(strftime_buf, sizeof(strftime_buf), "%Y-%m-%d %H:%M:%S", &timeinfo);
|
||
printf("Time: %s\n", strftime_buf);
|
||
}
|
||
|
||
void print_chip_info(){
|
||
/* Print chip information */
|
||
esp_chip_info_t chip_info;
|
||
uint32_t flash_size;
|
||
esp_chip_info(&chip_info);
|
||
printf("This is %s chip with %d CPU core(s), %s%s%s%s, ",
|
||
CONFIG_IDF_TARGET,
|
||
chip_info.cores,
|
||
(chip_info.features & CHIP_FEATURE_WIFI_BGN) ? "WiFi/" : "",
|
||
(chip_info.features & CHIP_FEATURE_BT) ? "BT" : "",
|
||
(chip_info.features & CHIP_FEATURE_BLE) ? "BLE" : "",
|
||
(chip_info.features & CHIP_FEATURE_IEEE802154) ? ", 802.15.4 (Zigbee/Thread)" : "");
|
||
|
||
unsigned major_rev = chip_info.revision / 100;
|
||
unsigned minor_rev = chip_info.revision % 100;
|
||
printf("silicon revision v%d.%d, ", major_rev, minor_rev);
|
||
if(esp_flash_get_size(NULL, &flash_size) != ESP_OK) {
|
||
printf("Get flash size failed");
|
||
return;
|
||
}
|
||
|
||
printf("%" PRIu32 "MB %s flash\n", flash_size / (uint32_t)(1024 * 1024),
|
||
(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");
|
||
|
||
printf("Minimum free heap size: %" PRIu32 " bytes\n", esp_get_minimum_free_heap_size());
|
||
}
|
||
|
||
void app_main(void)
|
||
{
|
||
set_system_time_from_compiler();
|
||
printf("DHT11 temperature and humidity sensor read and send out\n");
|
||
print_chip_info();
|
||
|
||
while (1) {
|
||
uint8_t humidity_int, humidity_dec, checksum;
|
||
int8_t temperature_int;
|
||
uint8_t temperature_dec;
|
||
|
||
read_dht11(&humidity_int, &humidity_dec, &temperature_int, &temperature_dec, &checksum);
|
||
|
||
// Calculate humidity and temperature
|
||
float humidity = (float)humidity_int + (float)humidity_dec / 10.0f;
|
||
float temperature = (float)temperature_int + (float)temperature_dec / 10.0f;
|
||
|
||
// Print results
|
||
print_current_time();
|
||
printf("Humidity: %.1f%%\n", humidity);
|
||
printf("Temperature: %.1f°C\n", temperature);
|
||
printf("Checksum valid: %s\n", (checksum == (humidity_int + humidity_dec + temperature_int + temperature_dec)) ? "Yes" : "No");
|
||
|
||
// Wait 1 minute before next read
|
||
vTaskDelay(pdMS_TO_TICKS(5000));
|
||
}
|
||
} |