バイクのカスタムを行うにあたって、まずコンセプトが必要です。
ArduinoとLEDテープをバイクに搭載する場合も同様です。
当然、「仮面ライダー」なのですが、今回は「仮面ライダー555」をイメージしてプログラミングしたいと思います。
実は今の愛車のカラーリング、「仮面ライダーカイザ」の「サイドバッシャー」を意識しています。
記憶の中ではけっこう近かったのですが、こうやって見比べると全然違いますね。
いいんです、僕のバイクなので。
コンセプトは「仮面ライダー555」なのに、意識しているのは「仮面ライダーカイザ」。
いいんです、どっちもかっこいいから。
次は、イルミネーションです。
今のところ考えている挙動は、
キーオフで消灯、
キーオン(エンジン停止)で点灯、
キーオン(エンジン稼働)で消灯です。
違法にならないために、エンジンがかかったら消灯しますから、キーオンしてエンジンをかけるわずかな時間しか光りません。
僕のイメージ的には、仮面ライダー555が変身するときの待機音にあった光らせ方が似合うのかなぁと思っています。
知らない人はいないと思いますが、ちなみにこんな音です。
「「スタンディングバイ」+待機音.m4a」
プレミアムバンダイ公式サイトにあります。
次に、どうやってエンジンの稼働を検知するか、という問題になります。もちろんバイクに搭載しているPCにはさわれません。
バイクのバッテリは定格約12Vですが、エンジンが稼働(発電機稼働)すると、約14Vまで昇圧します。この差を見ればエンジンの稼働/停止を見分けられそうですね。
[キーオン(エンジン停止)]
端子台で測っていますが、バッテリの±端子と同電位です。
12.80Vを示しています。
[キーオン(エンジン稼働)]
14.32Vを示しています。
14Vの電圧をArduinoに直接入力するとICがぶっ壊れますので、分圧して入力します。
下の回路を組みます。
(↑A0間違いです。A2です。)
とても簡単な分圧回路です。
0V~15V の入力電圧を
0V~5V で取り出すことが出来ます。
この電圧値をアナログ信号としてArduinoに入力します。
1個ずつの抵抗素子を 50kΩ としていますが、もっと大きくしてもいいような気はします。
この分圧回路のせいで無駄に消費する電流が 0.08mA です。
ってなわけで、色々参考にしながら、下のようなスケッチを書きました。
//CBR400R、愛称「Predator」に搭載するためのプログラムです。
// 【重要】NeoPixelが焼損しないようにするため、1000μFのコンデンサーをLED電源に並列配線し、
// 300~500Ωの抵抗器を1番目のLED素子のDIN端子とArduinoの間に直列配線します。
// Arduino と1番目のLED素子は出来るだけ近接させます。
// 配線作業は、電源投入済みの回路では行なわないでください。
// もし、どうしてもそれが必要な場合、GNDから先に配線してください。
//1A以上の電流をかけようとしている場合(LED 1素子あたり20~50mA)は、テープLEDに5V電源を直接接続します。
//テープLEDのGNDは、Arduino のGNDと共有する必要があります。
#include <Adafruit_NeoPixel.h>
#define LEDPIN 3 //Arduino ピン番号
#define Pixels 144 //テープ上のLED素子数
#define Threshold_BatteryVoltage 13.5 //バッテリ発電中と認めるための電圧閾値[13.5]
// Adafruit_NeoPixel( Parameter 1 , Parameter 2 , Parameter 3 )
// Parameter 1 = テープ上のLED素子数
// Parameter 2 = Arduino ピン番号 (おおかた利用可)
// Parameter 3 = LED素子タイプフラグ(必要に応じて追加)
// NEO_KHZ800 800 KHz ビット信号 (LED「WS2812」を使用したほとんどの NeoPixel 品)
// NEO_KHZ400 400 KHz ビット信号 (旧い v1 (v2でない) FLORA, LEDドライバー「WS2811」)
// NEO_GRB LED素子はGRBビット信号で接続 (ほとんどの NeoPixel 品)
// NEO_RGB LED素子はRGBビット信号で接続 (v1 FLORA,v2 ではありません)
Adafruit_NeoPixel strip = Adafruit_NeoPixel( Pixels, LEDPIN , NEO_GRB + NEO_KHZ800);
/////////////////////////////////////////////////
////////////////グローバル変数定義////////////////
/////////////////////////////////////////////////
//バッテリ電圧を格納するための変数
double volt;
//バッテリは通常時(キーオン)は12V程度、発電時(エンジン稼働時)は14V程度
//0:0<=V<13.5 1:13.5<=V<15
int BatteryStatus=0;
int BatteryStatus_previous=0;
/////////////////////////////////////
////////////////SETUP////////////////
/////////////////////////////////////
void setup() {
//LEDテープの初期設定
//初期化を行う処理です。ここで指定の出力ピンにpinMode(pin, OUTPUT);を行ってます。
strip.begin();
//LEDの明るさを指定します。0-255の範囲です。
strip.setBrightness(255);
//この関数で実際に接続している全てのLEDに出力します。この場合、全てのLED素子を"off"
strip.show();
Serial.begin(115200UL);
}
////////////////////////////////////
////////////////LOOP////////////////
////////////////////////////////////
void loop() {
//A2(バイクのバッテリ)電圧値の読み込み
//バイクのバッテリーを分圧器にてMAX15V→MAX5Vへ降圧
//0V~5Vを0~1023の分解能で取得
volt = analogRead(A2);
//変数voltの値を0V~15Vに変換
volt*=5;
volt/=1024;
volt*=3;
//シリアル通信で画面に電圧を表示
Serial.println(volt);
//delay(1000);
if(volt<Threshold_BatteryVoltage){
StartUp(10,100);}
//なぜか分からんが消灯しているはずなのに消灯しないので、
//一度リセットする。
else software_reset();
//今回は使わない
//バッテリの状態を符号化
//Check();
//if(BatteryStatus==0){
// Breathe(3,1250);}
//if(BatteryStatus==1){
// StartUp(10,100);}
//PhotonBlood1(50,10); //今回は使わない
//PhotonBlood2(10,10); //今回は使わない
//rainbowCycle(10); //今回は使わない
}
///////////////////////////////////////
////////////////関数定義////////////////
///////////////////////////////////////
//Check()関数は、インターフェイスの変化を検知し、
//変化があった場合は 1 を、変化がなかった場合は 0 を返す関数です。
int Check(void){
//バッテリーの電圧の変化を確認
BatteryStatus_previous=BatteryStatus;
if(volt<Threshold_BatteryVoltage){
BatteryStatus=0;
}else BatteryStatus=1;
if(BatteryStatus_previous!=BatteryStatus){
return 1;
}
//インターフェイスに変化が何もない場合
return 0;
}
//software_reset()関数は、ソフトウェア上でArduinoのリセットを実行するための関数です。
//https://ehbtj.com/electronics/arduino-software-reset/
void software_reset() {
asm volatile (" jmp 0");
}
////////////////////////////////////////////////////////////////
////////////////////////発光パターン定義////////////////////////
////////////////////////////////////////////////////////////////
//Breathe()関数は、生物が呼吸をするようにLEDが明暗を繰り返す関数です。
//Breathe( 明るさが変わる間隔(ms) , 呼吸の間隔(ms) );
void Breathe(uint8_t wait,int interval){
int j,k;
//暗→明
for(j=0;j<256;j++){
//全ピクセルに色情報をセットします。
for(uint16_t i=0;i<strip.numPixels()+16;i++){
strip.setPixelColor(i,0,j,j); //さわやかな水色
}
strip.show();
delay(wait); //一段階明るくするまでの時間(ms)です。
}
//明→暗
for(k=255;k>-1;k--){
//全ピクセルに色情報をセットします。
for(uint16_t i=0;i<strip.numPixels();i++){
strip.setPixelColor(i,0,k,k); //さわやかな水色
}
strip.show();
delay(wait); //一段階暗くするまでの時間(ms)です。
}
//消灯の状態で待機します。
delay(interval);
}
//StartUp()関数は、仮面ライダー555の変身待機音に合わせたイルミネーションです。
void StartUp(uint8_t wait,int interval){
int k;
//明→暗
for(k=255;k>-1;k=k-8){
//全ピクセルに色情報をセットします。
for(uint16_t i=0;i<strip.numPixels();i++){
strip.setPixelColor(i,k,0,0); //ファイズのモチーフカラー(赤)
}
strip.show();
delay(wait); //一段階暗くするまでの時間(ms)です。
}
//消灯の状態で待機します。
delay(interval);
}
//PhotonBlood1()関数は、フォトンブラッドの流れを表現するイルミネーションです。
//フォトンブラッドはArduino側から先端へ流れます。
void PhotonBlood1(uint8_t wait,int interval){
uint16_t i,j,k;
for(i=0;i<strip.numPixels()+16;i++){
k=256;
//変数 i(=j) の位置から本体側まで16個のLEDを使ってグラデーション
//変数 k がLEDの光量を表す
for(j=i;j>i-16;j--){
if(k<=0)break;
strip.setPixelColor(j,k,k,0);
k=k-16;
}
strip.show();
delay(wait);
}
delay(interval);
}
/*いちおう成立してるけど、美しくない
//PhotonBlood2()関数は、フォトンブラッドの流れを表現するイルミネーションです。
//フォトンブラッドはArduino側から先端へ流れます。
void PhotonBlood2(uint8_t wait,int interval){
uint16_t i,j,k,n;
for(i=0;i<strip.numPixels()+16;i++){
k=255;
for(j=i;j>0;j--){
//if(j<0)break;
strip.setPixelColor(j,k,0,0);
k=k-16;
}
strip.show();
delay(wait);
}
delay(interval);
}
*/
//rainbowCycle()
void rainbowCycle(uint8_t wait) {
uint16_t i, j;
for(j=0; j<256; j++) {
for(i=0; i< strip.numPixels(); i++) {
strip.setPixelColor(i, Wheel((((i) * 256 / strip.numPixels()) + j) & 255));
}
strip.show();
delay(wait);
}
}
// 0 to 255の値を入力すると、RGB値を戻します
// 色は r - g - b - r …と変わってゆきます
uint32_t Wheel(byte WheelPos) {
if(WheelPos < 85) {
return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
} else if(WheelPos < 170) {
WheelPos -= 85;
return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
} else {
WheelPos -= 170;
return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
}
コメントアウトと無駄な文が多いのは勉強のためです。
変数名とか関数名とか、改行とかスペースとか、素人丸出しなのは許してください。
コメントアウトはともかく、参照しない関数とかただただ無駄なので、コンパイル時は消してもらってもいいです。
あと、割り込み処理使ってもうちょっとスマートなプログラムにしたかったのですが、デジタル信号しか割り込み出来ないみたいで、そのための回路作るのも面倒なので、こんかいはやめました。とりあえずこのプロジェクトが終わったら挑戦してみたいです。
実際に机の上で光らせている動画です。
今回は12V準備するのがめんどくさかったのと、部屋のなかでまぶし過ぎたので、
#define Threshold_BatteryVoltage 4.5 //バッテリ発電中と認めるための電圧閾値[13.5]
//LEDの明るさを指定します。0-255の範囲です。
strip.setBrightness(100);
としています。
便宜上、ArduinoのA2ポートに5Vの電源を印加すると、発電中(エンジンスタート)を検知したとします。
また、LEDの明るさは、最高255ですが、100です。
眠かったので何言ってるか聞き取りづらいですね。すみません。
という訳で、試行成功です。
ちなみに、こんな構成回路の写真はこんな感じです。
ここまでこれば、満を持してバイクに搭載!となりますが・・・・・・
気づいたと思いますが、この回路では、LEDテープに電源を与え続けている限り、キースイッチをオフにしてもLEDが光り続けます。
この点については、リレー受けして、キーオンの時だけ別回路でLEDテープに電源を与えようと思います。
その回路構築はまたこんど。