工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Manufacturing Technology >> 製造プロセス

ミニLEDマトリックス時計

コンポーネントと消耗品

>
Arduino Nano R3
× 1
Maxim Integrated DS3231M-±5ppm、I2Cリアルタイムクロック
× 1
押しボタンスイッチ、モーメンタリ
× 2
LEDマトリックスモジュール32x8
× 1

必要なツールとマシン

>
はんだごて(汎用)

アプリとオンラインサービス

>
Arduino IDE

このプロジェクトについて

「ニックのLEDプロジェクト」ページで、時計プロジェクトの魔女が8x8のLEDを備えた4つのマトリックスで時間を表示しているのを見つけました。彼は、マトリックスモジュールパネルのDIYキットを販売している「ICStation」ストアのマトリックスを使用して時計を作成しました。

コードの変更を最小限に抑えて、MAX7219ドットマトリックスモジュールのicrocontroller Four-in-One Displayを使用して時計を作成しました。これは、完全に折りたたまれており、はるかに安価です。 AliExpressから購入しました。

時計には多くの機能があります:

-大きな数字の基本モード

-数字が画面のオンとオフを切り替えるスライドモード

-秒モードの小さな数字

-言葉で書かれた時間、例: 「12時10分」

-日付表示

-12/24時間オプション

-明るさのオプション

-数時間ごとに表示モードを変更するランダムクロックモードオプション。

-セットアップとディスプレイ選択のためのプッシュボタン駆動メニュー。

<図>

回路でわかるように、マトリックスを除いて、arduinoボード、リアルタイムクロックモジュール、および設定用の2つのプッシュボタンが必要です。以下のリンクからライブラリと変更されたコードをダウンロードできます。

コード

  • コード
  • ライブラリ
コード Arduino
 / ********************************************** ************************* Mini Clock v1.0、2014年7月NickHallによるGPLの条件の下で配布。時計は私のブログを参照してください:http://123led.wordpress.com/IDEv1.6.5でテスト済み***************************** ****************************************** ///ライブラリを含める:#include "LedControl.h" #include  //フォントライブラリ#include  // DS1307 clock#include "RTClib.h" // DS1307 clock#include  //ボタンライブラリby Alexander Brevig //セットアップLEDマトリックス//ピン12はディスプレイのDataInに接続//ピン11はディスプレイのCLKに接続//ピン10はディスプレイのLOADに接続LedControllc =LedControl(12、11、 10、4); // 3つのピンを12、11、10に設定してから、4つのディスプレイを設定します(最大は8つのディスプレイ)//グローバル変数byteintense =7; //デフォルトの強度/明るさ(0-15)byte clock_mode =0; //デフォルトのクロックモード。デフォルト=0(basic_mode)bool random_mode =0; //ランダムモードを定義します-数時間ごとに表示タイプを変更します。デフォルト=0(オフ)byte old_mode =clock_mode; //前のクロックモードを保存するので、日付などに移動すると、after.bool ampm =0に戻るモードがわかります。 // 12時間または24時間の時間を定義します。 0 =24時間。 1 =12時間バイトchange_mode_time =0; //ランダムモードの場合、クロックモードが次に変更される時間を保持します。unsignedlongdelaytime=500; // displayint rtc [7]の更新の間に常に少し待機します; //リアルタイムクロックoutputchar日を保持します[7] [4] ={"Sun"、 "Mon"、 "Tue"、 "Wed"、 "Thu"、 "Fri"、 "Sat"}; //日配列-スライド、basic_mode、およびジャンブルモードで使用されます(DS1307は曜日に1〜7の値を出力します)chardaysfull [7] [9] ={"Sunday"、 "Monday"、 "Tuesday"、 "Wed "、"木曜日 "、"金曜日 "、"土曜日 "}; char接尾辞[4] [3] ={" st "、" nd "、" rd "、" th "}; //スライド、basic_mode、jumbleモードで使用される日付接尾辞配列。例:1st 2nd ... //定数を定義#defineNUM_DISPLAY_MODES 3 //数値表示モード(最初のモードとしてゼロを継続)#defineNUM_SETTINGS_MODES 4 //数値設定モード=6(最初のモードとしてゼロを継続)# define SLIDE_DELAY 20 //スライドモードでの文字ごとのスライド効果のミリ秒単位の時間。効果を遅くするには、これを高くします#define cls clear_display // displayRTC_DS1307をクリアしますds1307; // RTCオブジェクトを作成しますButtonbuttonA =Button(2、BUTTON_PULLUP); //ボタンAを設定します(ボタンライブラリを使用)Button buttonB =Button(3、BUTTON_PULLUP); //セットアップボタンB(ボタンライブラリを使用)void setup(){digitalWrite(2、HIGH); //ピン2のボタンのプルアップ抵抗をオンにしますdigitalWrite(3、HIGH); //ピン3のボタンのプルアップ抵抗をオンにしますdigitalWrite(4、HIGH); //ピン4のボタンのプルアップ抵抗をオンにしますSerial.begin(9600); //シリアルを開始します// 4つのマトリックスパネルを初期化します// LedControlを作成したときにデバイスの数をすでに設定していますintdevices =lc.getDeviceCount(); //ループ内のすべてのデバイスを初期化する必要がありますfor(int address =0; address  =0 &&x <=7){アドレス=3; } if(x> =8 &&x <=15){アドレス=2; x =x-8; } if(x> =16 &&x <=23){アドレス=1; x =x-16; } if(x> =24 &&x <=31){アドレス=0; x =x-24; } if(val ==1){lc.setLed(address、y、x、true); } else {lc.setLed(address、y、x、false); }} // clear screenvoid clear_display(){for(byte address =0; address <4; address ++){lc.clearDisplay(address); }} //フェード画面downvoidfade_down(){//グローバル強度から1にフェードfor(byte i =強度; i> 0; i-){for(byte address =0; address <4; address ++){lc .setIntensity(address、i); } delay(30); //これを変更してフェードダウン速度を変更します} clear_display(); //表示を完全にクリア(オフ)//インテントをグローバル値にリセットfor(byte address =0; address <4; address ++){lc.setIntensity(address、intensity); }} //電源投入LEDテストおよび表示ソフトウェアバージョン番号voidprintver(){byte i =0; char ver_a [9] ="Vers 1.0"; char ver_b [9] ="こんにちは!"; //すべてのLEDをテストします。 for(byte x =0; x <=31; x ++){for(byte y =0; y <=7; y ++){plot(x、y、1); }} delay(500);およびfade_down(); while(ver_a [i]){puttinychar((i * 4)、1、ver_a [i]); delay(35); i ++; } delay(700);およびfade_down(); i =0; while(ver_b [i]){puttinychar((i * 4)、1、ver_b [i]); delay(35); i ++; } delay(700);およびfade_down();} // puttinychar // myfontデータ構造から3x5文字のグリフをコピーして、左上が指定された座標にあるメモリを表示します//これは最適化されておらず、plot()を使用して各ドットを描画します。voidputtinychar (バイトx、バイトy、文字c){バイトドット; if(c> ='A' &&c <='Z' ||(c> ='a' &&c <='z')){c&=0x1F; // A-Zは1-26にマップされます} else if(c> ='0' &&c <='9'){c =(c-'0 ')+ 32; } else if(c ==''){c =0; //スペース} else if(c =='。'){c =27; //終止符} else if(c ==':'){c =28; //コロン} else if(c =='\' '){c =29; //一重引用符} else if(c =='!'){c =30; //一重引用符} else if(c =='?'){c =31; //一重引用符} for(byte col =0; col <3; col ++){dots =pgm_read_byte_near(&mytinyfont [c] [col]); for(char row =0; row <5; row ++){if(dots&(16>> row))plot(x + col、y + row、1); else plot(x + col、y + row、0); }}} void putnormalchar(byte x、byte y、char c){バイトドット; // if(c> ='A' &&c <='Z' ||(c> ='a' &&c <='z')){// c&=0x1F; // A-Zは1-26にマップされます//} if(c> ='A' &&c <='Z'){c&=0x1F; // A-Zは1-26にマップされます} else if(c> ='a' &&c <='z'){c =(c-'a ')+ 41; // A-Zは41-67にマップされます} else if(c> ='0' &&c <='9'){c =(c-'0 ')+ 31; } else if(c ==''){c =0; //スペース} else if(c =='。'){c =27; //終止符} else if(c =='\' '){c =28; //一重引用符} else if(c ==':'){c =29; // clock_modeセレクター矢印} else if(c =='>'){c =30; // clock_modeセレクター矢印} else if(c> =-80 &&c <=-67){c * =-1; } for(char col =0; col <5; col ++){dots =pgm_read_byte_near(&myfont [c] [col]); for(char row =0; row <7; row ++){//プロットを試みる前に座標が画面に表示されていることを確認します// if((x> =0)&&(x <=31)&&(y> =0)&&(y <=7)){if(dots&(64>> row)){// 7行のみ。 plot(x + col、y + row、1); } else {plot(x + col、y + row、0); } //}}}} // small_mode //時間を秒単位の小さい3x5文字で表示するdisplayvoidsmall_mode(){char textchar [8]; //表示バイトの16文字mins =100; // minsバイト秒=rtc [0]; //秒バイトold_secs =secs; //古い秒の値を保持します-秒が最後に更新された時刻からodisplay-秒が変更されたかどうかを確認するために使用されますcls(); // run_modeがtrueを返す限り、クロックのメインループを実行しますwhile(run_mode()){get_time(); //ボタンが押されているかどうかを確認if(buttonA.uniquePress()){switch_mode();戻る; } if(buttonB.uniquePress()){display_date();戻る; } //秒が変更された場合は、ディスプレイで更新しますsecs =rtc [0]; if(secs!=old_secs){// secs char buffer [3]; itoa(secs、buffer、10); //修正-numに先行ゼロがある場合と同様に、たとえば「03」秒、itoaはこれをスペース「3」の文字に変換します。 if(secs <10){buffer [1] =buffer [0]; buffer [0] ='0'; } puttinychar(20、1、 ':'); //秒コロンputtinychar(24、1、buffer [0]); //秒puttinychar(28、1、buffer [1]); //秒old_secs =secs; } //分が変更された場合は時間を変更しますif(mins!=rtc [1]){//次回の比較のためにこれらをリセットしますmins =rtc [1];バイト時間=rtc [2]; if(hours> 12){hours =hours-ampm * 12; } if(hours <1){hours =hours + ampm * 12; } //バイトダウ=rtc [3]; // DS1307は0-6を出力します。ここで0 =日曜日0-6ここで0 =日曜日です。 //バイト日付=rtc [4]; //文字を設定しますcharbuffer [3]; itoa(時間、バッファ、10); //修正-numに先行ゼロがある場合と同様に、たとえば「03」時間、itoaはこれをスペース「3」の文字に変換します。 if(hours <10){buffer [1] =buffer [0]; // 12時間モードの場合は、先行ゼロを空白にします。 if(ampm){buffer [0] =''; } else {buffer [0] ='0'; }} //時間を設定charstextchar [0] =buffer [0]; textchar [1] =buffer [1]; textchar [2] =':'; itoa(分、バッファー、10); if(mins <10){buffer [1] =buffer [0]; buffer [0] ='0'; } //最小文字を設定textchar [3] =buffer [0]; textchar [4] =buffer [1]; //秒を実行しますtextchar [5] =':'; buffer [3]; secs =rtc [0]; itoa(secs、buffer、10); //修正-numに先行ゼロがある場合と同様に、たとえば「03」秒、itoaはこれをスペース「3」の文字に変換します。 if(secs <10){buffer [1] =buffer [0]; buffer [0] ='0'; } //秒を設定textchar [6] =buffer [0]; textchar [7] =buffer [1];バイトx =0;バイトy =0; //各文字を出力します(byte x =0; x <6; x ++){puttinychar(x * 4、1、textchar [x]); }} delay(50); }およびfade_down();} // basic_mode()// 5x7文字で時間を表示voidbasic_mode(){cls(); char buffer [3]; // rtc値をcharに変換するintからcharへの変換では、画面に出力できますbyte offset =0; // 12時間モードで、時計に3桁しか表示されない場合に、桁のx位置をオフセットし、表示を中央に配置するために使用されます。例えば3:21バイトx、y; // 12時間モードで12:59-> 1:00 amにロールするときに、ディスプレイの左側の「1」の上にクリアボックスを描画するために使用されます。 // ampmが1バイト時間に設定されている場合は12/24時間変換を実行=rtc [2]; if(hours> 12){hours =hours-ampm * 12; } if(hours <1){hours =hours + ampm * 12; } //オフセット変換を行うif(ampm &&hours <10){offset =2; } //次の分を設定します// set_next_date();に日付を表​​示します//最初にminsを値100に設定します-したがって、クロックの最初のループでrtc [1]と等しくなることはありません。つまり、関数byte secs =100を入力するとクロック表示が描画されます。バイト分=100; int count =0; // run_modeがtrueを返す限り、クロックのメインループを実行しますwhile(run_mode()){//クロックチップから時刻を取得しますget_time(); //ボタンが押されているかどうかを確認if(buttonA.uniquePress()){switch_mode();戻る; } if(buttonB.uniquePress()){display_date();戻る; } //日付を自動的に表示する時間かどうかを確認します// check_show_date(); //点滅を描画します:秒が変更されたかのように。 if(secs!=rtc [0]){//秒を新しい値で更新secs =rtc [0]; //描画:プロット(15-オフセット、2、1); //トップポイントプロット(15-オフセット、5、1); //ボトムポイント数=400; } //カウントがなくなった場合は、:if(count ==0){plot(15-offset、2、0);をオフにします。 //トップポイントプロット(15-オフセット、5、0); //ボトムポイント} else {count--; } //ボタンが押された場合、またはmins!=rtc [1]の場合、つまり時間がminsに保存された時間から変更された場合(minsが100のときに最初に関数に入るときにもトリガーされます)if(mins!=rtc [1]){//分と時間を新しい値で更新しますmins =rtc [1];時間=rtc [2]; // ampmの時間を12時間モードに設定するif(hours> 12){hours =hours --ampm * 12; } if(hours <1){hours =hours + ampm * 12; } itoa(hours、buffer、10); //時間<10の場合、数値(例: "3"時間、itoaはこれをスペース "3"の文字に変換します。これは(hours <10){buffer [1] =buffer [0]; buffer [0] ='0'; } //時間の印刷// 12時間モードで時間<10の場合、先行ゼロを印刷せず、3桁で表示を中央に配置するようにオフセットを設定します。 if(ampm &&hours <10){オフセット=2; //時刻が午前1時の場合、この時点でオフセットが変更されるため、表示全体をクリアし、古い12:59を空白にする必要がありますif((hours ==1 &&mins ==0)){cls(); }} else {//オフセットなし、印刷時間数十桁オフセット=0; //時刻が午前10時の場合、この時点でオフセットが変更されるため、表示全体をクリアし、古い9:59を空白にする必要がありますif(hours ==10 &&mins ==0){cls(); } putnormalchar(1、0、buffer [0]); } //時間1桁を出力putnormalchar(7 --offset、0、buffer [1]); // minsを出力// mins <10 itoa(mins、buffer、10);の場合、先行ゼロを追加します。 if(mins <10){buffer [1] =buffer [0]; buffer [0] ='0'; } //最小数の10桁と1桁を出力putnormalchar(19-offset、0、buffer [0]); putnormalchar(25-オフセット、0、バッファ[1]); }}およびfade_down();} // basic_modeと似ていますが、スライド効果がありますvoid slide(){byte Digits_old [4] ={99、99、99、99}; //時間を保存する古い値。最初は時間と一致しないものに設定して、モードがバイトで開始するときにすべての数字が描画されるようにしますdigits_new [4]; //新しい数字の時間がスライドしてバイトを表示しますdigits_x_pos [4] ={25、19、7、1}; // char old_char [2]で各桁を描画するxpos; // itoaを使用して現在の数字(バイト型)をcharに転置し、アニメーション関数char new_char [2]に渡すときに使用されます。 // itoaを使用して新しい数字(バイト型)をcharに転置し、アニメーション関数に渡すときに使用されます//old_chars-5日と日付のサフィックス文字をディスプレイに格納します。例えば「mon」と「st」。これらの文字が更新されると、これらを現在の文字としてスライドアニメーションにフィードします。 //最初はAとして送信しました。これは、cloclがモードに入り、最後の文字が保存されていない場合に使用されます。 // char old_chars [6] ="AAAAA"; //時計のコロンをディスプレイにプロットしますcls(); putnormalchar(13、0、 ':');バイトold_secs =rtc [0]; //秒をold_secsに格納します。秒と古い秒を比較します。それらが異なる場合、run_modeがtrueを返す限り、表示を再描画します//クロックのメインループを実行しますwhile(run_mode()){get_time(); //ボタンが押されているかどうかを確認if(buttonA.uniquePress()){switch_mode();戻る; } if(buttonB.uniquePress()){display_date();戻る; } //秒が変更された場合は、表示を更新しますif(rtc [0]!=old_secs){old_secs =rtc [0]; // ampmが1バイト時間に設定されている場合は12/24時間変換を実行=rtc [2]; if(hours> 12){hours =hours-ampm * 12; } if(hours <1){hours =hours + ampm * 12; } //すべての日付と時刻を個々の数字に分割します-digits_new配列に貼り付けます// rtc [0] =secs //配列の位置と格納された数字// digits_new [0] =(rtc [0]%10); // 0-秒のもの// digits_new [1] =((rtc [0] / 10)%10); // 1-秒数十// rtc [1] =mins Digits_new [0] =(rtc [1]%10); // 2-mins ones Digits_new [1] =((rtc [1] / 10)%10); // 3-分数十// rtc [2] =時間digits_new [2] =(時間%10); // 4-時間1の数字digits_new [3] =((hours / 10)%10); // 5-時間10 // rtc [4] =日付// digits_new [6] =(rtc [4]%10); // 6-日付のもの// digits_new [7] =((rtc [4] / 10)%10); // 7 --date tens //すべての文字の初期画面を描画します。この後、変更を描画します。 //数字0から3(分と時間)を(byte i =0; i <=3; i ++){//数字が変更されたかどうかを確認... if(digits_old [i]!=Digits_new [i]) {//それぞれに対して9ステップのアニメーションシーケンスを順番に実行しますfor(byte seq =0; seq <=8; seq ++){//数字を文字列に変換しますitoa(digits_old [i]、old_char、10); itoa(digits_new [i]、new_char、10); // 12時間モードに設定されていて、2桁目(10時間モード)の場合は、これがゼロかどうかを確認します。そうである場合は、代わりに空白にして、02.00pmではなく2.00pmを取得しますif(ampm &&i ==3){if(digits_new [3] ==0){new_char [0] =''; } if(digits_old [3] ==0){old_char [0] =''; }} //各桁のアニメーションフレームを描画しますslideanim(digits_x_pos [i]、0、seq、old_char [0]、new_char [0]); delay(SLIDE_DELAY); }}} / * //日付桁6(1)と(7)10を比較します-これらのいずれかが変更された場合は、日付変更線を更新する必要があります。 1月31日から2月1日までの日付10を比較すると、1桁は変化しませんif((digits_old [6]!=Digits_new [6])||(digits_old [7]!=Digits_new [7])){ //表示される日を変更します。以下のループは、3つの文字のそれぞれを順番に通過します。 "MON" for(byte day_char =0; day_char <=2; day_char ++){//各文字のアニメーションシーケンスを実行for(byte seq =0; seq <=8; seq ++){//日(0-6 )この数値をdayschar配列に読み込みます。配列0〜2の秒数は、曜日名の3文字を取得します。例: m o n slideanim(6 * day_char、8、seq、old_chars [day_char]、days [rtc [3]] [day_char]); // 6 x day_charは、char delay(SLIDE_DELAY);のx位置を示します。 } //古い日のcharsを配列pos0-2のold_chars配列に保存します。次回日を変更するときにこれを使用し、現在の文字としてアニメーションにフィードします。更新された文字は、新しい文字としてフィードされます。 old_chars [day_char] =days [rtc [3]] [day_char]; } //日付の10桁(必要な場合)と1桁を変更します。 (日付の1桁は常に変更されますが、これを 'if'ループに入れると、コードが少しきれいになります。)for(byte i =7; i> =6; i-){if(digits_old [i] !=Digits_new [i]){for(byte seq =0; seq <=8; seq ++){itoa(digits_old [i]、old_char、10); itoa(digits_new [i]、new_char、10); slideanim(digits_x_pos [i]、8、seq、old_char [0]、new_char [0]); delay(SLIDE_DELAY); }}} //日の接尾辞 "nd" "rd" "th"などを出力します。最初のワークアウトの日付2文字の接尾辞-たとえば、st、nd、rd、thバイトs =3; //接尾辞配列を読み取るpos。バイト日付=rtc [4]; if(date ==1 || date ==21 || date ==31){s =0; } else if(date ==2 || date ==22){s =1; } else if(date ==3 || date ==23){s =2; } for(byte Supplement_char =0; Supplement_char <=1; Supplement_char ++){for(byte seq =0; seq <=8; seq ++){slideanim((suffix_char * 6)+ 36,8、seq、old_chars [suffix_char + 3 ]、suffix [s] [suffix_char]); // old_char配列charを現在の文字として渡し、接尾辞配列を新しいchar delay(SLIDE_DELAY);として渡します。 } //配列pos3および5の古いchars配列に十分な文字を保存します。次に接尾辞を変更して現在の文字としてアニメーションにフィードするときに、これらの文字を使用します。更新された文字は、新しい文字としてフィードされます。 old_chars [suffix_char + 3] =サフィックス[s] [suffix_char]; }} // end do date line * ///比較のためにdigita配列をoldに保存します次のループfor(byte i =0; i <=3; i ++){digits_old [i] =Digits_new [i]; }} // secs / oldsecs} // while loopfead_down();} //スライドによって呼び出されます//これは1つの文字がスライドしてオンになり、もう1つの文字がスライドしてオフになるアニメーションを描画します。アニメーションには8つのステップがあり、0〜7のステップの1つを描画する関数を呼び出します。//入力はchar xとy、アニメーションフレームシーケンス(0〜7)、現在の文字と新しい文字が描画されます。void slideanim(byte x、byte y、byte sequence、char current_c、char new_c){// 1つの文字をスライドさせて別の文字をスライドさせるには、9つのステップまたはフレームを順番に並べる必要があります... // seq#0123456 <-表示の行// | ||||||| // seq0 0123456 START-ディスプレイ0〜6のすべての行に、現在の文字の行0〜6が表示されます// seq1012345現在の文字がディスプレイの1行下に移動します。 0〜5行目だけが表示されます。表示位置1〜6にあります上部に空白行が挿入されています// seq2 601234現在の文字が2行下に移動します。これで、ディスプレイの行2〜6に行0〜4のみが表示されます。表示の1行目は空白です。行0は新しい文字の行6を示します// seq3 56 0123 // seq4 456012半分古い/半分新しい文字// seq5 3456 01 // seq6 23456 0 // seq7 123456 // seq8 0123456END-すべての行は新しい文字を示しますchar //上から見ることができます... // currentcharは0-6、0-5、0-4の順に0まで実行されます。開始Y位置は毎回1行ずつ増加します。 //新しいcharは6、5-6、4-6、3-6の順に実行されます。開始Y位置は毎回1行ずつ増加します。 //シーケンス番号が7未満の場合、現在の文字を描画する必要がありますif(sequence <7){byte dot; // if(current_c> ='A' &&||(current_c> ='a' &¤t_c <='z')){// current_c&=0x1F; // A-Zは1-26にマップされます//} if(current_c> ='A' &¤t_c <='Z'){current_c&=0x1F; // A-Zは1-26にマップされます} else if(current_c> ='a' &¤t_c <='z'){current_c =(current_c-'a ')+ 41; // A-Zは41-67にマップされます} else if(current_c> ='0' &¤t_c <='9'){current_c =(current_c-'0 ')+ 31; } else if(current_c ==''){current_c =0; //スペース} else if(current_c =='。'){current_c =27; //終止符} else if(current_c =='\' '){current_c =28; //一重引用符} else if(current_c ==':'){current_c =29; //コロン} else if(current_c =='>'){current_c =30; // clock_modeセレクター矢印} byte curr_char_row_max =7-シーケンス; //描画する行の最大数は6-シーケンス番号bytestart_y =sequence; //開始するyの位置-はシーケンス番号と同じです。この各ループを組み込みます//各行を最大行(シーケンス番号から計算)までプロットしますfor(byte curr_char_row =0; curr_char_row <=curr_char_row_max; curr_char_row ++){for(byte col =0; col <5; col ++){ドット=pgm_read_byte_near(&myfont [current_c] [col]); if(dots&(64>> curr_char_row))plot(x + col、y + start_y、1); //プロットはelseで導かれますplot(x + col、y + start_y、0); //それ以外のプロットは} start_y ++; // yに1を追加して、次の行を1つ下に描画します}} //シーケンスが1〜7の場合、文字間に空白行を描画します。これを行わないと、次のようになります。現在の文字の残りは、ディスプレイに残っている最後の位置if(sequence> =1 &&sequence <=8){for(byte col =0; col <5; col ++){plot(x + col、y +(sequence- 1)、0); //線を引くyの位置はシーケンス番号-1に相当します}} //シーケンスが2を超える場合は、新しい文字の描画も開始する必要がありますif(sequence> =2){//文字バイトを計算しますドット; // if(new_c> ='A' &&new_c <='Z' ||(new_c> ='a' &&new_c <='z')){// new_c&=0x1F; // A-Zは1-26にマップされます//} if(new_c> ='A' &&new_c <='Z'){new_c&=0x1F; // A-Zは1-26にマップされます} else if(new_c> ='a' &&new_c <='z'){new_c =(new_c-'a ')+ 41; // A-Zは41-67にマップされます} else if(new_c> ='0' &&new_c <='9'){new_c =(new_c-'0 ')+ 31; } else if(new_c ==''){new_c =0; //スペース} else if(new_c =='。'){new_c =27; //終止符} else if(new_c =='\' '){new_c =28; //一重引用符} else if(new_c ==':'){new_c =29; // clock_modeセレクター矢印} else if(new_c =='>'){new_c =30; // clock_modeセレクター矢印} byte newcharrowmin =6-(シーケンス-2); //新しいchar用に描画する最小行番号-シーケンス番号2〜8を指定すると、6〜0の出力が生成されます。これは、新しい文字バイトstart_y =0に対して描画する最小行です。 //開始するyの位置-はシーケンス番号と同じです。各行を追加します//各行を行の最小値(シーケンス番号で計算)から最大6までプロットしますfor(byte newcharrow =newcharrowmin; newcharrow <=6; newcharrow ++){for(byte col =0; col <5; col ++ ){ドット=pgm_read_byte_near(&myfont [new_c] [col]); if(dots&(64>> newcharrow))plot(x + col、y + start_y、1); //プロットはelseで導かれますplot(x + col、y + start_y、0); //それ以外のプロットは} start_y ++; // yに1を追加して、次の行を1つ下に描画します}}} //数字ではなく単語を使用して時計を出力しますvoidword_clock(){cls();文字数[19] [10] ={"1"、 "2"、 "3"、 "4"、 "5"、 "6"、 "7"、 "8"、 "9"、 "10"、 「11」、「12」、「13」、「14」、「15」、「16」、「17」、「18」、「19」}; char numberstenstens [5] [7] ={"ten"、 "twenty"、 "30"、 "40"、 "fifty"}; //文字を表示する可能性のある3行str_a [8]; char str_b [8]; char str_c [8]; // byte hours_y、mins_y; //時間と分と時間と分の行の位置bytehours =rtc [2]; if(hours> 12){hours =hours-ampm * 12; } if(hours <1){hours =hours + ampm * 12; } 時間をもらう(); //クロックチップから時刻を取得しますbyteold_mins =100; //分をold_minsに保存します。分と古い分を比較し、それらが異なる場合は表示を再描画します。最初はこれを100に設定して、モードの開始時に表示が描画されるようにします。バイト分; // run_modeがtrueを返す限り、クロックのメインループを実行しますwhile(run_mode()){//ボタンが押されているかどうかを確認しますif(buttonA.uniquePress()){switch_mode();戻る; } if(buttonB.uniquePress()){display_date(); } 時間をもらう(); //クロックチップから時間を取得しますmins =rtc [1]; // minsを取得します// minsがold_minsと異なる場合-表示を再描画しますif(mins!=old_mins){// old_minsを現在のmins値で更新しますold_mins =mins; //次回の比較のためにこれらをリセットしますmins =rtc [1];時間=rtc [2]; //時間を12時間形式にするif(hours> 12){hours =hours-12; } if(hours ==0){hours =12; } //最小値を2桁に分割intminsdigit =rtc [1]%10;バイトminsdigitten =(rtc [1] / 10)%10; // mins <=10の場合、一番上の行は「minsdigti past」を読み取る必要があり、一番下の行は時間を読み取る必要がありますif(mins <10){strcpy(str_a、numbers [minsdigit-1]); strcpy(str_b、 "PAST"); strcpy(str_c、numbers [hours-1]); } // mins =10の場合、上記のようにminsdigitを使用できないため、/ n時間を過ぎて10を印刷するソーシャルケース。 if(mins ==10){strcpy(str_a、numbers [9]); strcpy(str_b、 "PAST"); strcpy(str_c、numbers [hours-1]); } //時間が時間にない場合-つまり、両方の分桁がゼロでない場合、//最初の行に「時間」を読み取り、2行目と3行目に「分」「分」を読み取ります。例: "three / n 20 / n one" else if(minsdigitten!=0 &&minsdigit!=0){strcpy(str_a、numbers [hours-1]); // minsが10代の場合は、2行目のnumbers配列の10代を使用します。例: "fifteen" // if(mins> =11 &&mins <=19){if(mins <=19){strcpy(str_b、numbers [mins-1]); } else {strcpy(str_b、numberstens [minsdigitten-1]); strcpy(str_c、numbers [minsdigit-1]); }} // mins桁がゼロの場合、それを印刷しないでください。読む「時間」「分」を読む例: "three / n 20" else if(minsdigitten!=0 &&minsdigit ==0){strcpy(str_a、numbers [hours-1]); strcpy(str_b、numberstens [minsdigitten-1]); strcpy(str_c、 ""); } //両方の分がゼロの場合、つまり時間にある場合、上の行は「時間」を示し、下の行は「時」を示します。それ以外の場合、if(minsdigitten ==0 &&minsdigit ==0){strcpy(str_a、数値[時間-1]); strcpy(str_b、 "O'CLOCK"); strcpy(str_c、 ""); }} //ワークアウト時間を終了//ループで実行//行を「12」バイトで印刷len =0; while(str_a [len]){len ++; }; //メッセージの長さを取得バイトoffset_top =(31-((len-1)* 4))/ 2; ////時間のプロット行バイトi =0; while(str_a [i]){puttinychar((i * 4)+ offset_top、1、str_a [i]); i ++; } //表示を保持しますが、ボタンが押されているかどうかを確認しますint counter =1000; while(counter> 0){//ボタンが押されているかどうかを確認if(buttonA.uniquePress()){switch_mode();戻る; } if(buttonB.uniquePress()){display_date(); } delay(1);カウンター -; }およびfade_down(); //行bを印刷しますlen =0; while(str_b [len]){len ++; }; //メッセージの長さを取得offset_top =(31-((len --1)* 4))/ 2; i =0; while(str_b [i]){puttinychar((i * 4)+ offset_top、1、str_b [i]); i ++; } //表示を保持しますが、ボタンが押されているかどうかを確認しますcounter =1000; while(counter> 0){if(buttonA.uniquePress()){switch_mode();戻る; } if(buttonB.uniquePress()){display_date(); } delay(1);カウンター -; }およびfade_down(); //行cがある場合はそれを出力します。 len =0; while(str_c [len]){len ++; }; //メッセージの長さを取得offset_top =(31-((len --1)* 4))/ 2; i =0; while(str_c [i]){puttinychar((i * 4)+ offset_top、1、str_c [i]); i ++; }カウンター=1000; while(counter> 0){//ボタンが押されているかどうかを確認if(buttonA.uniquePress()){switch_mode();戻る; } if(buttonB.uniquePress()){display_date(); } delay(1);カウンター -; }およびfade_down(); //ディスプレイを空白のままにしますが、ボタンが押されているかどうかを確認してから再開します。カウンター=1000; while(counter> 0){//ボタンが押されているかどうかを確認if(buttonA.uniquePress()){switch_mode();戻る; } if(buttonB.uniquePress()){display_date(); } delay(1);カウンター -; }}およびfade_down();} ///スクロールメッセージ-現在は使用されていません-遅すぎます。voidscroll(){char message [] ={"Hello There"}; cls();バイトp =6; //文字列バイトの現在の位置chara [] ={0、1、2、3、4、5}; //文字列からの文字intx [] ={0、6、12、18、24、30}; //各charバイトのxposy =0; // y pos // clear_buffer(); while(message [p]!='\ 0'){//(byte c =0; c <6; c ++){putnormalchar(x [c]、y、message [chara [c]]の6文字すべてを描画します); //各文字の後にオフにされたピクセルの線を描画します。そうでない場合、文字間のギャップには、前の文字からのピクセルが残ります(byte yy =0; yy <8; yy ++){plot(x [c] + 5、yy、0); } //各文字の位置を1つ削除しますx [c] =x [c] -1; } //(byte i =0; i <=5; i ++){if(x [i] <-5){x [i] =31; chara [i] =p; p ++; }}}} // display_date-カーソルを点滅させて曜日、日付、月を出力しますeffectvoid display_date(){cls(); // DS1307バイトから日付を読み取りますdow =rtc [3]; //曜日0 =日曜日バイト日付=rtc [4];バイト月=rtc [5] -1; //ディスプレイに印刷する月の名前の配列。 char monthnames [12] [9] ={"January"、 "February"、 "March"、 "April"、 "May"、 "June"、 "July"で遊ぶには8文字しかないため、一部が短縮されています。 、 "8月"、 "9月"、 "10月"、 "11月"、 "12月"}; //日の名前を出力します//テキストの長さをピクセル単位で取得します。これにより、残りのピクセルb2を分割し、それをオフセットバイトとして使用してディスプレイの中央に配置できますlen =0; while(daysfull [dow] [len]){len ++; };バイトオフセット=(31-((len-1)* 4))/ 2; //テキストを中央に配置するためのオフセット//名前を出力しますinti =0; while(daysfull [dow] [i]){puttinychar((i * 4)+ offset、1、daysfull [dow] [i]); i ++; } delay(1000);およびfade_down(); cls(); //日付の数字を出力しますcharbuffer [3]; itoa(date、buffer、10);オフセット=10; // 3文字の場合、テキストを中央にオフセットします-例: 3番目//最初のワークアウト日付2文字の接尾辞-例:st、nd、rd、thなど// char接尾辞[4] [3] ={"st"、 "nd"、 "rd"、 "th"};コードバイトの先頭で定義されますs =3; if(date ==1 || date ==21 || date ==31){s =0; } else if(date ==2 || date ==22){s =1; } else if(date ==3 || date ==23){s =2; } //最初の日付番号を出力しますputtinychar(0 + offset、1、buffer [0]); //日付が10未満の場合、1桁しかないため、接尾辞などの位置を1文字近いバイトsuffixposx =4に設定します。 //日付が9を超える場合は、2番目の数値を出力し、接尾辞のxposを1文字離して設定しますif(date> 9){suffixposx =8; puttinychar(4 + offset、1、buffer [1]);オフセット=8; // 4文字の場合はテキストを中央にオフセットします} // 2つのサフィックス文字を出力しますputtinychar(suffixposx + offset、1、suffix [s] [0]); puttinychar(suffixposx + 4 + offset、1、suffix [s] [1]); delay(1000);およびfade_down(); //月の名前を出力します//テキストの長さをピクセル単位で取得します。そうすれば、残りのピクセルb2を分割し、それをオフセットとして使用して、ディスプレイの中央に配置できますlen =0; while(monthnames [month] [len]){len ++; };オフセット=(31-((len-1)* 4))/ 2; //テキストを中央に配置するためのオフセットi =0; while(monthnames [month] [i]){puttinychar((i * 4)+ offset、1、monthnames [month] [i]); i ++; } delay(1000);クロックモードを変更するfade_down();} // dislpayメニューvoidswitch_mode(){//現在のモードを記憶します。設定モードに入るときにこの値を使用するため、設定モード(6)から任意のモードに戻すことができます。私たちがいたモード。old_mode=clock_mode; char * mode [] ={"Basic"、 "Small"、 "Slide"、 "Words"、 "Setup"};バイトnext_clock_mode;バイトfirstrun =1; //ボタンを待機しているループ(モードXに戻るための35ループ後のタイムアウト)for(int count =0; count <35; count ++){//ユーザーがボタンを押した場合、clock_modeを変更しますif(buttonA.uniquePress()|| firstrun ==1){カウント=0; cls(); if(firstrun ==0){clock_mode ++; } if(clock_mode> NUM_DISPLAY_MODES + 1){clock_mode =0; } // 1行目にarrownと現在のclock_mode名を出力し、2行目に次のclock_mode名を出力しますchar str_top [9]; // strcpy(str_top、 "-"); strcpy(str_top、modes [clock_mode]); next_clock_mode =clock_mode + 1; if(next_clock_mode> NUM_DISPLAY_MODES + 1){next_clock_mode =0; }バイトi =0; while(str_top [i]){putnormalchar(i * 6、0、str_top [i]); i ++; } firstrun =0; } delay(50); }} // run_modeがtruebyteを返す限り、クロックのメインループを実行しますrun_mode(){//ランダムモードがオンの場合...モードを変更する時間を確認します。 if(random_mode){//変更モードの時間値の場合time =hours。次に、false =つまり、モードを終了します。 if(change_mode_time ==rtc [2]){//次のランダムクロックモードとそれを変更する時刻を設定しますset_next_random(); //現在のモードを終了します。 0を返します。 }} // else return1-このモードで実行を続けるreturn1;} //ランダムモードがオンのときに時計がモードを変更する次の時間を設定するvoidset_next_random(){//時計モードが変更される次の時間を設定する--current時間プラス1〜4時間get_time(); change_mode_time =rtc [2] +ランダム(1、5); // change_mode_timeが23を超えている場合は、午前1時から午前3時の間に設定しますif(change_mode_time> 23){change_mode_time =random(1、4); } //新しいクロックモードを設定しますclock_mode =random(0、NUM_DISPLAY_MODES + 1); //新しいランダムクロックモードを選択} // dislpayメニューでクロック設定を変更voidsetup_menu(){char * set_modes [] ={"Rndom"、 "24 Hr"、 "Set"、 "Brght"、 "Exit"}; if(ampm ==0){set_modes [1] =( "12 Hr"); }バイトsetting_mode =0;バイトnext_setting_mode;バイトfirstrun =1; //ボタンを待機しているループ(モードXに戻るための35ループ後のタイムアウト)for(int count =0; count <35; count ++){//ユーザーがボタンを押した場合は、clock_modeを変更しますif(buttonA.uniquePress()|| firstrun ==1){count =0; cls(); if(firstrun ==0){setting_mode ++; } if(setting_mode> NUM_SETTINGS_MODES){setting_mode =0; } // 1行目にarrownと現在のclock_mode名を出力し、2行目に次のclock_mode名を出力しますchar str_top [9]; strcpy(str_top、set_modes [setting_mode]); next_setting_mode =settings_mode + 1; if(next_setting_mode> NUM_SETTINGS_MODES){next_setting_mode =0; }バイトi =0; while(str_top [i]){putnormalchar(i * 6、0、str_top [i]); i ++; } firstrun =0; } delay(50); } //モードスイッチを選択します(setting_mode){case 0:set_random();壊す;ケース1:set_ampm();壊す;ケース2:set_time();壊す;ケース3:set_intensity();壊す;ケース4://メニューブレークを終了します。 } //change the clock from mode 6 (settings) back to the one it was in before clock_mode=old_mode;}//toggle random mode - pick a different clock mode every few hoursvoid set_random(){ cls(); char text_a[9] ="Off"; char text_b[9] ="On"; byte i =0; //if random mode is on, turn it off if (random_mode){ //turn random mode off random_mode =0; //print a message on the display while(text_a[i]) { putnormalchar((i*6), 0, text_a[i]); i ++; } } else { //turn randome mode on. random_mode =1; //set hour mode will change set_next_random(); //print a message on the display while(text_b[i]) { putnormalchar((i*6), 0, text_b[i]); i ++; } } delay(1500); //leave the message up for a second or so}//set 12 or 24 hour clockvoid set_ampm() { // AM/PM or 24 hour clock mode - flip the bit (makes 0 into 1, or 1 into 0 for ampm mode) ampm =(ampm ^ 1); cls();}//change screen intensityintensityvoid set_intensity() { cls(); byte i =0; char text[7] ="Bright"; while(text[i]) { puttinychar((i*4)+4, 0, text[i]); i ++; } //wait for button input while (!buttonA.uniquePress()) { levelbar (0,6,(intensity*2)+2,2); //display the intensity level as a bar while (buttonB.isPressed()) { if(intensity ==15) { intensity =0; cls (); } else { intensity++; } //print the new value i =0; while(text[i]) { puttinychar((i*4)+4, 0, text[i]); i ++; } //display the intensity level as a bar levelbar (0,6,(intensity*2)+2,2); //change the brightness setting on the displays for (byte address =0; address <4; address++) { lc.setIntensity(address, intensity); } delay(150); } }}// display a horizontal bar on the screen at offset xposr by ypos with height and width of xbar, ybarvoid levelbar (byte xpos, byte ypos, byte xbar, byte ybar) { for (byte x =0; x  
LibrariesArduino
プレビューなし(ダウンロードのみ)。

回路図


製造プロセス

  1. LEDシーケンサー
  2. 鳩時計
  3. MATLAB - 行列
  4. ミニボスバトル
  5. マスタークロック
  6. ベルリン時計
  7. アナログスタイルのLEDPOVクロック
  8. LEDマトリックス+モーションセンサードアディスプレイ[ArduinoHoliday]
  9. 音による8倍のLED照明
  10. Arduino Quadruped
  11. ホットグルーLEDマトリックスランプ