「技術メモ」カテゴリーアーカイブ

計装について

計装とは、主にプラントやビルなどで使用するパネルや筐体に取り付ける計測器です。

計装は、センサーとメーターの組み合わせで実現されますが、その間の伝送路は一般的な範囲で4mA~20mAと言った”電流値”で出力されることが多いです。
電流出力の場合、出力を行う装置は常に伝送路に出力する電流を一定に保つ様に制御を行なっています。
その為、例えば伝送路が長くなり、伝送路内の抵抗値が上がった際も、出力電流が設定値になる様に調整を行います。
これにより、伝送路を延長しても、”正確な電流値”をメータや制御装置へと伝送できる仕組みです。

電流値と計測値の変換は、例えば、K型熱電対の測定範囲が0~200℃の場合、4mAの時は0℃、20mAの時は200℃となります。
この様に、電流値によってメータの値を取得し表示を行なっています。

それでは。

Alexaで機器が複数台登録された際の対処法

AmazonEchoやアプリで、Alexa(アレクサ)をよく使いますが、
不具合があった為、その対処方法をまとめてみました。

先日、アレクサより突然

「エアコンという名前の端末が1台以上見つかりました。
それぞれに違う名前を付けて、もう一度検出してください。
数の端末を同時に操作したい場合は、グループを作成してください。」

と言った内容で、エアコンの操作ができなかった為、以下を試してみました。

・ アレクサのアプリを確認いたします。

・ 「デバイスの設定を開く」をタップし、以下の図の様に一覧を確認します。

・ エアコンが2台分表示されています。

・ 同じ名前の機器が2台登録されていますと、アレクサが”エアコン”という呼び名で混乱してしまうのも仕方がありません。
また、接続した機器は1台でしたが、何かの拍子に2台分登録されています。

・ ここで「サーバーが応答しません」と赤ポチで表示されているデバイスが、不具合を起こしている様に思えます。
その赤ポチのデバイスを選択し右上の歯車をタップし、続いて右上のゴミ箱ボタンをタップして削除を行います。

・ これで、”エアコン”に反応するデバイスが1台のみとなりますので、再度”エアコン”の操作を行なってみますと、無事に正常になりました。

めでたし、めでたし。

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で自作のライブラリや、他所のライブラリを使用したい時の方法です。

こんにちは北神です。

あまり多くはありませんが、自作したライブラリを反映させる際に、困ったのでまとめます。

作成しらプロジェクフォルダの中に、mainフォルダがあり、

ここにapp_main()が記載されたファイルが生成されると思います。

安易な方法ですが、そのmainフォルダに、反映させたいヘッダーファイルを入れます。

このフォルダ内に「CMakeLists.txt」があり、それを編集します。

idf_component_register(SRCS "app_mainのファイル.c" "リンクさせたいライブラリ.c"
INCLUDE_DIRS ".")

これで、反映させたいヘッダーファイルもコンパイルされて、バイナリファイルが生成されます。

一安心。

※カッコ内はカンマも要らないみたいです。

ではでは。

地図のオープンデータ「OpenStreetMap」

地図を使ったサービスを考える場合はGoogle Mapを使用しますが、
「$200 usage every month for no charge. That’s 28,500 maploads per month for no charge. 」
(https://mapsplatform.google.com/pricing/?hl=ja)
とあり、有名サイトになった場合には、有料になります。

そこで地図のオープンデータの使用を考えてみよう・・・・
OpenStreetMap(OSM)は、誰でも自由に地図を使えるよう、みんなでオープンデータの地理情報を作るプロジェクトです。
https://openstreetmap.jp
「OpenStreetMapとその協力者をクレジットすれば、データを自由にコピー、配布、送信、利用することができます。変更したり翻案したりしたデータは同じライセンスに従う場合のみ、提供することができます。」

Googleマップのようにマーカーを付けることが可能。
https://www.openstreetmap.org/?mlat=緯度&mlon=経度

弊社の位置だと、こちら。
https://www.openstreetmap.org/?mlat=35.70010&mlon=139.77402

ZOOMしたい場合は、URLに#map=ズームの数/緯度/経度を追加。
https://www.openstreetmap.org/?mlat=35.70010&mlon=139.77402#map=17/35.70010/139.77402

埋め込みも可能。

大きな地図を表示

公開されているGPSトラッキングが見えるので、精度の悪いGPS端末があるとズレることはあるが参考値としてはよいと思う。

弊社秋葉原駅付近のトラッキングデータ。

“Base map and data from OpenStreetMap and OpenStreetMap Foundation”

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は非常に便利な機能が多く、できなかった事が楽にできる様になりますのでおすすめです。

ではでは。

PythonでIoT用ミニマムな簡易APIサーバーを作る

Pythonでミニマム(最小形態)でサーバーを作ってみようと思う。

こんにちは、北神です。

IoTの開発を行う際に、ちょっとテストでサーバーが欲しい!という時に、Linuxを立ち上げアレやコレを入れて、
HTTPのPOSTやGETを取得するサーバーを組むのは時間がかかって仕方がない。

そこで、Pythonでお手軽にAPIサーバーの作り方をまとめていきます。

■ bottleを始めてみる

使うライブラリは「bottle」です。

このbottleは、高性能ではありませんが、数行でサーバーを立ち上げる事ができ、
POSTやGETといったREST-fullの構造を構築する事ができます。
また、HTMLの表示等もできますので、簡易な試験サーバーとして使用する際に重宝します。

早速インストールします

pip3 install bottle

これだけです。
また、bottleは1ソースで構成されたライブラリであることも人気の秘訣であり、以下のULRよりダウンロードすることで使用することも可能です。
https://bottlepy.org/bottle.py

早速、簡単なので以下のソースをテキストに貼り、server.pyと保存してみましょう。

from bottle import Bottle, run , post, get

app = Bottle()

@app.route('/')
def hello():
    return "Hello World!"

run(app, host='localhost', port=8080)

実行してみます。

python3 server.py

すると、コマンドラインには

Bottle v0.12.19 server starting up (using WSGIRefServer())...
Listening on http://localhost:8080/
Hit Ctrl-C to quit.

と表示されますので、試しにブラウザにて

localhost:8080 と入力して表示します。

Hello World! と表示されます。

■ bottleでAPI風を作成

早速API風な機能をつけていきます。

GETの機能は

@app.get('/get')
    def get_acction():
    return "GET Hello!"

で作成でき、

POSTの機能は

@app.post('/post')
    def post_acction():
    return "Post Hello!"

で作成できます。

これで、IoT機器でREST-fullの対応が試せる様になります。

ではでは。

DX白書2021|ディスラプターの脅威

IPAの発表した「DX白書2021」

2021年10月11日公開 独立行政法人情報処理推進機構 社会基盤センターより
https://www.ipa.go.jp/ikc/publish/dx_hakusho.html

DXの定義が曖昧ですが、IPAとしては
IPAとしては、「IoTから得られたデータを活用し、次に企業として進む方向を検討することができる仕組みを作って、その仕組みで常に変化し続ける(変革する)ことがDXです。」
(引用:「DXってIoTとどこが違うの?」https://www.ipa.go.jp/ikc/reports/mfg-dx-faq0104.html)
とのこと。

DX白書2021の内容で衝撃的なのは、IT、AIなどの日米を各項目で比較しているのですが、
凄いのはアメリカは30%以上が開発技術で「コンテナ/コンテナ運用自動化」を活用している。
日本は9%です。
AI導入はアメリカ44%、日本20%。
日本はDXが遅れていることをレポートでは強調している。

比較表で気になったのはこちらです。
「外部環境変化への機会としての認識」

(引用:DX白書2021)

日米誤差の範囲なのですが、1項目だけ10%以上の影響意識の差があります。
「ディスラプターの出現」の項目です。影響があると考えいるのはアメリカ68%、日本54%。
ディスラプター(disruptor)とは
創造的破壊者で、ここでいう意味は最新デジタル技術を使い旧サービスや市場を破壊的変えるサービスや企業になります。
「Airbnb」「Uber」「Netflix」などがあります。

日本では、卸売仕組みや規制や地域サービス格差がまだある為、意識が薄いと思いますが、
アメリカでは意識される項目になったことがわかります。
「Netflix」でいうと、日本のレンタルビデオは壊滅的影響がありました。

ESP32-IDFをWindowsで構築する

ESP32では、公式開発環境のESP32-IDFとAeduinoIDEの二種類の開発環境があります。
今までArduinoで開発してましたが、今回からESP-32-IDFを試してみたいと思います。

■ インストールの方法

 https://dl.espressif.com/dl/esp-idf/?idf=4.4

Online Installerで環境全体のインストールが可能です。

インストール後、デスクトップに「ESP-IDF 4.3 CMD」が登場し、ESP-IDF 4.3 CMDを使用してコマンドを入力します。

■ プロジェクト作成

「ESP-IDF 4.3 CMD」にて、プロジェクトファイルを生成します。
プロジェクトファイルを生成したいディレクトリまでcdコマンドで移動し

idf.py create-project プロジェクト名

例)

idf.py create-project Hello

で、作成ができます。

■ プログラムを編集

プロジェクト名のフォルダにmainフォルダがあり、その中にC言語ソースがあります。
初期では


#include <stadio.h>
void app_main(void)
{

}

が書かれていると思います。

app_mainがmainでない点は、別途Bootloder等があり、app_mainが呼び出されるまで別の処理が先に行われます。

#include <stadio.h>
void app_main(void)
{
    printf("Hello\n");
}

保存し、以下のコマンドを実行します。

idf.py build

最初は時間かかりますが、2回め以降変更がない際は早くコンパイルができます。

※コンパイル中に「FAILED: esp-idf/mbedtls/x509_crt_bundle」というエラーが表示された際

このエラーは、cryptographyがバージョンアップした際に関数の使い方を変更した事が原因です。
問題のバージョンは、cryptographyの35.0.0 – 2021-09-29のものです。
IDF側で対応されてば良いですが、まだ対応されてない際は、以下のコマンドで一つ前のバージョンを使用します。

pip uninstall -y cryptography
pip install cryptography==3.4.8

■ ESP32に書き込む

buildがうまくいったら、以下のコマンドで書き込みます。

idf.py flash -p ポート番号

Windowsの場合、COMポートの指定は以下の例の様にします。

idf.py flash -p COM11

■ ESP32でシリアルモニタを確認する

以下のコマンドでシリアル通信の確認ができます。
デフォルトでは115200bpsになります。

idf.py -p com11 monitor

コマンドを使って、ESP32の開発ができそうです。

ではでは。