Initial WiFi commit.
This commit is contained in:
commit
5afbef0177
|
@ -0,0 +1,6 @@
|
|||
# The following lines of boilerplate have to be in your project's
|
||||
# CMakeLists in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(dht_temp)
|
|
@ -0,0 +1,50 @@
|
|||
# Hello World Example
|
||||
|
||||
Starts a FreeRTOS task to print "Hello World".
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
## How to use example
|
||||
|
||||
Follow detailed instructions provided specifically for this example.
|
||||
|
||||
Select the instructions depending on Espressif chip installed on your development board:
|
||||
|
||||
- [ESP32 Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/stable/get-started/index.html)
|
||||
- [ESP32-S2 Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/get-started/index.html)
|
||||
|
||||
|
||||
## Example folder contents
|
||||
|
||||
The project **hello_world** contains one source file in C language [hello_world_main.c](main/hello_world_main.c). The file is located in folder [main](main).
|
||||
|
||||
ESP-IDF projects are built using CMake. The project build configuration is contained in `CMakeLists.txt` files that provide set of directives and instructions describing the project's source files and targets (executable, library, or both).
|
||||
|
||||
Below is short explanation of remaining files in the project folder.
|
||||
|
||||
```
|
||||
├── CMakeLists.txt
|
||||
├── pytest_hello_world.py Python script used for automated testing
|
||||
├── main
|
||||
│ ├── CMakeLists.txt
|
||||
│ └── hello_world_main.c
|
||||
└── README.md This is the file you are currently reading
|
||||
```
|
||||
|
||||
For more information on structure and contents of ESP-IDF projects, please refer to Section [Build System](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/build-system.html) of the ESP-IDF Programming Guide.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
* Program upload failure
|
||||
|
||||
* Hardware connection is not correct: run `idf.py -p PORT monitor`, and reboot your board to see if there are any output logs.
|
||||
* The baud rate for downloading is too high: lower your baud rate in the `menuconfig` menu, and try again.
|
||||
|
||||
## Technical support and feedback
|
||||
|
||||
Please use the following feedback channels:
|
||||
|
||||
* For technical queries, go to the [esp32.com](https://esp32.com/) forum
|
||||
* For a feature request or bug report, create a [GitHub issue](https://github.com/espressif/esp-idf/issues)
|
||||
|
||||
We will get back to you as soon as possible.
|
|
@ -0,0 +1,9 @@
|
|||
idf_component_register(
|
||||
SRCS
|
||||
"app_wifi.c"
|
||||
"main.c"
|
||||
"aht10/aht10.c"
|
||||
INCLUDE_DIRS
|
||||
"include"
|
||||
"aht10"
|
||||
)
|
|
@ -0,0 +1,20 @@
|
|||
menu "Application Configuration"
|
||||
|
||||
config APP_WIFI_SSID
|
||||
string "WiFi SSID"
|
||||
default "myssid"
|
||||
help
|
||||
SSID (network name) for the application to connect to.
|
||||
|
||||
config APP_WIFI_PASSWORD
|
||||
string "WiFi Password"
|
||||
default "mypassword"
|
||||
help
|
||||
WiFi password (WPA or WPA2) for the application to use.
|
||||
|
||||
config APP_MAXIMUM_RETRY
|
||||
int "Maximum retry"
|
||||
default 5
|
||||
help
|
||||
Set the Maximum retry to avoid station reconnecting to the AP unlimited when the AP is really inexistent.
|
||||
endmenu
|
|
@ -0,0 +1,134 @@
|
|||
#include <stddef.h>
|
||||
|
||||
/* Private header */
|
||||
#include "aht10.h"
|
||||
|
||||
#define AHT10_STATUS_CALIBRATED_MASK (1U << 3U)
|
||||
#define AHT10_STATUS_BUSY_MASK (1U << 7U)
|
||||
|
||||
#define AHT10_ERROR_CHECK(x) \
|
||||
if (x != AHT10_OK) return AHT10_FAIL
|
||||
|
||||
typedef struct {
|
||||
uint8_t status;
|
||||
uint32_t temperature;
|
||||
uint32_t humidity;
|
||||
} aht10_raw_t;
|
||||
|
||||
static aht10_ret_t aht10_software_reset(aht10_t *aht) {
|
||||
/* Reset and initialize device */
|
||||
|
||||
uint8_t tx_data[3] = {0xBA};
|
||||
|
||||
aht10_xfer_desc_t xfer = {
|
||||
.tx_data = tx_data,
|
||||
.tx_size = 1U,
|
||||
.rx_data = NULL,
|
||||
.rx_size = 0U,
|
||||
};
|
||||
|
||||
AHT10_ERROR_CHECK(aht->cb.xfer(aht->user_data, &xfer));
|
||||
|
||||
AHT10_ERROR_CHECK(aht->cb.delay(aht->user_data, 20));
|
||||
|
||||
tx_data[0] = 0xE1;
|
||||
tx_data[1] = 0x08;
|
||||
tx_data[2] = 0x00;
|
||||
|
||||
xfer.tx_size = 3U;
|
||||
|
||||
AHT10_ERROR_CHECK(aht->cb.xfer(aht->user_data, &xfer));
|
||||
|
||||
return AHT10_OK;
|
||||
}
|
||||
|
||||
static aht10_ret_t aht10_start_measurement(aht10_t *aht) {
|
||||
/* Start measurement */
|
||||
|
||||
uint8_t tx_data[3] = {0xAC, 0x33, 0x00};
|
||||
|
||||
aht10_xfer_desc_t xfer = {
|
||||
.tx_data = tx_data,
|
||||
.tx_size = 3U,
|
||||
.rx_data = NULL,
|
||||
.rx_size = 0U,
|
||||
};
|
||||
|
||||
AHT10_ERROR_CHECK(aht->cb.xfer(aht->user_data, &xfer));
|
||||
|
||||
return AHT10_OK;
|
||||
}
|
||||
|
||||
static aht10_ret_t aht10_read_result(aht10_t *aht, aht10_raw_t *raw) {
|
||||
/* Read conversion result */
|
||||
|
||||
uint8_t tx_data[] = {0x71};
|
||||
uint8_t rx_data[6];
|
||||
|
||||
aht10_xfer_desc_t xfer = {
|
||||
.tx_data = tx_data,
|
||||
.tx_size = 1U,
|
||||
.rx_data = rx_data,
|
||||
.rx_size = 6U,
|
||||
};
|
||||
|
||||
AHT10_ERROR_CHECK(aht->cb.xfer(aht->user_data, &xfer));
|
||||
|
||||
raw->humidity = rx_data[1] << 12U;
|
||||
raw->humidity |= rx_data[2] << 4U;
|
||||
raw->humidity |= rx_data[3] >> 4U;
|
||||
|
||||
raw->temperature = (rx_data[3] & 0x0FU) << 16U;
|
||||
raw->temperature |= rx_data[4] << 8U;
|
||||
raw->temperature |= rx_data[5];
|
||||
|
||||
raw->status = rx_data[0];
|
||||
|
||||
return AHT10_OK;
|
||||
}
|
||||
|
||||
aht10_ret_t aht10_init(aht10_t *aht) {
|
||||
/* Check if we need initialization */
|
||||
|
||||
/* Delay 40ms after POR */
|
||||
AHT10_ERROR_CHECK(aht->cb.delay(aht->user_data, 40));
|
||||
|
||||
aht10_raw_t raw;
|
||||
|
||||
/* Check 0x71 status byte, if uncalibrated then reset and calibrate it. */
|
||||
AHT10_ERROR_CHECK(aht10_read_result(aht, &raw));
|
||||
if ((raw.status & AHT10_STATUS_CALIBRATED_MASK) == 0) {
|
||||
AHT10_ERROR_CHECK(aht10_software_reset(aht));
|
||||
}
|
||||
|
||||
return AHT10_OK;
|
||||
}
|
||||
|
||||
aht10_ret_t aht10_measure(aht10_t *aht, aht10_result_t *result) {
|
||||
/* Start a measurement and read back result... */
|
||||
|
||||
AHT10_ERROR_CHECK(aht10_start_measurement(aht));
|
||||
|
||||
AHT10_ERROR_CHECK(aht->cb.delay(aht->user_data, 80));
|
||||
|
||||
aht10_raw_t raw;
|
||||
|
||||
uint8_t max_retries = 5U;
|
||||
|
||||
do {
|
||||
AHT10_ERROR_CHECK(aht10_read_result(aht, &raw));
|
||||
max_retries--;
|
||||
if (max_retries == 0) {
|
||||
return AHT10_FAIL;
|
||||
}
|
||||
#ifndef AHT10_SKIP_BUSY_CHECK
|
||||
} while (raw.status & AHT10_STATUS_BUSY_MASK);
|
||||
#else
|
||||
} while (0);
|
||||
#endif
|
||||
|
||||
result->temperature = ((double)raw.temperature * 200.0 / 1048576.0) - 50.0;
|
||||
result->humidity = (double)raw.humidity * 100.0 / 1048576.0;
|
||||
|
||||
return AHT10_OK;
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
#ifndef AHT10_H
|
||||
#define AHT10_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define AHT10_SKIP_BUSY_CHECK
|
||||
|
||||
typedef enum {
|
||||
AHT10_OK,
|
||||
AHT10_FAIL,
|
||||
} aht10_ret_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t *tx_data;
|
||||
uint8_t *rx_data;
|
||||
uint16_t tx_size;
|
||||
uint16_t rx_size;
|
||||
} aht10_xfer_desc_t;
|
||||
|
||||
typedef aht10_ret_t (*aht10_i2c_xfer_t)(void *pdev, aht10_xfer_desc_t *xfer);
|
||||
typedef aht10_ret_t (*aht10_delay_t)(void *pdev, uint32_t delay_msec);
|
||||
|
||||
typedef struct {
|
||||
double temperature;
|
||||
double humidity;
|
||||
} aht10_result_t;
|
||||
|
||||
typedef struct {
|
||||
aht10_i2c_xfer_t xfer;
|
||||
aht10_delay_t delay;
|
||||
} aht10_cb_t;
|
||||
|
||||
typedef struct {
|
||||
aht10_cb_t cb;
|
||||
void *user_data;
|
||||
} aht10_t;
|
||||
|
||||
aht10_ret_t aht10_init(aht10_t *aht);
|
||||
aht10_ret_t aht10_measure(aht10_t *aht, aht10_result_t *result);
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,93 @@
|
|||
/* ESP drivers */
|
||||
#include "esp_event.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_wifi.h"
|
||||
|
||||
/* FreeRTOS */
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
/* App specific */
|
||||
#include "app_wifi.h"
|
||||
|
||||
#define APP_LOG_TAG "APP_WIFI"
|
||||
|
||||
EventGroupHandle_t g_app_wifi_event_group;
|
||||
|
||||
static uint8_t s_retries = 0U;
|
||||
|
||||
static void app_wifi_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data);
|
||||
|
||||
esp_err_t app_wifi_init(void) {
|
||||
g_app_wifi_event_group = xEventGroupCreate();
|
||||
if (g_app_wifi_event_group == NULL) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
esp_netif_create_default_wifi_sta();
|
||||
|
||||
wifi_init_config_t wifi_init_cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_wifi_init(&wifi_init_cfg));
|
||||
|
||||
esp_event_handler_instance_t inst_any_id;
|
||||
esp_event_handler_instance_t inst_got_ip;
|
||||
|
||||
ESP_ERROR_CHECK(
|
||||
esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, app_wifi_event_handler, NULL, &inst_any_id));
|
||||
|
||||
ESP_ERROR_CHECK(
|
||||
esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, app_wifi_event_handler, NULL, &inst_got_ip));
|
||||
|
||||
wifi_config_t wifi_config = {
|
||||
.sta =
|
||||
{
|
||||
.ssid = CONFIG_APP_WIFI_SSID,
|
||||
.password = CONFIG_APP_WIFI_PASSWORD,
|
||||
.threshold.authmode = WIFI_AUTH_WPA2_PSK,
|
||||
},
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
|
||||
ESP_ERROR_CHECK(esp_wifi_start());
|
||||
|
||||
ESP_LOGI(APP_LOG_TAG, "WiFi initialized, heap free: %d.", esp_get_free_heap_size());
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void app_wifi_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) {
|
||||
/* Event handler */
|
||||
|
||||
if (event_base == WIFI_EVENT) {
|
||||
if (event_id == WIFI_EVENT_STA_START) {
|
||||
esp_wifi_connect();
|
||||
}
|
||||
|
||||
if (event_id == WIFI_EVENT_STA_DISCONNECTED) {
|
||||
if (s_retries < CONFIG_APP_MAXIMUM_RETRY) {
|
||||
esp_wifi_connect();
|
||||
s_retries++;
|
||||
|
||||
ESP_LOGI(APP_LOG_TAG, "Connection lost, retrying #%d/%d...", s_retries, CONFIG_APP_MAXIMUM_RETRY);
|
||||
} else {
|
||||
xEventGroupSetBits(g_app_wifi_event_group, APP_WIFI_EVENT_GROUP_EVENT_FAILED);
|
||||
|
||||
ESP_LOGW(APP_LOG_TAG, "Connection lost, maximum retries reached.");
|
||||
}
|
||||
}
|
||||
} else if(event_base == IP_EVENT) {
|
||||
if(event_id == IP_EVENT_STA_GOT_IP) {
|
||||
xEventGroupSetBits(g_app_wifi_event_group, APP_WIFI_EVENT_GROUP_EVENT_CONNECTED);
|
||||
s_retries = 0U;
|
||||
|
||||
ip_event_got_ip_t *event = event_data;
|
||||
|
||||
ESP_LOGI(APP_LOG_TAG, "Connected, IP address: "IPSTR, IP2STR(&event->ip_info.ip));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
#ifndef APP_WIFI_H
|
||||
#define APP_WIFI_H
|
||||
|
||||
/* ESP drivers */
|
||||
#include "esp_system.h"
|
||||
|
||||
/* FreeRTOS */
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/event_groups.h"
|
||||
|
||||
#define APP_WIFI_EVENT_GROUP_EVENT_CONNECTED (1 << 0U)
|
||||
#define APP_WIFI_EVENT_GROUP_EVENT_FAILED (1 << 1U)
|
||||
|
||||
extern EventGroupHandle_t g_app_wifi_event_group;
|
||||
|
||||
esp_err_t app_wifi_init(void);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: CC0-1.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* ESP drivers */
|
||||
#include "esp_log.h"
|
||||
|
||||
/* FreeRTOS */
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
/* NVS */
|
||||
#include "nvs_flash.h"
|
||||
|
||||
/* Config */
|
||||
#include "app_wifi.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#define APP_LOG_TAG "MAIN"
|
||||
|
||||
void app_main(void) {
|
||||
printf("Hello world!\n");
|
||||
|
||||
esp_err_t ret = nvs_flash_init();
|
||||
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
|
||||
ret = nvs_flash_init();
|
||||
|
||||
ESP_LOGW(APP_LOG_TAG, "NVS content corrupted or outdated, cleared.");
|
||||
}
|
||||
|
||||
ESP_ERROR_CHECK(ret);
|
||||
|
||||
ESP_ERROR_CHECK(app_wifi_init());
|
||||
|
||||
EventBits_t bits = xEventGroupWaitBits(g_app_wifi_event_group,
|
||||
APP_WIFI_EVENT_GROUP_EVENT_CONNECTED | APP_WIFI_EVENT_GROUP_EVENT_FAILED,
|
||||
pdFALSE, pdFALSE, portMAX_DELAY);
|
||||
|
||||
if (bits & APP_WIFI_EVENT_GROUP_EVENT_FAILED) {
|
||||
/* ?? */
|
||||
}
|
||||
|
||||
vTaskSuspend(NULL);
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
# ESP-IDF Partition Table
|
||||
# Name, Type, SubType, Offset, Size, Flags
|
||||
nvs, data, nvs, 0x9000, 0x6000,
|
||||
phy_init, data, phy, 0xf000, 0x1000,
|
||||
factory, app, factory, 0x10000, 3M,
|
|
|
@ -0,0 +1,22 @@
|
|||
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
from typing import Callable
|
||||
|
||||
import pytest
|
||||
from pytest_embedded_idf.dut import IdfDut
|
||||
from pytest_embedded_qemu.dut import QemuDut
|
||||
|
||||
|
||||
@pytest.mark.supported_targets
|
||||
@pytest.mark.generic
|
||||
def test_hello_world(dut: IdfDut, log_minimum_free_heap_size: Callable[..., None]) -> None:
|
||||
dut.expect('Hello world!')
|
||||
log_minimum_free_heap_size()
|
||||
|
||||
|
||||
@pytest.mark.esp32 # we only support qemu on esp32 for now
|
||||
@pytest.mark.host_test
|
||||
@pytest.mark.qemu
|
||||
def test_hello_world_host(dut: QemuDut) -> None:
|
||||
dut.expect('Hello world!')
|
|
@ -0,0 +1,7 @@
|
|||
# Minimum flash size set to 4MB
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
|
||||
|
||||
# Use custom partition table, 3MB application.
|
||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
||||
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue