LEDで蛍光灯を作る 4

ユニバーサル基板に半田付けしてみました。
なるべくちゃんと時間どおり動くようにポートを直接操作しています。
何をしてるか自分でもわからなくなりそうなのであんまりやりたくなかったのですが、プログラムした以上にちらついているのが面白くなくなってきたので、大幅に変更しました。

ATtiny85の場合、PORTBというのが出力のポートで、6ビットの整数をひとつ書き込むことで出力を一度に全部変更できます。
下位ビットからそれぞれd0~d4,resetに対応しています。
今回はd0~d3をデジタル出力として使うので、たとえば

  • B0000(二進数。十進数では0)が全消灯、
  • B0001(=1)がデジタル0番ピンのみ点灯、
  • B0011(=2+1=3)は0番、1番が点灯、B1111(=8+4+2+1=15)は全点灯、

というふうになります。

大体動きは決まってきたので一周期5分割のシーケンスをひたすら繰り返す形にしました。
PORTB = なんたら で4ミリ秒ごとに五つの状態をループしています。

あと、基板に組んだら電源が安定しすぎるのか乱数がうまくバラけなくなってきたので、ちょっと時間をおいてrandomSeedをとりなおしたりしています。

スケッチはこちら。
/*
LED fluorescent-light simulation.
Low speed PWM(50Hz 80 percent duration) flickers each light.
Each switch-on time delays randomly.
Sometime it turns off and on like an error.
output:d0-d3
random seed:a2
also detects mains off.
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[4] = {0, 1, 2, 3};
const byte ANA_PIN = 2;
const int PERIOD = 20;// T[ms}=1000[ms]/50[Hz]
int division = PERIOD / 5;
const unsigned long DELAY_MAX = 500/division;
const long BAD_DENOM_BOOT = 4; // denominator of failure probability on booting
const long BAD_DENOM_RUN = 40000/PERIOD; // denominator of failure probability on running
long mainsTh;
byte baseSeq[5] = {B0000, B0000, B0000, B0000, B0000};
const byte TURN_ON_MASK[4][5]={ {B0000, B0001, B0001, B0001, B0001}
,{B0010, B0000, B0010, B0010, B0010}
,{B0100, B0100, B0000, B0100, B0100}
,{B1000, B1000, B1000, B0000, B1000}
};
const byte FLICKER_SEQ[4][5]={ {B1110,B1101,B1010,B0110,B1110}
,{B1100,B1101,B1011,B0101,B1101}
,{B1010,B1001,B1011,B0111,B1011}
,{B1110,B0101,B0011,B0111,B0111}
};
const byte TURN_OFF_SEQ[4][5]={ {B1110,B1100,B1010,B0110,B1110}
,{B1100,B1101,B1001,B0101,B1101}
,{B1010,B1001,B1011,B0011,B1011}
,{B0110,B0101,B0011,B0111,B0111}
};
void setup() {
int valA = analogRead(ANA_PIN);
randomSeed(valA);
mainsTh = valA * 11 / 12;
for (int i = 0; i < 4; i++) {
pinMode(outPins[i], OUTPUT);
}
delay(random(DELAY_MAX * division / 2 ));
randomSeed(valA * analogRead(ANA_PIN));
int turnOnIntervals[4] = {random(DELAY_MAX/6), random(DELAY_MAX/4), random(DELAY_MAX/2), random(DELAY_MAX/6)};
shuffle(outPins, 4);
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 5; j++) {
baseSeq[j] |= TURN_ON_MASK[outPins[i]][j];
}
for (int j = 0; j < turnOnIntervals[i]; j++) {
doSeq( baseSeq );
}
}
if(random(BAD_DENOM_BOOT) == 0){
doBadSeq(outPins[2],DELAY_MAX,DELAY_MAX/3);
}
if(random(BAD_DENOM_BOOT/2) == 0){
doBadSeq(outPins[3],DELAY_MAX*2,DELAY_MAX/2);
}
}
void loop() {
doSeq( baseSeq );
if(random(BAD_DENOM_RUN) == 0){
doBadSeq(outPins[2],DELAY_MAX*4,DELAY_MAX/2);
}
if(random(BAD_DENOM_RUN/2) == 0){
doBadSeq(outPins[3],DELAY_MAX*5,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[]){
for(int i=0; i < 5; i++){
isMainsOff();
PORTB = seq[i];
delay(division);
}
return;
}
void isMainsOff(){
while(mainsTh > analogRead(ANA_PIN)){
PORTB = B000000;
delay(1);
}
return;
}
void doBadSeq(int outPin,unsigned long maxFlicker,unsigned long maxTurnOff){
long flickerInterval = random(maxFlicker);
for(int i=0;i<flickerInterval;i++){
doSeq( FLICKER_SEQ[outPin] );
}
long turnOffInterval = random(maxTurnOff);
for(int i=0;i<turnOffInterval;i++){
doSeq( TURN_OFF_SEQ[outPin] );
}
return;
}

コメント