WS2822Sのアニメーションについては下記記事を参照下さい
Adafruit TrinketでWS2822Sをアニメーション点灯
目的
- Adafruit Trinketで対象物との距離を測定する
- 距離センサはSHARP GP2Y0E03赤外線距離センサを利用する
秋月電子で800円弱で購入、参考にしたデータシートは下記
http://sharp-world.com/products/device/lineup/data/pdf/datasheet/gp2y0e03_e.pdf
出来上がった物
回路図
- Trinket 0Pin
WS2822SのADDRI (Address Input) に接続 → 他のWS2822Sへチェーン接続 - Trinket 1Pin
各WS2822SのDAI (Data Input)に接続 - Trinket 2Pin
SHARP GP2Y0E03のアナログ出力 Vout(A)を接続
GP2Y0E03のピンアサイン/出力電圧詳細は上記データシートを参照 SHARP GP2Y0E03
上記のブレッドボード図の左から下記となります
1 | VDD → 3.3V
2 | Vout(A) → Trinketのアナログ入力へ
3 | GND → GNDへ
4 | VIN(IO) → 3.3V
5 | GPIO1 → 3.3V
6 | SCL → I2C用のため利用しない
7 | SDA → I2C用のため利用しない3.3V生成
手持ちのLM317を利用3.3VをSHARP GP2Y0E03の
VDD/VIN(IO)/GPIO1 に入力- その他
TrinketのGNDはGP2Y0E03と共有
注意点 前回記事に色々記載をしておりますので参考にして下さい
ソースコード
#include <Ws2822s.h>
#include <avr/interrupt.h>
// WS2822Sセットアップ
#define NUM_PIXELS 3 // 使用するWS2822Sの数
#define LED_PIN 1 // WS2822SのDAIピンにつなげるTrinketのピン番号 #1
#define ADR_PIN 0 // WS2822SのADRIピンにつなげるTrinketのピン番号 #0
// センサーセットアップ
#define DISTANCE_SENSOR 1 // 距離センサーのアナログ出力値を取得 Trinketのピン番号#2
// TrinketでanalogRead利用時は AnalogPinNumberで記載する 1 = #2 となる
#define MAX_VOLTAGE 3.0
Ws2822s LED(LED_PIN , NUM_PIXELS);
// アニメーションパターンの定義
#define RGB 3
#define FRAME_MAX 2
PROGMEM const uint8_t displayAnim[][RGB*NUM_PIXELS*FRAME_MAX] = {
// R G B
// LED1
// LED2
// 近い
{
0x0F,0x00,0x00,
0x0F,0x00,0x00,
0x0F,0x00,0x00,
0x00,0x00,0x00,
0x00,0x00,0x00,
0x00,0x00,0x00,
},
// 中位
{
0x00,0x0F,0x00,
0x00,0x0F,0x00,
0x00,0x0F,0x00,
0x00,0x00,0x00,
0x00,0x00,0x00,
0x00,0x00,0x00,
},
// 遠い
{
0x00,0x00,0x0F,
0x00,0x00,0x0F,
0x00,0x00,0x0F,
0x00,0x00,0x00,
0x00,0x00,0x00,
0x00,0x00,0x00,
},
};
// interrupt関数で使いまわす変数
volatile uint8_t animPattern; // 実行するアニメーションのパターン
volatile uint8_t animFrameNum; // タイマー割り込みが toggleCount 回実行されたらアニメーションフレームが1進む
volatile uint16_t animWaitTime; // タイマー割り込みが toggleCount 回実行されたらアニメーションフレームが1進む
volatile uint16_t toggleCount; // タイマー割り込み時にカウントアップされるカウンタ
void setup()
{
// put your setup code here, to run once:
// tnx for information
// http://w8bh.net/avr/TrinketTimers.pdf
// http://tetunori.hatenablog.com
// http://www.geocities.jp/zattouka/GarageHouse/micon/Arduino/DMSU/DMSU2.htm
// Disable interrupts
cli();
// Clear Timer on Compare
TCCR1 = (1<<CTC1);
// all of the prescaler bits are set to 1. The prescaler divides the 8 MHz clock by 16384
// resulting in a counter frequency of 488 Hz
TCCR1 |= (1<<CS13) | (1<<CS12) | (1<<CS11) | (1<<CS10);
// The output frequency for CTC mode is: freq(Hz) = 8 MHz/2/prescaler/(OCR1C+1)
// resulting a calling TIM1_COMPA_vect frequency is 4.8 Hz
OCR1C = 50;
// Enable Timer1 interrupt (compare mode)
TIMSK = (1 << OCIE1A);
// init WS2822S Address (EEPROMの寿命を考えていません)
LED.setAddress(0, NUM_PIXELS-1);
//色配列の初期化
setAnimationPatternToBlank();
setAnimationPattern(2, 5);
// Enable interrupts
sei();
}
void loop()
{
// put your main code here, to run repeatedly:
// 着陸するヘリとの距離に応じてアニメーションを変化させる
int sensorValue = analogRead(DISTANCE_SENSOR);
float voltage = (float)sensorValue * (MAX_VOLTAGE / 1024.0);
if (voltage > 1.2) {
// 距離が約5cm以内 赤色点滅 早くアニメーション
setAnimationPattern(0, 1);
} else if (voltage > 0.6) {
// 距離が約15cm以内 緑色点滅 少しゆっくりとでアニメーション
setAnimationPattern(1, 3);
} else if (voltage < 0.6) {
// 距離が約15cm以上 青色点滅 ゆっくりとアニメーション
setAnimationPattern(2, 5);
}
}
void setAnimationPatternToBlank()
{
// 全てのWS2822Sピクセルの色情報をR,G,B=0,0,0とする
for (int ledAddr=0; ledAddr<NUM_PIXELS; ledAddr++) {
LED.setColor(ledAddr, 0, 0, 0);
}
LED.send();
}
void setAnimationPattern(uint8_t _animPattern, uint16_t _animWaitTime)
{
// アニメーションのパターンが現在の物と異なったら初期化
if (animPattern != _animPattern) {
animWaitTime = _animWaitTime;
animPattern = _animPattern;
animFrameNum = 0;
}
}
// LEDの色情報を1秒以内に再送信
ISR(TIM1_COMPA_vect)
{
// 設定されたアニメーションのパターンとフレームをLEDに設定 & 送信
for (int ledAddr=0; ledAddr<NUM_PIXELS; ledAddr++) {
LED.setColor(ledAddr, pgm_read_byte_near(&displayAnim[animPattern][(animFrameNum*NUM_PIXELS*RGB)+(ledAddr*RGB)]),
pgm_read_byte_near(&displayAnim[animPattern][(animFrameNum*NUM_PIXELS*RGB)+(ledAddr*RGB)+1]),
pgm_read_byte_near(&displayAnim[animPattern][(animFrameNum*NUM_PIXELS*RGB)+(ledAddr*RGB)+2]));
}
LED.send();
// タイマー割り込みのタイミング * animWaitTimeの値で アニメーションのフレームを進める
if (toggleCount < animWaitTime) {
toggleCount++;
} else {
if (animFrameNum < (FRAME_MAX-1)) {
animFrameNum++;
} else {
animFrameNum = 0;
}
toggleCount = 0;
}
}
利用した物
- Adafruit Trinket 5V Logic
https://www.switch-science.com/catalog/1501/
WS2822SシリアルLEDタイルモジュール(5個入り)
https://www.switch-science.com/catalog/2206/シャープ測距モジュール GP2Y0E03 (I2C&アナログ出力)
小型で性能の良い距離測定センサーです
http://akizukidenshi.com/catalog/g/gI-07547/3端子レギュレータ LM317
5Vから3.3Vを生成するために利用しました
- 抵抗
LM317の出力電圧調整に数種類試してよさそうな抵抗値を選択しました。
- ブレッドボード
多少余裕のある大きさをおすすめします
自分は秋月電子で600円の物を利用しています。
http://akizukidenshi.com/catalog/g/gP-00319/
- ジャンパキット 使い捨てでも良ければ安いものでも全然いけます
お高いですがヘタリが少なく繰り返し使え、ブレッドボードに刺さらない部品もクリップで接続できたり便利です
参考情報
http://www.geocities.jp/zattouka/GarageHouse/micon/Arduino/DMSU/DMSU2.htm
とても参考になりました、ありがとうございました。