「ESP32-IDF」タグアーカイブ

ESP32-IDFでUART通信を行ってみる

ESP32-IDFでUART機能を試してみます。

こんにちは、北神です。IoTではGPSや既存のシリアル通信機器が話題になることもあります。

さっそく、ESP32-IDFでUARTを試してみまいと思います。

詳しい資料は、以下の公式情報から辿ってみてください。

https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/uart.html

    #define UART_2_TXD  16
    #define UART_2_RXD  17

    const int uart_num = UART_NUM_2;
        uart_config_t uart_config = {
        .baud_rate = 9600,//115200,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .rx_flow_ctrl_thresh = 122,
    };
    uart_param_config(uart_num, &uart_config);
    uart_set_pin(uart_num, UART_2_RXD, UART_2_TXD, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
    uart_driver_install(uart_num, 128+1, 0,0, NULL, 0);

以上の通り、GPIO16とGPIO17(UART_2)をUART用に設定しました。
uart_configでは、見慣れたUARTの設定を細かく行っています。

uart_driver_installでハマった点は、rx_buffer_sizeが128以下に設定するとエラーがでるという点です。
多分、rx_buffer_sizeを用いてmallocを行なっている用に思えますので、小さすぎるバッファは作成できないのでしょう。
とりあえず、最小の128+1で構成すればOKです。

受信に関しては

    int len = uart_read_bytes(uart_num, data, 1 , 1000 / portTICK_RATE_MS);

で済みます。

uart_read_bytesは、公式より以下の関数になります。

    int uart_read_bytes(uart_port_tuart_num, void *buf, uint32_t length, TickType_t ticks_to_wait)

ここで、lengthを指定してあげれば、length分溜まったデータを取得することができます。
今回は、わざわざ1バイト毎の取得を行い改行文字でカッティングを行いたい為、lengthを1としました。

こんな感じで、UART通信も設定できるようです。

めでたし、めでたし。

それでは!

ESP32-IDFでI2C-Masterを試してみる

ESP32-IDF開発環境にてI2Cを操作する方法をまとめていきます。

こんにちは、北神です。IoTで良く使用するI2Cを使う場面もあるだろうと思い、まとめました。

詳しい資料は、以下の公式情報から辿ってみてください。

https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/i2c.html

また、以下の公式サンプルの一部を使用しております。

https://github.com/espressif/esp-idf/tree/master/examples/peripherals/i2c/i2c_tools

■ マスターのI2Cの設定

I2Cの設定情報を、以下の様に記載します。変更が多い SDAピン、SCLピン、クロック速度を外部で変更できるようにしてあります。
その他は固定で良いと思いますが、必要があれば変更してください。

#define I2C_MASTER_TX_BUF_DISABLE 0
#define I2C_MASTER_RX_BUF_DISABLE 0 
#define WRITE_BIT I2C_MASTER_WRITE 
#define READ_BIT I2C_MASTER_READ    
#define ACK_CHECK_EN 0x1           
#define ACK_CHECK_DIS 0x0         
#define ACK_VAL 0x0                 
#define NACK_VAL 0x1                

#define I2C_SDA     21
#define I2C_SCL     22

void i2c_master_setup(int sda_io_num,int scl_io_num,int clk_speed,i2c_port_t i2c_port)
{
    int i2c_master_port = 0;
    i2c_config_t conf = {
        .mode = I2C_MODE_MASTER,
        .sda_io_num = sda_io_num,
        .sda_pullup_en = GPIO_PULLUP_ENABLE,
        .scl_io_num = scl_io_num,
        .scl_pullup_en = GPIO_PULLUP_ENABLE,
        .master.clk_speed = clk_speed,
        
    };
    i2c_driver_install(i2c_port, I2C_MODE_MASTER, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
    i2c_param_config(i2c_port, &conf);
}

■ i2cdetectを試しに作ってみる

I2Cの設定を記述できたので、早速試してみようと思いました。
一番簡単で便利なi2cdetectをカバーしてみます。
多くの処理は、公式のサンプルを利用しています。

void app_main(void)
{

    i2c_port_t i2c_port = I2C_NUM_0;
    i2c_master_setup(I2C_SDA,I2C_SCL,100000,i2c_port);


    uint8_t address;
    printf("     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f\r\n");
    for (int i = 0; i < 128; i += 16) {
        printf("%02x: ", i);
        for (int j = 0; j < 16; j++) {
            fflush(stdout);
            address = i + j;
            i2c_cmd_handle_t cmd = i2c_cmd_link_create();
            i2c_master_start(cmd);
            i2c_master_write_byte(cmd, (address << 1) | WRITE_BIT, ACK_CHECK_EN);
            i2c_master_stop(cmd);
            esp_err_t ret = i2c_master_cmd_begin(i2c_port, cmd, 50 / portTICK_RATE_MS);
            i2c_cmd_link_delete(cmd);
            if (ret == ESP_OK) {
                printf("%02x ", address);
            } else if (ret == ESP_ERR_TIMEOUT) {
                printf("UU ");
            } else {
                printf("-- ");
            }
        }
        printf("\r\n");
    }

    i2c_driver_delete(i2c_port);
    return 0;
}

プログラムを書込み、実行すると、以下の様にコンソールに表示されました。

めでたし、めでたし。

それでは!

ESP32-IDFでアプセスポイントを構築する

ESP32-IDFでAPモードで起動する方法を試してみます。

こんにちは北神です。

ESP32はArduino環境とチップメーカ公式のIDFという開発環境があります。
日本ではArduino環境での開発が多くみられますが、ESP32の本場はIDFによる構築ですので、それに合わせて開発を試してみたいと思います。

今回試すのは、アクセスポイント(APモード)にする方法です。

細かく説明するには、FreeRTOSについてや、イベントについて話す必要がありますが、今回はサクッと動作するソースを載せておきます。

開発環境は ESP-IDF v4.3.1 を使用しております。

#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"

#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include <lwip/netdb.h>


void wifi_init_softap(void);

static const char *TAG = "ESP32_WS_APP";

//==========================//
// wifi_event_handler
//==========================// 
static void wifi_event_handler(void* arg, esp_event_base_t event_base,
                                    int32_t event_id, void* event_data)
{
    if (event_id == WIFI_EVENT_AP_STACONNECTED) {
        wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data;
        ESP_LOGI(TAG, "station "MACSTR" join, AID=%d",
                 MAC2STR(event->mac), event->aid);
    } else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) {
        wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data;
        ESP_LOGI(TAG, "station "MACSTR" leave, AID=%d",
                 MAC2STR(event->mac), event->aid);
    }
}

#define SSID    "ESP32_TEST"
#define PASS     "123456789012345"
//==========================// 
//  WiFi SoftAP
//==========================// 
void wifi_init_softap(void)
{
    esp_netif_create_default_wifi_ap();
 
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));
 
    ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
                                                        ESP_EVENT_ANY_ID,
                                                        &wifi_event_handler,
                                                        NULL,
                                                        NULL));
    wifi_config_t wifi_config = {
        .ap = {
            .ssid = SSID,
            .ssid_len = strlen(SSID),
            .channel = 7,
            .password = PASS,
            .max_connection = 2,
            .authmode = WIFI_AUTH_WPA_WPA2_PSK
        },
    };
    if (strlen(PASS) == 0) {
        wifi_config.ap.authmode = WIFI_AUTH_OPEN;
    }
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
    ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config));
    ESP_ERROR_CHECK(esp_wifi_start());
}

//==========================// 
//  app_main
//==========================// 
void app_main(void)
{
    ESP_ERROR_CHECK(nvs_flash_init());
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());

    ESP_LOGI(TAG, "ESP_WIFI_MODE_AP");    
    wifi_init_softap();
}

このソースを
idf.py flash -p COM11 で書き込み、 idf.py monitor -p COM11 で確認すると、以下の様にログが表示されます。


この状態で、スマフォ等でWiFiのSSIDを確認しに行くと、
SSID: ESP32_TEST
Pass: 123456789012345
で、接続しに行く事ができます。

無事に接続ができますと、IPを振り分けられます。
ログでは以下の様に表示されます。

これで、クライアントに「192.168.4.2」を配布できました。

ESP32-IDFはFreeRTOSで開発する為、一般的なシングルスレッドなマイコンの動作ではなく、決まった時間でタスクが切り替わる事を意識しながら開発する必要があります。

FreeRTOSは非常に便利な機能が多く、できなかった事が楽にできる様になりますのでおすすめです。

ではでは。