異文化交流した話【arduino/c++ ⇒ raspberrypi/python】

arduinoの民が...ラズパイに...出会ったぁ～([10日ぶり2回目](https://qiita.com/kei_tnk/items/2815002705fcf4c994f0)

# はじめに
- GWの間はラズパイ5の環境構築ばかりしてたけど、さすがに飽きたので、ラズパイのパーツを動かしてみた。
- ラズパイ5より、arduino系統っぽいラズパイzero2w（以下、pi02）を購入したのでそちらで作業してみた。
- pi02は、ラズパイ5と同様に[usb接続でssh接続可能](https://qiita.com/kei_tnk/items/33b2d99b4c84c564237e#%E3%81%8A%E3%81%BE%E3%81%91%E3%81%AE%E3%81%8A%E3%81%BE%E3%81%91%E8%BF%BD%E8%A8%98zero2w%E3%81%AE%E5%A0%B4%E5%90%88%E3%81%AEusb%E6%8E%A5%E7%B6%9A)にしてある。なお、osはlegacy_64bit版を使用。古い奴の方が、困ったときの事例検索が楽そうだったので。
- ledがマトリックス配置された[HAT](https://www.waveshare.com/rgb-led-hat.htm)が1340円で売ってたので付けてみた。こいつは、[ライザーpin](https://www.adafruit.com/product/4079)なしで付けられた。これをpythonで操作する。pythonって何それ、うまいの？牛だっけ？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733720/2cc0f1e1-211d-e316-dca7-78c87f049eb3.png)


# 環境準備
- [当初設定](https://qiita.com/kei_tnk/items/33b2d99b4c84c564237e#%E3%81%8A%E3%81%BE%E3%81%91%E3%81%AE%E3%81%8A%E3%81%BE%E3%81%91%E8%BF%BD%E8%A8%98zero2w%E3%81%AE%E5%A0%B4%E5%90%88%E3%81%AEusb%E6%8E%A5%E7%B6%9A)ではネット接続を母艦経由としてしまっているから、別途、pi02から直接wifi接続可能にする必要がある。やっぱり、母艦がいないとネット接続出来ないとかは、役立たずすぎるからね。
- wifi接続可能とするため、raspi-configでwifiの使用国、ssid、パスワードを入力したら、下記のルートとなった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733720/188f3ed3-2ae2-6e94-e38d-27efb0c9099a.png)
- この状態で、母艦のwifiを切ってしまうと、usbケーブルで繋がってるのに母艦からpi02への接続が切れる。具体的に言うと、母艦のターミナル上のsshで、上矢印キーを叩いても過去のコマンド履歴が出てこなくなる。母艦のwifiをオンにすると、上矢印キーの反応が復活する。これは、pi02にipアドレスが母艦のインターネット共有によるdhcpにより決定されているところ、母艦のwifiをオフにすることにより、その関係が壊れてしまうことと理解した。
- 母艦で、コマンドifconfigにより表示される端末のうち、インターネット共有による下記ブリッジ（bridge100）は、母艦のwifiがオンの時のみ表示され、wifiがオフの時は、表示されない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733720/7e2e8a62-48bf-25ab-439a-8547eabd95a0.png)
- pi02のwifiのssidとして、テザリング中のスマホのssidを与えると、スマホ上ではこのように表示された。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733720/81f761f3-ef08-1616-5aeb-37d979653372.png)
- 母艦ではこのように表示される。今回、初めてウザいipv6を外すオプション（-f inet）[ipv4のみ表示]を覚えたよ。下記画面から、ルーターとしてのスマホが192.168.252.175とわかり、上記画面と下記画面からpi02が192.168.252.1、母艦が192.168.252.130と分かる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733720/56a00fa0-4153-2ffd-bd63-8c63c9ae2bee.png)
- 次からは、母艦の画面だけでも、スマホのアドレスは分かるし、マスク部分がスマホと同じでFlagsがUHLWIiの方がpi02と判別できるな。
- なお当初はsshでrpi02w@raspberrypi.localで反応なかったから、ipアドレスを上記画面から拾ってアクセスしたけど、一度アクセスした後、sshをexitして、再度sshに入るときは@raspberrypi.localでも入れた。
- とりえあず、pi02のwifiが使えることが確認できたから、また、母艦とusb接続で繋ぎ直して作業する。パケットがもったいないし、やっぱり、反応が少し遅く感じた。

# はじめてのぱいそん
- 正直さっぱり分からないので、ネットで調べる。最初は参考書的なものを買った方が早いのかもね。
- メーカーの動画(https://www.waveshare.com/img/devkit/accBoard/RGB-LED-HAT/RGB-LED-HAT-DISPLAY.gif) を見ると、スマホで操作してる！すごいね！
- とりあえず、arduinoの民としては、パーツメーカーの[パーツ説明](https://www.waveshare.com/wiki/RGB_LED_HAT)を読むことから始める。サンプルスケッチ的なものがあるのだろう。
- おおっと、このコマンドを順に打ち込みだけで、とりあえず動く模様。pythonの文法も何も知らないのに、動くとこまで行っちゃうのはちょっと、どうなんだろ。arduinoの民としては、ちょっと文化圏の違いに戸惑う。これが、異文化交流の醍醐味か...。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733720/cdefc44c-99c4-b2a9-ea0f-c95683aa1e51.png)
- 心を無にして打ち込んでたら、pip3のinstallコマンドに-yオプションはないよと怒られた。`no such option: -y`サーセン。でも、悪いのは、waveshareパイセンなんす。でも、何も考えず従った僕が悪かったす、サーセン。
![GIF_20240512_182126_743.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733720/9f5f67ab-455a-5a7d-2327-520afc29afc5.gif)
- ちょっと！動いたのはいいんだけど、眩しいんですけど！
  ......図書館で作業してたから、とっても迷惑なんですけど！
- 思わず手で隠しちゃった。そして急いで、片手で`sudo shutdown now`を打って、pi02の緑のランプが消えたのを確認したのに、HATは光ったまま...ま、まぁ。明かりが眩しくなくなったところで動作が止まってたから、まあ、いいんだけど。そして、ブチッとケーブルを抜いて、やっと明かりが消えた。
- 続きのプログラム動作確認は、帰ってからやろう
- とりあえず、プログラムの中身を見てみるとこんな感じ。
`rpi02w@raspberrypi:~/RGB_LED_HAT $ cat ws2812.py ` 
```py
#encoding:utf-8
# NeoPixel library strandtest example
# Author: Tony DiCola (tony@tonydicola.com)
#
# Direct port of the Arduino NeoPixel library strandtest example.  Showcases
# various animations on a strip of NeoPixels.
import time
import random
from rpi_ws281x import Adafruit_NeoPixel, Color


# LED strip configuration:
LED_COUNT      = 32      # Number of LED pixels.
LED_PIN        = 18      # GPIO pin connected to the pixels (must support PWM!).
LED_FREQ_HZ    = 800000  # LED signal frequency in hertz (usually 800khz)
LED_DMA        = 10       # DMA channel to use for generating signal (try 5)
LED_BRIGHTNESS = 10    # Set to 0 for darkest and 255 for brightest
LED_INVERT     = False   # True to invert the signal (when using NPN transistor level shift)

# Create NeoPixel object with appropriate configuration.
strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS)
# Intialize the library (must be called once before other functions).
while 1:
	strip.begin()
	#order
	for i in range(0,strip.numPixels()):
		strip.setPixelColor(i, Color(0,0,255))	
		strip.setPixelColor(i-1, Color(0,0,200))
		strip.setPixelColor(i-2, Color(0,0,150))
		strip.setPixelColor(i-3, Color(0,0,100))
		strip.setPixelColor(i-4, Color(0,0,0))
		strip.show()
		time.sleep(0.1)
	#Reverse order	
	for i in range(0,strip.numPixels()):
		strip.setPixelColor(strip.numPixels()-i, Color(0,255,0))	
		strip.show()
		time.sleep(0.05)
	#Turn around
	for i in range(0,strip.numPixels()//4):
		strip.setPixelColor(i, Color(255,0,0))
		strip.show()
		time.sleep(0.05)
	for i in range(0,strip.numPixels()//8-1):
		strip.setPixelColor(7+8*i, Color(255,0,0))	
		strip.show()
		time.sleep(0.05)
	for i in range(0,strip.numPixels()//4+1):
		strip.setPixelColor(strip.numPixels()-i, Color(255,0,0))
		strip.show()
		time.sleep(0.05)
	for i in range(0,strip.numPixels()//8-1):
		strip.setPixelColor(16-8*i, Color(255,0,0))	
		strip.show()
		time.sleep(0.05)	
	for i in range(0,strip.numPixels()//4-1):
		strip.setPixelColor(i+8, Color(255,0,0))	
		strip.show()
		time.sleep(0.05)		
	for i in range(0,strip.numPixels()//4-1):
		strip.setPixelColor(strip.numPixels()-9-i, Color(255,0,0))	
		strip.show()
		time.sleep(0.05)	
	
	#Middle to both sides, both sides to the middle
	for i in range(0,strip.numPixels()//4-1):
		for y in range(0,strip.numPixels()//8):
			strip.setPixelColor(4+y*8+i, Color(0,255,255))
			strip.setPixelColor(3+y*8-i, Color(0,255,255))
		strip.show()
		time.sleep(0.1)
	for i in range(0,strip.numPixels()//4-1):
		for y in range(0,strip.numPixels()//8):
			strip.setPixelColor(7+y*8-i, Color(255,255,0))
			strip.setPixelColor(y*8+i, Color(255,255,0))
		strip.show()
		time.sleep(0.1)
	#random color
	for x in range(0,5):
		for i in range(0,strip.numPixels()):
			strip.setPixelColor(i, Color(random.randint(0, 255),random.randint(0, 255),random.randint(0, 255)))	
			strip.show()
		time.sleep(0.5)
```
- まあ、やってることは、arduinoIDEでのc++とそんなに変わらないかな？
- でも、「while 1:」のお尻が見えないのが、すごく気持ち悪い。これって、多分、エンドレスでループしろってことでしょ？
- もしかして、インデントに厳密な意味があって、それでお尻が分かるの？そう考えないと、whileやforのお尻が明示されてない仕組みが分からんし...
- つか、そう考えると、初心者にもわかりやすいのかも...え、あれ？pythonって、分かりやすくていいかも！異文化交流万歳！
- ...そして、帰宅...
- エンドレスループは嫌いなので、ループを５回で止めることとした。そして、ループが終わったあと、色がすべて消えるように、ランダム色を５回繰り返す項目をクリア項目に変更した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733720/d75bf3d8-1003-eab2-0d5a-3652e0ff7eb0.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733720/28511742-1590-c4a7-9c14-a943429128d9.png)
- そしたら、最初は、怒られた。`TabError: inconsistent use of tabs and spaces in indentation`。なるほどね、インデントを揃えるのにタブと空白を混ぜるな、と。混ぜるな危険！危険が危ない！！！
- で、無事にrunしても、最後にメッセージが...
```
munmap_chunk(): invalid pointer
Aborted
```
for文を見直して、`for z in range(0,5):`に書き直したけど、結果は変わらず。5回終わったあとに、同じエラーが出て終わる。お手上げです。
- あと、[ここ](https://forums.raspberrypi.com/viewtopic.php?t=212060)に書いてあるように、動作中、たまにランダムにledがフラッシュのように明るく輝く。公式HPにも、下記を`/boot/config.txt`に書き加えろと書かれていたから試したけど、改善せず。だめだこりゃ！
```
hdmi_force_hotplug=1
hdmi_force_edid_audio=1
```

# 公式HPのサンプルコードの続き
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733720/4735e64b-90d1-6af2-6041-8ed774f44696.png)
- bottle.....？
- まーた、さっぱりわからない概念が飛び込んできた
- もう、お腹いっぱいなんですけど！消化不良なんですけど〜！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733720/be247ee2-2d8e-c1cd-a8ae-65d83ef80893.png)
- とりあえず、言われるまま、bottleをインストールしたけど、次は何？同じネットワークにある、スマホのブラウザでアドレスを入れればいいの？つか、それなら、母艦のブラウザでもいいよね？
- 走らせたら、こんな風に指示された。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733720/8b55df45-f532-1565-6029-ff126c124033.png)
- safariで動いたけど、色は白から動かせず...breathやflashは反応した。色指定はタッチじゃなきゃだめなの？スマホだと、うまく行った。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733720/d81c9c17-dd8a-3cb2-023a-d0811e9bde91.png)

# おわりに
- とりあえず、ラズパイ用のパーツを買ってきて、動かすことができた。
- ラズパイ自体に高機能なosが動いているので、m5stackとは違うレベルのプログラムが簡単にできたのには、「異文化だなぁ」という感想を持ったね。
- とりあえず、pythonがよくわかってないので判断はできないけど、理解を深めるためにもう少しパーツを買って遊んでみようかな。
- すぐに思いつくのは、電子ペーパーモジュールを買って、ネットから天気を拾って表示することくらいかなぁ。