LEDで蛍光灯 コントロールユニット

コントロールユニットについてもう少し詳しく。


開発にはArduinoというのを使っています。
このへんが詳しいです。Arduino入門 (全12回)
お安くあげるためにATtiny85というのを使っています。ArduinoISPでATtinyへスケッチを書き込む(その1)


過去の制作記事を参照してください。
LEDで蛍光灯を作る 1
LEDで蛍光灯を作る 2
LEDで蛍光灯を作る 3
LEDで蛍光灯を作る 4
若干変更していますが、事情と制作のこまかいことは同じです。

変更点は
  • 4回路   ->  3回路に
  • 空いた端子で電圧検知 インジケータLEDもここに付けちゃう
  • バイパススイッチを省略
  • ランダムがばらけるようにアンテナパターン
  • 起動時以外のランダムちらつきはしない(スケッチ上でコメントアウトしてる)
図面
前に書いたのと違ってみえますが、ソフトが違うからです。
基板屋さんに発注しやすいようにEAGLEで書き直しました。
発注は作業時期が中国の春節にかぶってしまったのもあって、国内のp-ban.comにしました。ちょっと高くついたものの、日本語でやりとりできるし、ていねいな仕事で満足しています。


スケッチ
21行目"const unsigned long DELAY_MAX = 500/division;"の500を増減することで、全体的な動作スピードを調整できます。


/*
LED fluorescent-light simulation.
Low speed PWM(50Hz and 80 percent duration) flickers each light.
Each switch-on time delays randomly.
Sometime it turns off and on like an error.
output:d0-d2
random seed:a3
detects mains off:a2
Wire mains to a0 input through an resistor and a0 to ground through another resistor
in order to fit the input voltage within 0-5v.
(for example,I use dc12v as mains,so I choose 15k and 4.7k resistor to get almost 3v.)
*/
int outPins[3] = {0, 1, 2};
const byte ANA_PIN = 2;
const byte RND_PIN = 3;
const int PERIOD = 10;// T[ms}=1000[ms]/100[Hz]
int division = PERIOD / 5;
const unsigned long DELAY_MAX = 500/division;
const long BAD_DENOM_BOOT = 10; // denominator of failure probability on booting
const long BAD_DENOM_RUN = 800000/PERIOD; // denominator of failure probability on running
long mainsTh;
byte baseSeq[5] = {B0000, B0000, B0000, B0000, B0000};
const byte TURN_ON_MASK[3][5]={ {B000, B001, B001, B001, B001}
,{B010, B000, B010, B010, B010}
,{B100, B100, B000, B100, B100}
/*,{B1000, B1000, B1000, B0000, B1000} */
};
const byte FLICKER_SEQ[3][5]={ {B110,B101,B010,B110,B110}
,{B100,B101,B011,B101,B101}
,{B010,B001,B011,B111,B011}
/* ,{B1110,B0101,B0011,B0111,B0111} */
};
const byte TURN_OFF_SEQ[3][5]={ {B110,B100,B010,B110,B110}
,{B100,B101,B001,B101,B101}
,{B010,B001,B011,B011,B011}
/* ,{B0110,B0101,B0011,B0111,B0111} */
};
void setup() {
randomSeed(analogRead(RND_PIN));
// mainsTh = analogRead(ANA_PIN) * 3 / 4;
for (int i = 0; i < 3; i++) {
pinMode(outPins[i], OUTPUT);
}
delay(random(DELAY_MAX * division / 5 ));
int turnOnIntervals[3] = {random(DELAY_MAX/8), random(DELAY_MAX/6), random(DELAY_MAX/8)};
shuffle(outPins, 3);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 5; j++) {
baseSeq[j] |= TURN_ON_MASK[outPins[i]][j];
}
mainsTh = analogRead(ANA_PIN) * 3 / 4;
for (int j = 0; j < turnOnIntervals[i]; j++) {
doSeq( baseSeq,mainsTh );
}
}
if(random(BAD_DENOM_BOOT) < 4 ){
mainsTh = analogRead(ANA_PIN) * 5 / 6;
doBadSeq(outPins[1],DELAY_MAX/3,DELAY_MAX/4,mainsTh);
}
if(random(BAD_DENOM_BOOT) < 7 ){
mainsTh = analogRead(ANA_PIN) * 5 / 6;
doBadSeq(outPins[2],DELAY_MAX/3,DELAY_MAX/4,mainsTh);
}
}
void loop() {
static const byte baseSeq[5] = {B110,B101,B011,B111,B111};
mainsTh = analogRead(ANA_PIN) * 5 / 6;
doSeq( baseSeq,mainsTh );
/*
if(random(BAD_DENOM_RUN) < 1 ){
doBadSeq(outPins[1],DELAY_MAX/2,DELAY_MAX/2);
}
if(random(BAD_DENOM_RUN) < 2 ){
doBadSeq(outPins[2],DELAY_MAX/2,DELAY_MAX/2);
}
*/
}
void shuffle(int ary[], int arySize) {
for (int i = 0; i < arySize - 1; i++) {
int j = random(i, arySize);
int t = ary[i];
ary[i] = ary[j];
ary[j] = t;
}
}
void doSeq(const byte seq[],long mainsTh){
for(int i=0; i < 5; i++){
isMainsOff(mainsTh);
PORTB = seq[i];
delay(division);
}
return;
}
void isMainsOff(long mainsTh){
long mainsThL = mainsTh * 4 / 5;
const byte MAINS_OFF_SEQ[10] = {B000,B100,B000,B010,B000,B001,B000,B000,B000,B000};
int i = 0;
while(analogRead(ANA_PIN) < mainsTh ){
long mainsVal;
while( (mainsVal = analogRead(ANA_PIN)) > mainsThL && mainsVal < mainsTh){
PORTB = MAINS_OFF_SEQ[i];
delay(division);
i = i < 10 ? i+1 : 0 ;
}
PORTB = B000000;
delay(division);
}
return;
}
void badSeq1(int outPin,unsigned long maxFlicker,long mainsTh){
long flickerInterval = random(maxFlicker);
for(int i=0;i<flickerInterval;i++){
doSeq( FLICKER_SEQ[outPin], mainsTh );
doSeq( TURN_OFF_SEQ[outPin], mainsTh );
};
return;
}
void badSeq2(int outPin,unsigned long maxTurnOff,long mainsTh){
long turnOffInterval = random(maxTurnOff);
for(int i=0;i<turnOffInterval;i++){
doSeq( TURN_OFF_SEQ[outPin], mainsTh );
};
return;
}
void doBadSeq(int outPin,unsigned long maxFlicker,unsigned long maxTurnOff,long mainsTh){
if(random(2)){
badSeq1(outPin,maxFlicker,mainsTh);badSeq2(outPin,maxTurnOff,mainsTh);
}else{
badSeq2(outPin,maxTurnOff,mainsTh);badSeq1(outPin,maxFlicker,mainsTh);
};
randomSeed(analogRead(RND_PIN));
return;
}

コメント