كيفية جعل مخبر ملحوظ جدا من وحدة LED للإعلان في الهواء الطلق و Arduino

كيفية جعل مخبر ملحوظ للغاية من وحدة P10 و Arduino LED.


الغرض : توصيل مصفوفة P10 LED كبيرة بسرعة (16 × 32 سم) بجهاز كمبيوتر أو جهاز آخر ، وتحويل كل هذا إلى مخبر ملحوظ ومشرق للغاية مع تغيير ديناميكي للمعلومات المعروضة. هناك الكثير من التطبيقات لمثل هذا الشيء ، وكما تظهر الممارسة ، فإنه يجذب الانتباه. فقط تخيل ، الآن سيعرف الجميع على وجه اليقين أن مكيف الهواء الخاص بك يعمل ومن المفترض أن يتم إغلاق الباب!



الإضاءة الخلفية ليست من النافذة ، ولكن من اللوحة ؛)


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


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




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


تبدو وحدة LED (P10) على النحو التالي:



http://digital-wizard.net/avr_projects/p10_led_display_panel_interface


في الواقع ، هذه ليست سوى مصفوفة من مصابيح LED ملحومة بمخرجات سجلات التحول ، ولن نذهب إلى غابة الدوائر ، فالوحدات كلها قياسية وتختلف في الحجم فقط. يعني P10 أنه بين ثنائيين متجاورين 10 ملم. هناك لوحات أحادية اللون ولونين وحتى RGB. بالنسبة للمهتمين بالتفاصيل ، هناك بالفعل مقال مشابه ، ولكن مع التحيز إلى مستوى أقل.


الأجهزة


وبالنسبة لأولئك الذين يرغبون في الحصول على نتيجة "تشعر" بها بسرعة ، ستحتاج إلى:


  1. مصفوفة LED واحدة.
  2. اردوينو (لقد استخدمت mini ، ولكن سيكون من الأسهل عدم استخدام محولات إضافية للتواصل مع جهاز الكمبيوتر).
  3. امدادات الطاقة ل 5 V / 3A. المصفوفة شرهة ، إذا قمت بإضاءة جميع الثنائيات ، فأنت بحاجة إلى الكثير من الطاقة.
  4. كابل توصيل (عادة ما تأتي مع مصفوفة).
  5. الرغبة في إنهاء العمل.

سنقوم بعمل تصميم مترابط يتم توصيله للتو بمنفذ طاقة وجهاز كمبيوتر لعرض معلوماتنا الثمينة (مثل معدل البيتكوين) .


من الضروري أخذ الحلقة من المصفوفة ، وقطعها في نصف لحام في دائرة بسيطة إلى Arduino.



إذا كنت تستخدم Arduino Mini أو UNO ، فأنت بحاجة إلى لحام الدبابيس المقابلة عن طريق القياس.


إذا لم يكن لديك كبل لسبب ما ، يمكنك استبداله بكابل MIDI يربط موصل MIDI (خيار للمؤقتات القديمة) باللوحة في بطاقات الصوت القديمة أو استبداله بمقبسين Dupont (أم) مع 8 دبابيس. من حيث المبدأ ، الموصل قياسي ، يبدو بسهولة.



ولكن في غضون 10 دقائق حصلت على التصميم التالي ، يتحول محول USBtoUART الإضافي الذي لن يكون لديك إذا لم تستخدم Arduino Mini.




الجهاز جاهز ، ما عليك سوى توصيل وحدة تزويد طاقة إضافية 5V / 3A لتشغيل المصفوفة. للقيام بذلك ، يحتوي على موصل منفصل ، بالإضافة إلى زائد ، ناقص إلى ناقص. بل على العكس من ذلك ، لكنها لن تنجح. على الرغم من أنه أمر غريب ، لأن الجميع يعرف أن الإلكترونات ، كالمعتاد ، تتدفق من زائد إلى ناقص. وإذا أخذنا في الاعتبار أن الإلكترونات مشحونة سلبًا ، فليس من الواضح على الإطلاق لماذا تتدفق إلى القطب السالب ... ؛) اعتقدوا أشياء أقصر.



آمل أن تقوم بتوصيل مصدر الطاقة بشكل أكثر موثوقية ، وطريقتنا مناسبة فقط إذا كان لديك الكثير من إمدادات الطاقة الاحتياطية. يمكن انسحاب اردوين ( لا المسمار التنصت! ) إلى اللوحة نفسها ، تحتوي اللوحة على ثقوب مترابطة.


هذا كل شيء ، دعوا الآلهة DIY تغفر لي ، ولكن اليوم لم يكن هناك شريط أزرق. لا يستحق إنفاق مثل هذا المورد القيم على مثل هذه الأشياء عديمة القيمة.


جزء البرنامج


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


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


بشكل عام ، كل ما عليك فعله هو تحميل الرسم على اللوحة ، ولكن من هذا الدليل حيث ستقوم بفك أرشيفي ، حيث قمت بتعديله قليلاً ملف بعض المكتبات الموجودة في نفس المكان. تمت إضافة التحكم في السطوع و SPI المعطلة قليلاً ، ربما شيء آخر ، لا أتذكر. الرباط؟ لا تلمس!


لمزيد من الوضوح ، أضفت جهاز استشعار درجة الحرارة 18v20. إذا لم تقم بتوصيل واحد ، فلن يتم ببساطة عرض درجة الحرارة. وفقًا لفكرتي ، سيتم عرض وزن معين بالجرام هناك ، ولكن يمكنك عرض رقم فقط. لتغيير النص الذي يتم تمريره من الأسفل ، ما عليك سوى "تحميله" إلى منفذ Arduino COM باستخدام تنسيق خاص ، وهو نوع من تسلسل ESC. المرفق هو نص Python يرسل ببساطة الوقت الحالي إلى اللوحة.


تنسيق الأمر:


  1. 0x1B (ESC) + 0x40 ("@") // Identification ، تُرجع معرّف السلسلة للجهاز "P10_DISPLAY_V01 \ r \ n"
  2. 0xOC (CLR) // امسح الشاشة.
  3. 0x1F (الولايات المتحدة) + 0x58 ("X") + 0x80 // ضبط سطوع الشاشة ، أقصى سطوع 0x80.
  4. 0x1F (الولايات المتحدة) + 0x52 ("B") + String // تعيين الخط السفلي الذي سيتم تمريره.
  5. 0x1F (الولايات المتحدة) + 0x0A ("LF") + 0x31 ، 0x32 ، 0x33 ، 0x34 ، 0x35 // تمرير الرقم المكون من خمسة أرقام المعروض في أعلى "12345"

لم أجد الخط النهائي واضطررت لرسم الخط الروسي 5 * 7. ربما دراجة ، لكن هل نفعل دائمًا كل شيء بعقلانية؟


رسم:


كود
//====================== OneWire ==================================== #include <OneWire.h> OneWire ds2 (2); String res = ""; byte type_s; byte data[12]; byte addr_ds2[8]; bool temp_sensor_2_found = false; float temp1 = 999; //=================================================================== #include <SPI.h> #include "DMD.h" #include "TimerOne.h" #include "SystemFont5x7rus.h" #define CLR 0x0C #define US 0x1F #define ESC 0x1B #define LF 0x0A static const char ID[] = "P10_DISPLAY_V01\r\n"; // Device ID #define DISPLAYS_ACROSS 1 #define DISPLAYS_DOWN 1 DMD dmd(DISPLAYS_ACROSS, DISPLAYS_DOWN); //  ,     . #define max_char1 6 #define max_char2 176 unsigned char message1[max_char1] = {0x20,0x30,0x30,0x30,0x30,0x00}; // stores you message unsigned char message2[max_char2]; // stores you message unsigned char r_char; byte index1 = 4; byte index2 = 176; int i; long scrollSpeed = 25; char test[] = { 0x84,0x80,0x20,0x87,0x84,0x90,0x80,0x82,0x91,0x92,0x82,0x93,0x85,0x92,0x20,0x92, 0x8E,0x20,0x81,0x8B,0x80,0x83,0x8E,0x84,0x80,0x90,0x9F,0x20,0x97,0x85,0x8C,0x93, 0x20,0x8C,0x9B,0x20,0x8D,0x85,0x91,0x8C,0x8E,0x92,0x90,0x9F,0x20,0x8D,0x88,0x20, 0x8D,0x80,0x20,0x97,0x92,0x8E,0x20,0x88,0x20,0x82,0x8E,0x8F,0x90,0x85,0x8A,0x88, 0x20,0x82,0x91,0x85,0x8C,0x93,0x21,0x00}; //============================================================================= bool get_sensor(byte addr[8], OneWire ds) { //    if (! ds.search (addr)) { ds.reset_search (); delay (250); return false; } //        if (OneWire::crc8(addr, 7) != addr[7]) { Serial.println("get_sensor:CRC is not valid!"); return false; } //    switch (addr[0]) { case 0x10: //Chip = DS18S20 type_s = 1; break; case 0x28: //Chip = DS18B20 type_s = 0; break; case 0x22: //Chip = DS1822 type_s = 0; break; default: Serial.println("get_sensor:Device is not a DS18x20 family device."); return false; } return true; } //============================================================================= double get_temp(byte addr[8], OneWire ds) { double celsius; ds.reset (); ds.select (addr); //   ds.write (0x44, 1); //  ,     delay (750); ds.reset (); ds.select (addr); ds.write (0xBE); //     for (int i = 0; i < 9; i++) { //     data[i] = ds.read (); } //        ,           int raw = (data[1] << 8) | data[0]; if (type_s) { raw = raw << 3; // 9 bit resolution default if (data[7] == 0x10) { raw = (raw & 0xFFF0) + 12 - data[6]; } } else { byte cfg = (data[4] & 0x60); if (cfg == 0x00) raw = raw << 3; else if (cfg == 0x20) raw = raw << 2; else if (cfg == 0x40) raw = raw << 1; } celsius = (double)raw / 16.0; return celsius; }; //============================================================================= void massage2BufClear () { for(i=0; i<max_char2; i++) { message2[i] = '\0'; } index2=0; } //-------------------------------------------------------------- void massage1BufClear () { message1[0] = 0x20; message1[1] = 0x30; message1[2] = 0x30; message1[3] = 0x30; message1[4] = 0x30; message1[5] = 0x00; index1=0; } //-------------------------------------------------------------- void massage1Normalization () { char buf[5]; buf[0] = 0x20; buf[1] = 0x30; buf[2] = 0x30; buf[3] = 0x30; buf[4] = 0x30; int char_count = index1; for(i = char_count - 1; i >= 0; i--) { buf[i] = message1[i]; } massage1BufClear(); for(i = char_count - 1; i >= 0; i--) { message1[i+5-char_count] = buf[i]; } } //------------------------------------------------------------------ void ScanDMD() { dmd.scanDisplayBySPI(); } //------------------------------------------------------------------ void setup(void) { Timer1.initialize( 500 ); Timer1.attachInterrupt( ScanDMD ); dmd.clearScreen( true ); Serial.begin(9600); strcpy(message2,test); dmd.brightness = 70; temp_sensor_2_found = get_sensor(addr_ds2, ds2); dmd.selectFont(SystemFont5x7); } //------------------------------------------------------------------ void loop(void) { dmd.drawMarquee(message2 ,index2,(32*DISPLAYS_ACROSS)-1 ,8); if (temp_sensor_2_found) // !!!!!!! { // !!!!!!! res = String(get_temp(addr_ds2, ds2)); // !!!!!!! res.toCharArray(message1, 5); // !!!!!!! message1[4] = 0xF8; // !!!!!!! } // !!!!!!! long start=millis(); long timer=start; boolean ret=false; while(!ret) { if ((timer + scrollSpeed) < millis()) { dmd.drawFilledBox( 0,0,31,7, GRAPHICS_INVERSE); ret=dmd.stepMarquee(-1,0); timer=millis(); dmd.drawString( 1, 0, message1, 5, GRAPHICS_NORMAL ); if(Serial.available()) break; } } } //----------------------------------------------------------------------------------- void serialEvent() { delay(25); // Wait all data r_char = Serial.read(); if(r_char < 0x20) { switch (r_char) { case ESC: r_char = Serial.read(); if(r_char=='@') { Serial.write(ID); } break; case CLR: massage1BufClear(); massage2BufClear(); break; case US: r_char = Serial.read(); if(r_char=='X') { dmd.brightness = Serial.read(); } if(r_char=='B'){ massage2BufClear(); while(Serial.available() > 0) { r_char = Serial.read(); if(index2 < (max_char2-1)) { if(r_char > 0x1F) { message2[index2] = r_char; index2++; } } } } if(r_char==LF){ massage1BufClear(); while(Serial.available() > 0) { r_char = Serial.read(); if(index1 < (max_char1-1)) { if((r_char > 0x29) and (r_char < 0x3A)) { message1[index1] = r_char; index1++; } } } massage1Normalization(); } dmd.drawFilledBox( 0,8,31,15, GRAPHICS_INVERSE); break; default: break; } } while (Serial.available()) Serial.read(); dmd.writePixel(0,0,GRAPHICS_NORMAL,1); } 

عملية سطوع كامل:



العمل مع سطوع الإنسان:



العمل مع التحميل الديناميكي للوقت من جهاز كمبيوتر باستخدام برنامج نصي Python:



جميع المخالفات مع التمرير ترجع إلى التصوير على الكاميرا ، للعين من مسافة طبيعية ، يبدو كل شيء سلسًا وقابلًا للقراءة.


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


ربما في المستقبل سأفعل نفس الشيء على STM32F103C8T6 وعلى ESP-12F ، يجب أن يتحرك كل شيء بشكل أسرع هناك.


المراجع:


1. ربط الأرشيف برسم تخطيطي وما يتعلق به.
2. رابط آخر ل BitBucket


Source: https://habr.com/ru/post/ar404867/


All Articles