يعرض Winstar وضع الرسم والنص

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

قبل الشروع في النظر في العروض الرسومية الفعلية ، سننظر في المشكلة الدائمة مع مشاكل تبديل وضع النص الخاص بوحدة تحكم WS0010 ، والتي تلقت حلًا غير متوقع وواضح (أوه ، أين كانت عيني!).

حل مشكلات وضع النص WS0010


من المعروف جيدًا أن شاشات خط Winstar لديها مشكلات استقرار أثناء التهيئة. بالمناسبة ، اتضح أن هذا لم يكن فريدًا لـ "الصينية اللعينة": إن عينات شاشة العرض Newhaven 16x2 ، التي حصلت عليها بصعوبة كبيرة ، تقع على الجانب الآخر من الكرة الأرضية ، هي نسخة كاملة من Winstar خارجيًا ، باستثناء موقع بعض النقوش واسم الشركة على البقعة ( نفس الشكل والخط):

الصورة

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

يتم التعبير عن صعوبات وضع النص في حقيقة أنه عند البدء (على سبيل المثال ، عند إعادة التشغيل أو إعادة تعيين برنامج وحدة التحكم بالتحكم يدويًا) ، يمكن أن تظهر القمامة على شاشات العرض ، ويغير السطران 0 و 1 الأماكن بشكل عشوائي. أظهرت التجارب أنها لا تعتمد على طريقة التضمين (8 بت أو 4 بت). هذه المشكلة حادة بشكل خاص عندما تكون إعادة تشغيل البرامج الدورية ضرورية ، على سبيل المثال ، بواسطة Watchdog-timer.

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

ولكن هذا كله ، بالطبع ، مبادرة ونصف تدابير. جاء شخص SeregaB بطريقة جذرية (انظر منشوره على easyelectronics.ru - بفضل Tomasina للحصول على معلومات). في الواقع ، قام بمهمة مختلفة تمامًا: لتعلم كيفية العمل باستخدام الرسم فقط بدلاً من وضع النص. في محاولة للتبديل بين الأوضاع ، اكتشف بسرعة أن " التبديل إلى الوضع الرسومي كان طبيعيًا ، ومن الرسم إلى" نص "- أخرق جدًا ." ثم تذكر أنه " مرة واحدة ، منذ وقت طويل ، عندما كانت DShs لا تزال مطبوعة على الورق ، في بعض DShs على HD44780 قرأت أن أوضاع التبديل يجب أن يتم فقط عندما تكون الشاشة مغلقة ". وعملت.

من المنشور المذكور ، سأقوم بإعادة إنتاج إجراءين للتبديل هنا ، مع تكييفهما قليلاً للاستخدام مع LuquidCrystal (يسمى الفصل الدراسي OLED1 هنا).

قم بالتبديل إلى وضع الرسم:
OLED1.command(0x08);//  OLED1.command(0x1F);//   OLED1.command(0x01);//    (..  clear()) OLED1.command(0x08|0x04);//  

التبديل إلى وضع النص:
  OLED1.command(0x08);//  OLED1.command(0x17);//    OLED1.command(0x01);//    (..  clear()) OLED1.command(0x04 | 0x08);//  

كما سنرى لاحقًا ، فإن الإجراء الأول غير مطلوب حقًا: ينتقل WS0010 إلى وضع الرسم من نصف ركلة ، فقط أرسل الأمر 0x1F إليه. لكن التسلسل الثاني للأوامر كان هو الحال إلى حد كبير. بالنسبة للعينة ، تم تضمينها مباشرة في الرسم باستخدام LuquidCrystal في هذا النموذج:
 void reset_textmode() //     { OLED1.command(0x08);//  OLED1.command(0x17);//    OLED1.command(0x01);//    OLED1.command(0x04 | 0x08);//  } 

ثم تم استدعاء هذه الوظيفة في الإعداد مباشرة بعد بدء المكتبة:

  . . . . . OLED1.begin(16,2); //16  2  reset_textmode(); //  clear() . . . . . 

إذا قمت بإدخال بعض التأخير (500) قبل ذلك ، فقد اتضح أن العرض التوضيحي واضح للغاية: بعد الضغط على زر إعادة الضبط للوحة Arduino ، تظهر القمامة عادة على الشاشة ، ولكن للحظة فقط: بعد تشغيل الوظيفة ، يتم مسح الشاشة وعودة جميع الخطوط في مكانها .

تعمل الوظيفة على هذا النحو ، ولكن من أجل الراحة ، قمت باستبدال محتويات وظيفة LiquidCrystalRus :: clear () في ملف مكتبة LiquidCrystalRus_OLED.cpp التي تمت مناقشتها سابقًا مع هذا التسلسل من الأوامر (أذكرك أنه يمكنك تنزيلها من موقع المؤلف). لا يوجد انتظار لتنفيذ الأمر في المكتبة ، لذلك ، من أجل الموثوقية ، بعد كل أمر ، هناك تأخيرات يتم إدخالها 100 في النمط العام للمكتبة. في الرسومات باستخدام هذا المتغير من LiquidCrystalRus_OLED ، في بداية الإعداد ، من الضروري استدعاء وظيفة clear () ، وفي نفس الوقت ستقوم بمسح الشاشة.
ملاحظة
هناك مشكلة واحدة في تنظيف الشاشة: في ورقة البيانات في جدول الأوامر ، يلاحظ أن الأمر 0x01 يمكن أن يستمر حتى 6.2 مللي ثانية "عند fsp أو fosc = 250 كيلو هرتز". ما هو نوع "fsp أو fosc" في الواقع في وحدات تحكم محددة ، كانوا كسالى جدًا في الكتابة ، ولكن على أي حال ، حتى لو كان ميجا هرتز ، يجب أن يكون التأخير في هذا الأمر كبيرًا (ويذكر مؤلف LiquidCrystal هذا). ومع ذلك ، في الممارسة العملية ، اتضح أن فريق التنظيف يعمل لنفسه إذا لم يكن هناك تأخير على الإطلاق. لذلك لم أفهم ، لكنني تصرفت بناءً على قاعدة البرمجة المعروفة: "إنها تعمل - لا تلمس!".

الآن دعونا نتعامل أخيرًا مع وضع الرسومات.

يعرض وضع الرسم في النص WEH001602


بادئ ذي بدء ، حاولت تبديل عرض النص الذي كان لدي WEH001602BG إلى وضع الرسم. لاحظ أن الشاشات الرسومية 100 × 16 والنص (تكوين 20 × 2 ، و 16 × 2 تحتوي فقط على عدد أقل من النقاط الأفقية) لها مصفوفات متطابقة ، ويتم فصل شاشات النص فقط بفواصل في الألفة. هذا يحد بشدة من استخدام وضع الرسومات في عرض النص ، والمزيد من وضع النص في الرسومات. ولكن لاختبار كيفية عملها ، يمكنك استخدام أي منها.

تم توصيل الشاشة مع DS1307 بـ Arduino Nano وفقًا للمخطط التالي:
الصورة

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

للتبديل إلى الوضع الرسومي ، يمكنك استخدام الإجراء المحسن من القسم السابق ، ولكن وظيفة بسيطة من أمر واحد تعمل:
 . . . . . #define LCD_SETGRAPHICMODE 0x1f LiquidCrystal lcd(9, 4, 8, 7, 6, 5); void setGraphicMode(){ lcd.command(LCD_SETGRAPHICMODE); } . . . . . 

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

علاوة على ذلك ، استخدمت جزئيًا إنجازات مؤلف مكتبة WinstarOLED المذكورة (في حد ذاتها ، هذه الوظيفة الإضافية لـ LuquidCrystal ، في رأيي ، غير مكتملة ، وليس عمليًا استخدامها). قدم وظيفة ملائمة لتحديد المؤشر الرسومي (تم إصلاح الخطأ الأصلي فيما يتعلق بالقيمة القصوى للقيمة س هنا):
 void setGraphicCursor( uint8_t x, uint8_t y ){ if( 0 <= x && x <= 99 ){ lcd.command(LCD_SETDDRAMADDR | x); } if( 0 <= y && y <= 1 ){ lcd.command(LCD_SETCGRAMADDR | y); } } 

يتم تعريف LCD_SETDDRAMADDR المستمر في مكتبة LiquidCrystal. تنقسم شاشة عرض مقاس 100x16 ، مثل شاشة عرض نصية ، إلى سطرين ، 0 و 1 ، لأن y يمكنك فقط أخذ قيمتين هنا. وتختلف الإحداثيات الأفقية x من 0 إلى 99. يتم إرسال بايت مع الأمر lcd.write () ، حيث تحدد البتات الفردية المواضع المضيئة للخط العمودي بطول 8 نقاط. يحتوي الموضع الموجود في أقصى اليسار في الخط العلوي على إحداثيات 0،0 ، في أقصى اليمين في الأسفل - 99،1. علاوة على ذلك ، فإن أدنى نقطة تتوافق مع البت الأقل أهمية ، وأقل نقطة - الأعلى.

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

الصورة

كل هذا مكتوب في مصفوفة ثنائية الأبعاد من النموذج:
 const byte Data2[2][10]={{0x06,0x07,0x03,0x03,0x03,0x83,0xc3,0x63,0x3f,0x1e}, {0xf0,0xf8,0xcc,0xc6,0xc3,0xc1,0xc0,0xc0,0xc0,0xc0}}; 

لكل رقم من 0 إلى 9 ، يتم إنشاء مصفوفة منفصلة: Data0 و Data1 و Data2 وما إلى ذلك. بالنسبة للساعات ، بالإضافة إلى الأرقام ، ستحتاج أيضًا إلى نقطة مزدوجة. يمكن جعله أقصر:
 const byte DataDP[2][2]={{0x70,0x70}, {0x1c,0x1c}};//  

نظرًا لأن وحدة التحكم لا تعرف كيفية "الوميض" في وضع الرسم ، فمن الضروري أن تطرف القولون برمجيًا. يمكنك إطفاء نقطة مزدوجة ببساطة عن طريق عرض الأصفار في المواضع المقابلة ، ولكن من أجل التوحيد قمت بعمل مصفوفة منفصلة
 const byte DataDPclr[2][2]={{0x00,0x00}, {0x00,0x00}};// .  

لعرض كل رقم وبشكل منفصل لنقطة مزدوجة ، تتم كتابة وظيفة منفصلة:
 void draw2 (byte x/* */) // “2” { for (byte i = x; i<x+10; i++){ setGraphicCursor(i, 0); lcd.write(Data2[0][ix]); setGraphicCursor(i, 1); lcd.write(Data2[1][ix]);} } 

جميع الوظائف متشابهة ، ولكن استخدم صفائف مختلفة ، ونقطة مزدوجة ، يتم أيضًا استخدام حدود أخرى للحلقة. اتضح أنه ليس اقتصاديًا للغاية من حيث كمية الرمز (انظر المزيد في هذا لاحقًا) ، ولكن من الواضح أنه من السهل تصحيح الأخطاء. تؤخذ الفجوات بين الشخصيات في الاعتبار في مرحلة الإخراج ، مما يشير إلى الموضع المقابل ( تستخدم مكتبة RTClib لقراءة الساعة):
 void loop() { DateTime clock = RTC.now(); if (clock.second()!=old_second) { uint8_t values; values=clock.hour()/10; //  drawValPos(values,0); values=clock.hour()%10; //  drawValPos(values,12); values=clock.minute()/10; //  drawValPos(values,28); values=clock.minute()%10; //end   drawValPos(values,40); if (clock.second()%2) drawDP(24); else drawDPclr(24); old_second=clock.second(); }//end if clocksecond } 

ستشغل عشرة أرقام من 20 بايت لكل منها 200 بايت في الذاكرة - حوالي 10٪ من حجمها (والخط العريض هو 16x16 ، كما في المثال أدناه ، وكل 16٪). خط أحادي اللغة كامل بهذا الحجم ، مع الأرقام ، دون مراعاة جميع أنواع علامات الترقيم والعروض الخاصة. أحرف ، تحتوي على 62 حرفًا (الإنجليزية) إلى 74 حرفًا (الروسية بدون E) ، وستشغل القيمة ما يقرب من نصف ذاكرة الوصول العشوائي ATmega328. لذلك ، يجب إلغاء الحيل التي تحتوي على صفائف ووظائف الإخراج لكل حرف على حدة ، ويتم ذلك كما هو متوقع. أي ، يجب ترك الخطوط في ذاكرة البرنامج وتنزيلها عبر PROGMEM ، ويجب ترتيب جميع أنماط الحروف الرسومية كمصفوفة خط واحد ، وتحميلها للإخراج برقم الرمز في جدول واحد. خلاف ذلك ، لن تكون هناك ذاكرة كافية وسوف ينتفخ رمز البرنامج إلى وحدة تخزين لا يمكن السيطرة عليها. لن نتحدث هنا عن هذا ، لأنه في أمثلةنا البسيطة ، كل هذا غير مطلوب - في كل مرة سنقتصر على عدد صغير من الشخصيات الضرورية للغاية.

نظرًا للحجم الكبير للنص الكامل لرسم GraphicOLED_DC1307 ، لا أحمله ؛ يمكنك تنزيله من هنا . يتم حفظ وظيفة resetOLED في النص ، مما يشوه قوة العرض عند إعادة تشغيل وحدة التحكم (عبر pwrPin D2) ، ولكن لم يكن هناك حاجة إليها مطلقًا ، لذلك يمكن إزالتها بأمان. تظهر نتيجة البرنامج في الصورة:

الصورة

لسوء الحظ ، يتم استبعاد الإقامة المتزامنة في وضع النص والرسومات ، لذلك ، إذا كنت ترغب في استخدام المساحة المتبقية ، فسيتعين عليك رسم خطوطك الخاصة (لا يزال هناك مساحة لحوالي 7 أحرف من خط 5x7 في كل سطر).

عرض رسومي WEG010016A


أخيرًا ، عندما وصلت العروض الرسومية المرتبة WEG010016AL ، بدأت بمحاولة إدخالها في وضع النص لمعرفة ما جاء منها.

للتحقق من وضع النص ، تم تنزيل برنامج لمحاكاة عرض ساعة التقويم مع مستشعر درجة حرارة خارجي ، تم وصفه في منشور سابق . جعلتني النتيجة أتذكر أنه يمكن توجيه شاشات Winstar المختلفة بشكل مختلف فيما يتعلق بالموصل (في هذه الحالة ، يحتوي WEG010016A على موصل في الأعلى ، للنص WEH001602B ، الذي استخدمناه أعلاه ، في الأسفل ، ونوع C في الجانب):

الصورة

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

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

نظرًا لأنني قمت بالفعل برسم عشرة أرقام للحالة السابقة ، فبالنسبة للمهمة الأخيرة ، بقيت تقديم إجراء عكس البرنامج:
 byte reverse(byte x) { byte result=0,i; for(i=0;i<8;i++) { if (x & (1 << i)) { result |= 1 << (7-i); } } return result; } 

يمكنك تغيير ترتيب الإحداثيات الأفقية والخطوط العمودية عن طريق إجراء تغييرات على وظيفة setGraphicCursor:
 void setGraphicCursor( uint8_t x, uint8_t y ){ if( 0 <= x && x <= 99 ){ lcd.command(LCD_SETDDRAMADDR | (99-x)); } if( 0 <= y && y <= 1 ){ lcd.command(LCD_SETCGRAMADDR | (1-y)); } } 

تبقى وظائف الإخراج لصفيف كل رقم كما هي ، ويتم إضافة انعكاس البت فقط:
 void draw2 (byte x/* */) // 2 { for (byte i = x; i<x+10; i++){ setGraphicCursor(i, 0); byte b=reverse(Data2[0][ix]); lcd.write(b); setGraphicCursor(i, 1); b=reverse(Data2[1][ix]); lcd.write(b);} } 

يمكن تنزيل الرسم التخطيطي الكامل لإخراج ساعة GraphicOLED_DC1307_100x16 من هنا ، وتظهر نتيجة شاشة WEG010016AL في الصورة:

الصورة

ولكن في هذه الصورة خط من نوع مختلف (16x16) على شاشة WEG010016CG (الشاشة مقلوبة أيضًا):

الصورة

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

الصورة
 const byte DataATR[2][8]={{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, {0x01,0x02,0x04,0x28,0x30,0x78,0x60,0x80}}; 

وظائف لإخراج الأسهم متعددة الاتجاهات:
 . . . . . void drawSW (byte x) //   (  ) { for (byte i = x; i<x+8; i++){ setGraphicCursor(i, 0); lcd.write(DataATR[0][ix]); setGraphicCursor(i, 1); lcd.write(DataATR[1][ix]);} } void drawNW (byte x) //   (  ) {//   : for (byte i = x; i<x+8; i++){ setGraphicCursor(i, 0); byte b=reverse(DataATR[1][ix]); lcd.write(b); setGraphicCursor(i, 1); b=reverse(DataATR[0][ix]); lcd.write(b);} } void drawNE (byte x) //   (  ) {//  ,    for (byte i = x; i<x+8; i++){ setGraphicCursor(i, 0); byte b=reverse(DataATR[1][7-(ix)]); lcd.write(b); setGraphicCursor(i, 1); b=reverse(DataATR[0][7-(ix)]); lcd.write(b);} } void drawSE (byte x) //   (  ) {//   for (byte i = x; i<x+8; i++){ setGraphicCursor(i, 0); lcd.write(DataATR[0][7-(ix)]); setGraphicCursor(i, 1); lcd.write(DataATR[1][7-(ix)]);} } . . . . . 

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

الصورة

في الختام ، سأضيف أن هنا مكتبة مثيرة للاهتمام للغاية للعمل مع WS0010 في الأوضاع الرسومية والنصية باستخدام SPI. في النص ، يقوم في الغالب بنسخ Liquid Crystal (وماذا يمكن أن تفكر فيه أيضًا؟) ، وفي الرسم يحتوي على وظائف رسم بدائي رسومي ، وخطوط مدمجة (سميكة ، مثل بلدي ، و 5 x7 المعتادة) وأكثر من ذلك بكثير.

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


All Articles