* easy-CでNeoPixelを制御するためのメモ#1 -(by [[K]], 2024.02.10) ** (1) -資料1: https://garretlab.web.fc2.com/arduino.cc/docs/tutorials/uno-r4-wifi/r4-wifi-getting-started/ -資料2: https://cediablog.com/arduino-unor4wifi-review/ -資料3: https://maicommon.ciao.jp/ss/Arduino_g/serial/index.htm -資料4: https://maicommon.ciao.jp/ss/Arduino_g/intrupt/index.htm -資料5: https://maicommon.ciao.jp/ss/Arduino_g/ -資料6: https://qiita.com/hsgucci/items/eee5894e3651d0a8cb75 -資料7: https://www.zep.co.jp/nbeppu/article/z-pico-da2/ -資料8: https://ysin1128.hatenablog.com/entry/2021/08/25/143519 -資料9: https://ysin1128.hatenablog.com/entry/2021/12/10/131817 -資料10: https://kats-eye.net/info/2018/11/07/neopixel/ -資料11: https://learn.adafruit.com/adafruit-neopixel-uberguide -資料12: https://ja.librosnews.com/getting-started-with-neopixel-ws2812-rgb-led -資料1~6: Arduino UNO 向けの資料 -資料7~9: ラズベリーパイ pico 向けの資料 -ラズベリーパイ pico はモデルHがよい。なぜならピンが最初からついているから。 -Arduino UNO でも ラズパイpico でも、どちらでもできそう。ラズパイpicoのほうがたぶん安い。 -Arduino UNO R3 の場合、処理能力が十分かどうかは少し心配。 -しかしArduino UNO R4 Wifiで試したところうまくいかなかったので、UNO R3でやり直したらうまくいった。たぶんライブラリ<Adafruit_NeoPixel.h>がR4に対応できてないのだと思われる。 ** (2) -NeoPixelは1つにつき60mAを要すると書いてあります(資料11)。だから28個なら1.68Aになる可能性があります。64個なら3.84A。これが大きすぎるときは、最大輝度にしないように調整する必要があるそうです。 //-まず[資料1]でArduino IDEをインストール。Arduino UNO R4のボードマネージャーをIDE内でインストール。 ** (3) -必要なもの: --Arduino UNO R3 (AmazonでUSBケーブル付きで1230円くらい・互換品) --WS2812B 7LED (Amazonなら2個で550円くらい・互換品) --300~500オームの抵抗(家にあったものを流用) //--1000uFのコンデンサ(Amazonなら10個で500円くらい) --結線用のジャンプワイヤ・はんだ --(これでUSB電源だけでも合計500mA弱まではいける?) -資料10を参考にして、Arduino側やNeoPixelを準備 ~ -Arduino UNO R3側のコード(スケッチ) #include <Adafruit_NeoPixel.h> #ifdef __AVR__ #include <avr/power.h> // Required for 16 MHz Adafruit Trinket #endif #define Pin 6 #define Pin 6 // (GP6 for RaspberryPiPico) #define NumPixels 7 Adafruit_NeoPixel pixels(NumPixels, Pin, NEO_GRB + NEO_KHZ800); void setup() { Serial.begin(115200); pixels.begin(); } void loop() { for (;;) { int c = Serial.read(); if (c < 0) { delay(3); continue; } if (c == 0xf1) { pixels.clear(); continue; } if (c == 0xf2) { pixels.show(); continue; } if (c == 0xf3) { while (Serial.available() < 3) {} int i = Serial.read() << 8; i |= Serial.read(); // big endian. int n = Serial.read(); while (n > 0) { while (Serial.available() < 3) {} int r = Serial.read(); int g = Serial.read(); int b = Serial.read(); pixels.setPixelColor(i, pixels.Color(r, g, b)); i++; n--; } } } } -Arduinoでのシリアル通信の資料: https://miraiworks.org/?p=3688 ~ -PC側のコード(ひとまずテスト用にC言語で書いています、まだeasy-C用ではありません) #include <stdio.h> #include <tchar.h> #include <windows.h> int main() { HANDLE comPort = CreateFile(_T("COM3"), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); // シリアルポートを開き、ハンドルを取得(※10番以上のCOMポート名は _T("\\\\.\\COM10") としないと認識してくれない) DCB dcb; // シリアルポートの構成情報が入る構造体 GetCommState(comPort, &dcb); // 現在の設定値を読み込み dcb.BaudRate = 115200; // 速度 dcb.ByteSize = 8; // データ長 dcb.Parity = NOPARITY; // パリティ dcb.StopBits = ONESTOPBIT; // ストップビット長 dcb.fOutxCtsFlow = FALSE; // 送信時CTSフロー dcb.fRtsControl = RTS_CONTROL_ENABLE; // RTSフロー SetCommState(comPort, &dcb); // 変更した設定値を書き込み Sleep(3000); // とりあえず安定させるために待つ. static unsigned char a[] = { 0xf1, 0xf3, 0x00, 0x00, 3, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0xf2 // [1 0 0] [0 1 0] [0 0 1] // 電力さえ心配なければ[255 0 0]などでももちろんいいが、1でも十分に視認できるほど明るい. }; DWORD n; WriteFile(comPort, a, sizeof a, &n, NULL); CloseHandle(comPort); } -WindowsからCOMポートで通信する資料: https://www.saluteweb.net/~oss_winapi232.html -Arduinoとの通信パラメータの資料: https://www.arduino.cc/reference/en/language/functions/communication/serial/begin/ --これでSerial.begin()のデフォルトパラメータが SERIAL_8N1 だとわかる。 ** (4) -上記のコードだと Arduino UNO R3 では問題なく動くけど、Raspberry Pi Pico では動かない(通信時にハングアップする)。 -原因は DCB の設定が足りてないこと。 --参考: https://ysin1128.hatenablog.com/entry/2021/08/25/143519 -ということで、DTRフローの設定もやる。このコードはたぶん Arduino UNO R3 でも動く。 #include <stdio.h> #include <tchar.h> #include <windows.h> int main() { HANDLE comPort = CreateFile(_T("COM3"), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); // シリアルポートを開き、ハンドルを取得(※10番以上のCOMポート名は _T("\\\\.\\COM10") としないと認識してくれない) DCB dcb; // シリアルポートの構成情報が入る構造体 GetCommState(comPort, &dcb); // 現在の設定値を読み込み dcb.BaudRate = 115200; // 速度 dcb.ByteSize = 8; // データ長 dcb.Parity = NOPARITY; // パリティ dcb.StopBits = ONESTOPBIT; // ストップビット長 dcb.fOutxCtsFlow = FALSE; // 送信時CTSフロー dcb.fRtsControl = RTS_CONTROL_ENABLE; // RTSフロー dcb.fDtrControl = DTR_CONTROL_ENABLE; // DTRフロー ←ここを追加! SetCommState(comPort, &dcb); // 変更した設定値を書き込み Sleep(3000); // とりあえず安定させるために待つ. static unsigned char a[] = { 0xf1, 0xf3, 0x00, 0x00, 3, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0xf2 // [1 0 0] [0 1 0] [0 0 1] // 電力さえ心配なければ[255 0 0]などでももちろんいいが、1でも十分に視認できるほど明るい. }; DWORD n; WriteFile(comPort, a, sizeof a, &n, NULL); CloseHandle(comPort); }