Arduino 9-1) 4連 Digital Tube LED Displayの点滅問題を考える
2019.03.03
その後、いろんな角度からテストをしてみました。

まず、5, 6ピンを使うとmillis(), micros(), delay(), delayMicroseconds()などの関数が正常に動かなくなるという情報をネットでみたので、接続するピンを
#define SCLK 4
#define RCLK 7
#define DIO 8
としてみる。
失敗

電源をUSB供給から電池に変えてみる。
失敗

Deleyの代わりにmillisを使ってみる。
Deleyのように簡単に使えるようにするため
void milliswait(int loop_i){
old_time=millis(); //最新の実行時間を保存
while (millis() - old_time < loop_i);
}

このような関数を作って実行してみた。
どうやらDelayが悪いのではなく、
処理能力が低下すると高速書き換えができなくなるだけのことだった。
複雑な処理を乗せるとDelayじゃなくても起きる現象ということで
失敗

先人のライブラリを使ってみる。
TM74HC595で検索すると結構使ってる人がいるもので、
Youtubeに投稿してる人も何人かいました。
https://www.youtube.com/watch?v=S_Hnx20GzGs
↑この方の意見を全面的に取り入れて試してみます。
https://github.com/kostarev/TM74HC595-4dig-display
にアクセスしてダウンロードしインストール。
ソースコードを書き換えて実行。
同じ症状でした。
失敗

結局の所、ネットで調べ倒して見た結果、
この製品は4キャラクタのうち、1文字を表示した直後、
他のモジュールの文字が消えてしまう仕様のようで
高速に4モジュールを表示し直して、目をごまかすような処理が必要のようだ。
Loop内でDelayを使うとその更新が阻害されるため
点滅したように見えてしまうというのが真実らしい。
これの解決策として、割り込みを利用し
ある一定周期で更新させることができれば、
Loop内だろうがDelayで止めようが
表示は安定するのではというのが最適解のようです。

#include <mstimer2.h>
int Denatu = 0;
int OutNum = 0;


//接続するピンを設定する
#define SCLK 4
#define RCLK 7
#define DIO 8


byte digitBuffer[4]; //キャラ数(文字数を設定)この配列に入れた数字がそのまま表示される。

void setup(){
Serial.begin( 9600 ); //シリアルモニタを使うときの儀式
pinMode(13, OUTPUT); //ボードのLEDを使用する
pinMode(RCLK, OUTPUT);
pinMode(SCLK, OUTPUT);
pinMode(DIO, OUTPUT);
MsTimer2::set(1, showDisplay); // 1msの周期で結果を4LEDに表示
MsTimer2::start();
}


void loop(){
digitalWrite(13, HIGH); //LEDを光らせる
Denatu = analogRead(0); //A0ピンの電圧を測る0(0V)~1023(5V)
Serial.println(Denatu); //シリアルモニタに値を出力
OutNum = Denatu;


//4文字目に数字を表示
digitBuffer[3] = OutNum % 10; //10で割ってあまりを求める。
OutNum = OutNum / 10; //値を10で割って結果を元の数字に返す。これで4ケタが3ケタにシフトする。

//3文字目に数字を表示
digitBuffer[2] = OutNum % 10; //10で割ってあまりを求める。
OutNum = OutNum / 10; //値を10で割って結果を元の数字に返す。これで3ケタが2ケタにシフトする。

//2文字目に数字を表示
digitBuffer[1] = OutNum % 10; //10で割ってあまりを求める。
OutNum = OutNum / 10; //値を10で割って結果を元の数字に返す。これで2ケタが1ケタにシフトする。


//1文字目に数字を表示
digitBuffer[0] = OutNum % 10; //10で割ってあまりを求める。


delay(Denatu); //読み取った値分処理を止める1023=1.023秒
digitalWrite(13, LOW); //LEDを消す
delay(Denatu); //読み取った値分処理を止める1023=1.023秒
}


//表示するために関数を定義
void showDisplay(){
const byte digit[10] = {
0b11000000,//0
0b11111001,//1
0b10100100,//2
0b10110000,//3
0b10011001,//4
0b10010010,//5
0b10000010,//6
0b11111000,//7
0b10000000,//8
0b10010000 //9
};
const byte chr[4] = {
0b00001000,//1
0b00000100,//2
0b00000010,//3
0b00000001,//4
};


for(byte i = 0; i <= 3; i++){
digitalWrite(RCLK, LOW);
shiftOut(DIO,SCLK,MSBFIRST, digit[digitBuffer[i]]);
shiftOut(DIO,SCLK,MSBFIRST, chr[i]);
digitalWrite(RCLK, HIGH);
delayMicroseconds(1);
}
}


最初の実験の影響で、ピンの位置を先日のものと変えています。注意。
そして実行



イエ━ヽ(*´∇`)人(´∇`*)━ィ!!
ただこの方法、人間には区別はつかないけど高速点滅しているので目には優しくないと思われる。

- CafeNote -