الصفحة الرئيسية · صحة · DIY بها بنفسك ساعة شارع LED. ساعة معصم محلية الصنع. ساعة جاهزة على اردوينو

DIY بها بنفسك ساعة شارع LED. ساعة معصم محلية الصنع. ساعة جاهزة على اردوينو

مع عرض ديناميكي. لا توجد شكاوى حول عمل الساعة: المسار الدقيق والإعدادات المريحة. لكن أحد العيوب الكبيرة هو أن مؤشرات LED يصعب رؤيتها في النهار. لحل المشكلة ، قمت بالتبديل إلى مؤشر ثابت ومصابيح LED أكثر إشراقًا. كما هو الحال دائما في البرمجيات ، شكرا جزيلا لسوار. بشكل عام ، أوجه انتباهكم إلى ساعة خارجية كبيرة بها مؤشر ثابت ، وظلت وظائف الإعداد كما هي في الساعات السابقة.

لديهم شاشتان - العرض الرئيسي (بالخارج في الشارع) والآخر الإضافي على المؤشرات - في الداخل ، على جسم الجهاز. يتم تحقيق السطوع العالي باستخدام مصابيح LED فائقة السطوع ، بتيار عمل يبلغ 50 مللي أمبير ، ورقائق السائق.

مخطط ساعة إلكترونية للشارع على المصابيح الساطعة

لتفليش وحدة التحكم بالملفات واستخدام إعدادات المصهر التالية:

لوحات الدوائر المطبوعة للساعة ووحدة التحكم والوحدة الخارجية بتنسيق LAY.


ميزات مخطط الساعة هذا:

- تنسيق عرض الوقت 24 ساعة.
- تصحيح دقة الضربات الرقمية.
- تحكم مدمج في مصدر الطاقة الرئيسي.
- ذاكرة غير متطايرة للميكروكونترولر.
- يوجد ميزان حرارة يقيس درجة الحرارة في حدود -55 - 125 درجة.
- من الممكن إخراج معلومات بالتناوب حول الوقت ودرجة الحرارة للمؤشر.


يؤدي الضغط على الزر SET_TIME إلى تبديل المؤشر في دائرة من وضع الساعة الرئيسي (عرض الوقت الحالي). في جميع الأوضاع ، يؤدي الضغط باستمرار على زري علامة الجمع / الطرح إلى إجراء إعداد متسارع. ستتم كتابة التغييرات التي تم إجراؤها على الإعدادات بعد 10 ثوانٍ من آخر تغيير في القيمة على ذاكرة غير متطايرة (EEPROM) وستتم قراءتها من هناك عند تشغيل الطاقة مرة أخرى.


ميزة أخرى كبيرة للخيار المقترح هي أن السطوع قد تغير ، والآن في الطقس المشمس ، يكون السطوع ممتازًا. انخفض عدد الأسلاك من 14 إلى 5. يبلغ طول السلك إلى الشاشة الرئيسية (الخارجية) 20 مترًا. أنا راضٍ عن عمل الساعة الإلكترونية ، فقد اتضح أنها ساعة تعمل بكامل طاقتها - ليلاً ونهارًا. مع خالص التقدير ، سوار ألكساندروفيتش.

هناك العديد من الطرق لتجميع ساعة إلكترونية بيديك: يتم تمثيل المخططات على نطاق واسع في الأدبيات وعلى الإنترنت. تعتمد معظم التطبيقات الحديثة على المتحكمات الدقيقة. غالبًا ما يتطلب تنفيذ مثل هذه المشاريع مهارات عملية واسعة ومعرفة نظرية في مجال الإلكترونيات: القدرة على استخدام البرامج المتخصصة ، وإنشاء لوحات الدوائر المطبوعة في المنزل باستخدام نقش كلوريد الحديديك ، ولحام البئر. تحتاج أيضًا إلى الكثير من الأدوات والمستلزمات.

ومع ذلك ، هناك طريقة سهلة وبأسعار معقولة لبناء ساعة رقمية بيديك في المنزل: استخدم منصة Arduino. إنه مجمع للبرامج والأجهزة مصمم خصيصًا لتدريس أساسيات البرمجة والإلكترونيات. بمساعدة Arduino ، سيتمكن أي شخص ، حتى بدون تدريب مسبق خاص ، من بناء ساعة إلكترونية بأيديهم: ليست هناك حاجة إلى مخططات الدوائر والبرامج الهندسية وحتى مكواة اللحام!

يتم توصيل جميع المكونات الإلكترونية على لوح توصيل خاص ("غير ملحوم") ، مما يقضي على مخاطر الحروق والجروح والإصابات الأخرى - لذلك ، يمكنك أيضًا العمل مع مصمم Arduino مع الأطفال. وستساعد الطريقة المرئية لعرض مخطط الدائرة على عدم ارتكاب أخطاء عند تجميع الجهاز.

الخطوة 1 قائمة المكونات

لتجميع ساعة مصفوفة LED بسيطة ، تحتاج فقط إلى بعض المكونات الرخيصة:

  • منصة اردوينو. أبسط النماذج ستفعل - أو مايكرو ؛
  • اتصال اللوح
  • توصيل الأسلاك للوح ؛
  • وحدة ساعة الوقت الحقيقي Adafruit DS3231 ؛
  • 32x8 MAX7219 وحدة مصفوفة LED ؛
  • زرين.

ستحتاج أيضًا إلى جهاز كمبيوتر شخصي وكابل USB-mini-USB لتنزيل برنامج التحكم على الذاكرة. هذا كل شيء - ليست هناك حاجة إلى مكواة لحام وكماشة وسكاكين وأدوات احترافية أخرى: يتم تنفيذ جميع العمليات يدويًا. ما لم يكن استخدام الملقط أكثر ملاءمة في بعض الحالات ، لكن يمكنك الاستغناء عنه.


الخطوة 2. تجميع الدائرة الإلكترونية

ستبدو دائرة الساعة الإلكترونية مع مؤشر LED باستخدام Arduino ، حتى بالنسبة لهواة الراديو عديمي الخبرة ، بسيطة للغاية. مطلوب فقط عدد قليل من الموصلات للتجميع. جدول الاتصال:

وحدة اردوينو → مصفوفة LED 32x8 MAX7219

وحدة Arduino → Adafruit DS3231 في الوقت الحقيقي على مدار الساعة

وحدة اردوينو → الأزرار

D2 - زر 1

D3 - زر 2

الدبوس الثاني من الأزرار متصل بـ GND.

تحتاج فقط إلى الانتباه وتذكر كيف يتم إغلاق فتحات التلامس الموجودة على اللوح مع بعضها البعض. يوضح الرسم البياني التالي كيفية توصيل فتحات التلامس داخليًا:


يتم إغلاق الصفين (1 و 4) على كلا الجانبين أفقيًا - وعادة ما يتم استخدامهما كخط طاقة +5 فولت وأرضي GND. يتم إغلاق جميع جهات الاتصال الداخلية (2 و 3) عموديًا. في هذه الحالة ، يتم تقسيم لوحة التثبيت رأسياً وأفقياً إلى جزأين متماثلين مستقلين عن بعضهما البعض. يسمح هذا ، على سبيل المثال ، بتجميع جهازين مختلفين على نفس اللوحة.

يظهر الرسم التخطيطي للساعة الإلكترونية مع مؤشر LED ، بالإضافة إلى ترتيب العناصر على لوحة الدائرة في الرسم التوضيحي:

تحقق بعناية من أن جميع الاتصالات تتوافق مع المخطط المحدد. تأكد أيضًا من أن الموصلات مثبتة جيدًا في فتحات التلامس بلوحة الدائرة.


الخطوة 3: البرامج الثابتة Arduino

بعد اكتمال تجميع الدائرة والتحقق منها ، يمكنك البدء في تحميل برنامج التحكم (أو "البرنامج الثابت") في ذاكرة Arduino.


للقيام بذلك ، تحتاج إلى تثبيت بيئة تطوير رسمية مجانية -. ستحتاج أيضًا إلى الكود المصدري للمشروع ، والذي يمكنك تنزيله أدناه في الأرشيف مع جميع المكتبات والرسم التخطيطي ، وإذا كنت بحاجة فقط إلى رسم تخطيطي ، فيمكنك نسخه بشكل منفصل:

// include libraries: #include "LedControl.h" #include // مكتبة الخطوط # تضمين // DS1307 clock # تتضمن "RTClib.h" // DS1307 clock #include // مكتبة الأزرار بواسطة Alexander Brevig // Setup LED Matrix // pin 12 متصل بـ DataIn على الشاشة // pin 11 متصل بـ CLK على الشاشة // pin 10 متصل بـ LOAD على الشاشة LedControl lc = LedControl (6 ، 5 ، 4 ، 4) ؛ // يعين 3 دبابيس على أنها 12 و 11 و 10 ثم يعين 4 شاشات (بحد أقصى 8 شاشات) // كثافة بايت المتغيرات العامة = 7 ؛ // الكثافة / السطوع الافتراضي (0-15) بايت clock_mode = 0 ؛ // وضع الساعة الافتراضي. الافتراضي = 0 (الوضع الأساسي) bool random_mode = 0 ؛ // تحديد الوضع العشوائي - يغير نوع العرض كل بضع ساعات. الافتراضي = 0 (إيقاف) بايت old_mode = clock_mode ؛ // يخزن وضع الساعة السابق ، لذلك إذا ذهبنا إلى التاريخ أو أي شيء آخر ، فنحن نعرف الوضع الذي سنعود إليه بعد ذلك. منطقي أمبير = 0 ؛ // تحديد الوقت 12 أو 24 ساعة. 0 = 24 ساعة. 1 = 12 ساعة بايت change_mode_time = 0 ؛ // يحمل الساعة عندما يتغير وضع الساعة بعد ذلك إذا كان في الوضع العشوائي. وقت تأخير طويل بدون توقيع = 500 ؛ // ننتظر دائمًا قليلاً بين تحديثات العرض int rtc ؛ // يحمل أيام إخراج ساعة الوقت الحقيقي = ("الأحد" ، "الإثنين" ، "الثلاثاء" ، "الأربعاء" ، "الخميس" ، "الجمعة" ، "السبت") ؛ // يوم مصفوفة - تُستخدم في أوضاع الشريحة و basic_mode و jumble (ينتج DS1307 قيم من 1 إلى 7 ليوم من الأسبوع) char daysfull = ("الأحد" ، "الإثنين" ، "الثلاثاء" ، "الأربعاء" ، "الخميس "،" الجمعة "،" السبت ") ؛ لاحقة char = ("st"، "nd"، "rd"، "th")؛ // مصفوفة لاحقة التاريخ ، تُستخدم في أوضاع الشريحة و basic_mode و jumble. e ، g ، 1st 2nd ... // تحديد الثوابت #define NUM_DISPLAY_MODES 3 // أوضاع عرض الأرقام (شرط الصفر كالوضع الأول) #define NUM_SETTINGS_MODES 4 // أوضاع إعدادات الأرقام = 6 (شرط صفر كوضع أول) # حدد SLIDE_DELAY 20 // الوقت بالمللي ثانية لتأثير الشريحة لكل حرف في وضع الشريحة. اجعل هذا أعلى للحصول على تأثير أبطأ # تعريف cls clear_display // مسح العرض RTC_DS1307 ds1307 ؛ // إنشاء زر كائن RTC buttonA = زر (2 ، BUTTON_PULLUP) ؛ // زر الإعداد A (باستخدام مكتبة الأزرار) Button buttonB = زر (3 ، BUTTON_PULLUP) ؛ // زر الإعداد B (باستخدام مكتبة الأزرار) إعداد باطل () (كتابة رقمية (2 ، عالية) ؛ // قم بتشغيل المقاوم pullup للزر الموجود على الدبوس 2 digitalWrite (3 ، HIGH) ؛ // قم بتشغيل المقاوم pullup للزر الموجود على الدبوس 3 digitalWrite (4 ، HIGH) ؛ // تشغيل المقاوم pullup للزر الموجود على الطرف 4 Serial.begin (9600) ؛ // بدء المسلسل // تهيئة لوحات المصفوفة الأربعة // لقد قمنا بالفعل بتعيين عدد الأجهزة عندما أنشأنا أجهزة LedControl int = lc.getDeviceCount () ؛ // يتعين علينا بدء جميع الأجهزة في حلقة من أجل (عنوان int = 0 ؛ العنوان< devices; address++) { /*The MAX72XX is in power-saving mode on startup*/ lc.shutdown(3-address, false); /* Set the brightness to a medium values */ lc.setIntensity(3-address, intensity); /* and clear the display */ lc.clearDisplay(3-address); } //Setup DS1307 RTC #ifdef AVR Wire.begin(); #else Wire1.begin(); // Shield I2C pins connect to alt I2C bus on Arduino #endif ds1307.begin(); //start RTC Clock if (! ds1307.isrunning()) { Serial.println("RTC is NOT running!"); ds1307.adjust(DateTime(__DATE__, __TIME__)); // sets the RTC to the date & time this sketch was compiled } //Show software version & hello message printver(); //enable red led digitalWrite(13, HIGH); } void loop() { //run the clock with whatever mode is set by clock_mode - the default is set at top of code. switch (clock_mode){ case 0: basic_mode(); break; case 1: small_mode(); break; case 2: slide(); break; case 3: word_clock(); break; case 4: setup_menu(); break; } } //plot a point on the display void plot (byte x, byte y, byte val) { //select which matrix depending on the x coord byte address; if (x >= 0 && x<= 7) { address = 3; } if (x >= 8 && x<= 15) { address = 2; x = x - 8; } if (x >= 16 && x<= 23) { address = 1; x = x - 16; } if (x >= 24 && x<= 31) { address = 0; x = x - 24; } if (val == 1) { lc.setLed(address, y, x, true); } else { lc.setLed(address, y, x, false); } } //clear screen void clear_display() { for (byte address = 0; address < 4; address++) { lc.clearDisplay(address); } } //fade screen down void fade_down() { //fade from global intensity to 1 for (byte i = intensity; i >0 ؛ i--) (لـ (عنوان البايت = 0 ؛ العنوان< 4; address++) { lc.setIntensity(address, i); } delay(30); //change this to change fade down speed } clear_display(); //clear display completely (off) //reset intentsity to global val for (byte address = 0; address < 4; address++) { lc.setIntensity(address, intensity); } } //power up led test & display software version number void printver() { byte i = 0; char ver_a = "MADE"; char ver_b = "IN"; char ver_c = "RUSSIA"; //test all leds. for (byte x = 0; x <= 32; x++) { for (byte y = 0; y <= 7; y++) { plot(x, y, 1); } } delay(300); fade_down(); while (ver_a[i]) { puttinychar((i * 4), 1, ver_a[i]); delay(35); i++; } delay(500); fade_down(); i = 0; while (ver_b[i]) { puttinychar((i * 4), 1, ver_b[i]); delay(35); i++; } delay(500); fade_down(); i = 0; while (ver_c[i]) { puttinychar((i * 4), 1, ver_c[i]); delay(35); i++; } delay(500); fade_down(); } // puttinychar // Copy a 3x5 character glyph from the myfont data structure to display memory, with its upper left at the given coordinate // This is unoptimized and simply uses plot() to draw each dot. void puttinychar(byte x, byte y, char c) { byte dots; if (c >= "أ" && ج<= "Z" || (c >= "أ" && ج<= "z")) { c &= 0x1F; // A-Z maps to 1-26 } else if (c >= "0" && ج<= "9") { c = (c - "0") + 32; } else if (c == " ") { c = 0; // space } else if (c == ".") { c = 27; // full stop } else if (c == ":") { c = 28; // colon } else if (c == "\"") { c = 29; // single quote mark } else if (c == "!") { c = 30; // single quote mark } else if (c == "?") { c = 31; // single quote mark } for (byte col = 0; col < 3; col++) { dots = pgm_read_byte_near(&mytinyfont[c]); for (char row = 0; row < 5; row++) { if (dots & (16 >> صف)) قطعة أرض (س + عمود ، ص + صف ، 1) ؛ مؤامرة أخرى (س + عمود ، ص + صف ، 0) ؛ ))) وضع عادي باطل (بايت x ، بايت y ، char c) (بايت نقاط ؛ // if (c> = "A" && c<= "Z" || (c >= "أ" && ج<= "z")) { // c &= 0x1F; // A-Z maps to 1-26 // } if (c >= "أ" && ج<= "Z") { c &= 0x1F; // A-Z maps to 1-26 } else if (c >= "أ" && ج<= "z") { c = (c - "a") + 41; // A-Z maps to 41-67 } else if (c >= "0" && ج<= "9") { c = (c - "0") + 31; } else if (c == " ") { c = 0; // space } else if (c == ".") { c = 27; // full stop } else if (c == "\"") { c = 28; // single quote mark } else if (c == ":") { c = 29; // clock_mode selector arrow } else if (c == ">") (c = 30؛ // Clock_mode selector arrow) وإلا إذا (c> = -80 && c<= -67) { c *= -1; } for (char col = 0; col < 5; col++) { dots = pgm_read_byte_near(&myfont[c]); for (char row = 0; row < 7; row++) { //check coords are on screen before trying to plot //if ((x >= 0) && (x<= 31) && (y >= 0) && (ذ<= 7)){ if (dots & (64 >> صف)) (// فقط 7 rows.plot (x + col، y + row، 1)؛) else (plot (x + col، y + row، 0)؛) //)))) // small_mode // إظهار الوقت بأحرف 3 × 5 صغيرة مع عرض الثواني باطل small_mode () (char textchar ؛ // 16 حرفًا على شاشة العرض بايت mins = 100 ؛ // mins byte secs = rtc ؛ // ثانية بايت old_secs = ثانية ؛ / / يحمل قيمة الثواني القديمة - منذ آخر مرة تم تحديث الثواني o العرض - تستخدم للتحقق مما إذا كانت الثواني قد تغيرت cls () ؛ // تشغيل حلقة الساعة الرئيسية طالما أن run_mode يعود صحيحًا أثناء (run_mode ()) (get_time () ؛ / / تحقق من الضغط على الزر إذا (buttonA.uniquePress ()) (switch_mode () ؛ عودة ؛) if (buttonB.uniquePress ()) (display_date () ؛ return ؛) // إذا تغيرت الثواني ، فقم بتحديثها على شاشة العرض = ثانية rtc؛ if (secs! = old_secs) (// secs char buffer؛ itoa (secs، buffer، 10)؛ // إصلاح - وإلا إذا كانت num تحتوي على صفر بادئ ، على سبيل المثال "03" secs ، فإن itoa يغطي هذا إلى أحرف ذات مسافة "3". if (secs< 10) { buffer = buffer; buffer = "0"; } puttinychar(20, 1, ":"); //seconds colon puttinychar(24, 1, buffer); //seconds puttinychar(28, 1, buffer); //seconds old_secs = secs; } //if minute changes change time if (mins != rtc) { //reset these for comparison next time mins = rtc; byte hours = rtc; if (hours > < 1) { hours = hours + ampm * 12; } //byte dow = rtc; // the DS1307 outputs 0 - 6 where 0 = Sunday0 - 6 where 0 = Sunday. //byte date = rtc; //set characters char buffer; itoa(hours, buffer, 10); //fix - as otherwise if num has leading zero, e.g. "03" hours, itoa coverts this to chars with space "3 ". if (hours < 10) { buffer = buffer; //if we are in 12 hour mode blank the leading zero. if (ampm) { buffer = " "; } else { buffer = "0"; } } //set hours chars textchar = buffer; textchar = buffer; textchar = ":"; itoa (mins, buffer, 10); if (mins < 10) { buffer = buffer; buffer = "0"; } //set mins characters textchar = buffer; textchar = buffer; //do seconds textchar = ":"; buffer; secs = rtc; itoa(secs, buffer, 10); //fix - as otherwise if num has leading zero, e.g. "03" secs, itoa coverts this to chars with space "3 ". if (secs < 10) { buffer = buffer; buffer = "0"; } //set seconds textchar = buffer; textchar = buffer; byte x = 0; byte y = 0; //print each char for (byte x = 0; x < 6 ; x++) { puttinychar(x * 4, 1, textchar[x]); } } delay(50); } fade_down(); } // basic_mode() // show the time in 5x7 characters void basic_mode() { cls(); char buffer; //for int to char conversion to turn rtc values into chars we can print on screen byte offset = 0; //used to offset the x postition of the digits and centre the display when we are in 12 hour mode and the clock shows only 3 digits. e.g. 3:21 byte x, y; //used to draw a clear box over the left hand "1" of the display when we roll from 12:59 ->1:00 صباحًا في وضع 12 ساعة. // قم بالتحويل 12/24 ساعة إذا تم ضبط الأمبير على 1 بايت ساعة = rtc ؛ إذا (ساعات> 12) (ساعات = ساعات - أمبير * 12 ؛) إذا (ساعات< 1) { hours = hours + ampm * 12; } //do offset conversion if (ampm && hours < 10) { offset = 2; } //set the next minute we show the date at //set_next_date(); // initially set mins to value 100 - so it wll never equal rtc on the first loop of the clock, meaning we draw the clock display when we enter the function byte secs = 100; byte mins = 100; int count = 0; //run clock main loop as long as run_mode returns true while (run_mode()) { //get the time from the clock chip get_time(); //check for button press if (buttonA.uniquePress()) { switch_mode(); return; } if (buttonB.uniquePress()) { display_date(); return; } //check whether it"s time to automatically display the date //check_show_date(); //draw the flashing: as on if the secs have changed. if (secs != rtc) { //update secs with new value secs = rtc; //draw: plot (15 - offset, 2, 1); //top point plot (15 - offset, 5, 1); //bottom point count = 400; } //if count has run out, turn off the: if (count == 0) { plot (15 - offset, 2, 0); //top point plot (15 - offset, 5, 0); //bottom point } else { count--; } //re draw the display if button pressed or if mins != rtc i.e. if the time has changed from what we had stored in mins, (also trigggered on first entering function when mins is 100) if (mins != rtc) { //update mins and hours with the new values mins = rtc; hours = rtc; //adjust hours of ampm set to 12 hour mode if (hours >12) (ساعات = ساعات - أمبير * 12 ؛) إذا (ساعات< 1) { hours = hours + ampm * 12; } itoa(hours, buffer, 10); //if hours < 10 the num e.g. "3" hours, itoa coverts this to chars with space "3 " which we dont want if (hours < 10) { buffer = buffer; buffer = "0"; } //print hours //if we in 12 hour mode and hours < 10, then don"t print the leading zero, and set the offset so we centre the display with 3 digits. if (ampm && hours < 10) { offset = 2; //if the time is 1:00am clear the entire display as the offset changes at this time and we need to blank out the old 12:59 if ((hours == 1 && mins == 0)) { cls(); } } else { //else no offset and print hours tens digit offset = 0; //if the time is 10:00am clear the entire display as the offset changes at this time and we need to blank out the old 9:59 if (hours == 10 && mins == 0) { cls(); } putnormalchar(1, 0, buffer); } //print hours ones digit putnormalchar(7 - offset, 0, buffer); //print mins //add leading zero if mins < 10 itoa (mins, buffer, 10); if (mins < 10) { buffer = buffer; buffer = "0"; } //print mins tens and ones digits putnormalchar(19 - offset, 0, buffer); putnormalchar(25 - offset, 0, buffer); } } fade_down(); } //like basic_mode but with slide effect void slide() { byte digits_old = {99, 99, 99, 99}; //old values we store time in. Set to somthing that will never match the time initially so all digits get drawn wnen the mode starts byte digits_new; //new digits time will slide to reveal byte digits_x_pos = {25, 19, 7, 1}; //x pos for which to draw each digit at char old_char; //used when we use itoa to transpose the current digit (type byte) into a char to pass to the animation function char new_char; //used when we use itoa to transpose the new digit (type byte) into a char to pass to the animation function //old_chars - stores the 5 day and date suffix chars on the display. e.g. "mon" and "st". We feed these into the slide animation as the current char when these chars are updated. //We sent them as A initially, which are used when the clocl enters the mode and no last chars are stored. //char old_chars = "AAAAA"; //plot the clock colon on the display cls(); putnormalchar(13, 0, ":"); byte old_secs = rtc; //store seconds in old_secs. We compare secs and old secs. WHen they are different we redraw the display //run clock main loop as long as run_mode returns true while (run_mode()) { get_time(); //check for button press if (buttonA.uniquePress()) { switch_mode(); return; } if (buttonB.uniquePress()) { display_date(); return; } //if secs have changed then update the display if (rtc != old_secs) { old_secs = rtc; //do 12/24 hour conversion if ampm set to 1 byte hours = rtc; if (hours >12) (ساعات = ساعات - أمبير * 12 ؛) إذا (ساعات< 1) { hours = hours + ampm * 12; } //split all date and time into individual digits - stick in digits_new array //rtc = secs //array pos and digit stored //digits_new = (rtc%10); //0 - secs ones //digits_new = ((rtc/10)%10); //1 - secs tens //rtc = mins digits_new = (rtc % 10); //2 - mins ones digits_new = ((rtc / 10) % 10); //3 - mins tens //rtc = hours digits_new = (hours % 10); //4 - hour ones digits_new = ((hours / 10) % 10); //5 - hour tens //rtc = date //digits_new = (rtc%10); //6 - date ones //digits_new = ((rtc/10)%10); //7 - date tens //draw initial screen of all chars. After this we just draw the changes. //compare digits 0 to 3 (mins and hours) for (byte i = 0; i <= 3; i++) { //see if digit has changed... if (digits_old[i] != digits_new[i]) { //run 9 step animation sequence for each in turn for (byte seq = 0; seq <= 8 ; seq++) { //convert digit to string itoa(digits_old[i], old_char, 10); itoa(digits_new[i], new_char, 10); //if set to 12 hour mode and we"re on digit 2 (hours tens mode) then check to see if this is a zero. If it is, blank it instead so we get 2.00pm not 02.00pm if (ampm && i == 3) { if (digits_new == 0) { new_char = " "; } if (digits_old == 0) { old_char = " "; } } //draw the animation frame for each digit slideanim(digits_x_pos[i], 0, seq, old_char, new_char); delay(SLIDE_DELAY); } } } /* //compare date digit 6 (ones) and (7) tens - if either of these change we need to update the date line. We compare date tens as say from Jan 31 ->01 شباط (فبراير) ، فإن رقم الآحاد لا يتغير إذا ((digits_old! = digits_new) || (digits_old! = digits_new)) (// غيّر اليوم المعروض. تمر الحلقة أدناه عبر كل من الأحرف الثلاثة بدورها ، على سبيل المثال "MON" من أجل (بايت day_char = 0 ؛ day_char<=2 ; day_char++){ //run the anim sequence for each char for (byte seq = 0; seq <=8 ; seq++){ //the day (0 - 6) Read this number into the days char array. the seconds number in the array 0-2 gets the 3 chars of the day name, e.g. m o n slideanim(6*day_char,8,seq,old_chars,days); //6 x day_char gives us the x pos for the char delay(SLIDE_DELAY); } //save the old day chars into the old_chars array at array pos 0-2. We use this next time we change the day and feed it to the animation as the current char. The updated char is fed in as the new char. old_chars = days; } //change the date tens digit (if needed) and ones digit. (the date ones digit wil alwaus change, but putting this in the "if" loop makes it a bit neater code wise.) for (byte i = 7; i >= 6 ؛ i -) (if (digits_old [i]! = digits_new [i]) (لـ (بايت 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,new_char); delay(SLIDE_DELAY); } } } //print the day suffix "nd" "rd" "th" etc. First work out date 2 letter suffix - eg st, nd, rd, th byte s = 3; //the pos to read our suffix array from. byte date = rtc; 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 suffix_char = 0; suffix_char <=1 ; suffix_char++){ for (byte seq = 0; seq <=8 ; seq++){ slideanim((suffix_char*6)+36,8,seq,old_chars,suffix[s]); // we pass in the old_char array char as the current char and the suffix array as the new char delay(SLIDE_DELAY); } //save the suffic char in the old chars array at array pos 3 and 5. We use these chars next time we change the suffix and feed it to the animation as the current char. The updated char is fed in as the new char. old_chars = suffix[s]; } }//end do date line */ //save digita array tol old for comparison next loop for (byte i = 0; i <= 3; i++) { digits_old[i] = digits_new[i]; } }//secs/oldsecs }//while loop fade_down(); } //called by slide //this draws the animation of one char sliding on and the other sliding off. There are 8 steps in the animation, we call the function to draw one of the steps from 0-7 //inputs are are char x and y, animation frame sequence (0-7) and the current and new chars being drawn. void slideanim(byte x, byte y, byte sequence, char current_c, char new_c) { // To slide one char off and another on we need 9 steps or frames in sequence... // seq# 0123456 <-rows of the display // | ||||||| // seq0 0123456 START - all rows of the display 0-6 show the current characters rows 0-6 // seq1 012345 current char moves down one row on the display. We only see it"s rows 0-5. There are at display positions 1-6 There is a blank row inserted at the top // seq2 6 01234 current char moves down 2 rows. we now only see rows 0-4 at display rows 2-6 on the display. Row 1 of the display is blank. Row 0 shows row 6 of the new char // seq3 56 0123 // seq4 456 012 half old / half new char // seq5 3456 01 // seq6 23456 0 // seq7 123456 // seq8 0123456 END - all rows show the new char //from above we can see... //currentchar runs 0-6 then 0-5 then 0-4 all the way to 0. starting Y position increases by 1 row each time. //new char runs 6 then 5-6 then 4-6 then 3-6. starting Y position increases by 1 row each time. //if sequence number is below 7, we need to draw the current char if (sequence < 7) { byte dots; // if (current_c >= "A" && || (current_c> = "a" && current_c<= "z")) { // current_c &= 0x1F; // A-Z maps to 1-26 // } if (current_c >= "A" && current_c<= "Z") { current_c &= 0x1F; // A-Z maps to 1-26 } else if (current_c >= "a" && current_c<= "z") { current_c = (current_c - "a") + 41; // A-Z maps to 41-67 } else if (current_c >= "0" && current_c<= "9") { current_c = (current_c - "0") + 31; } else if (current_c == " ") { current_c = 0; // space } else if (current_c == ".") { current_c = 27; // full stop } else if (current_c == "\"") { current_c = 28; // single quote mark } else if (current_c == ":") { current_c = 29; //colon } else if (current_c == ">") (current_c = 30؛ // clock_mode selector arrow) byteيرة_char_row_max = 7 - تسلسل ؛ // الحد الأقصى لعدد الصفوف المراد رسمها هو 6 - عدد البايت المتسلسل start_y = التسلسل ؛ // y موضع البدء عند - هو نفسه رقم التسلسل نحن نضع هذا في كل حلقة // نرسم كل صف حتى الصف الأقصى (محسوبًا من رقم التسلسل) لـ (byteurr_char_row = 0 ؛urr_char_row<= curr_char_row_max; curr_char_row++) { for (byte col = 0; col < 5; col++) { dots = pgm_read_byte_near(&myfont); if (dots & (64 >>urr_char_row)) قطعة الأرض (x + col ، y + start_y ، 1) ؛ // مؤامرة أدت إلى مؤامرة أخرى (x + col ، y + start_y ، 0) ؛ // else plot أدى) start_y ++ ؛ // أضف واحدًا إلى y لذلك نرسم الصف التالي واحدًا لأسفل)) // ارسم خطًا فارغًا بين الأحرف إذا كان التسلسل بين 1 و 7. إذا لم نفعل ذلك فسنحصل على بقيت بقايا الأحرف الحالية من آخر موضع على الشاشة إذا (التسلسل> = 1 && تسلسل<= 8) { for (byte col = 0; col < 5; col++) { plot(x + col, y + (sequence - 1), 0); //the y position to draw the line is equivalent to the sequence number - 1 } } //if sequence is above 2, we also need to start drawing the new char if (sequence >= 2) (// عمل char byte dots؛ // if (new_c> = "A" && new_c<= "Z" || (new_c >= "a" && new_c<= "z")) { // new_c &= 0x1F; // A-Z maps to 1-26 //} if (new_c >= "A" && new_c<= "Z") { new_c &= 0x1F; // A-Z maps to 1-26 } else if (new_c >= "a" && new_c<= "z") { new_c = (new_c - "a") + 41; // A-Z maps to 41-67 } else if (new_c >= "0" && new_c<= "9") { new_c = (new_c - "0") + 31; } else if (new_c == " ") { new_c = 0; // space } else if (new_c == ".") { new_c = 27; // full stop } else if (new_c == "\"") { new_c = 28; // single quote mark } else if (new_c == ":") { new_c = 29; // clock_mode selector arrow } else if (new_c == ">") (new_c = 30 ؛ / / سهم محدد الساعة_الساعة) بايت newcharrowmin = 6 - (تسلسل - 2) ؛ // minimumm row num للرسم من أجل char جديد - ينتج عن ذلك ناتج من 6 إلى 0 عند تغذية أرقام التسلسل 2-8 نحن ندخله في كل صف // نرسم كل صف من الصف الأدنى (محسوبًا برقم التسلسل) حتى 6 لـ (بايت newcharrow = newcharrowmin ؛ newcharrow<= 6; newcharrow++) { for (byte col = 0; col < 5; col++) { dots = pgm_read_byte_near(&myfont); if (dots & (64 >> newcharrow)) المؤامرة (x + col، y + start_y، 1) ؛ // مؤامرة أدت إلى مؤامرة أخرى (x + col ، y + start_y ، 0) ؛ // else plot أدى) start_y ++ ؛ // أضف واحدًا إلى y لذلك نرسم الصف التالي لأسفل))) // اطبع ساعة باستخدام الكلمات بدلاً من الأرقام باطل word_clock () (cls () ؛ أرقام char = ("one "،" اثنان "،" ثلاثة "،" أربعة "،" خمسة "،" ستة "،" سبعة "،" ثمانية "،" تسعة "،" عشرة "،" أحد عشر "،" اثني عشر "،" ثلاثة عشر "، "أربعة عشر" ، "خمسة عشر" ، "ستة عشر" ، "سبعة عشر" ، "ثمانية عشر" ، "تسعة عشر") ؛ شار numberstens = ("عشرة" ، "عشرين" ، "ثلاثون" ، "أربعون" ، "خمسون") ؛ // يحتمل أن تكون 3 أسطر لعرض char str_a؛ char str_b؛ char str_c؛ // byte hours_y، mins_y؛ // الساعات والدقائق والمواضع للساعات والدقائق من الأسطر بايت ساعات = rtc ؛ إذا كانت (ساعات> 12) (ساعات = ساعات - أمبير * 12 ؛) إذا (ساعات< 1) { hours = hours + ampm * 12; } get_time(); //get the time from the clock chip byte old_mins = 100; //store mins in old_mins. We compare mins and old mins & when they are different we redraw the display. Set this to 100 initially so display is drawn when mode starts. byte mins; //run clock main loop as long as run_mode returns true while (run_mode()) { //check for button press if (buttonA.uniquePress()) { switch_mode(); return; } if (buttonB.uniquePress()) { display_date(); } get_time(); //get the time from the clock chip mins = rtc; //get mins //if mins is different from old_mins - redraw display if (mins != old_mins) { //update old_mins with current mins value old_mins = mins; //reset these for comparison next time mins = rtc; hours = rtc; //make hours into 12 hour format if (hours >12) (ساعات = ساعات - 12 ؛) إذا (ساعات == 0) (ساعات = 12 ؛) // قسمة قيمة الدقائق إلى رقمين منفصلين int minsdigit = rtc٪ 10 ؛ البايت minsdigitten = (rtc / 10)٪ 10 ؛ // إذا دقيقة<= 10 , then top line has to read "minsdigti past" and bottom line reads hours if (mins < 10) { strcpy (str_a, numbers); strcpy (str_b, "PAST"); strcpy (str_c, numbers); } //if mins = 10, cant use minsdigit as above, so soecial case to print 10 past /n hour. if (mins == 10) { strcpy (str_a, numbers); strcpy (str_b, " PAST"); strcpy (str_c, numbers); } //if time is not on the hour - i.e. both mins digits are not zero, //then make first line read "hours" and 2 & 3rd lines read "minstens" "mins" e.g. "three /n twenty /n one" else if (minsdigitten != 0 && minsdigit != 0) { strcpy (str_a, numbers); //if mins is in the teens, use teens from the numbers array for the 2nd line, e.g. "fifteen" //if (mins >= 11 && دقيقة<= 19) { if (mins <= 19) { strcpy (str_b, numbers); } else { strcpy (str_b, numberstens); strcpy (str_c, numbers); } } // if mins digit is zero, don"t print it. read read "hours" "minstens" e.g. "three /n twenty" else if (minsdigitten != 0 && minsdigit == 0) { strcpy (str_a, numbers); strcpy (str_b, numberstens); strcpy (str_c, ""); } //if both mins are zero, i.e. it is on the hour, the top line reads "hours" and bottom line reads "o"clock" else if (minsdigitten == 0 && minsdigit == 0) { strcpy (str_a, numbers); strcpy (str_b, "O"CLOCK"); strcpy (str_c, ""); } }//end worknig out time //run in a loop //print line a "twelve" byte len = 0; while (str_a) { len++; }; //get length of message byte offset_top = (31 - ((len - 1) * 4)) / 2; // //plot hours line byte i = 0; while (str_a[i]) { puttinychar((i * 4) + offset_top, 1, str_a[i]); i++; } //hold display but check for button presses int counter = 1000; while (counter >0) (// تحقق من الضغط على الزر إذا كان (buttonA.uniquePress ()) (switch_mode () ؛ رجوع ؛) if (buttonB.uniquePress ()) (display_date () ؛) تأخير (1) ؛ counter-- ؛) fade_down () ؛ // طباعة الخط ب لين = 0 ؛ بينما (str_b) (لين ++ ؛) ؛ // الحصول على طول الرسالة offset_top = (31 - ((len - 1) * 4)) / 2 ؛ أنا = 0 ؛ while (str_b [i]) (puttinychar ((i * 4) + offset_top، 1، str_b [i])؛ i ++؛) // عقد العرض ولكن تحقق من عداد ضغطات الزر = 1000 ؛ while (counter> 0) (if (buttonA.uniquePress ()) (switch_mode () ؛ رجوع ؛) if (buttonB.uniquePress ()) (display_date () ؛) تأخير (1) ؛ counter-- ؛) fade_down () ؛ // طباعة الخط c إذا كان هناك. لين = 0 ؛ بينما (str_c) (لين ++ ؛) ؛ // الحصول على طول الرسالة offset_top = (31 - ((len - 1) * 4)) / 2 ؛ أنا = 0 ؛ while (str_c [i]) (puttinychar ((i * 4) + offset_top، 1، str_c [i])؛ i ++؛) عداد = 1000 ؛ while (counter> 0) (// تحقق من الضغط على الزر إذا (buttonA.uniquePress ()) (switch_mode () ؛ رجوع ؛) إذا (buttonB.uniquePress ()) (display_date () ؛) تأخير (1) ؛ عداد- - ؛) fade_down () ؛ / / عقد الشاشة فارغة ولكن تحقق من الضغط على الزر قبل البدء مرة أخرى. عداد = 1000 ؛ while (counter> 0) (// تحقق من الضغط على الزر إذا (buttonA.uniquePress ()) (switch_mode () ؛ رجوع ؛) إذا (buttonB.uniquePress ()) (display_date () ؛) تأخير (1) ؛ عداد- - ؛)) fade_down () ؛ ) /// رسالة التمرير - غير مستخدمة حاليًا - بطيئة جدًا. تمرير باطل () (char message = ("Hello There") ؛ cls () ؛ البايت p = 6 ؛ // الموضع الحالي في سلسلة بايت chara = (0 ، 1 ، 2 ، 3 ، 4 ، 5) ؛ // chars من السلسلة int x = (0، 6، 12، 18، 24، 30)؛ // xpos لكل حرف بايت y = 0؛ // y pos // clear_buffer ()؛ while (message [p]! = "\ 0 ") (// ارسم كل الأحرف الستة من أجل (البايت c = 0 ؛ ج< 6; c++) { putnormalchar(x[c],y,message[ chara[c] ]); //draw a line of pixels turned off after each char,otherwise the gaps between the chars have pixels left in them from the previous char for (byte yy = 0 ; yy < 8; yy ++) { plot(x[c] + 5, yy, 0); } //take one off each chars position x[c] = x[c] - 1; } //reset a char if it"s gone off screen for (byte i = 0; i <= 5; i++) { if (x[i] < -5) { x[i] = 31; chara[i] = p; p++; } } } } //display_date - print the day of week, date and month with a flashing cursor effect void display_date() { cls(); //read the date from the DS1307 byte dow = rtc; // day of week 0 = Sunday byte date = rtc; byte month = rtc - 1; //array of month names to print on the display. Some are shortened as we only have 8 characters across to play with char monthnames = { "January", "February", "March", "April", "May", "June", "July", "August", "Sept", "October", "November", "December" }; //print the day name //get length of text in pixels, that way we can centre it on the display by divindin the remaining pixels b2 and using that as an offset byte len = 0; while(daysfull) { len++; }; byte offset = (31 - ((len-1)*4)) / 2; //our offset to centre up the text //print the name int i = 0; while(daysfull[i]) { puttinychar((i*4) + offset , 1, daysfull[i]); i++; } delay(1000); fade_down(); cls(); // print date numerals char buffer; itoa(date,buffer,10); offset = 10; //offset to centre text if 3 chars - e.g. 3rd // first work out date 2 letter suffix - eg st, nd, rd, th etc // char suffix={"st", "nd", "rd", "th" }; is defined at top of code byte 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; } //print the 1st date number puttinychar(0+offset, 1, buffer); //if date is under 10 - then we only have 1 digit so set positions of sufix etc one character nearer byte suffixposx = 4; //if date over 9 then print second number and set xpos of suffix to be 1 char further away if (date >9) (اللاحقة = 8 ؛ puttinychar (4 + offset ، 1 ، buffer) ؛ الإزاحة = 8 ؛ // الإزاحة إلى النص المركزي إذا كانت 4 أحرف) // اطبع حرفين لاحقتين puttinychar (لاحقة + إزاحة ، 1 ، لاحقة [s ]) ؛ puttinychar (لاحقة + 4 + إزاحة ، 1 ، لاحقة [ق]) ؛ تأخير (1000) ؛ fade_down () ؛ // print the month name // احصل على طول النص بالبكسل ، وبهذه الطريقة يمكننا توسيطه على الشاشة عن طريق divindin وحدات البكسل المتبقية b2 واستخدام ذلك كإزاحة len = 0 ؛ while (monthnames) (len ++ ؛) ؛ الإزاحة = (31 - ((لين -1) * 4)) / 2 ؛ // الإزاحة الخاصة بنا لتوسيط النص i = 0 ؛ while (monthnames [i]) (puttinychar ((i * 4) + offset، 1، monthnames [i])؛ i ++؛) تأخير (1000) ؛ fade_down () ؛ ) // قائمة dislpay لتغيير وضع الساعة باطل switch_mode () (// وضع التذكر الذي نحن فيه. نستخدم هذه القيمة إذا انتقلنا إلى وضع الإعدادات ، حتى نتمكن من التغيير مرة أخرى من وضع الإعدادات (6) إلى أي وضع كنا فيه في. old_mode = clock_mode ؛ أوضاع char * = ("أساسي" ، "صغير" ، "شريحة" ، "كلمات" ، "إعداد") ؛ بايت next_clock_mode ؛ بايت firstrun = 1 ؛ // حلقة انتظار للزر (مهلة بعد 35 حلقات للعودة إلى الوضع X) من أجل (عدد العمليات = 0 ؛ عدد< 35 ; count++) { //if user hits button, change the clock_mode if (buttonA.uniquePress() || firstrun == 1) { count = 0; cls(); if (firstrun == 0) { clock_mode++; } if (clock_mode >NUM_DISPLAY_MODES + 1) (clock_mode = 0 ؛) // طباعة السهم واسم وضع الساعة الحالي في السطر الأول وطباعة اسم وضع الساعة التالي على السطر الثاني char str_top ؛ // strcpy (str_top، "-") ؛ strcpy (str_top ، أوضاع) ؛ next_clock_mode = clock_mode + 1 ؛ إذا (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 ؛ ) تأخير (50) ؛ )) // قم بتشغيل الحلقة الرئيسية على مدار الساعة طالما أن run_mode ترجع البايت الحقيقي run_mode () (// إذا كان الوضع العشوائي قيد التشغيل ... تحقق من الساعة عندما نغير الوضع. إذا (الوضع العشوائي) (// إذا كانت قيمة الساعة في وضع التغيير الوقت = ساعات ، ثم أعد العودة إلى الخطأ = أي وضع الخروج. / else return 1 - استمر في العمل في هذا الوضع ، رجوع 1 ؛) / / اضبط الساعة التالية التي ستغير فيها الساعة الوضع عندما يكون الوضع العشوائي في باطل set_next_random () (/ / اضبط الساعة التالية التي سيتغير فيها وضع الساعة - الوقت الحالي زائد 1-4 ساعات get_time () ؛ change_mode_time = rtc + عشوائي (1 ، 5) ؛ // إذا كان وقت change_mode_time يتجاوز 23 عامًا ، فاضبطه على ما بين 1 و 3 صباحًا إذا (change_mode_time> 23) (change_mode_time = عشوائي (1 ، 4) ؛) // اضبط وضع الساعة الجديد clock_mode = عشوائي (0 ، NUM_DISPLAY_MODES + 1) ؛ // اختر وضع الساعة العشوائي الجديد) // قائمة dislpay لتغيير إعدادات الساعة باطل setup_menu () ( char * set_modes = ("Rndom"، "24 Hr"، "Set"، "Brght"، "Exit")؛ إذا (ampm == 0) (set_modes = ("12 Hr") ؛) byte setting_mode = 0 ؛ بايت next_setting_mode ؛ البايت الأول = 1 ؛ // حلقة انتظار للزر (مهلة بعد 35 حلقة للعودة إلى الوضع X) من أجل (عدد العمليات = 0 ؛ العد< 35 ; count++) { //if user hits button, change the clock_mode if(buttonA.uniquePress() || firstrun == 1){ count = 0; cls(); if (firstrun == 0) { setting_mode++; } if (setting_mode >NUM_SETTINGS_MODES) (setting_mode = 0 ؛) // طباعة السهم واسم وضع الساعة الحالي في السطر الأول وطباعة اسم Clock_mode التالي على السطر الثاني char str_top ؛ strcpy (str_top، set_modes) ؛ next_setting_mode = setting_mode + 1 ، إذا (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 ؛ ) تأخير (50) ؛ ) // اختر مفتاح الوضع (وضع_الضبط) (الحالة 0: set_random () ؛ كسر ؛ الحالة 1: set_ampm () ؛ استراحة ؛ الحالة 2: set_time () ؛ استراحة ؛ الحالة 3: set_intensity () ؛ استراحة ؛ الحالة 4: // الخروج من فاصل القائمة ؛) // تغيير الساعة من الوضع 6 (الإعدادات) إلى الساعة التي كانت عليها قبل clock_mode = old_mode ؛ ) // تبديل الوضع العشوائي - اختر وضع ساعة مختلفًا كل بضع ساعات باطل set_random () (cls () ؛ char text_a = "Off" ؛ char text_b = "On" ؛ البايت i = 0 ؛ // إذا كان الوضع العشوائي قيد التشغيل ، قم بإيقاف تشغيله إذا (وضع عشوائي) (// إيقاف تشغيل الوضع العشوائي random_mode = 0 ؛ // طباعة رسالة على الشاشة أثناء (text_a [i]) (putnormalchar ((i * 6)، 0، text_a [i]) ؛ i ++؛)) else (// تشغيل الوضع العشوائي. random_mode = 1 ؛ // سيغير وضع الساعة set_next_random () ؛ // طباعة رسالة على الشاشة أثناء (text_b [i]) (putnormalchar ((i * 6) ، 0 ، text_b [i]) ؛ i ++ ؛)) تأخير (1500) ؛ // اترك الرسالة لمدة ثانية أو نحو ذلك) // تعيين 12 أو 24 ساعة على مدار الساعة فارغة set_ampm () (// صباحًا / مساءً أو وضع 24 ساعة - اقلب البت (يجعل 0 إلى 1 ، أو 1 إلى 0 لوضع أمبير) أمبير = (أمبير ^ 1) ؛ cls () ؛) // تغيير كثافة الشاشة باطل set_intensity () (cls () ؛ byte i = 0؛ char text = "Bright"؛ while (text [i]) (puttinychar ((i * 4) +4، 0، text [i])؛ i ++؛) // انتظر إدخال الزر أثناء (! زر ألف فريد الصحافة ()) ( شريط المستوى (0.6 ، (الكثافة * 2) +2.2) ؛ // اعرض مستوى الشدة على شكل شريط بينما (buttonB.isPressed ()) (if (كثافة == 15) (كثافة = 0 ؛ cls () ؛) آخر (كثافة ++ ؛) // اطبع القيمة الجديدة i = 0 ؛ while (text [i]) (puttinychar ((i * 4) +4، 0، text [i])؛ i ++؛) // عرض مستوى الشدة كشريط مستوى شريط (0،6، (كثافة * 2) + 2،2) ؛ // تغيير إعداد السطوع على شاشات العرض (عنوان البايت = 0 ؛ العنوان< 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, ybar void levelbar (byte xpos, byte ypos, byte xbar, byte ybar) { for (byte x = 0; x < xbar; x++) { for (byte y = 0; y <= ybar; y++) { plot(x+xpos, y+ypos, 1); } } } //set time and date routine void set_time() { cls(); //fill settings with current clock values read from clock get_time(); byte set_min = rtc; byte set_hr = rtc; byte set_date = rtc; byte set_mnth = rtc; int set_yr = rtc; //Set function - we pass in: which "set" message to show at top, current value, reset value, and rollover limit. set_date = set_value(2, set_date, 1, 31); set_mnth = set_value(3, set_mnth, 1, 12); set_yr = set_value(4, set_yr, 2013, 2099); set_hr = set_value(1, set_hr, 0, 23); set_min = set_value(0, set_min, 0, 59); ds1307.adjust(DateTime(set_yr, set_mnth, set_date, set_hr, set_min)); cls(); } //used to set min, hr, date, month, year values. pass //message = which "set" message to print, //current value = current value of property we are setting //reset_value = what to reset value to if to rolls over. E.g. mins roll from 60 to 0, months from 12 to 1 //rollover limit = when value rolls over int set_value(byte message, int current_value, int reset_value, int rollover_limit){ cls(); char messages = { "Set Mins", "Set Hour", "Set Day", "Set Mnth", "Set Year"}; //Print "set xyz" top line byte i = 0; while(messages[i]) { puttinychar(i*4 , 1, messages[i]); i++; } delay(2000); cls(); //print digits bottom line char buffer = " "; itoa(current_value,buffer,10); puttinychar(0 , 1, buffer); puttinychar(4 , 1, buffer); puttinychar(8 , 1, buffer); puttinychar(12, 1, buffer); delay(300); //wait for button input while (!buttonA.uniquePress()) { while (buttonB.isPressed()){ if(current_value < rollover_limit) { current_value++; } else { current_value = reset_value; } //print the new value itoa(current_value, buffer ,10); puttinychar(0 , 1, buffer); puttinychar(4 , 1, buffer); puttinychar(8 , 1, buffer); puttinychar(12, 1, buffer); delay(150); } } return current_value; } void get_time() { //get time DateTime now = ds1307.now(); //save time to array rtc = now.year(); rtc = now.month(); rtc = now.day(); rtc = now.dayOfWeek(); //returns 0-6 where 0 = Sunday rtc = now.hour(); rtc = now.minute(); rtc = now.second(); //flash arduino led on pin 13 every second //if ((rtc % 2) == 0) { // digitalWrite(13, HIGH); //} //else { // digitalWrite(13, LOW); //} //print the time to the serial port - useful for debuging RTC issues /* Serial.print(rtc); Serial.print(":"); Serial.print(rtc); Serial.print(":"); Serial.println(rtc); */ }

الآن ، لإكمال العمل على الجهاز ، ما عليك سوى إجراء عدد من العمليات البسيطة:


سيستغرق تجميع رمز البرنامج والتحميل الإضافي في ذاكرة وحدة التحكم الدقيقة بعض الوقت ، وعادة لا تزيد عن دقيقة واحدة. سيتم الإبلاغ عن اكتمال العملية بنجاح في وحدة تحكم Arduino IDE. بعد ذلك ، يبقى فقط إعادة تشغيل Arduino باستخدام زر إعادة الضبط على الجهاز - ساعة بسيطة على مصفوفات LED جاهزة!

ساعة جاهزة على اردوينو

يتم ضبط الساعة باستخدام زرين. يدعم الجهاز تنسيق الوقت 12 و 24 ساعة ، عرض التاريخ واليوم من الأسبوع ، عرض الوقت بالثواني وبدونها. من الممكن أيضًا تغيير سطوع مصابيح LED.


قد ترغب في إضافة المزيد من الميزات لاحقًا (مثل مقياس الحرارة) ، أو تثبيت الجهاز في علبة التصميم الخاصة بك - يمكن تحقيق نتائج جيدة من خلال تصنيع القطع بالليزر. ولكن الآن يمكنك القول بأمان أنك قمت بتجميع ساعة إلكترونية كاملة بيديك!

أقترح لتكرار مخطط ساعة إلكترونية بسيطة مع منبه ، مصنوع على نوع PIC16F628A. إضافة كبيرة لهذه الساعة هي مؤشر LED لنوع ALS لعرض الوقت. أنا شخصياً تعبت من جميع أنواع شاشات LCD وأريد أن أكون قادرًا على رؤية الوقت من أي مكان في الغرفة ، بما في ذلك في الظلام ، وليس فقط مع الإضاءة الجيدة. تحتوي الدائرة على الحد الأدنى من التفاصيل ولديها قابلية تكرار ممتازة. تم اختبار الساعة لمدة شهر ، مما أظهر موثوقيتها وأدائها. أفكر في جميع المخططات على الإنترنت ، هذا هو أسهل تجميع وتشغيل.

رسم تخطيطي لساعة إلكترونية مع منبه على متحكم دقيق:


كما يتضح من مخطط الساعة ، فهي الدائرة الدقيقة الوحيدة المستخدمة في هذا الجهاز. لضبط تردد الساعة ، يتم استخدام مرنان كوارتز 4 ميجا هرتز. لعرض الوقت ، يتم استخدام مؤشرات حمراء ذات أنود مشترك ، ويتكون كل مؤشر من رقمين مع علامات عشرية. في حالة استخدام باعث بيزو ، يمكن حذف المكثف C1 - 100 ميكروفاراد.

يمكنك استخدام أي مؤشرات مع أنود مشترك ، طالما أن لكل رقم أنود خاص به. لكي تكون الساعة الإلكترونية مرئية بوضوح في الظلام ومن مسافة بعيدة ، حاول اختيار ALS-ki الأكبر.


يتم عرض الساعة ديناميكيًا. في هذه المرحلة المحددة من الوقت ، يتم عرض رقم واحد فقط ، والذي يمكن أن يقلل بشكل كبير من الاستهلاك الحالي. يتم التحكم في الأنودات لكل رقم بواسطة متحكم PIC16F628A. يتم توصيل الأجزاء المكونة من أربعة أرقام معًا ومتصلة بأطراف منفذ MK من خلال مقاومات تحديد التيار R1 ... R8. نظرًا لأن المؤشر يضيء بسرعة كبيرة ، فإن وميض الأرقام يصبح غير محسوس.


لضبط الدقائق والساعات والإنذارات ، يتم استخدام أزرار الضغط. يتم استخدام Pin 10 كمخرج لإشارة الإنذار ، ويتم استخدام سلسلة على الترانزستورات VT1،2 كمضخم. باعث الصوت هو عنصر كهرضغطية من نوع ZP. لتحسين الصوت ، يمكنك وضع مكبر صوت صغير بدلاً من ذلك.


يتم تشغيل الساعة بواسطة مصدر 5V مستقر. يمكن أيضا أن تعمل بالبطارية. تحتوي الساعة على 9 أوضاع عرض. يتم الانتقال من خلال الوضعين باستخدام أزرار "+" و "-". قبل عرض المؤشرات نفسها ، يتم عرض تلميح قصير لاسم الوضع على المؤشرات. مدة إخراج التلميح ثانية واحدة.


باستخدام زر "التصحيح" ، يتم تحويل الساعة - المنبه إلى وضع الإعدادات. في هذه الحالة ، يتم عرض موجه قصير لمدة نصف ثانية ، وبعد ذلك تبدأ القيمة المصححة في الوميض. يتم تصحيح المؤشرات بواسطة الأزرار "+" و "-". عند الضغط على الزر لفترة طويلة ، يتم تنشيط وضع التكرار التلقائي بتردد معين. تتم كتابة جميع القيم ، باستثناء الساعات والدقائق والثواني ، على EEPROM واستعادتها بعد إيقاف التشغيل - تشغيل الطاقة.


إذا لم يتم الضغط على أي من الأزرار في غضون ثوانٍ قليلة ، تتحول الساعة الإلكترونية إلى وضع عرض الوقت. بالضغط على زر "تشغيل / إيقاف" ، يتم تشغيل المنبه أو إيقاف تشغيله ، ويتم تأكيد هذا الإجراء بصوت قصير. عند تشغيل المنبه ، تضيء النقطة الموجودة في رقم الترتيب المنخفض في المؤشر. فكرت في مكان إرفاق الساعة في المطبخ ، وقررت تركيبها مباشرة في موقد الغاز :) تم إرسال المواد بواسطة in_sane.


ناقش المقال Electronic CLOCK ALARM CLOCK

يا geektimes! في الجزء الأول من المقال ، تم النظر في مبادئ الحصول على الوقت المحدد لساعة محلية الصنع. دعنا نذهب إلى أبعد من ذلك ونفكر في كيفية وما هو الأفضل لعرضه هذه المرة.

1. أجهزة الإخراج

لذلك ، لدينا منصة معينة (Arduino ، Raspberry ، PIC / AVR / STM controller ، إلخ) ، والمهمة هي توصيل نوع من المؤشرات بها. هناك العديد من الخيارات التي سننظر فيها.

عرض الجزء

كل شيء بسيط هنا. يتكون مؤشر المقطع من مصابيح LED عادية ، وهي متصلة بشكل حقيقي بالمتحكم الدقيق من خلال مقاومات التبريد.

احذر من حركة المرور!

الإيجابيات: تصميم بسيط ، زوايا مشاهدة جيدة ، سعر منخفض.
ناقص: كمية المعلومات المعروضة محدودة.
يوجد نوعان من تصميمات المؤشرات ، مع الكاثود المشترك والأنود المشترك ، يبدو بداخله شيئًا كهذا (الرسم التخطيطي من موقع الشركة المصنعة على الويب).

هناك 1001 مقالة حول كيفية توصيل مصباح LED بجهاز تحكم دقيق ، Google للمساعدة. تبدأ الصعوبات عندما نريد صنع ساعة كبيرة - بعد كل شيء ، فإن النظر إلى مؤشر صغير ليس مريحًا للغاية. ثم نحتاج إلى مثل هذه المؤشرات (صورة من eBay):

يتم تشغيلها بجهد 12 فولت ، ولن تعمل ببساطة مباشرة من وحدة التحكم الدقيقة. هذا هو المكان الذي تأتي فيه الرقاقة الدقيقة للإنقاذ. CD4511، مصمم لذلك فقط. فهو لا يحول البيانات من خط 4 بت إلى الأرقام المطلوبة فحسب ، بل يحتوي أيضًا على مفتاح ترانزستور مدمج لتزويد المؤشر بالجهد الكهربي. وبالتالي ، في الدائرة ، سنحتاج إلى جهد "طاقة" من 9 إلى 12 فولت ، ومحول منفصل (على سبيل المثال ، L7805) لتشغيل "منطق" الدائرة.

مؤشرات المصفوفة

في الواقع ، هذه هي نفس مصابيح LED ، فقط في شكل مصفوفة 8x8. صورة من موقع eBay:

تباع على موقع eBay على شكل وحدات مفردة أو كتل جاهزة ، على سبيل المثال ، 4 قطع. إدارتها بسيطة للغاية - إن الدائرة المصغرة ملحومة بالفعل على الوحدات ماكس 7219، مما يضمن تشغيلها وتوصيلها بالميكروكونترولر بخمسة أسلاك فقط. هناك العديد من المكتبات الخاصة بـ Arduino ، أولئك الذين يرغبون في الاطلاع على الكود.
الإيجابيات: سعر منخفض ، زوايا مشاهدة جيدة وسطوع.
السلبيات: دقة منخفضة. لكن مهمة إخراج الوقت كافية.

مؤشرات LCD

مؤشرات LCD هي رسومية ونصية.

الرسوم البيانية أكثر تكلفة ، لكنها تسمح لك بعرض معلومات أكثر تنوعًا (على سبيل المثال ، رسم بياني للضغط الجوي). تعتبر النصوص النصية أرخص وأسهل في التعامل معها ، كما أنها تتيح لك عرض رسومات زائفة - من الممكن تحميل أحرف مخصصة على الشاشة.

ليس من الصعب العمل مع مؤشر LCD من الكود ، ولكن هناك ناقصًا معينًا - يتطلب المؤشر الكثير من خطوط التحكم (من 7 إلى 12) من وحدة التحكم الدقيقة ، وهو أمر غير مريح. لذلك ، توصل الصينيون إلى فكرة الجمع بين مؤشر LCD ووحدة تحكم i2c ، والتي اتضح أنها مريحة للغاية في النهاية - 4 أسلاك فقط كافية للاتصال (صورة من eBay).


مؤشرات LCD رخيصة جدًا (إذا كنت تأخذها على eBay) ، كبيرة الحجم ، يسهل توصيلها ، ويمكنك عرض مجموعة متنوعة من المعلومات. السلبية الوحيدة ليست زوايا مشاهدة كبيرة جدًا.

مؤشرات OLED

إنها استمرار محسّن للإصدار السابق. وهي تتراوح من 1.1 بوصة صغيرة ورخيصة إلى كبيرة ومكلفة. صور من موقع eBay.

في الواقع ، كل شيء جيد باستثناء السعر. أما بالنسبة للمؤشرات الصغيرة ، 0.9-1.1 "في الحجم ، فمن الصعب العثور على أي تطبيق عملي لها (باستثناء تعلم كيفية العمل مع i2c).

مؤشرات تصريف الغاز (IN-14 ، IN-18)

أصبحت هذه المؤشرات الآن شائعة جدًا ، على ما يبدو بسبب "صوت المصباح الدافئ للضوء" وأصالة التصميم.


(الصورة من nocrotec.com)

مخطط اتصالهم أكثر تعقيدًا إلى حد ما ، لأن. تستخدم مؤشرات الإشعال هذه جهدًا يبلغ 170 فولت. يمكن إجراء المحول من 12V => 180V على شريحة ماكس 771. يتم استخدام دائرة كهربائية صغيرة سوفيتية لتزويد المؤشرات بالجهد الكهربي. K155ID1الذي تم إنشاؤه خصيصًا لهذا الغرض. سعر الإصدار للتصنيع الذاتي: حوالي 500 روبل لكل مؤشر و 100 روبل لـ K155ID1 ، جميع التفاصيل الأخرى ، كما كتبوا في المجلات القديمة ، "لا يوجد نقص في المعروض". تكمن الصعوبة الرئيسية هنا في أن كلاً من IN-xx و K155ID1 قد توقف إنتاجهما منذ فترة طويلة ، ولا يمكنك شرائهما إلا في أسواق الراديو أو في عدد قليل من المتاجر المتخصصة.

2. اختيار المنصة

لقد اكتشفنا المؤشر بشكل أو بآخر ، ويبقى أن نقرر أي نظام أساسي للأجهزة هو الأفضل للاستخدام. هناك العديد من الخيارات هنا (لا أعتبر الخيارات محلية الصنع ، لأن أولئك الذين يعرفون كيفية فصل اللوحة عن المعالج لا يحتاجون إلى هذه المقالة).

اردوينو

أسهل خيار للمبتدئين. اللوحة النهائية غير مكلفة (حوالي 10 دولارات على موقع eBay مع الشحن المجاني) ، وتحتوي على جميع الموصلات اللازمة للبرمجة. صورة من موقع eBay:

يوجد تحت Arduino عدد كبير من المكتبات المختلفة (على سبيل المثال ، لشاشات LCD نفسها ، وحدات الوقت الفعلي) ، Arduino هو جهاز متوافق مع العديد من الوحدات الإضافية.
العيب الرئيسي: تعقيد التصحيح (فقط من خلال وحدة التحكم في المنفذ التسلسلي) ومعالج ضعيف نوعًا ما وفقًا للمعايير الحديثة (2KB RAM و 16 MHz).
الإضافة الرئيسية: يمكنك القيام بالكثير من الأشياء ، عمليًا دون القلق من اللحام ، وشراء مبرمج وألواح أسلاك ، يكفي توصيل الوحدات ببعضها البعض.

معالجات STM 32 بت

بالنسبة لأولئك الذين يريدون شيئًا أكثر قوة ، هناك لوحات جاهزة مع معالجات STM ، على سبيل المثال ، لوحة مع STM32F103RBT6 وشاشة TFT. صورة من موقع eBay:

هنا لدينا بالفعل تصحيح أخطاء كامل في IDE كامل (من بين جميع الأنواع المختلفة ، أحببت Coocox IDE أكثر) ، ومع ذلك ، ستحتاج إلى مصحح أخطاء ST-LINK منفصل مع موصل JTAG (سعر الإصدار 20 دولارًا- 40 على موقع ئي باي). بدلاً من ذلك ، يمكنك شراء لوحة تصحيح الأخطاء STM32F4Discovery ، والتي تم دمج هذا المبرمج فيها بالفعل ، ويمكن استخدامها بشكل منفصل.

فطيرة التوت

وأخيرًا ، بالنسبة لأولئك الذين يريدون الاندماج الكامل مع العالم الحديث ، هناك أجهزة كمبيوتر أحادية اللوحة مع Linux ، وربما يعرف الجميع بالفعل Raspberry PI. صورة من موقع eBay:

هذا كمبيوتر كامل مع Linux وذاكرة وصول عشوائي (RAM) بسعة جيجابايت ومعالج رباعي النواة. يتم عرض لوحة مكونة من 40 سنًا على حافة اللوحة ، مما يسمح لك بتوصيل العديد من الأجهزة الطرفية (تتوفر المسامير من الكود ، على سبيل المثال ، في Python ، ناهيك عن C / C ++) ، وهناك أيضًا USB قياسي في شكل 4 موصلات (يمكنك توصيل WiFi). هناك أيضًا معيار HDMI.
قوة اللوحة كافية ، على سبيل المثال ، ليس فقط لعرض الوقت ، ولكن أيضًا لتشغيل خادم HTTP لضبط المعلمات عبر واجهة الويب ، وتنزيل توقعات الطقس عبر الإنترنت ، وما إلى ذلك. بشكل عام ، فإن نطاق رحلة خيالية كبير.

هناك صعوبة واحدة فقط في Raspberry (ومعالجات STM32) - تستخدم دبابيسه منطق 3V ، ومعظم الأجهزة الخارجية (على سبيل المثال ، شاشات LCD) تعمل "بالطريقة القديمة" من 5V. بالطبع ، يمكنك توصيلها بهذه الطريقة ، من حيث المبدأ ، ستنجح ، لكن هذه ليست الطريقة الصحيحة تمامًا ، ومن المؤسف إلى حد ما تدمير لوحة الـ 50 دولارًا. الطريقة الصحيحة هي استخدام "محول المستوى المنطقي" ، والذي يكلف 1-2 دولار فقط على موقع eBay.
صورة من موقع eBay:

الآن يكفي توصيل أجهزتنا من خلال هذه الوحدة ، وسيتم تنسيق جميع المعلمات.

ESP8266

هذه الطريقة غريبة نوعًا ما ، ولكنها واعدة نظرًا لاكتناز الحل ورخصه. مقابل القليل جدًا من المال (حوالي 4-5 دولارات أمريكية على موقع eBay) ، يمكنك شراء وحدة ESP8266 تحتوي على معالج وشبكة WiFi على متنها.
صورة من موقع eBay:

في البداية ، كان الغرض من هذه الوحدات هو أن تكون جسر WiFi للتبادل عبر منفذ تسلسلي ، ومع ذلك ، فقد كتب المتحمسون الكثير من البرامج الثابتة البديلة التي تتيح لك العمل مع أجهزة الاستشعار وأجهزة i2c و PWM وما إلى ذلك. افتراضيًا ، من الممكن جدًا الحصول على الوقت من خادم NTP وعرضه عبر i2c على الشاشة. بالنسبة لأولئك الذين يرغبون في توصيل الكثير من الأجهزة الطرفية المختلفة ، هناك لوحات NodeMCU خاصة بها عدد كبير من المسامير ، وسعر الإصدار حوالي 500 روبل (بالطبع ، على موقع eBay):

العيب الوحيد هو أن ESP8266 يحتوي على ذاكرة وصول عشوائي (RAM) قليلة جدًا (اعتمادًا على البرامج الثابتة ، من 1 إلى 32 كيلو بايت) ، ولكن هذا يجعل المهمة أكثر إثارة للاهتمام. تستخدم وحدات ESP8266 منطق 3 فولت ، لذلك سيكون محول المستوى أعلاه مفيدًا أيضًا هنا.

في هذا الصدد ، يمكن إكمال رحلة تمهيدية في الإلكترونيات محلية الصنع ، ويتمنى المؤلف للجميع تجارب ناجحة.

بدلا من الاستنتاج

استقررت أخيرًا على استخدام Raspberry PI مع مؤشر نص مهيأ للعمل مع رسومات زائفة (والتي تبين أنها أرخص من شاشة رسومية من نفس القطر). التقطت صورة لشاشة ساعة سطح المكتب أثناء كتابة هذا المقال.

تعرض الساعة الوقت المحدد المأخوذ من الإنترنت ، والطقس الذي يتم تحديثه من Yandex ، كل هذا مكتوب بلغة Python ، ويعمل بشكل جيد منذ عدة أشهر. في الوقت نفسه ، يعمل خادم FTP على الساعة ، مما يسمح (مع إعادة توجيه المنفذ على جهاز التوجيه) بتحديث البرامج الثابتة عليها ليس فقط من المنزل ، ولكن أيضًا من أي مكان يوجد فيه الإنترنت. على سبيل المكافأة ، تعد موارد Raspberry كافية بشكل أساسي لتوصيل كاميرا و / أو ميكروفون مع القدرة على مراقبة الشقة عن بُعد ، أو التحكم في الوحدات / المرحلات / المستشعرات المختلفة. يمكنك إضافة جميع أنواع "الكعك" ، مثل مؤشر LED للبريد الوارد ، وما إلى ذلك.

ملاحظة: لماذا موقع ئي باي؟
كما ترى ، تم تقديم أسعار أو صور من موقع ئي باي لجميع الأجهزة. لماذا هذا؟ لسوء الحظ ، غالبًا ما تتبع متاجرنا مبدأ "اشتريت 1 دولار ، وبعت 3 دولارات ، وأعيش على 2 في المائة". كمثال بسيط ، تكلفة Arduino Uno R3 (في وقت كتابة هذا التقرير) 3600r في سانت بطرسبرغ ، و 350 r على موقع eBay مع الشحن المجاني من الصين. الفرق هو في الحقيقة ترتيب من حيث الحجم ، دون أي مبالغة أدبية. نعم ، عليك الانتظار لمدة شهر لاستلام الطرد من مكتب البريد ، لكنني أعتقد أن هذا الفارق في السعر يستحق ذلك. ولكن بالمناسبة ، إذا احتاجها شخص ما الآن وبشكل عاجل ، فمن المحتمل أن يكون هناك خيار في المتاجر المحلية ، وهنا يقرر الجميع بنفسه.

أوجه انتباهكم الإلكترونية ساعة متحكم. دائرة الساعة بسيطة للغاية ، وتحتوي على الحد الأدنى من التفاصيل ، وهي متاحة للتكرار من قبل هواة الراديو المبتدئين.

تم تجميع التصميم على متحكم دقيق وساعة الوقت الحقيقي DS1307. يتم استخدام مؤشر LED المكون من أربعة أرقام المكون من سبعة أجزاء كمؤشر للوقت الحالي (توهج أزرق فائق السطوع ، يبدو جيدًا في الظلام ، وفي نفس الوقت تلعب الساعة دور الضوء الليلي) . يتم التحكم في الساعة بواسطة زرين. بفضل استخدام شريحة الساعة في الوقت الحقيقي DS1307 ، اتضح أن خوارزمية البرنامج بسيطة للغاية. يتصل المتحكم الدقيق بساعة الوقت الحقيقي عبر ناقل I2C ، ويتم تنظيمه بواسطة البرنامج.

تخطيط الساعة:

لسوء الحظ ، يوجد خطأ في الرسم التخطيطي:
- يجب ربط استنتاجات عضو الكنيست بقواعد الترانزستورات:
PB0 إلى T4 ، PB1 إلى T3 ، PB2 إلى T2 ، PB3 إلى T1
أو قم بتغيير اتصال مجمعات الترانزستور بتات المؤشر:
T1 إلى DP1 ... .. T4 إلى DP4

التفاصيل المستخدمة في دارة الساعة:

♦ متحكم ATTiny26:

♦ ساعة الوقت الحقيقي DS1307:

♦ مؤشر LED مكون من 4 أرقام مكون من 7 مقاطع - FYQ-5641UB -21 الكاثود المشترك (أزرق فائق السطوع):

♦ كوارتز 32.768 كيلو هرتز ، بسعة إدخال 12.5 بيكو فاراد (يمكن أخذها من اللوحة الأم للكمبيوتر) ، تعتمد دقة الساعة على هذا الكوارتز:

♦ جميع الترانزستورات عبارة عن هياكل NPN ، يمكنك استخدام أي (KT3102 ، KT315 ونظيراتها الأجنبية) ، لقد استخدمت BC547C
♦ رقاقة منظم جهد كهربي نوع 7805
♦ جميع المقاومات 0.125 واط
♦ المكثفات القطبية لجهد التشغيل لا تقل عن جهد الإمداد
♦ طاقة احتياطية DS1307 - خلية ليثيوم 3 فولت CR2032

يمكن استخدام أي شاحن هاتف خلوي غير ضروري لتشغيل الساعة (في هذه الحالة ، إذا كان الجهد عند خرج الشاحن في حدود 5 فولت ± 0.5 فولت ، فإن جزءًا من الدائرة - يمكن استبعاد منظم الجهد على شريحة 7805)
الاستهلاك الحالي للجهاز - 30 مللي أمبير.
يمكن حذف البطارية الاحتياطية لساعة DS1307 ، ولكن بعد ذلك ، إذا فشل جهد التيار الكهربائي ، فسيتعين ضبط الوقت الحالي مرة أخرى.
لا تظهر لوحة الدوائر المطبوعة للجهاز ، فقد تم تجميع التصميم في علبة من ساعة ميكانيكية معيبة. يعمل LED (بتردد وميض 1 هرتز ، من خرج SQW DS1307) على فصل الساعات والدقائق على المؤشر.

إعدادات المصنع الخاصة بالمتحكم الدقيق: تردد الساعة - 1 ميجا هرتز ، بتات الصمامات لا تحتاج إلى لمسها.

خوارزمية الساعة(في منشئ الخوارزمية):

1. ضبط مؤشر المكدس
2. ضبط المؤقت T0:
- تردد SK / 8
- مقاطعات الفائض (مع مثل هذا التردد المحدد مسبقًا ، يُطلق على المقاطعة كل ملي ثانية)
3. تهيئة المنافذ (تم تكوين المسامير PA0-6 و PB0-3 للإخراج ، PA7 و PB6 للإدخال)
4. تهيئة ناقل I2C (دبابيس PB4 و PB5)
5. فحص البتة السابعة (CH) من السجل الصفري DS1307
6. تمكين المقاطعة العالمية
7. إدخال حلقة مع زر انقر فوق اختبار

عند تشغيل DS307 لأول مرة ، أو تشغيله مرة أخرى إذا لم تكن هناك طاقة احتياطية ، فسوف ينتقل إلى الإعداد الأولي للوقت الحالي. في هذه الحالة: الزر S1 - لضبط الوقت ، الزر S2 - الانتقال إلى الفئة التالية. ضبط الوقت - تتم كتابة الساعات والدقائق على DS1307 (يتم ضبط الثواني على صفر) ، ويتم تكوين دبوس SQW / OUT (الدبوس السابع) لتوليد نبضات مستطيلة بتردد 1 هرتز.
عندما تضغط على الزر S2 (S4 - في البرنامج) ، يتم تعطيل المقاطعات بشكل عام ، وينتقل البرنامج إلى الروتين الفرعي لتصحيح الوقت. في الوقت نفسه ، يتم ضبط عشرات ووحدات الدقائق باستخدام زري S1 و S2 ، ثم من 0 ثانية ، بالضغط على الزر S2 ، يتم تسجيل الوقت المحدد في DS1307 ، ويتم تمكين المقاطعة العامة والعودة إلى يتم تنفيذ البرنامج الرئيسي.

أظهرت الساعة دقة جيدة ، وانجراف الوقت لمدة شهر هو 3 ثوان.
لتحسين دقة الدورة ، يوصى بتوصيل الكوارتز بـ DS1307 ، كما هو موضح في ورقة البيانات:

تمت كتابة البرنامج في بيئة Algorithm Builder.
يمكنك ، باستخدام برنامج الساعة كمثال ، التعرف على خوارزمية توصيل المتحكم الدقيق بالأجهزة الأخرى عبر ناقل I2C (يتم التعليق على كل سطر بالتفصيل في الخوارزمية).

صورة للجهاز المجمع ولوحة الدوائر المطبوعة بصيغة play. من قارئ موقع اناتولي بيلجوك Anatoly Pilguk شكرا جزيلا له!

يستخدم الجهاز: ترانزستورات - SMD VS847 ومقاومات رقاقة

ملاحق المقال:

(42.9 كيلوبايت ، 3233 نتيجة)

(6.3 كيلوبايت ، 4183 نتيجة)

(3.1 كيلوبايت ، 2662 نقرة)

(312.1 كيلوبايت ، 5932 نتيجة)


الإصدار الثاني من برنامج Clock في AB (لمن لا يقوم بتنزيل النسخة الأولى)

(11.4 كيلو بايت ، تضرب 1947)