2019/07/21

はてなブログへの帰還。。。

はてなブログの広告表示が辛くて、広告の入らないBloggerに移ってきましたが、どうもやっぱりUIが使い慣れないし、なんかBloggerは寂しいくて、無駄話レベルだと全然書く気に慣れず、、、で、、はてなブログに戻ることにしました。また、はてぶの方を見てください。
戻り先ー>https://chakoku.hatenablog.com/

行ったり来たりですみません。

2019/06/01

ESP32 + CMOS Camera(OV7670 w/FIFO)

ESP32 に CMOS Camera(FIFO 7670)を接続してmicroPythonで制御してみる。これはもう作例が多くて陳腐化した構成なのだが。。 敢えて言うと、、Arduinoでの実装は多いが、microPythonで扱う事例が少ないというぐらいか。。 microPythonだとループが遅いので、FIFO無しだと水平同期中にCMOSカメラからの画像データを 引き抜けないのでFIFOが必要。FIFOがあれば読み出しクロックでデータの引き抜きを遅延させることができる。
試作しているけど、めちゃくちゃ描画が遅い。しかも、、FIFOのR/Wタイミングがおかしいのか、水平同期が狂ったような画像になっている。。うーーむ。。

OV7670の仕様書
http://e-structshop.com/structwp/wp-content/uploads/2014/12/OV7670_DataSheet.pdf

I2Cの仕様書
https://www.nxp.com/docs/ja/user-guide/UM10204.pdf

かなり近い実装(これは多分microPythonではなくArduionoだろう)
http://bitluni.net/ov7670-with-fifo/

http://embeddedprogrammer.blogspot.com/2012/07/hacking-ov7670-camera-module-sccb-cheat.html

https://os.mbed.com/users/diasea/notebook/ov7670_FIFO_AL422B/

https://forum.arduino.cc/index.php/topic,159557.0.html
https://www.play-zone.ch/en/fileuploader/download/download/?d=1&file=custom%2Fupload%2FFile-1402681702.pdf
https://github.com/dalmirdasilva/ArduinoCamera/blob/master/CameraAL422B/datasheet/OV7670%20Implementation%20Guide%20%28V1.0%29.pdf

■追記
水平同期がおかしいのは、COMSカメラでキャプチャしたWidth,Heightが当初の想定とちがっていたから。OV7670は設定できるレジスタ数とパラメータが山盛りで、どれが最適値なのか全然わからない。ちょっと間違えると絵がおかしくなる。これまでレジスタの設定値が不適切ため、シュールなモアレ模様が撮れていた。これは、結線とか、エンコードミスではなく、単に設定パラメータが間違っていたためであった。


大元の記事:
CQ出版社 「トランジスタ技術」 2012年 3月号

https://synapse.kyoto/glossary/glossary.php?word=74HC165

2019/05/18

ESP32-DevKitにmicropythonをインストール、esptoolで焼いてみる

普段はGUIのフラッシュライタ(flash_download_tool)でファームを更新していたが、、pythonで書かれたesptoolでESP32-DevKitのファーム更新をしてみる。 esptoolは以下のGITにあるが、、 https://github.com/espressif/esptool pipでも入るそうである。自分の環境はCygwinでpythonをあれこれ入れてかなり環境がおかしくなっていので、フルパスでpipを起動しないとエラーになる。
 /usr/bin/pip2.7 install --upgrade pip
 /usr/bin/pip2.7 install esptool
コマンドは以下(micropythonサイトより)
esptool.py --chip esp32 --port /dev/ttyUSB0 erase_flash
esptool.py --chip esp32 --port /dev/ttyUSB0 --baud 460800 write_flash -z 0x1000 esp32-20190125-v1.10.bin
cygwinの場合、人にもるかもしませんが、自分のcygwinでは、/dev/ttyS10のようである。
$ esptool.py --chip esp32 --port /dev/ttyS10 erase_flash
esptool.py v2.6
Serial port /dev/ttyS10
Connecting....
Chip is ESP32D0WDQ5 (revision 1)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
MAC: 30:ae:a4:ca:da:18
Uploading stub...
Running stub...
Stub running...
Erasing flash (this may take a while)...
Chip erase completed successfully in 9.3s
Hard resetting via RTS pin...
次にファームを焼いてみる。 http://micropython.org/download#esp32 esp32-ppp-fix.bin (latest) が最新らしいので、、素直にこれを選択。
$ esptool.py --chip esp32 --port /dev/ttyS10  write_flash -z 0x1000  esp32-ppp-fix.bin
esptool.py v2.6
Serial port /dev/ttyS10
Connecting........_
Chip is ESP32D0WDQ5 (revision 1)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
MAC: 30:ae:a4:ca:da:18
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Auto-detected Flash size: 4MB
Compressed 1147552 bytes to 717585...
Wrote 1147552 bytes (717585 compressed) at 0x00001000 in 63.7 seconds (effective 144.2 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...
手動でフラッシュを焼いてた時は、ENとBOOTピンをGNDに落として電源OFF/ONしてCPUのモードを切り替えて、、とやっていたけど、DevKitのボードでは手動リセットが不要のようである。これは、DTS/CTS等でEN/BOOTを操作してくれているから?? 回路図みないとどういうからくりなのかちょっと分からず。 uPythonから再起動させてみた。バージョンは、 v1.10-331-ge38c68310-dirty 。。dirtyって何?
>>> machine.reset()
ets Jun  8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:4936
load:0x40078000,len:9332
load:0x40080400,len:6216
entry 0x400806e8
I (432) cpu_start: Pro cpu up.
I (432) cpu_start: Application information:
I (432) cpu_start: Compile time:     23:54:40
I (434) cpu_start: Compile date:     May  8 2019
I (440) cpu_start: ESP-IDF:          v3.3-beta1-268-g5c88c5996
I (446) cpu_start: Starting app cpu, entry point is 0x40082844
I (438) cpu_start: App cpu up.
I (457) heap_init: Initializing. RAM available for dynamic allocation:
I (464) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (470) heap_init: At 3FFB9B88 len 00026478 (153 KiB): DRAM
I (476) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (482) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (489) heap_init: At 40093398 len 0000CC68 (51 KiB): IRAM
I (495) cpu_start: Pro cpu start user code
I (66) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.
MicroPython v1.10-331-ge38c68310-dirty on 2019-05-09; ESP32 module with ESP32
Type "help()" for more information.
慣れたらCUIでファーム焼く方が楽。バッチ化もできるし。

ESP32 初期状態でのブートメッセージ

購入したばかりのESP32-DevKitC-32Dで電源ONした際のブートメッセージを記録。今後microPythonを焼てしまうのでもう同じメッセージは出ないと思われ。


ets Jun  8 2016 00:22:57

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0x00
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3ffc0000,len:0
load:0x3ffc0000,len:2304
load:0x40078000,len:3788
ho 0 tail 12 room 4
load:0x40098000,len:532
entry 0x4009813c


**************************************
*       hello espressif ESP32!       *
*        2nd boot is running!        *
*            version (V0.1)          *
**************************************
compile time 18:16:58

  SPI Speed      : 40MHz
  SPI Mode       : DIO
  SPI Flash Size : 4MB
Partition Table:
## Label            Usage          Type ST Offset   Length
 0 factory          factory app      00 00 00010000 00100000
 1 rfdata           RF data          01 01 00110000 00040000
 2 wifidata         WiFi data        01 02 00150000 00040000
End of partition table
Loading app partition at offset 00010000
section 0: paddr=0x00000020 vaddr=0x00000000 size=0x0ffe8 ( 65512)
section 1: paddr=0x00010010 vaddr=0x3f400010 size=0x05b64 ( 23396) map
section 2: paddr=0x00015b7c vaddr=0x3ffba720 size=0x01378 (  4984) load
section 3: paddr=0x00016efc vaddr=0x40080000 size=0x00400 (  1024) load
section 4: paddr=0x00017304 vaddr=0x40080400 size=0x126ac ( 75436) load
section 5: paddr=0x000299b8 vaddr=0x00000000 size=0x06658 ( 26200)
section 6: paddr=0x00030018 vaddr=0x400d0018 size=0x325b4 (206260) map
start: 0x400807ac

Initializing heap allocator:
Region 19: 3FFBBA98 len 00024568 tag 0
Region 25: 3FFE8000 len 00018000 tag 1
Pro cpu up.
Pro cpu start user code
nvs_flash_init
frc2_timer_task_hdl:3ffbc564, prio:22, stack:2048
tcpip_task_hdlxxx : 3ffbeca8, prio:20,stack:2048
phy_version: 80, Aug 26 2016, 13:04:06, 0
pp_task_hdl : 3ffc34f0, prio:23, stack:8192

:>enter uart init
uart init wait fifo succeed
exit uart init

IDF version : master(db93bceb)

WIFI LIB version : master(934d079b)

ssc version : master(r283 4d376412)

!!!ready!!!
mode : softAP(32:ae:a4:ca:da:18)
dhcp server start:(ip: 192.168.4.1, mask: 255.255.255.0, gw: 192.168.4.1)

+WIFI:AP_START

2019/05/12

土曜日の楽しみ、、NHKのドラマ「腐女子、うっかりゲイに告(コク)る」

普段はドラマ見ないのですが、BL好きな女子が男子に告白したけど、相手が芸だったというドラマ。これは面白すぎて(というと不謹慎でしょうか)、映像の作りが非常に細やかで、心を追いかけており、見ずにはおれない。
NHKとしてはラブシーンとかかなり踏み込んで映像化している印象。二人はまだ高校生だけど、お互いがどこまで分かり合えるのか。。これからの話の展開が非常に気になります。ちなにみに、、無料コミックはPixiv等で読めるようです。

ご参考URL
腐女子、うっかりゲイに告(コク)る。 (NHKサイト)
https://www.nhk.or.jp/drama/yoru/fujoshi/

彼女が好きなものはホモであって僕ではない(Pixiv)
https://comic.pixiv.net/works/5500

彼女が好きなものはホモであって僕ではない(Amazon)

2019/04/27

1.8inch SPI TFT液晶をESP32に接続する

Amazonで購入した、1.8Inch SPI接続のTFT液晶をESP32につないで表示させたい。
商品名は、KMR-1.8 SPI ?  乗ってるチップはST7735Rらしい。

Amazonでの商品名:

HiLetgo 1.8インチ ドライバ IC ST7735R SPIインタフェース 解像度128*160 TFT液晶ディスプレイモジュール 


基板にはSPI用の接続端子が出ているのだが、、A0をどう使うのかちと分からず。
さらに調べると、SPIの仕様としてはMOSI/MISO/CLK/CSの4本であるが、A0はData/Commandの識別信号のようであった。7735Rの仕様書によると、A0を使わない接続の場合は、SPIで送信するデータの先頭ビットをData/Commandの識別ビットとして使うようである(ST7735Rの仕様書,P34あたり)。さらに、HiLetgoの液晶基板の接続端子はMOSI/CLK/Reset/CS/A0(DC)であり、MISOが無いので、ST7735Rからの出力は受け取れない。ということは、、ST7735Rのレジスタが読めないのでデバッグができない。なんという仕様だろうか。。自分でドライバを書くのはやめて(そもそも自作だと品質も怪しいが)、先人の作ってくれたのをそのまま使うことにする。

https://www.rockbox.org/wiki/pub/Main/SonyNWZE370/ILI9163.pdf
https://cdn-shop.adafruit.com/datasheets/ST7735R_V0.2.pdf
https://s3-ap-northeast-1.amazonaws.com/sain-amzn/20/20-011-920/TFT18.rar

https://buildmedia.readthedocs.org/media/pdf/adafruit-circuitpython-rgb-display/latest/adafruit-circuitpython-rgb-display.pdf
AdafruitRGB DisplayLibraryDocumentation

https://github.com/adafruit/Adafruit_CircuitPython_ST7735

まずは、、Adafruitが提供してくれている、ST7735用ドライバを使ってEPS32上のMicroPythonで動作できるかを試してみる。

Adafruitが提供してくれているST7735用ドライバを使って、ESP32+TFT液晶の表示が行えた。使ったクラスは、ST7735Rではなく、ST7735の方。ただ、、白い線が入っていてどうも初期不良のようである。他のドライバでも試してみるつもりだが。

白線の件は一旦おいといて、、
シリアルカメラ(4D Systemの uCAM-IIIを買いなおした)で取得したRAWイメージを表示させるとどうも色合いがおかしい。シリアルカメラはRGB565という形式で、R:5+G:6+B:5の並びで16ビット表現になっているのだが、調べてみると、買った液晶は、B:5+G:6+R:5と、RとBが逆転して表示されている。
 lcd.fill(0xF800)ー>R:11111なので、赤色に塗りつぶされるべきだが液晶は青になる
 lcd.fill(0x001F)ー>B:11111なので、青色に塗りつぶされるべきだが液晶は赤になる
これは液晶のせいというより、ドライバの設定がそうなっているためと思われる。先人の記事でも色が入れ替わっているという指摘を目にすることがあり。。ドライバに手パッチを当てるとなんとかなりそうだが。

https://cycle.eek.jp/mbed/aitendo-18TFT  サイクルきゃあ様より引用
ST7735のレジスタにMADCTL(36h)という(Mode Controlの略だろう)のがあり、そこのbit3にRGBビットがあることを発見。RGBにするか、BGRにするかの選択し、ここがBGRのほうに設定されているので、そこをな直したら、全部正常になった。Color指定でBlueと書いてるのにRedになったり、それもなくなった。
 上記を参考に手パッチを当てたらなんとかなるかも。

ST7735R_V0.2.pdf の仕様書中、
P113 に以下の章があり、D3がRGB/BGRの切り替えフラグのようである。
10.1.27 MADCTL (36h): Memory Data Access Control

Adafruit_CircuitPython_ST7735 のソースを再確認すると、以下の記述があり、bottom to top refreshしたければ、D4を変えるべきで、(0x10)、0x08を指定するとRGB反転させている。。。ドライバが間違ってると思われる。。(このソースはもうメンテされていないし)
file:st7735.py  75行目:
        (_MADCTL, b'\x08'), # bottom to top refresh  ー>0x10 とすべきでは

st7735.pyのMADCTLを0x10に修正すると液晶のRGB表示も正しくなった。。はぁーー
サイクルきゃあ様に感謝。。 下の写真が白線が入った液晶。買ってからしばらく使ってなかったのだが。。やっとつないでみたら白線が入っていて、画面クリアさせても消えない。電源Off/Onしても同じ所に出てくる。さらに、、本数が増えた。

2019/03/30

sdcard.pyで正しく読めないSDカードを調査

ESP32でSDカードを読ませたいのだが、一部のSDカードを除き、普通にWindowsでフォーマットしたSDは正しく読めない。sdcard.pyではブロック単位でリードが可能なので(RAWデバイスとしてブロック単位で直書きができる)、SDの先頭ブロックを読んでみた。以下は正しく読めるSDの先頭ブロック(512バイト分)(マウントできるSDカード、micropython のファイルシステムで、FATファイルシステムとして認識できるSD)



fa b8 00 10 8e d0 bc 00 b0 b8 00 00 8e d8 8e c0 . . . . . . . . . . . . . . . .
fb be 00 7c bf 00 06 b9 00 02 f3 a4 ea 21 06 00 . . . | . . . . . . . . . ! . .
00 be be 07 38 04 75 0b 83 c6 10 81 fe fe 07 75 . . . . 8 . u . . . . . . . . u
f3 eb 16 b4 02 b0 01 bb 00 7c b2 80 8a 74 01 8b . . . . . . . . . | . . . t . .
4c 02 cd 13 ea 00 7c 00 00 eb fe 00 00 00 00 00 L . . . . . | . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 48 f7 0b 00 00 00 80 01 . . . . . . . . H . . . . . . .
01 00 0e f7 3e 09 3e 00 00 00 62 58 02 00 00 00 . . . . > . > . . . b X . . . .
01 0a 83 a6 cc fc a0 58 02 00 60 1f ed 00 00 00 . . . . . . . X . . ` . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa . . . . . . . . . . . . . . U .
以下は正しく読めない場合の先頭ブロック(マウント時にエラーになるSDカード、micropython のファイルシステムで、FATファイルシステムとして認識できないSD))

fa 33 c0 8e d0 bc 00 7c 8b f4 50 07 50 1f fb fc . 3 . . . . . | . . P . P . . .
bf 00 06 b9 00 01 f2 a5 ea 1d 06 00 00 be be 07 . . . . . . . . . . . . . . . .
b3 04 80 3c 80 74 0e 80 3c 00 75 1c 83 c6 10 fe . . . < . t . . < . u . . . . .
cb 75 ef cd 18 8b 14 8b 4c 02 8b ee 83 c6 10 fe . u . . . . . . L . . . . . . .
cb 74 1a 80 3c 00 74 f4 be 8b 06 ac 3c 00 74 0b . t . . < . t . . . . . < . t .
56 bb 07 00 b4 0e cd 10 5e eb f0 eb fe bf 05 00 V . . . . . . . ^ . . . . . . .
bb 00 7c b8 01 02 57 cd 13 5f 73 0c 33 c0 cd 13 . . | . . . W . . _ s . 3 . . .
4f 75 ed be a3 06 eb d3 be c2 06 bf fe 7d 81 3d O u . . . . . . . . . . . } . =
55 aa 75 c7 8b f5 ea 00 7c 00 00 49 6e 76 61 6c U . u . . . . . | . . I n v a l
69 64 20 70 61 72 74 69 74 69 6f 6e 20 74 61 62 i d   p a r t i t i o n   t a b
6c 65 00 45 72 72 6f 72 20 6c 6f 61 64 69 6e 67 l e . E r r o r   l o a d i n g
20 6f 70 65 72 61 74 69 6e 67 20 73 79 73 74 65   o p e r a t i n g   s y s t e
6d 00 4d 69 73 73 69 6e 67 20 6f 70 65 72 61 74 m . M i s s i n g   o p e r a t
69 6e 67 20 73 79 73 74 65 6d 00 00 00 00 00 00 i n g   s y s t e m . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 . . . . . . . . . . . . . . . .
04 00 06 05 e5 cb 81 00 00 00 7f df 1d 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa . . . . . . . . . . . . . . U .

sdcard.pyで、sd.readblocks(sector,buffer)の関数は正常に動作するので、SDのメディア自体は正しく認識されている。FATファイルシステムが解釈できない問題。どう違うのか、FATの仕様書と読み比べると原因が分かりそうだけど、、そこまで時間が取れない。 SD カードフォーマッターという、SDコンソーシアム?の公式フォーマットツールを使ってフォーマットしたところ、MBR領域は綺麗になったが、やはりマウント時にエラーになった。なぜだろうか。。

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 df dd 21 e5 00 00 00 02 . . . . . . . . . . ! . . . . .
04 00 06 1f ff ca 81 00 00 00 1f de 1d 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa . . . . . . . . . . . . . . U .

調べ切れていないが、これはフォーマットの違いではなく、SDカードの仕様に対応しきれていないのが原因ではないかと考えている。SDカードに対してReadBlocks/WriteBlocks要求を出す時、読み書きする対象の領域を指定するのに2つの方式があり、バイトアドレス指定か、ブロックアドレス指定か?に分かれている。
本来は、OCR中のCCS[30]を見てどっちかを決めないといけないそうなのだが(ElmChan氏解説記事より)、どうもこの部分が正しく実装されていないのでは?と思える(今はまだ推測)。sdcard.pyではブロックアドレス方式のSDカードしか扱えないのではないか。。 
以下は仮説含みでの自分なりの解釈

  • mountでエラーになってアクセスできないSDは1G程度の比較的容量の少ないやつ
  • エラー発生は、SDカードに対するwriteblocksコマンド実行時で、エラー内容はアドレス指定に対するアライメントエラー。1ブロックが512Bなので、512の倍数でアドレスを指定しないといけないのだが指定時はそうなっていない(これは確認済み)
  • エラーを起こしているSDはバイトアドレス指定方式のタイプと思われる
  •  sdcard.pyではブロックアドレス指定のみで実装されており、バイトアドレス指定方式の場合、上記の アライメントエラーが発生する。 
  • 一方、エラーが発生しないSDは4Gタイプでこれらはブロックアドレス方式のタイプと思われる(OCRの値を確認できていないので推測、だけど指定アドレスが小さい値なのでブロックアドレスを指定していると思われる)。だから、正常に読める。
  最初はSDカードのフォーマットの違い(MBRの配置あたり)かと思っていたけど、多分SD容量に起因する、アドレス指定方式の違いによってマウントできるSD,できないSDに分かれたと推測。 
参考にしたElmChan氏のSDカード解説
 http://elm-chan.org/docs/mmc/mmc.html
KingstonのSDアクセス手引き
https://docsplayer.net/41452623-Kingston-technology.html

2019/03/29

ESP32(トラ技スペシャル IoT Express)でSDを動かす

自分が使っているESPボードは、トラ技スペシャルの付録の、IoT Expressボードで、SDカードが付いているので、これを動かしてみる。sdカード用ドライバが必要なようで、これをuPyCraftを使ってESPのフラッシュに送り込む。

https://github.com/micropython/micropython/blob/master/drivers/sdcard/sdcard.py

https://github.com/pycom/pycom-micropython-sigfox/blob/master/drivers/sdcard/sdcard.py

トラ技スペシャルより、SPIは1系統で、CSはGPIO5なので以下を指定
import machine, sdcard, os
sd = sdcard.SDCard(machine.SPI(1), machine.Pin(5))
しっかり怒られた。
>>> sd = sdcard.SDCard(machine.SPI(1), machine.Pin(5))
Traceback (most recent call last):
  File "", line 1, in 
  File "sdcard.py", line 54, in __init__
  File "sdcard.py", line 82, in init_card
OSError: no SD card
本ではもう少しオプションが付いていて、その通りに打ち込んだ。
spi = machine.SPI(1,baudrate=32000000,polarity=1,phase=0,sck=machine.Pin(18),mosi=machine.Pin(23),miso=machine.Pin(19))
すると、下記のように、動いているように思える。
>>> sdcard.SDCard(spi,machine.Pin(5))
 [0;32mI (1471856) gpio: GPIO[23]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0  [0m
 [0;32mI (1471856) gpio: GPIO[19]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0  [0m
 [0;32mI (1471866) gpio: GPIO[18]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0  [0m
 [0;32mI (1472166) gpio: GPIO[23]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0  [0m
 [0;32mI (1472166) gpio: GPIO[19]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0  [0m
 [0;32mI (1472176) gpio: GPIO[18]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0  [0m

>>> 

osライブラリのコマンドを使ってマウントが必要 https://dfram.hatenablog.jp/entry/2017/11/27/215940
>>> os.listdir()
['boot.py', 'blink.py', 'sdcard.py', 'sd']
>>> os.listdir('/sd')
[]
>>> 

>>> os.mount(sd,'/sd')
Traceback (most recent call last):
  File "", line 1, in 
OSError: [Errno 19] ENODEV


フォーラム等を見てみる。。
https://forum.pycom.io/category/21/micropython
https://forum.micropython.org/


https://github.com/micropython/micropython/issues/3816#issuecomment-392512522


上記コメントによると、0セクタを読んだ時にバッファの最後は0x55aa でないといけないとある。
ためしてみると。。以下の通り、SDのセクタ読み込みのレベルでは正しく動作しているようである。
buffer=bytearray(512)
sd.readblocks(0,buffer)
>>> "{:x}".format(buffer[510])
'55'
>>> "{:x}".format(buffer[511])
'aa'

試しに、BeagleBoneの起動SDならマウントできた(一体どのようなフォーマットだったのか)。よって、読めるかどうかは、マウントさせようとしているSDのファイルフォーマットによると思われる。

ラズパイ用の起動SDだとエラーになった。
>>> uos.mount(sd,'/sd')
Traceback (most recent call last):
  File "", line 1, in 
OSError: [Errno 1] EPERM
memo

https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo

読める、読めないの違いは、SDカードのMBR(Master Boot Record)の扱いの差と思っているのですが、
そもそもたまたま読めるBeagleBone用のSDがどういう素性なのかわかっておらず。

https://jp.easeus.com/partition-manager/how-to-format-sd-card.html
https://qiita.com/mt08/items/c684d72345b591f4a27f

2019/03/24

SwitchScienceの BME280を扱う


ESP32で温湿度を計測したいので、BME280を接続して計測する

https://github.com/BoschSensortec/BME280_driver


MicroPython用にBME280用ドライバが公開されているのでそれを使わせてもらう。

https://github.com/catdog2/mpy_bme280_esp8266

以下のコードで動くようである(上記GitHUBの説明より引用)。すばらしい。
import machine
import bme280

i2c = machine.I2C(scl=machine.Pin(5), sda=machine.Pin(4))
bme = bme280.BME280(i2c=i2c)

print(bme.values)

手元のESP32はCQのトランジスタ技術スペシャルの付録基板で、空いてる適当なGPIOとしては、14,15があるのでこれをI2Cに使うことにする。よって、以下のピン指定で動くはず。

import machine
import bme280

i2c = machine.I2C(scl=machine.Pin(14), sda=machine.Pin(15))
bme = bme280.BME280(i2c=i2c)

print(bme.values)

参考:
NodeMCU(Lua)によるBME280のライブラリ例
https://nodemcu.readthedocs.io/en/dev/modules/bme280/#example

http://trac.switch-science.com/wiki/BME280
http://pages.switch-science.com/letsiot/airquality/

2019/03/23

ESP32でGrove Serial Camera(OV528)を使う


ESP32でGrove Serial Cameraを使う



Grove - Serial Camera Kit

http://wiki.seeedstudio.com/Grove-Serial_Camera_Kit/

使っているコントローラ:OV528の仕様書

GroveSerialCameraとはUARTで接続する。ただし、ESP32にシルク印刷されているRxD,TxDは、開発用に使っているので、その他のピンで使えるUARTを探す

MicroPython リファレンスより

Available Pins are from the following ranges (inclusive): 0-19, 21-23, 25-27, 32-39. 

  • Pins 1 and 3 are REPL UART TX and RX respectively
  • Pins 6, 7, 8, 11, 16, and 17 are used for connecting the embedded flash, and are not recommended for other uses
  • Pins 34-39 are input only, and also do not have internal pull-up resistors
  • The pull value of some pins can be set to Pin.PULL_HOLD to reduce power consumption during deepsleep.

Pin1,Pin3とは、GPIO1,GPIO3の事の様である(下記のRxD,TxDと一致)
UARTは3系統あるはずで、開発用のUART0以外がどうなっているのかを確認。
結果、U2TxD:GPIO17,U2RxD:GPIO16を使うことにする。

esp32-wroom-32_datasheet_en.pdf  より


No.NameTypeFunction
1GNDPGround
23V3PPower supply
3ENIModule-enable signal. Active high.
4SENSOR_VPIGPIO36, ADC1_CH0, RTC_GPIO0
5SENSOR_VNIGPIO39, ADC1_CH3, RTC_GPIO3
6IO34IGPIO34, ADC1_CH6, RTC_GPIO4
7IO35IGPIO35, ADC1_CH7, RTC_GPIO5
8IO32I/OGPIO32, XTAL_32K_P (32.768 kHz crystal oscillator input),ADC1_CH4,TOUCH9, RTC_GPIO9
9IO33I/OGPIO33, XTAL_32K_N (32.768 kHz crystal oscillator output),ADC1_CH5,TOUCH8,RTC_GPIO8 Espressif Systems 3 ESP32-WROOM-32 Datasheet V2.8
10IO25I/OGPIO25, DAC_1, ADC2_CH8, RTC_GPIO6, EMAC_RXD0
11IO26I/OGPIO26, DAC_2, ADC2_CH9, RTC_GPIO7, EMAC_RXD1
12IO27I/OGPIO27, ADC2_CH7, TOUCH7, RTC_GPIO17, EMAC_RX_DV
13IO14I/OGPIO14, ADC2_CH6, TOUCH6, RTC_GPIO16, MTMS, HSPICLK, HS2_CLK,SD_CLK, EMAC_TXD2
14IO12I/OGPIO12, ADC2_CH5, TOUCH5, RTC_GPIO15, MTDI, HSPIQ, HS2_DATA2,SD_DATA2, EMAC_TXD3
15GNDPGround
16IO13I/OGPIO13, ADC2_CH4, TOUCH4, RTC_GPIO14, MTCK, HSPID, HS2_DATA3,SD_DATA3, EMAC_RX_ER
17SHD/SD2*I/OGPIO9, SD_DATA2, SPIHD, HS1_DATA2, U1RXD
18SWP/SD3*I/OGPIO10, SD_DATA3, SPIWP, HS1_DATA3, U1TXD
19SCS/CMD*I/OGPIO11, SD_CMD, SPICS0, HS1_CMD, U1RTS
20SCK/CLK*I/OGPIO6, SD_CLK, SPICLK, HS1_CLK, U1CTS
21SDO/SD0*I/OGPIO7, SD_DATA0, SPIQ, HS1_DATA0, U2RTS
22SDI/SD1*I/OGPIO8, SD_DATA1, SPID, HS1_DATA1, U2CTS
23IO15I/OGPIO15, ADC2_CH3, TOUCH3, MTDO, HSPICS0, RTC_GPIO13, HS2_CMD,SD_CMD, EMAC_RXD3
24IO2I/OGPIO2, ADC2_CH2, TOUCH2, RTC_GPIO12, HSPIWP, HS2_DATA0,SD_DATA0
25IO0I/OGPIO0, ADC2_CH1, TOUCH1, RTC_GPIO11, CLK_OUT1, EMAC_TX_CLK
26IO4I/OGPIO4, ADC2_CH0, TOUCH0, RTC_GPIO10, HSPIHD, HS2_DATA1,SD_DATA1, EMAC_TX_ER
27IO16I/OGPIO16, HS1_DATA4, U2RXD, EMAC_CLK_OUT
28IO17I/OGPIO17, HS1_DATA5, U2TXD, EMAC_CLK_OUT_180
29IO5I/OGPIO5, VSPICS0, HS1_DATA6, EMAC_RX_CLK
30IO18I/OGPIO18, VSPICLK, HS1_DATA7
31IO19I/OGPIO19, VSPIQ, U0CTS, EMAC_TXD0
32NC--
33IO21I/OGPIO21, VSPIHD, EMAC_TX_EN
34RXD0I/OGPIO3, U0RXD, CLK_OUT2
35TXD0I/OGPIO1, U0TXD, CLK_OUT3, EMAC_RXD2
36IO22I/OGPIO22, VSPIWP, U0RTS, EMAC_TXD1
37IO23I/OGPIO23, VSPID, HS1_STROBE
38GNDPGround



memo heap in MicroPython
https://docs.micropython.org/en/latest/reference/constrained.html#the-heap


OV528の仕様書より、立ち上げ時はまずコネクション確立を行うようにと書かれていて、速度は9600bpsであった。それに従い、まずは、SYNCコマンドを送る関数を作る。

OV528(Seeed Studio Grove Serial Cameraのコントローラ)に対してシリアルで接続してコネクションを確立するまでの手順 (言語はMycroPython)
--------------------------------------------------
#

from machine import UART
from time import sleep

uart1 = UART(1, 9600)
uart1.init(9600, bits=8, parity=None, stop=1,tx=17,rx=16) 

INIT = bytes([0xAA,0x0D,0x00,0x00,0x00,0x00])

def make_connection():
   for x in range(60):
      uart1.write(INIT)
      sleep(1)
      if(uart1.any() > 0):
          packet=uart1.read(uart1.any())
          show_packet(packet)
          return True
      #print(uart1.any())
      #print(uart1.read(1))
   return False


def show_packet(packet):
  for i in range(6):
     print("[{:02x}]".format(packet[i]),end="")
  print("")
--------------------------------------------------
シリアルコンソールでの表示
>>> make_connection()
[aa][0e][0d][00][00][00]
True
多少てこずったのでオシロで確認
同期が確立した時の波形
上がカメラへの送信、下がカメラからの返却
速度は9600bps
安定動作のためには、SYNCパケット送信の際、一発目を送ってから、少し時間を空けて2発目を送ると、かなり確実にACKが返る。上記実装例では1秒のSLEEPを入れている。連続してバリバリに送ると、いつまでたってもACKが返らない。


追記
Grove Serial Cameraの製品説明ページで確認すると、電源5Vで、信号は232Cと書かれている。5Vのシリアルではなく、本気の232Cなのだろう。。多分。今回は、カメラの電源は5Vを供給しているが、カメラのシリアルはESP32のバス直結なので、3.3Vで繋いでいる。現状動いているがこれは規格外と思われる。Grove Serial Cameraの基板側の回路図がないので、基板内のレベル変換がどうなっているのか分からず。

2019/03/16

MicroPythonで使えるモジュール一式

MicroPythonで使えるモジュール一式

ざっと見てみると、、http,urllib等は無いけど、websocket,mqttなんてのがある。。

>>> help('modules')
__main__          framebuf          socket            upip
_boot             gc                ssl               upip_utarfile
_onewire          hashlib           struct            upysh
_thread           heapq             sys               urandom
_webrepl          inisetup          time              ure
apa106            io                ubinascii         urequests
array             json              ucollections      uselect
binascii          machine           ucryptolib        usocket
btree             math              uctypes           ussl
builtins          micropython       uerrno            ustruct
cmath             neopixel          uhashlib          utime
collections       network           uhashlib          utimeq
dht               ntptime           uheapq            uwebsocket
ds18x20           onewire           uio               uzlib
errno             os                ujson             webrepl
esp               random            umqtt/robust      webrepl_setup
esp32             re                umqtt/simple      websocket_helper
flashbdev         select            uos               zlib
Plus any modules on the filesystem
>>>

ESP-32でWebREPLを使う


MicroPythonを使ってESPのプログラミングを行う場合、PCとESPをシリアルで接続するのが大半と思いますが、WebREPLを走らせることでPC上のブラウザからWeb経由でESPに接続してプログラミングすることも可能です。

ESP8266のMycroPythonの記述では、(0)のwebrepl_setupを行うだけでWebREPLが使えるらしいのですが、ESP32の場合、素でブートさせるとWiFiのAccessPointモードはDisableなので接続できないようです(調べきっていないので推測)。

手元のESP32はWiFiはStationモードで動作させているので、下記手順でWebREPLの動作を確認しました。
(0)最初に使うときは、improt webrepl_setup  を実行してEnableにする
(1)WiFiをStationモード(STA_IF)で立ち上げ、WiFiルータと接続してIPを取得
(2)WebREPLを起動して ESP-32側でWebREPL待ち受けに設定
--------------------------------------
# wifi でネットワーク接続
import network
AP_NAME = "AP名を設定"
AP_PASS = "接続パスワードを設定"
sta_if = network.WLAN(network.STA_IF)
sta_if.active(True)
sta_if.scan()                             # Scan for available access points
sta_if.connect(AP_NAME, AP_PASS)
sta_if.isconnected()                      # Check for successful connection

# WebREPLを起動

import webrepl
webrepl.start()
--------------------------------------

ESPが待ち受けになっている状態で、PC側(ブラウザが動いているPC)で、webrepl.htmlをブラウザに読み込ませると、JS経由でWebSocketが動いてESPと接続されます。


ESP8266用のMicroPythonの解説では起動時、WiFiはAPモードで立ち上がり、WebREPL Enableなら何も設定せずともWebREPLとしてデバッグできるようですが、手元のESP32の場合、起動時にAPモードDisableになっている。だから、、もし起動時にWebREPLの待ち受けをさせたい場合は、ESP32の起動時にWebREPLが走るように仕組んで置く必要あり。そうすればシリアルなしでもWebブラウザからプログラミングができるはず。ただ、、WebREPLの動作はシリアル接続の場合と比べてかなり遅いです。ですので、試してみたけど、WebREPLは使わない予定。

PC側のブラウザ内で動作させるスクリプト(WebREPL Client)は以下に接続することでロードされる。
http://micropython.org/webrepl/

PCのローカルにファイル一式をダウンロードして、ブラウザで起動してWebREPL Clientを動かすのも可能
https://github.com/micropython/webrepl

2019/03/09

MicroPythonでサーボ制御をやってみる

MicroPythonの仕様をざっと読んでみたので、以前からやってみたかったサーボ制御をやってみる。入力は1Kのボリュームで、それをAD変換して、得られたレベルに従って、PWM変換してデューティを変えてサーボの角度を調整する。

まずは、ボリューム値を定期的に取ってくるサンプル。
アッテネーションを11DBに設定して3.3Vでも扱えるようにする。また、取得値の幅は計算がしやすいように0-1023と設定。以下のサンプルではIO32に0V-3.3Vまでの変動する電圧がかかるのを想定している。

from machine import ADC
import time

adc = ADC(Pin(32))          # create ADC object on ADC pin
adc.atten(ADC.ATTN_11DB)    # set 11dB input attentuation (voltage range roughly 0.0v - 3.6v)
adc.width(ADC.WIDTH_10BIT)   # set 9 bit return values (returned range 0-1023)

while True:
  print(adc.read())   
  time.sleep_ms(500)

オンラインマニュアルよりコードを引用して改変
http://docs.micropython.org/en/latest/esp32/quickref.html#adc-analog-to-digital-conversion


 上記ADCのサンプルとPWMによるサーボ制御を連結させて作ったのが以下のソース
PWMの設定として、50Hz周期で、パルス幅が0.5 - 2.4の間を変動させることでサーボのアームの角度が変わる。ボリュームのレベルの比率で、0.5msec-2.4msecの間を遷移させればボリュームの回した状態に応じてアームが動くと。。
  デバッグ用にprintさせている、また、貧乏省のため、loop内では100msecWAIT(sleep)を入れている。100msecのWAITを入れるとやっぱり応答が遅くなり、微妙な制御の目的には使えない。一方、WAITを取ってしまうと、AD変換でサンプリングの誤差が出て、サーボがプルプル微振動する。だから、、人のフィードバックには忠実に、しかも、サンプリングした値をサーボに与える時点で±1~2の変動は丸めるといった変換が必要と思う。簡単なフィルタ関数かと。。


#-------------------------------------------------------------
# servo_ctrl.py

from machine import Pin, PWM
from machine import ADC
import time

LOOP_WAIT = 100             # wait 100msec

SERVO_MIN = 27
SERVO_MAX = 126
SERVO_CENTER = int((SERVO_MAX - SERVO_MIN)/2) + SERVO_MIN

servo = PWM(Pin(12), freq=50, duty=SERVO_CENTER)  # setup servo  freq=50Hz  set Center=77

vol = ADC(Pin(32))          # create ADC object on ADC pin
vol.atten(ADC.ATTN_11DB)    # set 11dB input attentuation (voltage range roughly 0.0v - 3.6v)
vol.width(ADC.WIDTH_10BIT)   # set 9 bit return values (returned range 0-1023)

while True:
  level = vol.read()
  servo_setting = int((SERVO_MAX - SERVO_MIN) * level / 1023) + SERVO_MIN
  servo.duty(servo_setting)
  print("VR:{:d} Servo:{:d}".format(level,servo_setting))
  time.sleep_ms(LOOP_WAIT)

ESP-WROOM-03にサーボとボリュームを付けて動かしているところ。デバッグにはオシロも欠かせない。













勝手にリンク。。
http://nomolk.hatenablog.com/entry/2017/04/09/222415
滅茶苦茶サーボに詳しい記事 nomolkのブログ 様

ESP32上でMicroPythonを使う

 組込み用にMicroPythonを使うので、ESP起動時に自分の書いたpythonスクリプトが走ってほしい。ファイルシステムがどうなっているのか??
os モジュールが提供されているようで、osモジュール内にlistdir関数があるのでそれを実行してみる。。すると、boot.pyなるファイルが存在する。これが多分起動時に呼ばれると思われる。

>>> import os
>>> dir(os)['__class__', '__name__', 'remove', 'VfsFat', 'chdir', 'dupterm', 'dupterm_notify', 'getcwd', 'ilistdir', 'listdir', 'mkdir', 'mount', 'rename', 'rmdir', 'stat', 'statvfs', 'umount', 'uname', 'urandom']
>>> os.listdir()
['boot.py']

boot.pyを読んでみる。catコマンドとかあるのかもしれないが、、調べるのがまどろっこしいので、、ファイルオープンしてreadしてみる。

>>> with open('boot.py') as b:
...     print(b.read())
...
...
...
# This file is executed on every boot (including wake-boot from deepsleep)
#import esp
#esp.osdebug(None)
#import webrepl
#webrepl.start()

webreplが走っている。これはREPLがwebサーバとして提供されているということと思えるが。。シリアルコンソール以外に、web版のREPLも提供しているということか? と思ったら、、落ち着いてよく考えると、#はpythonのコメントなので、boot.pyは実質何もしていないということか。

microbitの場合、microfsというツールが提供されており、microfsツールを使うことでMicroPythonが管理するファイルシステムにプログラム等を転送できるようである。

https://microbit-micropython.readthedocs.io/ja/latest/tutorials/storage.html

で、、main.pyなるファイルを置いておけば、MicroPython起動時にmain.pyが読み込まれて実行されるらしい。micropython  main.py で逆引きしたら、、以下のようにESP8266でもmain.pyを内蔵ファイルシステムに置いておけば走りますということであった。

https://docs.micropython.org/en/latest/esp8266/tutorial/filesystem.html#start-up-scripts

だから、、開発スタイルとしては、、REPLでチビチビテストしながら部品を作って、部品は内蔵ファイルシステムにmoduleとして配置する。自作モジュールが揃ってそれらを組み立ててテストしてOKなら、最後の起動関数をmain.pyに書き込めば、電源ONで希望する動きをするはず。

まずはお決まりのLチカをやってみる。上記スクリプトでIO12のポートがH->Lと変化する。LEDを接続すれば光る。

from machine import Pin

p12 = Pin(12, Pin.OUT)

p12.on()

p12.off()

以下のスクリプトはwhileループでLHLH...を繰り返す。これをオシロで測ればループの速度も分かる。(on/offさせるのがIOレジスタを直接操作しておらずメソッドなのでオーバーヘッドは大きいが)
while True:
    p12.on()
    p12.off()
オシロで計測すると、1サイクル76usecで13.6KHz。マイコンコアの速度が240MHzだったのでスクリプトでの実行という点でオーバーヘッドが大きい。。

直接IOのレジスタを叩く手法

Accessing hardware directly

http://docs.micropython.org/en/latest/reference/speed_python.html#accessing-hardware-directly

ESP WROOM-32 ROMを焼く (MicroPython)

ESP WROOM-32の内蔵ROMに書き込むには GOIO0をGNDに落としてResetをかける。ResetはENをH->L->Hにすることでリセットがかかる。この時のメッセージは以下

rst:0x1 (POWERON_RESET),boot:0x3 (DOWNLOAD_BOOT(UART0/UART1/SDIO_REI_REO_V2))
waiting for download

以前ESP8266を触っていた時はpythonの書き込みツールを使っていた。が、、VMWare内のUbuntuで開発環境を構築していてかなり忘れたので、、ここはおとなしく、Espressif社が提供してくれている書き込みツールでMicroPythonを焼いてみる。

ESP32用のMicroPythonは以下から入手可能

 MicroPython



http://micropython.org/download#esp32

書き込み上のポイントとして、(1)FLASHを消去する(2)開始番地は0x1000

MicroPythonのサイトでもesptool.pyによる書き込みが案内されているが、、Ubuntuから書き込むのは面倒なので、、Espressifの書き込みツールで書いてみることに。以下がDownload Toolの設定。焼きたいファイルを指定して、開始番地を指定(0x1000)。開始番地はデフォルトでも設定されるかもしれません。そこまで調査しておらず。[START]で書き込む前に、上記助言に従い、[ERASE]を実行しました。



ファーム書き込みのハマリ点としては、、[ERASE]した後、すぐに[START]で書き込みはできず、ESP WROOM 32を再度ダウンロードモードに遷移させてから[START]で書き込む必要あり。これをやらなかったので、[ERASE]->[START]と続けて操作したら通信タイムアウトになった。 

書き込みが終了後、ResetするとMicroPythonが起動される。起動メッセージは以下

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
ets Jun  8 2016 00:22:57

rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:5060
load:0x40078000,len:8788
ho 0 tail 12 room 4
load:0x40080400,len:6772
entry 0x40081610
I (251) cpu_start: Pro cpu up.
I (251) cpu_start: Application information:
I (251) cpu_start: Compile time:     00:48:25
I (253) cpu_start: Compile date:     Mar  9 2019
I (259) cpu_start: ESP-IDF:          v3.3-beta1-268-g5c88c5996
I (265) cpu_start: Single core mode
I (270) heap_init: Initializing. RAM available for dynamic allocation:
I (277) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (283) heap_init: At 3FFB92B0 len 00026D50 (155 KiB): DRAM
I (289) heap_init: At 3FFE0440 len 0001FBC0 (126 KiB): D/IRAM
I (295) heap_init: At 40078000 len 00008000 (32 KiB): IRAM
I (302) heap_init: At 40092834 len 0000D7CC (53 KiB): IRAM
I (308) cpu_start: Pro cpu start user code
I (27) cpu_start: Starting scheduler on PRO CPU.
OSError: [Errno 2] ENOENT
MicroPython v1.10-194-g41e7ad647 on 2019-03-09; ESP32 module with ESP32
Type "help()" for more information.
>>>
特に苦労なくmicroPythonが入り、リセットすることでmicroPythonが起動された。
Single core mode となっている。。 ESP32は以下のようにDual Coreだったはず
  Architecture: Xtensa Dual-Core 32-bit LX6
また、OSError [Error 2] ENOENT  のメッセージが気になるが。。

マニュアル類:

Quick reference for the ESP32

micropythonのGithub

ESP WROOM-32 を使ってみる

 諸般の事情により、IoT技術を自習することになった。一番使いやすいデバイス、ESP WROOM-32を使ってみることに。デバイスを理解するためになるべく周辺回路が付いていない素の状態から立ち上げたいので、SwitchScience社の「ESP-WROOM-32ピッチ変換済みモジュール」を買って、モジュールに電源とか最低限のPIN PullUp/Downを設定して走らせてみた。 WROOM-32 起動時のブートメッセージは以下

**************************************
*       hello espressif ESP32!       *
*        2nd boot is running!        *
*            version (V0.1)          *
**************************************
compile time 18:16:58

  SPI Speed      : 40MHz
  SPI Mode       : DIO
  SPI Flash Size : 4MB
Partition Table:
## Label            Usage          Type ST Offset   Length
 0 factory          factory app      00 00 00010000 00100000
 1 rfdata           RF data          01 01 00110000 00040000
 2 wifidata         WiFi data        01 02 00150000 00040000
End of partition table
Loading app partition at offset 00010000
section 0: paddr=0x00000020 vaddr=0x00000000 size=0x0ffe8 ( 65512)
section 1: paddr=0x00010010 vaddr=0x3f400010 size=0x05b64 ( 23396) map
section 2: paddr=0x00015b7c vaddr=0x3ffba720 size=0x01378 (  4984) load
section 3: paddr=0x00016efc vaddr=0x40080000 size=0x00400 (  1024) load
section 4: paddr=0x00017304 vaddr=0x40080400 size=0x126ac ( 75436) load
section 5: paddr=0x000299b8 vaddr=0x00000000 size=0x06658 ( 26200)
section 6: paddr=0x00030018 vaddr=0x400d0018 size=0x325b4 (206260) map
start: 0x400807ac

Initializing heap allocator:
Region 19: 3FFBBA98 len 00024568 tag 0
Region 25: 3FFE8000 len 00018000 tag 1
Pro cpu up.
Pro cpu start user code
nvs_flash_init
frc2_timer_task_hdl:3ffbc564, prio:22, stack:2048
tcpip_task_hdlxxx : 3ffbeca8, prio:20,stack:2048
phy_version: 80, Aug 26 2016, 13:04:06, 0
pp_task_hdl : 3ffc34f0, prio:23, stack:8192

:>enter uart init
uart init wait fifo succeed
exit uart init

IDF version : master(db93bceb)
WIFI LIB version : master(934d079b)
ssc version : master(r283 4d376412)

!!!ready!!!
mode : softAP(26:0a:c4:07:55:e4)
dhcp server start:(ip: 192.168.4.1, mask: 255.255.255.0, gw: 192.168.4.1)
+WIFI:AP_START


 PIN設定上の注意点:3番ピンのEN(Enable)について、、最初チップ内部でプルアップされていると思って、プルアップにせず放置していたらまともに起動しなかった。ENは10K等の抵抗を介して3.3Vに引き上げるべし。。当たり前か。。

内蔵ROMの工場出荷状態では、softAP(AccessPoint)として動作するようで、ATコマンド等で制御可能(のはず)。 RxD,TxDでシリアル接続していて、115200baudで通信中

適当にATコマンドを叩いても:>what?と聞き返されコマンドは受け付けられず。。? を打ち込むと以下のメッセージが。

Please refer to document ssc_commands.xlsx for detail

他人の記事を見て、、例えば以下の様にコマンドを打ち込んで使うらしい。

:>ap -S -s esp3    .....  自分の入力
+SAP:OK                 .....   ESPからの応答(上記入力には正しく応答)

microPythonで制御したいので、初期ファームの確認はこれぐらいで終わりにする。

2019/02/09

定年までサポートアプリのアイコンを作成

 噴飯モノ(?)の定年までサポートアプリであるが、まだ開発中とはいえ、アイコンが無くてレーダーチャートみたいなアイコンで起動するのはもう嫌だ。。というわけで、勘亭流というのか、江戸文字というのか、正しくは分からないが、ぶっといフォントで定年の定だけを使ってアイコンを作ってみた。アイコンの作り方は、本によると、1536x1536 pixcelでまず作って、各サイズにリサイズするらしい。リサイズするサービスがあって、自分は、MakeAppIconというサービスサイトで変換した。変換するとメールで送られてくるので、開発中のプロジェクトの該当フォルダ(AppIcon.appiconset)にCopy&Pasteすればプロジェクトに組み込まれる。ビルドしてiPhoneに転送すると確認できる。左はXCodeでアイコンが組み込まれたところ。右は自分のiPhoneで表示させたところ。笑える。。

定年までサポートプログラムをGITに設定

 仕事ではSVNとかTracとか使ってるけど、設定してくれた人がいて、自分は利用させてもらっているだけだ。GitHubもソースを取ってくることはあるけど、自分でリポジトリをセットアップしたこともない。分からないだらけなのだが、、今作って居る、「定年までサポートプログラム」のレポジトリをGitHub作ってみた。GitHubとXCodeは同期させることができるようだけど、どうやったらいのかまだ分からない。。すくなくとも、アドバイスのテキストはGitHub上で管理して、更新したらアプリがダウンロードできるようにしたい。

定年までサポートプログラムのリポジトリ ->今は作っただけ
https://github.com/dune-geek/retire-support.git

何も設定せずXcodeでgitにコミットとかやったら、circleciのレポジトリにコミットされたようなのだが。。そうなのか!? circleciって無料?? よく分からん

XcodeではVersionControlが画面左の箱のような所で行うことが分かり、ここでGitHubの設定を行うことで、自分のリポジトリにアップすることができた。まだお試し中なので、just4learnとした。ここに今開発中のソースが上がっています。

https://github.com/dune-geek/just4learn

2019/02/03

iPhoneアプリ;定年までサポート(仮)

 曜日がSat等の英語表現になっていたのは、FormatterでLocaleをja_JPに指定していなかったためと分かった。修正したので、今は漢字の曜日になった。
 曜日を数値で取得して、switch/caseで曜日ごとにメッセージを出し分けるように実装した。7日経つとまた同じメッセージなのですぐに飽きるけど、まぁ無いよりはまし。各曜日に対応したメッセージを大量に用意しておいて該当する曜日の候補から乱数でメッセージを選択して表示するようにしたい。







■メモ
https://kiririmode.hatenablog.jp/entry/20160503/1462256139
macでemacsを使っていて、Ctrl+SPでイラっとなる件の対応策
->MarkSetになった。。感謝