2021年7月24日土曜日

Raspberry Pi Picoを買ってみた

 そういえば買えるようになったら買おうと思っていたラズパイピコの在庫があったので買ってみた。ピンヘッダ付きとか何かとセットになってるやつは在庫あるのに単品の550円で買えるやつがなかなか在庫なかったので諦めてたんだけど。

たしかにピンヘッダ付きもいいんだけどピンヘッダ持ってるし、なによりこのコスパの高さがこいつのいいところな気がして…
microUSBなのは少し残念だが、もげにくようなスルーホールタイプの端子なのでいいかも。USBホスト機能もついてるようなのでmicroUSB用のOTGケーブルもあるといいかも。FireTVとかで使うようなUSBから給電できるやつたとか。
ピン名は裏面にシルクで印刷されている。これブレッドボードとかに指しちゃうと不便かも。書き込みボタンが無かったらピンヘッダを裏表逆にハンダする人もいそう。

デフォルトではMicroPythonで開発できるようになってるっぽい。Linuxが動くラズパイではPythonで色々作ってみてるけど、マイコン用のPythonはどんな感じなんだろうか…
とりあえずArduino IDEも対応しているようだからArduino IDE使おうかなぁ

2021年7月18日日曜日

WT32-SC01でタッチパネル対応GUIを使ってみる。

 先日入手したWT32-SC01でタッチスクリーンを試すのにかっこいいGUIが作れるLVGLライブラリを使ってみた。このライブラリを使うと画像ファイルなしでもかっこいいGUIが作れるらしい?

Arduino IDEでも使えるようだし、液晶パネルのライブラリは前回使用したTFT_eSPIライブラリをそのまま使えるみたい。TFT_eSPIのタッチパネル対応は抵抗膜方式だけっぽかったのでLVGLライブラリでタッチパネルに対応させるためには別なライブラリを使用することに。

まずはタッチパネルの動作確認から。
WT32-SC01のタッチパネル用ライブラリはArduino-FT6336Uを使ってみた。設定もシンプルで良さそうだったし。

WT32-SC01ではFT6336Uの接続はI2Cのみの接続になっていたので、ライブラリで使われている割り込みPinとリセットPinはTPで出ているだけで未接続だった。なのでタッチパネルに触ったかどうかの判別はポーリングで行うことに。

とりあえずサンプルスケッチで動作確認。

#include "FT6336U.h"
#define I2C_SDA 18
#define I2C_SCL 19

FT6336U ft6336u(I2C_SDA, I2C_SCL, -1, -1);

サンプルスケッチの上の方はこんな感じで割り込みPinとリセットPinを無効にしてみた。そんでもってINT_N_PINの判別をなくしてシリアルコンソールで入力を確認できた。

ft6336u.read_td_status()

でタッチパネルに触れている指の数(最大2)がわかるっぽいので、ポーリングだけでも触ったことがわかりそうだから問題なさそう。

タッチパネルがなんとなく動いてそうなことがわかったのでお次はLVGLの設定。LVGLライブラリの設定は結構たいへんだった…
まずはライブラリを入れたあとにlv_conf_template.hをArduinoのlibrariesにlv_conf.hとしてコピーして"#if 0"を"#if 1"に変更したり、DEMOを使えるように#define LV_USE_DEMO_WIDGETSを1に変更したりexampleフォルダをコピーしたりする。詳しくは本家サイト参照

そんでもってサンプルのLVGL_Arduino.inoをいじってタッチパネル部分をFT6336Uに対応させてみた。

先程のサンプルスケッチの上の方をそのまま移植して、

void my_touchpad_read( lv_indev_drv_t * indev_drv, lv_indev_data_t * data )
{
    uint16_t touchX, touchY;

    uint8_t touched = ft6336u.read_td_status();
    if( touched == 0 )
    {
        data->state = LV_INDEV_STATE_REL;
    }
    else
    {
        data->state = LV_INDEV_STATE_PR;
        touchY = 320 - ft6336u.read_touch1_x();
        touchX = ft6336u.read_touch1_y();
        data->point.x = touchX;
        data->point.y = touchY;
    }
}

タッチパネルが90°ズレていたのでmy_touchpad_read関数を上のように変更した。

setup内ではtft.setRotation( 1 );をtft.setRotation( 3);に変更して液晶の向きを戻して、tft.setTouch( calData );をft6336u.begin();に変更してTFT_eSPIのタッチパネル機能から別ライブラリのArduino-FT6336Uに変更できた。
TFT_eSPIの設定は前回のものそのままで使用できた。例によってバックライト用の2行も追加しないと画面が真っ暗のままなので注意。

ちなみにタッチスクリーンを使うときは上の方で出てきたlv_conf.hの中の#define LV_TICK_CUSTOMを1に変更する必要があるっぽい。(これをやらないと読み込まれない)
そしてついでにタッチパネルのテストをしたいので#define LV_USE_DEMO_WIDGETSも1にしておいた。

サンプルスケッチのlv_demo_widgets();のコメントアウトを外して書き込めばとりあえずタッチパネルのテストができる。

LVGL Arduino
とりあえずシングルタッチで実装してみたけどスワイプもいい感じに動いてる。ESP32でこんなにきれいなGUIを実装できるなんてLVGLライブラリ恐るべし。
欲を言えばGUIのツールとかで作れたら良いんだけどなぁ
LVGLのサンプル動かすのも結構設定が面倒だったので、簡単にタッチLCDを動かしたいなら多少高くてもM5Stackとかのほうがいいんだろうなぁ…

このWidgetサンプルを実行するのも少し大変だったけど、LVGLライブラリがWT32-SC01上で動くことがわかったのでこれでかっこいいGUI使ったなにか作れるかな。


2021年7月17日土曜日

WT32-SC01を買ってみた。

 Aliexpressを見ていたらESP32に静電容量式タッチ対応LCDがついたボードが安かったのでポチってみた。WT32-SC01ってやつ。3500円ぐらいだった。M5Stackとかもいいなーと思っていたんだけどこっちのほうが安くてLCDも大きかったので…

ESP32-WROVER-Bモジュールと3.5インチのSPI接続のディスプレイが乗っている。2ポイントまでの静電容量タッチディスプレイらしい。
WL-352215
表面はツルツル。左側に穴が空いているように見えるけど黒い部分が抜かれてるだけで、部品は未実装だった。光センサとかつけようとしていたのかな?
裏面にはピンヘッダが並んでいる。このピンヘッダ、2.0mmピッチっぽいので少し扱いにくいかも…
USBシリアル変換機も内蔵していててSiliconLabsのVCPドライバを入れておけば認識する。
ちなみに発注時の画像にも合ったけど技適マーク付きのESP32-WROVER-Bモジュールだった。

LCDのコントローラはST7796SでESP32とはSPI接続されているっぽい。タッチコントローラはFT6336UがI2Cで接続されている。バックライトはPWMで調整できる。

まずはArduino IDEを使ってLCD表示を試してみた。
使用したライブラリはTFT_eSPI

ライブラリマネージャからライブラリをインストールしたらライブラリのフォルダに行って(Arduino\libraries\TFT_eSPIの中)
User_Setup.hをWT32-SC01用に書き換える。
上の方からディスプレイコントローラは
#define ST7796_DRIVER
のところだけをコメントアウト外す。(他のところはコメントアウト)
ピン配置設定のところは全部コメントアウトして
#define USE_HSPI_PORT 1 
#define TFT_MISO 12 
#define TFT_MOSI 13 
#define TFT_SCLK 14 
#define TFT_CS 15 
#define TFT_DC 21 
#define TFT_RST 22 
#define TFT_BL 23 
とした。
そしてSPIクロック設定は
#define SPI_FREQUENCY  80000000
に変更した。
あとは適当なサンプルを実行してみた。
バックライトをONにするために

pinMode(TFT_BL, OUTPUT);
digitalWrite(TFT_BL, 128);
上の2行を
tft.init();
の下辺りに入れる。128のところを変更すれば明るさが調整できるので可変できるようにしてもいいかも。
最初User_Setup.hをいじるの知らなくてバックライトがうねうねしてたけどちゃんと設定したら映った。
解像度も480x320あるので結構色々な情報が表示できそう。ESP32はCANトランシーバをつけるだけでCANが使えるので車載OBD2ディスプレイとかも作れそう。デュアルコア活用できそうだし。

LCDの動作確認もできたので次回はタッチスクリーンの確認してみないと。


2021年7月10日土曜日

HX711をI2Cから読めるようにしてみた

 Orange Pi PCでうまくHX711が使えなかったので、やっぱりSBCとかで使うにはI2Cのほうが便利ということでHX711をI2C経由で使えるようにしてみた。
やっぱりこういうデバイスはGPIOで頑張るよりちょっとしたマイコンで読んでもらったほうが楽勝な気がする…SBC側のCPU負荷も減るんじゃないかな。

今回はとりあえずAttiny202を使ってHX711のデータを連続で読みに行って、読んだ値をI2C用のレジスタに格納しておいてI2Cからはスレーブでレジスタを読みに来ればいい感じにしてみた。

HX711は10spsモードだからといって一定周期で読もうとすると変なデータになってしまったりするので調べてみるとナゾの一定周期パルスが出ている影響らしい?
とりあえず適当に対策してみたら10spsモードのHX711とAttiny202を繋いで連続で読みに行くと平均177msかかってる。一定周期パルスの2倍の周期でしか読めなかったけど、とりあえず用途的には十分なので良し。
I2C側は割り込みだし、loop内はHX711にだけ注力していればいいので簡単に対策できた。

I2Cでレジスタを読む形のスレーブデバイスを作る部分はちょっと前に作成したコードがそのままattiny202でも使えた。それにHX711を読み込むところを追加したぐらい…

#include <Arduino.h>
#include <Wire.h>

#define DAT 1
#define CLK 0
#define SLAVE_ADDRESS 0x60

#define DISABLE_INTERNAL_PULLUP

//使用するレジスタ範囲指定
#define I2C_REG_ROW 1
#define I2C_REG_COL 4
uint8_t I2C_REG[I2C_REG_ROW][I2C_REG_COL];

//読み書きするレジスタアドレス
uint8_t REG_SELECTED;

//i2c受信イベント
void receiveEvent(int _length) {
  //1byte目を読み込む(レジスタアドレス指定)
  REG_SELECTED = Wire.read();
  uint8_t startRow = REG_SELECTED >> 4;
  uint8_t startCol = (REG_SELECTED & 0x0F);

  while (Wire.available() > 0) {
    if (startRow < I2C_REG_ROW && startCol < I2C_REG_COL) {
      I2C_REG[startRow][startCol] = Wire.read();
    } else {
      Wire.read();
    }
    ++startCol;
  }
}

void requestEvent() {
  uint8_t startRow = REG_SELECTED >> 4;
  uint8_t startCol = (REG_SELECTED & 0x0F);
  if (startRow < I2C_REG_ROW && startCol < I2C_REG_COL) {
    Wire.write(&I2C_REG[startRow][startCol], I2C_REG_COL - startCol);
  }
}

void setup() {
  //SlaveでWireライブラリを初期化
  Wire.begin(SLAVE_ADDRESS);
  //イベント設定
  Wire.onReceive(receiveEvent);
  Wire.onRequest(requestEvent);

  //内蔵プルアップ無効にする場合
#ifdef DISABLE_INTERNAL_PULLUP
  pinMode(SDA, INPUT);
  pinMode(SCL, INPUT);
#endif
  //HX711用ピン設定
  pinMode(CLK, OUTPUT);
  pinMode(DAT, INPUT);
}

void loop() {
  //HX711データ取得
  uint8_t rawdata[3] = {0, 0, 0};
  while (digitalRead(DAT) == 0);
  while (digitalRead(DAT) != 0);
  for (char k = 0; k < 3; k++) {
    for (char i = 0; i < 8; i++) {
      digitalWrite(CLK, 1);
      delayMicroseconds(1);
      digitalWrite(CLK, 0);
      delayMicroseconds(1);
      rawdata[k] = (rawdata[k] << 1) | (digitalRead(DAT));
    }
  }
  
  I2C_REG[0][0] = 0x12;
  I2C_REG[0][1] = rawdata[2];
  I2C_REG[0][2] = rawdata[1];
  I2C_REG[0][3] = rawdata[0];
}

mills()/micros()を無効にして、Attiny202の67%に収まってる。とりあえずゲインの調整とかもなしで生データをひたすら177msで更新しているので適当なタイミングでi2cから読みに行けばいい感じ。50ms周期とかで読んでもデータ化けはなかったので用途的には大丈夫そうかな。

一応HX711側は5Vで使う場合はI2C側かHX711側でレベル変換すれば良さそう。HX711側でDATだけを抵抗分圧だけで行けないかなとか思っている。テストではFETでI2C側をレベル変換しているけど。

生データでそのまま吐き出しているので(一応ヘッダ的なのはつけておいたけど)、Orange Pi PC側のPythonのライブラリで値を取得するところだけsmbusからデータ取るようにしたらそのまま使えないかなぁとか思ったり。SBC側のソフトは作成中…
i2cdumpではうまく動いている。

せっかくI2Cデバイスにしてマイコン挟むならゲイン調整とかゼロセットとか、重量の換算までできるようにしたいな。I2Cだから複数のHX711を取り扱うのは楽になりそう。

2021年7月3日土曜日

安価なSDカードリーダ買ってみた

 KingstoneのSDカードリーダを使っていたんだけど、どうもカードを指しても認識しなくなる時があって何回か指し直すと認識はするんだけども面倒になったのでAliexpressで送料含めても1.8ドルで売っていたのを買ってみた。

まぁ例によって梱包がアレなので細かい擦り傷がついていたり文字が一部消えていたり…
上海問屋のDN-915045とそっくり。というか印刷が違うだけ?
ちなみに上海問屋のやつは550円なのでこっちは半額以下である…
USB3.0対応で、SDとmicroSDカードが使える。

この前ドラレコ用に購入した高耐久microSDと同じものを購入しておいたので測定してみた。

Kingstoneのリーダーでの結果と比べるとQ1T1以外はほぼ同じ。Q1T1だけ遅くなってる。どうやらこのリーダーのコントローラーはシングルキューが遅いよう?

まぁ200円ぐらいのリーダーとしては十分かな?そんなに早いカード使わないし…
ちなみにLEDは青色でアクセスランプではなく電源ランプっぽい。