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

7セグメントアレイクロック

コンポーネントと消耗品

>
SparkFun Arduino Pro Mini 328-5V / 16MHz
× 1
リアルタイムクロック(RTC)
「Arduino用DS1302リアルタイムクロックモジュール」を購入し、ICソケットとクリスタルのはんだ付けを解除します。
× 1
CR1220バッテリーとホルダー
「5pcs、Black Housing CR1220 CR1225 Button Cell Battery Socket HolderBS-1220-1」を検索
× 1
コンデンサ0.1uf1206 SMD
× 1
コンデンサ10uF1206SMDセラミック
× 1
触覚スイッチ、上部作動
ボタントップ付きの12mmバリアント
× 4
3AミニDC-DC降圧コンバータモジュール
× 1
0.28in Common Cathode 4 Digit 7 Segment Display
× 36
MAX7219 DIP IC
× 18
ブザー
× 1
マシンヘッダー
男性と女性の両方のヘッダーが必要です。通常は40のストリップで提供されるため、男性のストリップは8つになります。機械加工されたピンとメスの機械加工されたソケットの8つのストリップ
× 1
DC電源ソケット
「12VDC電源ジャックソケットメスパネルマウントコネクタ5.5 x2.ODZ2」を検索
× 1

必要なツールとマシン

>
はんだごて(汎用)
3Dプリンター(汎用)

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

>
Arduino IDE

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

Hackaday.ioを閲覧しているときに、Frughaによる7セグメントディスプレイの配列で作られた美しい時計に出くわしました。本当に作りたかったのですが、0.56 "7セグメントディスプレイを使用しているため、Frughaのバージョンはかなり大きいです。私のデザインでは0.28" 7セグメントディスプレイを使用しているため、サイズは4分の1にすぎません。

ソフトウェアは、目覚まし時計と、時刻、日付、アラームを設定するための設定画面を組み込むように書き直されました。

ビデオ

設定画面

時計は4つのボタンで制御されます。 SELECTボタン(一番上)に設定画面が表示されます。現在の選択が点滅します。 SELECTボタンをもう一度押すと、さまざまな構成セクション(つまり、時刻、日付、アラーム、調整、明るさ、日付形式、時計)が順番に表示されます。

<図>

メニュー項目の1つを選択した状態でENTERボタン(上から2番目)を押すと、設定を変更できます。メニュー項目に複数の設定がある場合、ENTERボタンがそれらの間を循環します。アクティブな設定が点滅します。

設定が点滅しているときは、上ボタンと下ボタン(下の2つのボタン)で設定が変更されます。

日付画面

時計が表示されているときにENTERボタン(上から2番目)を押すと、日付画面が5秒間表示されます。

<図>

構成画面の[日付形式]セクションでは、使用する日付形式(DD-MMまたはMM-DD)とフォントを設定できます。

<図>

設計上の考慮事項

ボードのデザインを簡単にするために、私のバージョンでは、元のバージョンで使用されていた1桁のディスプレイではなく、4桁のディスプレイを使用しています。 0.28インチのディスプレイは小さいため、MAX7219チップを別のボードに配置する必要がありました。簡単に配線するには、機械加工されたオスとメスのピンヘッダーを使用してボードを接続します。

ボードを商業的に作成したい場合、または私が行ったように自分で作成したい場合に備えて、Eagleファイルが含まれています。私はトナー法を使って私のものを作りました。

コラムボード

すべてのディスプレイを保持する6つのカラムボードを作成する必要があります。オスのマシンヘッダーをはんだ付けするときは、真ん中のセットから始めて、外側の端に向かって作業します。ピンを簡単にはんだ付けできるように、マッチ棒などを使用してソケットを十分に持ち上げます。先端が細い小さなはんだごてと0.5mmのはんだを使用してください。

<図>

カラムモジュールを作成したら、ディスプレイの境界線をマットブラックペイントでペイントすることをお勧めします。これにより、ディスプレイが隣接するディスプレイと完全に位置合わせされていない場合に、白いエッジが表示されなくなります。また、マーカーペンを使用して、各列モジュールに番号を付けます。これは、MAX7219マザーボードに挿入するときに役立ちます。

<図>

MAX7219マザーボード

マザーボードとカラムボードを設計するときに、正しいMAX7219セグメントまたは数字を対応するディスプレイピンにマップしませんでした。 PCBレイアウトをできるだけシンプルに保ち、ソフトウェアの違いに合わせて調整したかったのです。

<図>

メスの機械加工されたソケットに関しては、最初に支柱ボードのオスのピンに配置し、次にそれらが接続されている間にアセンブリを所定の位置にはんだ付けすることをお勧めします。これは、カラムピンが対応するソケットと正確に整列することを意味します。それらを削除する必要がある場合は、列モジュールに番号を付けると、同じ位置に戻ることが保証されます。

MPUボード

マイクロプロセッサボードには、他のすべてのコンポーネントが含まれています。 4つのボタンと2つのSMDコンデンサはボードの背面に取り付けられ、他のすべてのコンポーネントはボードの前面に取り付けられています。ロープロファイルを維持するために、通常Arduino ProMiniにはんだ付けされているFTDIピンヘッダーがPCBに直接はんだ付けされるようになりました。 2本のワイヤがDTRピンとVCCピンからPCBに直接接続されています。

<図>

ケースを作る

前面と背面のSTLファイルが含まれています。両方とも、0.2層の高さとつばを使用して印刷されました。フロントには、ビルドプレートのみに接触するサポートも有効になっています。

カラムモジュールを備えたMAX7219マザーボードは、前面からスライドインします。少し緩んでいる場合は、マスキングテープを1〜2層詰めてください。

<図>

MPUボードは背面に熱接着されています。

<図>

ソフトウェア

このソフトウェアでは、MD_MAX72XXライブラリがArduinoIDEにインストールされている必要があります。テスト用にHardware_Test_V1スケッチを提供しました。すべてのセグメントが点灯するので、短絡や配線の断線をチェックできます。表示が機能したら、Clock_V4スケッチをアップロードします。

コード

  • Clock_V4.ino
  • Digits.h
  • Tunes.h
  • Button.h
  • Button.cpp
  • Hardware_Test_V1.zip
Clock_V4.ino C / C ++
 / * ------------------------------------------------- ------ * 7セグメントアレイクロック** Frugha(https://hackaday.io/project/169632-7-segment-display-array-clock)によるクロックに基づく* * John Bradnam(jbrad2089 @)による変更gmail.com)* --0.28 "7セグメントディスプレイを使用するようにハードウェアを変更しました。*-MAX7219デバイス、桁、およびセグメントの順序を、単純に*複雑なPCBボードルーティングに変更しました。*-ハードウェアはArduino Mini Pro、DS1302 RTC、および4を使用します。プッシュボタン*-選択可能なアラームusicを備えたアラーム機能を追加*-明るさ設定を追加*-時刻、日付、アラーム、音楽、明るさを設定するセットアップ画面を追加*-日付画面を追加(ENTERボタンを押すと2秒間表示される* 2020を更新-06-16 *-構成画面に日付形式オプションを追加しました*-日付画面のタイムアウトを2秒から5秒に増やしました*-日付表示用の構成可能なフォントの選択を追加しました* -------------- ------------------------------------ * / #include  #include  #include  #include  #include  #include "button.h" #include "Tunes.h" #include "Digits.h" #define HARDWARE_TYPE MD_MAX72XX ::GENERIC_HW#define MAX_DEVICES 18#define LED_CLK 13 //またはSCK(WHI)#define LED_DATA 11 //またはMOSI(BRN)#define LED_CS 10 //またはSS(YEL)#define SPEAKER 2#define SW_UP 3#define SW_DOWN 4#define RTC_CLK 5#define RTC_IO 6#define SW_ENTER 7#define RTC_CE 8#define SW_SELECT 9DS1302RTC rtc(RTC_CE、RTC_IO、RTC_CLK); // SPIハードウェアインターフェイスMD_MAX72XXmx =MD_MAX72XX(HARDWARE_TYPE、LED_CS、MAX_DEVICES); //任意のピン// MD_MAX72XX 、LED_DATA、LED_CLK、LED_CS、MAX_DEVICES); // EEPROM処理#defineEEPROM_ADDRESS 0#define EEPROM_MAGIC 0x0BAD0DADtypedef struct {uint32_t magic;ブールアラーム; uint8_t分; uint8_t時間; bool format12hr; uint8_t明るさ; uint8_t tune; bool formatDmy; bool squareFont;} EEPROM_DATA; EEPROM_DATA EepromData; //現在のEEPROM設定voidclockButtonPressed(void); void enterButtonPressed(void); void downButtonPressed(void); void upButtonPressed(void); Button * clockButton; Button * enterButton; Button * downButton; Button * upButton; //動作モードboolinSubMenu =false; #define SETUP_FLASH_RATE 200; unsigned long setupTimeout; bool setupDisplayState =false; enum ClockButtonModesEnum {CLOCK、TIME_SET、DATE_SET、ALARM_SET、TUNE_SET、BRIGHT_SET、FORMAT_SET}; ClockButtonModesEnum clockMode =CLOCK; enum TimeSetMenuEnum {TIME_H timeSetMode =TIME_HOUR; enum DateSetMenuEnum {DATE_YEAR、DATE_MONTH、DATE_DAY}; DateSetMenuEnum dateSetMode =DATE_YEAR; enum AlarmSetMenuEnum {ALARM_HOUR、ALARM_MIN、ALARM_STATE}; -1; bool alarmRinging =false; //アラームがオンブールの場合はtruealarmCancelled =false; // userboolによってキャンセルされたアラームmusicPlaying =false; // songboolを再生する場合はtrueclockColon =false; // colonint8_tを表示/非表示dom [] ={31,28,31,30,31,30,31,31,30,31,30,31}; tmElements_t newTime; //新しいtimevoidsetup(){Serial.begin(115200);を保存するために使用されます// Eprom readEepromData(); //ボタンを初期化しますclockButton =new Button(SW_SELECT); enterButton =new Button(SW_ENTER); downButton =new Button(SW_DOWN); downButton-> Repeat(downButtonPressed); upButton =new Button(SW_UP); upButton-> Repeat(upButtonPressed); //サウンドを初期化しますpinMode(SPEAKER、OUTPUT); mx.begin(); mx.control(MD_MAX72XX ::INTENSITY、EepromData.brightness); //0..MAX_INTENSITY mx.update(MD_MAX72XX ::OFF); //自動更新なしsetSyncProvider(rtc.get); // RTCから時刻を取得する関数if(timeStatus()!=timeSet){Serial.println( "RTC Sync Bad"); newTime.Year =CalendarYrToTm(2020); newTime.Month =5; newTime.Day =30; newTime.Hour =14; newTime.Minute =53; newTime.Second =0; time_t t =makeTime(newTime); setTime(t); rtc.set(t); if(rtc.set(t)!=0){Serial.println( "Set Time Failed"); }} newTime.Year =CalendarYrToTm(year()); newTime.Month =month(); newTime.Day =day(); newTime.Hour =hour(); newTime.Minute =minutes(); newTime.Second =second(); Serial.println( "Time:" + String(newTime.Hour)+ ":" + String(newTime.Minute)+ ":" + String(newTime.Second)); Serial.println( "日付:" + String(newTime.Day)+ "/" + String(newTime.Month)+ "/" + String(tmYearToCalendar(newTime.Year))); clockMode =CLOCK; showTime(true);} void loop(){testButtons(); if(clockMode ==CLOCK){showTime(false); if(EepromData.alarm &&EepromData.hours ==hour()&&EepromData.minutes ==minutes()){if(!alarmCancelled){alarmRinging =true; playSong(melodies [EepromData.tune]); }} else {alarmCancelled =false; alarmRinging =false; }} else {showSetup(false); } delay(100);} // --------------------------------------------- ---------------------- //ボタンが押されているかどうかをテストしますvoidtestButtons(){//ボタンを1回押すif(clockButton-> Pressed()){ clockButtonPressed(); } if(enterButton-> Pressed()){enterButtonPressed(); } //ボタンハンドラーは繰り返し関数upButton-> Pressed();を呼び出すため、押された結果を確認する必要はありません。 downButton-> Pressed();} // ---------------------------------------- ----------------------- //ハンドルCLOCKbttonvoid clockButtonPressed(){if(cancelAlarm())return; inSubMenu =false; clockMode =(clockMode ==FORMAT_SET)? CLOCK:(ClockButtonModesEnum)((int)clockMode + 1); if(clockMode ==CLOCK){Serial.println( "Saving Time:" + String(newTime.Hour)+ ":" + String(newTime.Minute)); Serial.println( "From:" + String(hour())+ ":" + String(minute())); if(newTime.Year!=CalendarYrToTm(year())|| newTime.Month!=month()|| newTime.Day!=day()|| newTime.Hour!=hour()|| newTime.Minute!=minutes()){//更新時刻Serial.println( "Updating RTC"); newTime.Second =second(); time_t t =makeTime(newTime); setTime(t); rtc.set(t); if(rtc.set(t)!=0){Serial.println( "Set Time Failed"); }} writeEepromData(); showTime(true); } else {if(clockMode ==TIME_SET){newTime.Year =CalendarYrToTm(year()); newTime.Month =month(); newTime.Day =day(); newTime.Hour =hour(); newTime.Minute =minutes(); newTime.Second =second(); Serial.println( "読み込み時間:" + String(hour())+ ":" + String(minute())); } showSetup(true); }} // ---------------------------------------------- ----------------- // ENTER bttonvoid enterButtonPressed(){if(cancelAlarm())return;を処理します。 if(clockMode!=CLOCK){if(!inSubMenu){timeSetMode =TIME_HOUR; dateSetMode =DATE_YEAR; alarmSetMode =ALARM_HOUR; formatSetMode =DAY_MONTH; inSubMenu =true; } else {スイッチ(clockMode){case TIME_SET:timeSetMode =(timeSetMode ==TIME_FORMAT)? TIME_HOUR:(TimeSetMenuEnum)((int)timeSetMode + 1);壊す;ケースDATE_SET:dateSetMode =(dateSetMode ==DATE_DAY)? DATE_YEAR:(DateSetMenuEnum)((int)dateSetMode + 1);壊す;ケースALARM_SET:alarmSetMode =(alarmSetMode ==ALARM_STATE)? ALARM_HOUR:(AlarmSetMenuEnum)((int)alarmSetMode + 1);壊す;ケースFORMAT_SET:formatSetMode =(formatSetMode ==FONT_STYLE)? DAY_MONTH:(FormatSetMenuEnum)((int)formatSetMode + 1);壊す; }} showSetup(true); } else {showDate(day()、month()、year()); delay(5000); }} // ---------------------------------------------- ----------------- //ハンドルDOWNbttonvoid downButtonPressed(){if(cancelAlarm())return; switch(clockMode){case TIME_SET:if(inSubMenu){switch(timeSetMode){case TIME_HOUR:newTime.Hour =(newTime.Hour + 24-1)%24;壊す;ケースTIME_MIN:newTime.Minute =(newTime.Minute + 60-1)%60;壊す;ケースTIME_FORMAT:EepromData.format12hr =!EepromData.format12hr;壊す; } showSetup(true); } 壊す; case DATE_SET:if(inSubMenu){switch(dateSetMode){case DATE_YEAR:newTime.Year =((newTime.Year-30 + 100)-1)%100 + 30;壊す;ケースDATE_MONTH:newTime.Month =((newTime.Month-1 + 12)-1)%12 + 1;壊す;ケースDATE_DAY:uint8_t md =daysInMonth(newTime.Year、newTime.Month); newTime.Day =((newTime.Day-1 + md)-1)%md + 1;壊す; } showSetup(true); } 壊す; case ALARM_SET:if(inSubMenu){switch(alarmSetMode){case ALARM_HOUR:EepromData.hours =(EepromData.hours + 24-1)%24;壊す;ケースALARM_MIN:EepromData.minutes =(EepromData.minutes + 60-1)%60;壊す;ケースALARM_STATE:EepromData.alarm =!EepromData.alarm;壊す; } showSetup(true); } 壊す;ケースTUNE_SET:EepromData.tune =(EepromData.tune + NUM_OF_MELODIES-1)%NUM_OF_MELODIES; showSetup(true);壊す;ケースBRIGHT_SET:EepromData.brightness =(EepromData.brightness + MAX_INTENSITY-1)%MAX_INTENSITY; mx.control(MD_MAX72XX ::INTENSITY、EepromData.brightness); //0..MAX_INTENSITY showSetup(true);壊す; case FORMAT_SET:if(inSubMenu){switch(formatSetMode){case DAY_MONTH:EepromData.formatDmy =!EepromData.formatDmy;壊す;ケースFONT_STYLE:EepromData.squareFont =!EepromData.squareFont;壊す; }} showSetup(true);壊す; }} // ---------------------------------------------- ----------------- // UP bttonvoid upButtonPressed(){if(cancelAlarm())return;を処理します。 switch(clockMode){case TIME_SET:if(inSubMenu){switch(timeSetMode){case TIME_HOUR:newTime.Hour =(newTime.Hour + 1)%24;壊す;ケースTIME_MIN:newTime.Minute =(newTime.Minute + 1)%60;壊す;ケースTIME_FORMAT:EepromData.format12hr =!EepromData.format12hr;壊す; } showSetup(true); } 壊す; case DATE_SET:if(inSubMenu){switch(dateSetMode){case DATE_YEAR:newTime.Year =((newTime.Year-30)+ 1)%100 + 30;壊す;ケースDATE_MONTH:newTime.Month =((newTime.Month-1)+ 1)%12 + 1;壊す;ケースDATE_DAY:uint8_t md =daysInMonth(newTime.Year、newTime.Month); newTime.Day =(newTime.Day%md)+ 1;壊す; } showSetup(true); } 壊す; case ALARM_SET:if(inSubMenu){switch(alarmSetMode){case ALARM_HOUR:EepromData.hours =(EepromData.hours + 1)%24;壊す;ケースALARM_MIN:EepromData.minutes =(EepromData.minutes + 1)%60;壊す;ケースALARM_STATE:EepromData.alarm =!EepromData.alarm;壊す; } showSetup(true); } 壊す;ケースTUNE_SET:EepromData.tune =(EepromData.tune + 1)%NUM_OF_MELODIES; showSetup(true);壊す;ケースBRIGHT_SET:EepromData.brightness =(EepromData.brightness + 1)%MAX_INTENSITY; mx.control(MD_MAX72XX ::INTENSITY、EepromData.brightness); //0..MAX_INTENSITY showSetup(true);壊す; case FORMAT_SET:if(inSubMenu){switch(formatSetMode){case DAY_MONTH:EepromData.formatDmy =!EepromData.formatDmy;壊す;ケースFONT_STYLE:EepromData.squareFont =!EepromData.squareFont;壊す; }} showSetup(true);壊す; }} // ---------------------------------------------- ----------------- // tuneboolを再生している場合はアラームをオフにしますcancelAlarm(){if(musicPlaying){musicPlaying =false; alarmCancelled =alarmRinging; trueを返します。 } 収率(); falseを返します;} // -------------------------------------------- ------------------- //セットアップメニューを表示し、選択した現在の項目をフラッシュしますvoid showSetup(bool force){setupDisplayState =setupDisplayState |力;力=力|| (millis()> setupTimeout); if(force){setupTimeout =millis()+ SETUP_FLASH_RATE; bool on =setupDisplayState; setupDisplayState =!setupDisplayState; mx.clear(); if(on ||!(clockMode ==TIME_SET &&!inSubMenu))displayString(0,7、 "TINE"); if(on ||!(clockMode ==TIME_SET &&inSubMenu &&timeSetMode ==TIME_HOUR))displayNumber(0,13、newTime.Hour、2、true); if(on ||!(clockMode ==TIME_SET &&inSubMenu &&timeSetMode ==TIME_MIN))displayNumber(0,16、newTime.Minute、2、true); if(on ||!(clockMode ==TIME_SET &&inSubMenu &&timeSetMode ==TIME_FORMAT))displayString(0,19、(EepromData.format12hr)? "12HR": "24HR"); if(on ||!(clockMode ==DATE_SET &&!inSubMenu))displayString(1,7、 "DATE"); if(on ||!(clockMode ==DATE_SET &&inSubMenu &&dateSetMode ==DATE_YEAR))displayNumber(1,13、tmYearToCalendar(newTime.Year)、4、true); if(on ||!(clockMode ==DATE_SET &&inSubMenu &&dateSetMode ==DATE_MONTH))displayNumber(1,18、newTime.Month、2、true); if(on ||!(clockMode ==DATE_SET &&inSubMenu &&dateSetMode ==DATE_DAY))displayNumber(1,21、newTime.Day、2、true); if(on ||!(clockMode ==ALARM_SET &&!inSubMenu))displayString(2,6、 "ALARN"); if(on ||!(clockMode ==ALARM_SET &&inSubMenu &&alarmSetMode ==ALARM_HOUR))displayNumber(2,13、EepromData.hours、2、true); if(on ||!(clockMode ==ALARM_SET &&inSubMenu &&alarmSetMode ==ALARM_MIN))displayNumber(2,16、EepromData.minutes、2、true); if(on ||!(clockMode ==ALARM_SET &&inSubMenu &&alarmSetMode ==ALARM_STATE))displayString(2,19、(EepromData.alarm)? "ON": "OFF"); if(on ||!(clockMode ==TUNE_SET &&!inSubMenu))displayString(3,7、 "TUNE"); if(on ||!(clockMode ==TUNE_SET &&inSubMenu)){switch(EepromData.tune){case 0:displayString(3,13、 "ELISE");壊す;ケース1:displayString(3,13、 "RANGE");壊す;ケース2:displayString(3,13、 "SUNSHINE");壊す; }} if(on ||!(clockMode ==BRIGHT_SET &&!inSubMenu))displayString(4,1、 "BRIGHTNESS"); if(on ||!(clockMode ==BRIGHT_SET &&inSubMenu))displayNumber(4,13、EepromData.brightness、0、false); if(on ||!(clockMode ==FORMAT_SET &&!inSubMenu))displayString(5,0、 "DATE FORNAT"); if(on ||!(clockMode ==FORMAT_SET &&inSubMenu &&formatSetMode ==DAY_MONTH))displayString(5,13、(EepromData.formatDmy)? "DD-NN": "NN-DD"); if(on ||!(clockMode ==FORMAT_SET &&inSubMenu &&formatSetMode ==FONT_STYLE))displayString(5,19、(EepromData.squareFont)? "FONT1": "FONT2"); mx.update(); }} // ---------------------------------------------- ----------------- //変更された場合は現在の時刻をディスプレイに表示します// force-変更されていない場合でも常に時刻を表示しますvoidshowTime(bool force){force =force || (lastSeconds!=second()); if(force){lastSeconds =second(); showTime(hour()、minute()、true、true、(second()&0x01)、(clockMode!=CLOCK ||!EepromData.format12hr)); }} // ---------------------------------------------- ----------------- //時間をディスプレイに表示する// h-時間// m-分// he-時間有効// me-分有効// ce --colon enable void showTime(int h、int m、bool he、bool me、bool ce、bool f24){mx.clear(); if(he){if(!f24 &&h> 12){h =h-12; } if(h> 9 || f24){displayLargeDigit(0、h / 10); } displayLargeDigit(5、h%10); } if(me){displayLargeDigit(13、m / 10); displayLargeDigit(18、m%10); } if(ce){displayLargeDigit(11、10); } mx.update();} // ---------------------------------------- ----------------------- void showDate(int d、int m、int y){#define XOFS 3 mx.clear(); if(EepromData.formatDmy){displayDateDigit(XOFS + 0、d / 10); displayDateDigit(XOFS + 4、d%10); displayDateDigit(XOFS + 8、10); //コロンdisplayDateDigit(XOFS + 12、m / 10); displayDateDigit(XOFS + 16、m%10); } else {displayDateDigit(XOFS + 0、m / 10); displayDateDigit(XOFS + 4、m%10); displayDateDigit(XOFS + 8、10); //コロンdisplayDateDigit(XOFS + 12、d / 10); displayDateDigit(XOFS + 16、d%10); } displayNumber(5、10、y、0、false); mx.update();} // --------------------------------------------------------- ---------------------- //構成設定に基づいて正方形または小さな数字を書き込む// x =0〜23 // v =大きな数字または正方形の数字をdisplay(0..10)void displayDateDigit(uint8_t x、uint8_t v){if(EepromData.squareFont){displaySquareDigit(x、v); } else {displaySmallDigit(x、v); }} // ---------------------------------------------- ----------------- //セグメントビットマスクを書き込む// x =0〜23 // v =表示する大きな数字(0..10)void displayLargeDigit(uint8_t x 、uint8_t v){if(x <24 &&v <11){for(uint8_t row =0; row <6; row ++){for(uint8_t col =0; col <6; col ++){writePhysicalDigit(row、col + x、pgm_read_byte(&largeDigits [v] [row] [col])、false); }}}} // -------------------------------------------- ------------------- //セグメントビットマスクを書き込む// x =0〜23 // v =表示する大きな数字(0..10)void displaySmallDigit( uint8_t x、uint8_t v){if(x <24 &&v <11){for(uint8_t row =0; row <5; row ++){for(uint8_t col =0; col <3; col ++){writePhysicalDigit(row、 col + x、pgm_read_byte(&smallDigits [v] [row] [col])、false); }}}} // -------------------------------------------- ------------------- //セグメントビットマスクを書き込む// x =0〜23 // v =表示する大きな数字(0..10)void displaySquareDigit( uint8_t col、uint8_t v){//セグメントの順序defbca _ g uint8_t mask =ascii [v]; if(mask ==B00000000){//ハイフンマスク=B00000001; } if(mask&B00000100){//セグメントA writePhysicalDigit(0、col + 0、0xff、false); writePhysicalDigit(0、col + 1、0xff、false); writePhysicalDigit(0、col + 2、0xff、false); } if(mask&B00010000){//セグメントB writePhysicalDigit(0、col + 2、0xff、false); writePhysicalDigit(1、col + 2、0xff、false); writePhysicalDigit(2、col + 2、0xff、false); } if(mask&B00001000){// seg C writePhysicalDigit(2、col + 2、0xff、false); writePhysicalDigit(3、col + 2、0xff、false); writePhysicalDigit(4、col + 2、0xff、false); } if(mask&B10000000){//セグメントD writePhysicalDigit(4、col + 0、0xff、false); writePhysicalDigit(4、col + 1、0xff、false); writePhysicalDigit(4、col + 2、0xff、false); } if(mask&B01000000){//セグメントC writePhysicalDigit(2、col、0xff、false); writePhysicalDigit(3、col、0xff、false); writePhysicalDigit(4、col、0xff、false); } if(mask&B00100000){// seg E writePhysicalDigit(0、col、0xff、false); writePhysicalDigit(1、col、0xff、false); writePhysicalDigit(2、col、0xff、false); } if(mask&B00000001){//セグメントD writePhysicalDigit(2、col + 0、0xff、false); writePhysicalDigit(2、col + 1、0xff、false); writePhysicalDigit(2、col + 2、0xff、false); }} // ---------------------------------------------- ----------------- //文字列を書き込むuint8_tdisplayString(uint8_t row、uint8_t col、String s){for(int i =0; i  0x5F){c =0x3F; //スペース文字として使用} c =c-0x30; writePhysicalDigit(row、col、ascii [c]、true); col =col + 1; }} // ---------------------------------------------- ----------------- //数値を書き込むuint8_tdisplayNumber(uint8_t row、uint8_t col、int number、int padding、bool LeadingZeros){if(padding ==0){padding =(数値> 0)? floor(log10(number))+ 1:1; } col =col +パディング; bool first =true; for(int i =0; i <パディング; i ++){col--; if(number!=0 || first){writePhysicalDigit(row、col、ascii [number%10]、true);数=数/ 10;最初=false; } else {writePhysicalDigit(row、col、ascii [(leadingZeros)?0:0x0F]、true); }}} // ------------------------------------------------- ------------------ //セグメントビットマスクを書き込む//行=0〜5 // col =0〜23 // v =セグメントマスク//消去=trueすべての古いパターンを置き換えます。falseは既存のvoidwritePhysicalDigit(uint8_t row、uint8_t col、uint8_t v、bool Erase){if(row <6 &&col <24){uint8_t dig =(col&0x03)+((row& 0x01)?4:0); uint8_t dev =(col>> 2)* 3 +(row>> 1); uint16_t c =((uint16_t)dev <<3)| DigitMap [dig]; if(!erase){v =v | mx.getColumn(c); } mx.setColumn(c、v); }} // ---------------------------------------------- ----------------- //うるう年または世紀の変わり目でない限り、指定された年と月の日数を返す// 2月は28日uint8_tdaysInMonth(int y、int m) {return dom [m --1] +((m ==2 &&(y%4)==0 &&(y%100)!=0)?1:0);} // ------- -------------------------------------------------- ------ // EepromData構造をEEPROMに書き込みますvoidwriteEepromData(){//この関数はEEPROM.update()を使用して書き込みを実行するため、値が変更されていない場合は値を書き換えません。 EEPROM.put(EEPROM_ADDRESS、EepromData);} // -------------------------------------- ------------------------- // EEPROMからEepromData構造を読み取り、必要に応じて初期化しますvoid readEepromData(){// Eprom EEPROM.get(EEPROM_ADDRESS、 EepromData); //Serial.println("magic: "+ String(EepromData.magic、16)+"、alarm: "+ String(EepromData.alarm)+"、time: "+ String(EepromData.hours)+": "+ String(EepromData.minutes)+ "、12hr:" + String(EepromData.format12hr)+ "、明るさ:" + String(EepromData.brightness)); if(EepromData.magic!=EEPROM_MAGIC){Serial.println( "Initialising EEPROM ..."); EepromData.magic =EEPROM_MAGIC; EepromData.alarm =false; EepromData.minutes =30; EepromData.hours =5; EepromData.format12hr =false; EepromData.brightness =8; EepromData.tune =0; EepromData.formatDmy =false; writeEepromData(); } Serial.println( "alarm:" + String(EepromData.alarm)+ "、time:" + String(EepromData.hours)+ ":" + String(EepromData.minutes)+ "、12hr:" + String(EepromData .format12hr)+ "、明るさ:" + String(EepromData.brightness));} // ----------------------------- ---------------------------------- //メロディーを再生するplaySong(const uint16_t * melody){//再生するeach note in the melody until the END_OF_TUNE note is encountered musicPlaying =true; int thisNote =0; uint16_t noteRaw =pgm_read_word(&melody[thisNote++]); while (musicPlaying &¬eRaw !=END_OF_TUNE) { testButtons(); yield(); playNote(noteRaw); noteRaw =pgm_read_word(&melody[thisNote++]); } //while delay(50);}//---------------------------------------------------------------//Play a single notevoid playNote(uint16_t noteRaw){ // to calculate the note duration, take one second divided by the note type. // e.g. quarter note =1000 / 4, eighth note =1000/8, etc. uint16_t frequency =noteRaw &0x1FFF; uint16_t duration =(noteRaw &0xE000)>> 13; if (duration ==7) duration =8; uint16_t noteDuration =1800 / duration; if (frequency !=REST) { tone(SPEAKER, frequency, noteDuration); } // to distinguish the notes, set a minimum time between them. // the note's duration + 30% seems to work well:uint16_t pauseBetweenNotes =(noteDuration * 13) / 10; delay(pauseBetweenNotes); if (frequency !=REST) { // stop the tone playing:noTone(SPEAKER); }} 
Digits.hC/C++
/*--------------------------------------------------- * 7 Segment array clock * define each digit in a 6x6 byte array *--------------------------------------------------*/ #pragma once//---------------------------------------------------// Standard MAX7219 wiring// Digit order 0,1,2,3,4,5/*// Segment order _ a b c d e f g#define _______ B00000000#define __cd___ B00011000#define _bcde_g B00111101#define abcdefg B01111111#define __cdefg B00011111#define __c____ B00010000#define ab__efg B01100111#define abcd_fg B01111011#define abcde_g B01111101#define ab_defg B01101111#define _bc____ B00110000#define a__defg B01001111#define ____ef_ B00000110#define ___defg B00001111#define abc__fg B01110011#define a___ef_ B01000110#define _b_____ B00100000#define ab___f_ B01100010#define _bcd___ B00111000#define a___ef_ B01000110#define ab_____ B01100000#define ____e__ B00000100#define __cde_g B00011101#define a____f_ B01000010#define a_cdefg B01011111#define ___de__ B00001100#define _____f_ B00000010#define ab___fg B01100011#define a__def_ B01001110#define __cde__ B00011100#define a___efg B01000111#define a__d___ B01001000#define abc____ B01110000#define _bc_ef_ B00110110#define ___def_ B00001110#define abc_ef_ B01110110#define _bcdef_ B00111110#define a__def_ B01001110#define abcd___ B01111000*///Segment order d e f b c a _ g#define _______ B00000000#define __cd___ B10001000#define _bcde_g B11011001#define abcdefg B11111101#define __cdefg B11101001#define __c____ B00001000#define ab__efg B01110101#define abcd_fg B10111101#define abcde_g B11011101#define ab_defg B11110101#define _bc____ B00011000#define a__defg B11100101#define ____ef_ B01100000#define ___defg B11100001#define abc__fg B00111101#define a___ef_ B01100100#define _b_____ B00010000#define ab___f_ B00110100#define _bcd___ B10011000#define a___ef_ B01100100#define ab_____ B00010100#define ____e__ B01000000#define __cde_g B11001001#define a____f_ B00100100#define a_cdefg B11101101#define ___de__ B11000000#define _____f_ B00100000#define ab___fg B00110101#define a__def_ B11100100#define __cde__ B11001000#define a___efg B01100101#define a__d___ B10000100#define abc____ B00011100#define _bc_ef_ B01111000#define ___def_ B11100000#define abc_ef_ B01111100#define _bcdef_ B11111000#define a__def_ B11100100#define abcd___ B10011100//Square Numbers//ASCII Character Set//Numbers 0 - 9//Letters A - Z//Segment order d e f b c a _ guint8_t ascii[] ={ B11111100, B00011000, B11010101, B10011101, B00111001, B10101101, B11101101, B00011100, B11111101, B10111101, B00000000, B00000000, B00000000, B00000001, B00000000, B00000000, B00000000, B01111101, B11101001, B11100100, B11011001, B11100101, B01100101, B10111101, B01111001, B00011000, B11011000, B00000000, B11100000, B00000000, B01001001, B11001001, B01110101, B00000000, B01000001, B10101101, B11100001, B11001000, B00000000, B00000000, B00000000, B10111001, B00000000, B11001100, B01010001, B10011100, B00000000, B10000000};//Digit sequence for each device (MAX7219)uint8_t digitMap[] ={5, 2, 6, 4, 1, 7, 3, 0};//------------------------------------------------------------// Digits using logical coordinates//------------------------------------------------------------const int8_t largeDigits[11][6][6] PROGMEM ={ { //0 { _______, _______, __cd___, _bcde_g, abcdefg, __cdefg }, { _______, __c____, abcdefg, ab__efg, abcd_fg, abcdefg }, { _______, abcde_g, ab_defg, _______, _bc____, a__defg }, { _______, abcdefg, ____ef_, __c____, abcdefg, ____ef_ }, { _______, abcdefg, __cdefg, abcdefg, a___efg, _______ }, { _______, abc__fg, abcdefg, ab__efg, _______, _______ } }, { //1 { _______, _______, _______, __c____, abcdefg, __cdefg }, { _______, _______, _______, abcdefg, abcdefg, ____ef_ }, { _______, _______, _bcde_g, abcdefg, a__defg, _______ }, { _______, _bc____, abcdefg, abcdefg, ____ef_, _______ }, { _______, abcdefg, abcdefg, a___ef_, _______, _______ }, { _b_____, abcdefg, abcdefg, _______, _______, _______ } }, { //2 { _______, _______, __cd___, _bcde_g, abcdefg, __cdefg }, { _______, _bc____, abcdefg, ab___f_, abcd_fg, abcdefg }, { _______, _______, _______, _bcd___, abcdefg, a___ef_ }, { _______, _______, _bcde_g, abcdefg, a___ef_, _______ }, { __c____, abcdefg, abcdefg, a___ef_, _______, _______ }, { _b_____, abc__fg, abcdefg, abcdefg, ab__efg, _______ } }, { //3 { _______, _______, __cd___, abcdefg, abcdefg, __cdefg }, { _______, _b_____, abcdefg, ab___f_, abcd_fg, abcdefg }, { _______, _______, __cd___, _bcde_g, abcdefg, a___ef_ }, { _______, _______, ab_____, abc__fg, abcdefg, ____e__ }, { _______, __cd___, __cde_g, _bcde_g, abcdefg, ____ef_ }, { _b_____, abc__fg, abcdefg, abcdefg, a____f_, _______ } }, { //4 { _______, _______, _bcd___, abcdefg, __c____, abcdefg }, { _______, __c____, abcdefg, a___ef_, abcde_g, a__defg }, { _______, abcde_g, abcdefg, _bcd___, abcdefg, ____ef_ }, { __c____, abcdefg, abcdefg, abcdefg, abcdefg, _______ }, { _______, _______, __c____, abcdefg, ____ef_, _______ }, { _______, _______, abcdefg, ab__efg, _______, _______ } }, { //5 { _______, _______, _bcde_g, abcdefg, abcdefg, abcdefg }, { _______, _bc____, abcdefg, a_cdefg, ___de__, _______ }, { _______, _______, abc__fg, abcdefg, abcdefg, ____ef_ }, { _______, _______, _______, _bc____, abcdefg, ____ef_ }, { _______, __cde_g, __cde_g, _bcde_g, abcdefg, _____f_ }, { _b_____, abcdefg, abcdefg, ab__efg, a____f_, _______ } }, { //6 { _______, _______, _______, __cd___, abcdefg, ____ef_ }, { _______, _______, _bcde_g, abcdefg, a____f_, _______ }, { _______, _bcd___, abcdefg, abcdefg, abcdefg, ____e__ }, { __c____, abcdefg, a___ef_, ab_____, abcdefg, ____ef_ }, { _bc____, abcdefg, __cdefg, _bcde_g, abcdefg, _______ }, { _______, abc__fg, abcdefg, ab__efg, _______, _______ } }, { //7 { _______, _bc____, abcdefg, abcdefg, abcdefg, __cdefg }, { _______, _b_____, ab___fg, ab___fg, abcdefg, abcdefg }, { _______, _______, _______, _bcde_g, abcdefg, a___ef_ }, { _______, _______, _bcde_g, abcdefg, ab__efg, _______ }, { _______, _bcde_g, abcdefg, a___ef_, _______, _______ }, { _b_____, abcdefg, abcdefg, _______, _______, _______ } }, { //8 { _______, _______, __cd___, abcdefg, abcdefg, __cdefg }, { _______, _bc____, abcdefg, ab___f_, abcd_fg, abcdefg }, { _______, _b_____, abcdefg, _bcde_g, abcdefg, a___ef_ }, { _______, _bcde_g, ab__efg, abc__fg, abcdefg, ____e__ }, { _bc____, abcdefg, __cde_g, _bcde_g, abcdefg, ____ef_ }, { _______, abc__fg, abcdefg, abcdefg, a____f_, _______ } }, { //9 { _______, _______, __cde_g, abcdefg, __cdefg, ___de__ }, { _______, _bcd___, abcdefg, ab___fg, abcd_fg, abcdefg }, { _______, abcdefg, a_cdefg, __cde__, abcdefg, a__defg }, { _______, ab_____, abcd_fg, abcdefg, abcdefg, _____f_ }, { _______, __cd___, abcdefg, ab__efg, _______, _______ }, { _b_____, abcdefg, a___ef_, _______, _______, _______ } }, { //Colon { _______, _______, _______, _______, _______, _______ }, { _______, __cde_g, _______, _______, _______, _______ }, { _______, _______, _______, _______, _______, _______ }, { _______, _______, _______, _______, _______, _______ }, { __cde_g, _______, _______, _______, _______, _______ }, { _______, _______, _______, _______, _______, _______ } }};const int8_t smallDigits[11][5][3] PROGMEM ={ { //0 { a___ef_, a__d___, abc____ }, { _bc_ef_, _______, _bc_ef_ }, { _bc_ef_, _______, _bc_ef_ }, { _bc_ef_, _______, _bc_ef_ }, { ___def_, a__d___, _bcd___ } }, { //1 { _______, abc_ef_, _______ }, { _______, _bc_ef_, _______ }, { _______, _bc_ef_, _______ }, { _______, _bc_ef_, _______ }, { _______, _bcdef_, _______ } }, { //2 { a__def_, a__d___, abc____ }, { _______, _______, _bc_ef_ }, { a___ef_, a__d___, _bcd___ }, { _bc_ef_, _______, _______ }, { ___def_, a__d___, abcd___ } }, { //3 { a__def_, a__d___, abc____ }, { _______, _______, _bc_ef_ }, { _______, a__def_, _bc____ }, { _______, _______, _bc_ef_ }, { a__def_, a__d___, _bcd___ } }, { //4 { abc_ef_, _______, abc_ef_ }, { _bc_ef_, _______, _bc_ef_ }, { ___def_, a__d___, _bc____ }, { _______, _______, _bc_ef_ }, { _______, _______, _bcdef_ } }, { //5 { a___ef_, a__d___, abcd___ }, { _bc_ef_, _______, _______ }, { ___def_, a__d___, abc____ }, { _______, _______, _bc_ef_ }, { a__def_, a__d___, _bcd___ } }, { //6 { a___ef_, a__d___, abcd___ }, { _bc_ef_, _______, _______ }, { ____ef_, a__d___, abc____ }, { _bc_ef_, _______, _bc_ef_ }, { ___def_, a__d___, _bcd___ } }, { //7 { a__def_, a__d___, abc____ }, { _______, _______, _bc_ef_ }, { _______, _bc_ef_, _______ }, { _______, _bc_ef_, _______ }, { _______, _bcdef_, _______ }, }, { //8 { a___ef_, a__d___, abc____ }, { _bc_ef_, _______, _bc_ef_ }, { ____ef_, a__d___, _bc____ }, { _bc_ef_, _______, _bc_ef_ }, { ___def_, a__d___, _bcd___ } }, { //9 { a___ef_, a__d___, abc____ }, { _bc_ef_, _______, _bc_ef_ }, { ___def_, a__d___, _bc____ }, { _______, _______, _bc_ef_ }, { a__def_, a__d___, _bcd___ } }, { //Hyphen { _______, _______, _______ }, { _______, _______, _______ }, { a__def_, a__d___, abcd___ }, { _______, _______, _______ }, { _______, _______, _______ } }};
Tunes.hC/C++
プレビューなし(ダウンロードのみ)。
Button.hC/C++
/*Class:ButtonAuthor:John Bradnam ([email protected])Purpose:Arduino library to handle buttons*/#pragma once#include "Arduino.h"#define DEBOUNCE_DELAY 10//Repeat speed#define REPEAT_START_SPEED 500#define REPEAT_INCREASE_SPEED 50#define REPEAT_MAX_SPEED 50class Button{ public://Simple constructor Button(int pin); Button(int name, int pin); Button(int name, int pin, int analogLow, int analogHigh, bool activeLow =true); //Background function called when in a wait or repeat loop void Background(void (*pBackgroundFunction)()); //Repeat function called when button is pressed void Repeat(void (*pRepeatFunction)()); //Test if button is pressed bool IsDown(void); //Test whether button is pressed and released //Will call repeat function if one is provided bool Pressed(); //Return button state (HIGH or LOW) - LOW =Pressed int State(); //Return button name int Name(); private:int _name; int _pin; bool _range; int _low; int _high; bool _activeLow; void (*_repeatCallback)(void); void (*_backgroundCallback)(void);};
Button.cppC/C++
/*Class:ButtonAuthor:John Bradnam ([email protected])Purpose:Arduino library to handle buttons*/#include "Button.h"Button::Button(int pin){ _name =pin; _pin =pin; _range =false; _low =0; _high =0; _backgroundCallback =NULL; _repeatCallback =NULL; pinMode(_pin, INPUT_PULLUP);}Button::Button(int name, int pin){ _name =name; _pin =pin; _range =false; _low =0; _high =0; _backgroundCallback =NULL; _repeatCallback =NULL; pinMode(_pin, INPUT_PULLUP);}Button::Button(int name, int pin, int analogLow, int analogHigh, bool activeLow){ _name =name; _pin =pin; _range =true; _low =analogLow; _high =analogHigh; _activeLow =activeLow; _backgroundCallback =NULL; _repeatCallback =NULL; pinMode(_pin, INPUT);}//Set function to invoke in a delay or repeat loopvoid Button::Background(void (*pBackgroundFunction)()){ _backgroundCallback =pBackgroundFunction;}//Set function to invoke if repeat system requiredvoid Button::Repeat(void (*pRepeatFunction)()){ _repeatCallback =pRepeatFunction;} bool Button::IsDown(){ if (_range) { int value =analogRead(_pin); return (value>=_low &&value <_high); } else { return (digitalRead(_pin) ==LOW); }}//Tests if a button is pressed and released// returns true if the button was pressed and released// if repeat callback supplied, the callback is called while the key is pressedbool Button::Pressed(){ bool pressed =false; if (IsDown()) { unsigned long wait =millis() + DEBOUNCE_DELAY; while (millis() =time) { _repeatCallback(); unsigned long faster =speed - REPEAT_INCREASE_SPEED; if (faster>=REPEAT_MAX_SPEED) { speed =faster; } time =millis() + speed; } } pressed =true; } } return pressed;}//Return current button stateint Button::State(){ if (_range) { int value =analogRead(_pin); if (_activeLow) { return (value>=_low &&value <_high) ? LOW :HIGH; } else { return (value>=_low &&value <_high) ? HIGH :LOW; } } else { return digitalRead(_pin); }}//Return current button nameint Button::Name(){ return _name;}
Hardware_Test_V1.zipC/C++
Hardware test sketch - Turns on all segments and tests speaker
No preview (download only).

カスタムパーツとエンクロージャー

回路図

Schematic for each MAX7219 (repeated 18 times) Holds six 7 segment 4 digit displays (6 boards required) PCB files in Eagle format eagle_files_KPhUOj6Ezv.zip

製造プロセス

  1. Arduinoハメ撮りビジョンクロック
  2. Simple Word Clock(Arduino)
  3. イスラムの祈りの時間とArduino時計
  4. マスタークロック
  5. シングルLEDマトリックスArduinoフリップクロック
  6. ArduinoUnoでLEDマトリックスを制御する
  7. eDOT-Arduinoベースの精密時計および気象観測所
  8. Arduinoを搭載したミニレーダー
  9. リアルタイムクロック付きArduinoOLED温度ディスプレイ
  10. ArduinoシールドNCS314ニキシー管時計IN-14
  11. DS1302RTCを備えたシンプルな目覚まし時計