كل طقس جيد: مؤشر الطقس الذي تأثيري



دعونا نتخيل أنه بعد مناوشة مع ديف بومان ، كانت بقايا الذكاء الذي كان قوياً ذات يوم من طراز HAL 9000 كافية لإعادة Discovery One إلى الأرض ، وتحت شعار "الموت لجميع الناس" ، قم بتحطيمه على هذا الكوكب ، حتى لا يكون من الخطأ القيام بذلك مع أجهزة الكمبيوتر.

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

إذا تخلصنا من الرومانسية ، فإن الحقيقة القاسية للحياة هي أن ITEAD سيئ السمعة عرضت شاشة Nextion HMI NX4832T035 للاختبار .

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

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

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

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

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

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

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



لذا ، كان لدي 3.5 بوصات ، 480 × 320 بكسل ، والتي بدت واجهة برمجة تطبيقات بسيطة إلى حد ما وسبعة معلمات يجب عرضها (بين قوسين هي أجهزة الاستشعار المرفقة بهذا):

1) درجة الحرارة من الداخل والخارج (BMP085 / DHT22)
2) الرطوبة داخل و الخارج (DHT22 / DHT22)
4) الضغط الجوي (BMP085)
5) تركيز الغازات غير المفيدة للغاية في الغرفة ، وخاصة ثاني أكسيد الكربون (MQ135)
6) تركيز المواد الصلبة في هواء الغرفة ، وخاصة PM2.5 (Sharp GP2Y1010AU0F)

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

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

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

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

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

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

الشاشة الرئيسية مع القراءات الحالية لأجهزة الاستشعار:




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

شاشة مع رسوم بيانية. في الواقع ، هناك أربعة منهم لعرضها من واحد إلى أربعة رسوم بيانية ، ولكن في الواقع كلها متطابقة. على سبيل المثال ، شاشة بها رسم بياني واحد وأربعة:




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

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

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

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

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

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

منطق الواجهة كما يلي. وضع التشغيل الرئيسي هو وضع الاستعداد مع سطوع الشاشة بنسبة 15٪ من القيمة الاسمية والتحديث المنتظم للقراءات.

المس أي مكان - اتصل بالإنترنت بدرجة سطوع 100٪. بعد ذلك ، النقر على القراءات حددها للعرض اللاحق على الرسم البياني ، والنقر على HAL "عين" ينتقل إلى الشاشة مع الرسوم البيانية.

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

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

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

بالمناسبة ، يمكن تغيير صور الخلفية إذا رغبت في ذلك. حتى أنني أعددت بعض الخيارات الإضافية.

للمستعمرين:


للهوبيتس:


للرومانسية:


لعشاق القهوة:


من حيث المفهوم ، فإن الجهاز بأكمله ليس محطة أرصاد جوية بقدر ما هو شاشة لاسلكية متخصصة. لذلك ، التصميم بسيط للغاية: فقط الشاشة و Arduino Pro Mini وجهاز الاستقبال 433 MHz مع تعديل السعة في الداخل. لا توجد ميزات في التجميع على الإطلاق: الشاشة مخصصة لمنفذ الطاقة والمنفذ التسلسلي ، وجهاز الاستقبال مخصص للطاقة والدبوس 2 لوحدة التحكم. وبصرف النظر عن الحاجة إلى أجهزة استشعار خارجية متوافقة - هذا كل شيء.

لفهم البساطة ، أعرض أحد خيارات السكن مع حشوة مثبتة تقريبًا:





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

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

بالطبع ، لكي يعمل كل هذا ولا يتسبب في رعب حيواني عند رؤية كتل من الأسلاك ، ومجموعة من أجهزة الاستشعار وأجهزة التحكم الدقيقة المعلقة في الهواء ، يجب عليك معرفة الحالات.

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

من وجهة نظر مستشعر الطقس ، فهو مثالي ، حيث يتم نفخه من قبل جميع الرياح وفي نفس الوقت يخفي الفوضى بفاعلية وفعالية. بعد هذه التحولات ، توقفت BDS-M عن الوجود: أصبحت الآن براقة (إذا لم تقترب) Multisensor:

Shell:



Assembled and in place:



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

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



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

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

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

بنغو ، فكرت في نفسي ، وبدأت على الفور في انتزاع التفاصيل. بعد كل شيء ، طباعة حالة ورسمها أكثر جمالية من تحويل منزل إلى موقع بناء كامل الحجم. بشكل عام ، كان الطلاء باهظ الثمن بشكل غير إنساني ، ولكنه رائع جدًا (للمهتمين - Rust-Oleum American Accents Stone).

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

كان:



أصبح:







من السهل أن نرى أنه لا يوجد أثر للكتلة ، ولكن لسبب ما هذا الشكل هو أكثر ما يعجبني. سأتحدث عن ذلك. وداعا.

المنظر ، بطبيعة الحال ، هاوٍ ، لأن بعض مخلفات الشاشة (نفس الحلقة من لوحة اللمس) في الأفق ، ولا يمكن فعل شيء بهذا بطرق معقولة. غير معقول ، في رأيي ، - التراكبات ، والطلاء ، والأشرطة اللاصقة.

وبما أنني طبعت بالبلاستيك الشفاف ، ليلا في الفضاء العام:



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

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

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

لذلك ، لا يمكن للمرء فقط التقاط وعرض أي خط. أي نظريًا - نعم. يمكن تنزيل أي خط Windows في المحول المدمج في بيئة Nextion وسيكون الناتج نقطية مسننة إلى حد ما لا تبدو أفضل.

على سبيل المثال ، قارن الخط الذي تم تحويله بالخط الأصلي:


لذلك ، كان علي أن أسلك الطريق الكئيب. وهي - لتكوين الأرقام والتوقيعات من العناصر الرسومية المعدة مسبقًا في GIMP.

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

حسنًا ، اكتشفت أن هذا ليس كل شيء. اتضح أن 255 نقطة منطقية لا يتم قياسها بواسطة العرض عندما يتغير ارتفاع عنصر الرسم البياني Waveform. لذلك ، عند تغيير ارتفاع عنصر الرسم البياني Waveform ، من الضروري تغيير مقياس القيم بشكل متناسب ، وإلا سيتم "قطع" الرسم البياني.

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

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

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

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

ثم أتجول في الخارج بطلبات مثل:

- افتح أبواب بود باي ، هال

صحيح ، هل سيكون الأمر مضحكًا؟

PS في تصنيع الجهاز تم توجيهه بواسطة كتيبات:

" Nextion HMI Solution
" FLProg + Nextion HMI. الدرس 1
» FLProg + Nextion HMI. الدرس 2
» FLProg + Nextion HMI. الدرس 3

يمكنني أيضًا أن أقدم:

" تخطيط الواجهة للتحرير في محرر Nextion
"عرض ملف واجهة التنزيل

عرض كود الجزء لاردوينو
// v5:     Serial - Arduino, Serial1 - Nextion
// v6:  
// v7:     
// v8:      ( ,    ,  )
// v9:       DHT.h Adafruit
// v10:     ,      
// v11:    CO2/PM2.5
// v12:     , reDraw   statusBoolean = true
// ToDo:   40 ,     ,     (  )


#include <DHT.h>
#include <RCSwitch.h> //   http://code.google.com/p/rc-switch/
#include <MQ135.h> //    CO2

#define measurePin  A1  // analog
#define ledPower  12 // digital

#define samplingTime 280
#define deltaTime 40
#define sleepTime 9680

float voMeasured = 0;
float calcVoltage = 0;
float dustDensity = 0;
float ppm = 0;


#define analogPin A0 //   MQ135    A0 Arduino

MQ135 gasSensor = MQ135(analogPin); //   


//   



#define tempInX 10
#define tempOutX 380 // 415
#define humidityInX 320 //325
#define humidityOutX 410
#define pressureX 20 // 10
#define ppmX 20
#define pmX 370
#define Y0 0 //    
#define Y1 5 // , 
#define Y2 125 // 
#define Y3 230 // ppm&pm
#define dotY 125 //  
#define minusY 115// 

//    
#define minusXOut 380

//    
#define minusXIn 10

//  
#define minusH 3 

//    
#define minusPicID 2 

#define symbolID 1 //     

#define statusTimeOut 2200000 //  ""   (,       ) 900000
#define updateTimeOut 300000 //      60000 (300000)
#define historyTimeOut 1800000 //      (1800000)
#define selectionTimeOut 5000 //      
#define backLightTimeOut 300000 //      
#define waveLimit 254

int parameterS[7]; //  . : tempIn, tempOut, humidityIn, humidityOut, pressure, ppm, pm
byte statusS[7]; //         ( /  )
boolean statusBoolean[7]; //   

/*
//      
int coordinateX[7] = {tempInX, tempOutX, humidityInX, humidityOutX, pressureX, ppmX, pmX};
int coordinateY[7] = {Y2, Y2, Y1, Y1, Y1, Y3, Y3};
*/

//  
//  : tempIn, tempOut, humidityIn, humidityOut, pressure, ppm, pm
int historyArray[7][48]; // 7   48 
boolean drawArray[7]; //       
int arrayMax; //       
int arrayMin;
byte waveShift; //        waveform 0 - 255
float arrayNorm; //        

byte count=0; //    
byte arrayCounter; //   
byte waveCount; //    
int splitData[4]; //       [, , , ]
byte thousands, hundreds, tens, ones; //    
int tempIn, tempOut, humidityIn, humidityOut, pressure;
// int tempIn, tempOut, humidityIn, humidityOut, pressure, ppm, pm;
int symbolX0;
int posX; //    X  
byte tempInStatus, tempOutStatus, humidityInStatus, humidityOutStatus, pressureStatus, ppmStatus, pmStatus; //       StatusTimeOut
byte symbolCount, symbolWidth;
boolean minusIn = false; //   
boolean minusOut = false;
byte i = 0; //  
unsigned long statusTime, updateTime, historyTime, selectionTime, backLightTime;
String stringToNextion;
byte historyCount;
boolean backLight; //           

int weatherData = 0;
int dht22Humidity = 0;


//CLICKER VARIABLE SECTION
byte buffer[30]; // buffer for bytes coming from HMI.
byte waveCounter = 0; //    
// boolean drawArray[7]; //     
boolean allClear;
byte currentPage = 0; //   
byte searchTarget, searchNumber, searchCounter, pageNum, drawCounter, channelToDraw;
// int historyArray[7][48]; // 7   48 
// int arrayMax; //       
// int arrayMin;
// byte waveShift; //        waveform 0 - 255
// float arrayNorm; //        
byte iconCounter = 0;

// int splitData[4]; //       [, , , ]
// int posX; //    X  
// byte count = 0; //    
// String stringToNextion;
// int symbolX0;
// byte symbolCount;

//  
#define minusH 3 

//    
#define minusPicID 2 

//       
int axisX[5][7] = {{10, 380, 320, 410, 20, 20, 370}, //  0
               {0, 0, 0, 0, 0, 0, 0},
               {0, 0, 0, 0, 0, 0, 0},
               {0, 0, 0, 0, 0, 0, 0},
               {0, 0, 0, 0, 0, 0, 0}}; //  1-4

int axisY[5][7] = {{115, 115, 5, 5, 5, 230, 230}, //  0
               {145,0, 0, 0, 0, 0, 0}, //  1
               {63, 226, 0, 0, 0, 0, 0}, //  2 
               {37, 145, 253, 0, 0, 0, 0 }, //  3
               {25, 105, 185, 265, 0, 0, 0}}; //  4


byte symbolW[5][11] = {{25, 15, 30, 25, 30, 30, 25, 30, 25, 30, 5},
                       {11, 6, 12, 12, 14, 13, 12, 13, 12, 12, 3},
                       {11, 6, 12, 12, 14, 13, 12, 13, 12, 12, 3},
                       {11, 6, 12, 12, 14, 13, 12, 13, 12, 12, 3},
                       {11, 6, 12, 12, 14, 13, 12, 13, 12, 12, 3}};//   0, 1, 2, 3, 4, 5, 6, 7, 8, 9

// {13, 7, 15, 13, 17, 15, 13, 14, 14, 14, 5}   25 Comfortaa Light

byte numberPic[5] = {1, 3, 3, 3, 3}; // ID   

byte symbolH[5] = {60, 18, 18, 18, 18}; //     25   25 Comfortaa Light

// CLICKER VARIABLE SECTION ENDS    

// TREND VARIABLE SECTION

#define x2 70 //    

int trendArray[3][6] = {{0, 0, 0, 0, 0, 0}, //    
                        {-5, -3, -1, 1, 3, 5},
                        {0, 0, 0, 0, 0, 0}};

int sumY, sumXY;
byte trendCount;
int trend; 

// TREND VARIABLE SECTION ENDS                  

#define DHTPIN 7
#define DHTTYPE DHT22

// Setup a DHT22 instance
DHT dht(DHTPIN, DHTTYPE);




// Setup RC-Switch
RCSwitch mySwitch = RCSwitch();


void sendToNextion() {
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.write(0xff);
}



//      
void drawMark(byte mark, byte markNum) {

int markX;

//        
if (allClear == true) {
  allClear = false;
}

markX = axisX[0][markNum];

if (markNum == 1 || markNum == 3 || markNum == 6) {
  markX = 475;
} 

if (markNum == 0 || markNum == 4 || markNum == 5) {
  markX = 0;
}

if (markNum == 2) {
  markX = markX - 15;
}

    stringToNextion = String("fill ");
    stringToNextion = stringToNextion + String(markX); // String(axisX[page, type]);
    stringToNextion = stringToNextion + String(",");
    stringToNextion = stringToNextion + String(axisY[0][markNum]+30); // String(axisY[page, type]);
    stringToNextion = stringToNextion + String(",");
    stringToNextion = stringToNextion + String("5");
    stringToNextion = stringToNextion + String(",");
    stringToNextion = stringToNextion + String("30");
    stringToNextion = stringToNextion + String(",");

if (mark == 1) {

    stringToNextion = stringToNextion + String("RED"); //     0, 0
    // Serial2.println("Mark set");

}

if (mark == 0) {

    stringToNextion = stringToNextion + String("BLACK"); //     0, 0
    // Serial2.println("Mark clear");

}

    // Serial2.println(stringToNextion);
    Serial.print(stringToNextion);
    sendToNextion();
  
}

//  :     
void clearSelection() {

  for (byte jj = 0; jj < 7; jj++) {
   if (drawArray[jj] == true) {
    drawArray[jj] = false;
    drawMark(0, jj);
   }
  }

  allClear = true; //   
  waveCounter = 0;
}





void updateHistory() {
mySwitch.disableReceive();

//   ,       -   ,       
for (arrayCounter = 0; arrayCounter < 7; arrayCounter++) {
  // Serial2.print("StatusBoolean for array #");// Serial2.print(arrayCounter);// Serial2.print(" = "); // Serial2.println(statusBoolean[arrayCounter]);
  if (statusBoolean[arrayCounter] == true) { //       
    for (i = 47; i > 0; i--) {
      historyArray[arrayCounter][i] = historyArray[arrayCounter][i-1]; // 
    }
    historyArray[arrayCounter][0] = parameterS[arrayCounter]; //  
  }

// statusBoolean[arrayCounter] = false; // ,       

  }

for (arrayCounter = 0; arrayCounter < 7; arrayCounter++) {
 for (i = 0; i < 47; i++) {
   // Serial2.print(historyArray[arrayCounter][i]);// Serial2.print(", ");
  }
 // Serial2.println();
}

// Serial2.println();  

mySwitch.enableReceive(0);
  
}



void drawTrend(byte arrayToTrend) {

int markX;

markX = axisX[0][arrayToTrend];

//   X   
if (arrayToTrend == 1 || arrayToTrend == 3 || arrayToTrend == 6) {
  markX = 472;
} 

if (arrayToTrend == 0 || arrayToTrend == 4 || arrayToTrend == 5) {
  markX = 0;
}

if (arrayToTrend == 2) {
  markX = markX - 15;
}

    stringToNextion = String("xpic ");
    stringToNextion = stringToNextion + String(markX); //   X
    stringToNextion = stringToNextion + String(",");
    stringToNextion = stringToNextion + String(axisY[0][arrayToTrend]); //   Y
    stringToNextion = stringToNextion + String(",");
    stringToNextion = stringToNextion + String("8"); //    7x18
    stringToNextion = stringToNextion + String(",");
    stringToNextion = stringToNextion + String("18"); //
    stringToNextion = stringToNextion + String(",");

if (trend > 0) {


    stringToNextion = stringToNextion + String("0"); //    0
    stringToNextion = stringToNextion + String(","); // 
    stringToNextion = stringToNextion + String("0"); //  Y    0

  
}

if (trend < 0) {

    stringToNextion = stringToNextion + String("8"); //    5
    stringToNextion = stringToNextion + String(","); // 
    stringToNextion = stringToNextion + String("0"); //  Y    0
    
}

if (trend == 0) {

    stringToNextion = stringToNextion + String("16"); //     10
    stringToNextion = stringToNextion + String(","); // 
    stringToNextion = stringToNextion + String("0"); //  Y    0
 
}

    stringToNextion = stringToNextion + String(",");
    stringToNextion = stringToNextion + String("5"); // ID    
    // Serial2.println(stringToNextion);    
    Serial.print(stringToNextion);
    sendToNextion();
 
}



void splitRoutine(int input) {



input = abs(input); //      ,   

for (count = 0; count < 4; count++) {
  splitData[count] = 0; //   
}

count = 0;

if (input > 9999) { //     
  count = 5;
} else {

if (input > 999) { //  9999
  splitData[3] = input/1000;
  input = input - splitData[3]*1000;
  count = 4;
/*
  Serial.print("SplitData Count 4:");
  Serial.println(splitData[3]);
*/
}

if (input > 99) { //  999
  splitData[2] = input/100;
  input = input - splitData[2]*100;
  if (count == 0) {
    count = 3;
/*
  Serial.print("SplitData Count 3:");
  Serial.println(splitData[2]);
*/  
  }
}

if (input > 9) { //  99
  splitData[1] = input/10;
  input = input - splitData[1]*10;
  if (count == 0) {
    count = 2;
/*
  Serial.print("SplitData Count 2:");
  Serial.println(splitData[1]);
*/  
  }
} 

if (input < 10) {
  splitData[0] = input;
  if (count == 0) {
    count = 1;
/*
  Serial.print("SplitData Count 1:");
  Serial.println(splitData[0]);
*/  
  }
}

}
/*
  Serial.print("Input = ");
  Serial.println(input);
  Serial.print("Count = ");
  Serial.println(count);
*/

}




void drawRoutine(byte page, int value, byte type, int drawX, int drawY) { 

mySwitch.disableReceive();  
// page -  ; value = ; type =       ; drawX    X, drawY -  Y
  
  boolean minusSign = false;

  splitRoutine(value);  

if (page == 0) { //    
//   (  pm25)         ( 470 = 480 - 10)
  if (type == 1) { //   
    drawX = 470 - count*30 - 5; //       10      ,  30    + 5  
    if (count == 1) {
      drawX = drawX - 30; //   0,        
    }
  }

  if (type == 6) { //  pm25
    drawX = 470 - count*30 - 5; //       20      ,  30   
    if (count == 1) {
      drawX = drawX - 30;
    }
  }
}

  int posX = drawX;

 if (value < 0) {
  minusSign = true;
 }

 

 if (count < 5) { //    9999

  if ((count == 1) && ((type == 0) || (type  == 1) || (type  == 6))) { //    pm2.5     0,  0   
  // xpic X, Y, , , X, Y, 

    // 
    stringToNextion = String("xpic ");
    stringToNextion = stringToNextion + String(drawX); // String(axisX[page, type]);
    stringToNextion = stringToNextion + String(",");
    stringToNextion = stringToNextion + String(drawY); // String(axisY[page, type]);
    stringToNextion = stringToNextion + String(",");
    stringToNextion = stringToNextion + String(symbolW[page][0]);
    stringToNextion = stringToNextion + String(",");
    stringToNextion = stringToNextion + String(symbolH[page]);
    stringToNextion = stringToNextion + String(",");
    stringToNextion = stringToNextion + String("0"); //     0, 0
    stringToNextion = stringToNextion + String(","); //     0, 0
    stringToNextion = stringToNextion + String("0"); //     0, 0
    stringToNextion = stringToNextion + String(",");
    stringToNextion = stringToNextion + String(numberPic[page]);
   // // Serial2.println("Temp leading zero");
   // // Serial2.println(stringToNextion);
    Serial.print(stringToNextion);
    sendToNextion();
    drawX = drawX + symbolW[page][0]; //     0
      
   } // count = 1

   for (byte ii = count; ii > 0; ii--) { //   ,    

    if ((ii == 1) && ((type == 0) || (type == 1) || (type == 6))) { //  ,     
      stringToNextion = String("xpic ");
      stringToNextion = stringToNextion + String(drawX); // String(axisX[page, type]);
      stringToNextion = stringToNextion + String(",");
      stringToNextion = stringToNextion + String(drawY); // String(axisY[page, type]);
      stringToNextion = stringToNextion + String(",");
      stringToNextion = stringToNextion + String(symbolW[page][10]);
      stringToNextion = stringToNextion + String(",");
      stringToNextion = stringToNextion + String(symbolH[page]);
      stringToNextion = stringToNextion + String(",");
      if (page == 0) {
        stringToNextion = stringToNextion + String("265"); //        265
      } else {
        stringToNextion = stringToNextion + String("118"); //       135  Comfortaa Light 25
      }
      stringToNextion = stringToNextion + String(","); // 
      stringToNextion = stringToNextion + String("0"); //    Y    0
      stringToNextion = stringToNextion + String(",");
      stringToNextion = stringToNextion + String(numberPic[page]); 
     // // Serial2.println("Temp decimal dot");
     // // Serial2.println(stringToNextion);      
      Serial.print(stringToNextion);
      sendToNextion();
      drawX = drawX + symbolW[page][10]; //     
    } // ii == 1 && type == 0 || type == 1

    //       
    symbolX0 = 0; //       
    for (symbolCount = 0; symbolCount < (splitData[ii-1]);symbolCount++) { //     X    (   )
      symbolX0 = symbolX0 + symbolW[page][symbolCount];
    }

    stringToNextion = String("xpic ");
    stringToNextion = stringToNextion + String(drawX); // String(axisX[page, type]);
    stringToNextion = stringToNextion + String(",");
    stringToNextion = stringToNextion + String(drawY); // String(axisY[page, type]);
    stringToNextion = stringToNextion + String(",");
    stringToNextion = stringToNextion + String(symbolW[page][splitData[ii-1]]);
    stringToNextion = stringToNextion + String(",");
    stringToNextion = stringToNextion + String(symbolH[page]);
    stringToNextion = stringToNextion + String(",");
    stringToNextion = stringToNextion + String(symbolX0); //     0, 0
    stringToNextion = stringToNextion + String(","); //     0, 0
    stringToNextion = stringToNextion + String("0"); //     0, 0
    stringToNextion = stringToNextion + String(",");
    stringToNextion = stringToNextion + String(numberPic[page]);
   // // Serial2.print("Symbol: "); // Serial2.println(splitData[ii-1]);
  //  // Serial2.println(stringToNextion);    
    Serial.print(stringToNextion);
    sendToNextion();
    drawX = drawX + symbolW[page][splitData[ii-1]];
  }

  if (minusSign == true) {

    /*
    symbolX0 = 0; //    
    for (byte ii = count; ii > 0; ii--) { 
      symbolX0 = symbolX0 + symbolW[page][splitData[ii-1]];
    }

    */
    
    stringToNextion = String("xpic ");
    stringToNextion = stringToNextion + String(posX); // String(axisX[page, type]);
    stringToNextion = stringToNextion + String(",");
    stringToNextion = stringToNextion + String(drawY-8); // String(axisY[page, type]);
    stringToNextion = stringToNextion + String(",");
    stringToNextion = stringToNextion + String(drawX - posX);
    stringToNextion = stringToNextion + String(",");
    stringToNextion = stringToNextion + String(minusH); //  
    stringToNextion = stringToNextion + String(",");
    stringToNextion = stringToNextion + String(0); //     0, 0
    stringToNextion = stringToNextion + String(","); //     0, 0
    stringToNextion = stringToNextion + String("0"); //     0, 0
    stringToNextion = stringToNextion + String(",");
    stringToNextion = stringToNextion + String(minusPicID);
//    // Serial2.print("Symbol: "); // Serial2.println(splitData[ii-1]);
 //   // Serial2.println(stringToNextion);    
    Serial.print(stringToNextion);
    sendToNextion();
    
  }
  
 } // if count < 5    9999
  mySwitch.enableReceive(0);
}         

//     ( )
void getMinMax(byte arrayToMax, byte maxCount) {
  
byte getMaxCount = 0;

arrayMax = historyArray[arrayToMax][getMaxCount]; //      
arrayMin = historyArray[arrayToMax][getMaxCount]; //      

for (byte getMaxCount = 0; getMaxCount < maxCount; getMaxCount++) { // maxCount 47   , 6  
  
  if (historyArray[arrayToMax][getMaxCount+1] > arrayMax){ 
    arrayMax = historyArray[arrayToMax][getMaxCount+1];
  }

  if (arrayMin > historyArray[arrayToMax][getMaxCount+1]){ 
    arrayMin = historyArray[arrayToMax][getMaxCount+1];
  }
  
}
 
}      

void getTrend(byte arrayToTrend) {
mySwitch.disableReceive();
getMinMax(0, 6); //        


for (trendCount = 0; trendCount < 6; trendCount++) {
  if (arrayMin < 0) {
    trendArray[0][trendCount] = historyArray[arrayToTrend][5-trendCount] + abs(arrayMin); //    
  } else {
    trendArray[0][trendCount] = historyArray[arrayToTrend][5-trendCount];
  }
}

sumY = 0;
sumXY = 0;

//   ,   XY
for (trendCount = 0; trendCount < 7; trendCount++) {
  sumY = sumY + trendArray[0][trendCount];
  sumXY = sumXY + trendArray[0][trendCount]*trendArray[1][trendCount];
}

trend = (int) (sumY/10 + (sumXY/x2)*trendArray[1][5]) - (sumY/10 + (sumXY/x2)*trendArray[1][0])+0.5;

// Serial2.print("Trend: "); // Serial2.println(trend);

drawTrend(arrayToTrend);
mySwitch.enableReceive(0);
}

void reDraw() {
 mySwitch.disableReceive();

// Serial2.println("Redraw main page");
/*    
 for (i = 0; i < 7; i++) {
  parameterS[i] = random(255);
  statusS[i] = 1;
 }
    */ 

 Serial.print("page 0");
 sendToNextion();
 // Serial.print("pic 0,0,6");
 // sendToNextion();
 
 
 
  for (i = 0; i < 7; i++) {
   // Serial2.print("StatusBoolean on reDraw for item "); // Serial2.print(i); // Serial2.print(" is "); // Serial2.println(statusBoolean[i]);
   if (statusBoolean[i] == true) { //     " "
    drawRoutine(currentPage, parameterS[i], i, axisX[currentPage][i], axisY[currentPage][i]);
    // Serial2.print("Redraw, ");// Serial2.print(i); // Serial2.print(": "); // Serial2.println(parameterS[i]);
    if (historyCount > 5) {
      getTrend(i);
    }

   }
    
  }

 mySwitch.enableReceive(0);
}




void getNorm() {

arrayNorm = 1.00; //  1:1

  arrayNorm = abs(arrayMax - arrayMin);
  
    arrayNorm = waveLimit/arrayNorm; //   
  
}



void drawHistory(byte arrayCounter, byte waveCount){
mySwitch.disableReceive();
byte tC01 = 0;
byte tC02 = 0; 
int interPoint, lineMulti;
int justPoint;

  byte channelCount = 0; //   ,   (ID = 0),           

      getMinMax(arrayCounter, 47); //  47   ,  39,        ,   
 //     // Serial2.print("arrayMax: "); // Serial2.println(arrayMax);
 //     // Serial2.print("arrayMin: "); // Serial2.println(arrayMin);
      getNorm();
      
      if (currentPage == 2) {
         arrayNorm = arrayNorm*0.5;      
      }

      if (currentPage == 3) {
         arrayNorm = arrayNorm*0.3;      
      }

      if (currentPage == 4) {
         arrayNorm = arrayNorm*0.2;
      }

 //     // Serial2.print("arrayNorm: "); // Serial2.println(arrayNorm);   

     
     

//  
      stringToNextion = String("add "); //   
      stringToNextion = stringToNextion + String(waveCount); //    ID
      stringToNextion = stringToNextion + String(",");
      stringToNextion = stringToNextion + String(channelCount); //   0, 1, 2  3
      stringToNextion = stringToNextion + String(",");
      if (arrayMin < 0) {
        justPoint = (int) (historyArray[arrayCounter][tC01] + abs(arrayMin))*arrayNorm + 0.5;
        stringToNextion = stringToNextion + String(justPoint); //    
      } else {
        justPoint = (int) historyArray[arrayCounter][tC01]*arrayNorm + 0.5;
        stringToNextion = stringToNextion + String(justPoint); //    
      }
      Serial.print(stringToNextion);
      // // Serial2.print("First point, original");// Serial2.println(historyArray[arrayCounter][tC01]);
      // // Serial2.print("First point: "); // Serial2.println(stringToNextion);          
      sendToNextion(); 
                
        for (tC01 = 0; tC01 < 46; tC01++) { //   37  46
          
          lineMulti = (historyArray[arrayCounter][tC01+1] - historyArray[arrayCounter][tC01])/9; //         
          
          if (arrayMin < 0) {
            justPoint = (int) historyArray[arrayCounter][tC01] + abs(arrayMin) + lineMulti+0.5;
            interPoint = justPoint;
          } else {
            justPoint = (int) historyArray[arrayCounter][tC01] + lineMulti + 0.5;
            interPoint = justPoint;
          }
          
          for (tC02 = 0; tC02 < 7; tC02++) { //   ,  ,    9
            stringToNextion = String("add "); //   
            stringToNextion = stringToNextion + String(waveCount); //     (1, 2, 3  4 )
            stringToNextion = stringToNextion + String(",");
            stringToNextion = stringToNextion + String(channelCount); //   0, 1, 2  3
            stringToNextion = stringToNextion + String(",");
            justPoint = (int) interPoint*arrayNorm;
            stringToNextion = stringToNextion + String(justPoint);
            interPoint = (int) interPoint + lineMulti;
            Serial.print(stringToNextion);   
           // // Serial2.print("Connecting point: "); // Serial2.println(stringToNextion);                               
            sendToNextion();                      
          }
          stringToNextion = String("add "); //   
          stringToNextion = stringToNextion + String(waveCount); //     (1, 2, 3  4 )
          stringToNextion = stringToNextion + String(",");
          stringToNextion = stringToNextion + String(channelCount); //   0, 1, 2  3
          stringToNextion = stringToNextion + String(",");
          if (arrayMin < 0) {
            justPoint = (int) (historyArray[arrayCounter][tC01+1] + abs(arrayMin))*arrayNorm + 0.5;
            stringToNextion = stringToNextion + String(justPoint); //    
          } else {
            justPoint = (int) historyArray[arrayCounter][tC01+1]*arrayNorm + 0.5;
            stringToNextion = stringToNextion + String(justPoint); //    
          }
          
          Serial.print(stringToNextion);
         // // Serial2.print("Next/Last point, original: ");// Serial2.println(historyArray[arrayCounter][tC01+1]);               
          // // Serial2.print("Next/Last point: "); // Serial2.println(stringToNextion);               
          sendToNextion();                                  
        }
    
 mySwitch.enableReceive(0);   
  }
  






void drawIcon(int where, byte what) {

//// Serial2.print("Where: "); // Serial2.println(where);
//// Serial2.print("What: "); // Serial2.println(what);

stringToNextion = String("xpic ");
stringToNextion = stringToNextion + String("0"); // String(axisX[page, type]);
stringToNextion = stringToNextion + String(",");
stringToNextion = stringToNextion + String(where-3); // String(axisY[page, type]);
stringToNextion = stringToNextion + String(",");
stringToNextion = stringToNextion + String(80); //   
stringToNextion = stringToNextion + String(",");
stringToNextion = stringToNextion + String(30);
stringToNextion = stringToNextion + String(",");
stringToNextion = stringToNextion + String(what*80); //     X = 80*  
stringToNextion = stringToNextion + String(","); // 
stringToNextion = stringToNextion + String("0"); //   Y  0
stringToNextion = stringToNextion + String(",");
stringToNextion = stringToNextion + String(4);
//// Serial2.println(stringToNextion);
Serial.print(stringToNextion);
sendToNextion();
  
}



void toPage(byte pageNum) {
mySwitch.disableReceive();
currentPage = pageNum;

/*
//    
stringToNextion = String("ref page");
stringToNextion = stringToNextion + String(pageNum);
Serial.print(stringToNextion);
sendToNextion();
*/

//    
  String stringToNextion = String("page ");
  stringToNextion = stringToNextion + String(pageNum);
 // // Serial2.print("Switch to: "); // Serial2.println(stringToNextion);
  Serial.print(stringToNextion);
  sendToNextion();



if (pageNum == 0) {
  clearSelection();
  reDraw();
}

//        
  if (pageNum > 0) {

    
    if (pageNum == 1 && waveCounter > 1) { //           
 //     // Serial2.print("Draw single, searchCounter-1: "); // Serial2.println(searchCounter-1);
      getMinMax(searchCounter-1, 47); //      
  //    // Serial2.print("arrayMax: "); // Serial2.println(arrayMax);
  //    // Serial2.print("arrayMin: "); // Serial2.println(arrayMin);
      drawRoutine(pageNum, arrayMax, searchCounter-1, 0, 117); // 115
      drawIcon(145, searchCounter-1);
      drawRoutine(pageNum, arrayMin, searchCounter-1, 0, 185); // 175
      drawHistory(searchCounter-1, 1); //  :     
     } else {

              //  
              iconCounter = 0;
              for (drawCounter = 0; drawCounter < 7; drawCounter++) {
                if (drawArray[drawCounter] == true) {
        //          // Serial2.print("pageNum: "); // Serial2.println(pageNum);
       //           // Serial2.print("iconCounter: "); // Serial2.println(iconCounter);
      //            // Serial2.print("drawCounter: "); // Serial2.println(drawCounter);
                  getMinMax(drawCounter, 39); //   39  47
      //            // Serial2.print("arrayMax: "); // Serial2.println(arrayMax);
     //             // Serial2.print("arrayMin: "); // Serial2.println(arrayMin);
                  drawRoutine(pageNum, arrayMax, drawCounter, 0, axisY[pageNum][iconCounter]-22);   // -30               
                  drawIcon(axisY[pageNum][iconCounter], drawCounter);
                  drawRoutine(pageNum, arrayMin, drawCounter, 0, axisY[pageNum][iconCounter]+35); // +30
                  iconCounter++;
                }
            }      
              channelToDraw = 1; //      ,    ,   - 
              for (drawCounter = 0; drawCounter < 7; drawCounter++) { //   " "
                if (drawArray[drawCounter] == true) {
                  drawHistory(drawCounter, channelToDraw);
           //       // Serial2.print("drawCounter / channelToDraw "); // Serial2.print(drawCounter); // Serial2.print(" | "); // Serial2.println(channelToDraw);
                  channelToDraw++;
                 }
              }
      }
    }
    
  mySwitch.enableReceive(0);
}



void setup() {

  pinMode(ledPower,OUTPUT);
 // pinMode(measurePin, INPUT);

 pinMode(4, OUTPUT);
 digitalWrite(4, HIGH);



 
  currentPage = 0;
  allClear = true;
  historyCount = 0; //       
  backLight = true; //          ,   false
  
//     
//  . : tempIn, tempOut, humidityIn, humidityOut, pressure, ppm, pm
 for (i = 0; i < 7; i++) {
  parameterS[i] = 0;
  statusS[i] = 1;
 }

//   
for (arrayCounter = 0; arrayCounter < 7; arrayCounter++) {
 for (i = 0; i<48; i++) {
  historyArray[arrayCounter][i]=0;
 }
}
 
 statusTime = millis();
 updateTime = millis();
 historyTime = millis();
 backLightTime = millis();

 Serial.begin(9600);
  Serial.print("baud=57600");
  sendToNextion();
 Serial.end();

 Serial.begin(57600);
 Serial.print("baud=57600");
 sendToNextion();
 
 // Serial2.begin(115200);
 dht.begin();
 mySwitch.enableReceive(0);
 delay(2000);
 Serial.print("page 0");
 sendToNextion();
 // Serial2.println("Ready");
 
 reDraw();
}



void loop() {


//    

   if (mySwitch.available()) { //  
    int value = mySwitch.getReceivedValue();
    if (value != 0) {
    // Serial2.print("RC-Switch: "); // Serial2.println(mySwitch.getReceivedValue());
//    
      if (mySwitch.getReceivedValue() / 100000 == 161) {

        weatherData = mySwitch.getReceivedValue() - 16100000;
        if (weatherData > 10000) { //  
          parameterS[3] = (weatherData - 10000)/10;
          statusS[3] = statusS[3]+1;   
          statusBoolean[3] = true;  
        }
        else { //  
          if (weatherData > 1000) { //  
            parameterS[1] = -(weatherData - 1000);
            minusOut = true;
          }
          else { //  
            parameterS[1] = weatherData;
            minusOut = false;
          }
        }
          statusS[1] = statusS[1]+1;
          statusBoolean[1] = true;
      }

//    
      if (mySwitch.getReceivedValue() / 10000 == 1210) {
        parameterS[4] = (mySwitch.getReceivedValue() - 12100000) / 1.33; //  
        statusS[4] = statusS[4]+1;   
        statusBoolean[4] = true;   
        // Serial2.print("Pressure: "); // Serial2.println(parameterS[4]);     
      }

      if (mySwitch.getReceivedValue() / 100000 == 131) {
        weatherData = mySwitch.getReceivedValue() - 13100000;
        if (weatherData > 1000) { //  
          parameterS[0] = -(weatherData - 1000);
          minusIn = true;
        }
        else { //  
          parameterS[0] = weatherData;
          minusIn = false;
        }
          statusS[0] = statusS[0]+1;
          statusBoolean[0] = true;
      }

//        

      if (mySwitch.getReceivedValue() / 10000 == 1212) {
        parameterS[2] = (mySwitch.getReceivedValue() - 12120000); // 
        statusS[2] = statusS[2]+1;   
        statusBoolean[2] = true;   
        // Serial2.print("HumidityIn: "); // Serial2.println(parameterS[2]);     
      }
// CO2 PPM
      if (mySwitch.getReceivedValue() / 10000 == 1213) {
        parameterS[5] = (mySwitch.getReceivedValue() - 12130000); // CO2
        statusS[5] = statusS[5]+1;   
        statusBoolean[5] = true;   
        // Serial2.print("CO2 PPM: "); // Serial2.println(parameterS[5]);     
      }      
// PM2.5
      if (mySwitch.getReceivedValue() / 10000 == 1214) {
        parameterS[6] = (mySwitch.getReceivedValue() - 12140000); // PM2.5
        statusS[6] = statusS[6]+1;   
        statusBoolean[6] = true;   
        // Serial2.print("PM2.5: "); // Serial2.println(parameterS[6]);     
      } 

    }
    mySwitch.resetAvailable();
    //    mySwitch.enableReceive(0); //  RC Switch
  }   

  
//    
if (currentPage == 0) {
  if ((millis() - selectionTime) > selectionTimeOut) { 
    if (allClear == false) {
      clearSelection();
    }
  }
 }

  if (Serial.available())
  {
    bool moretocome = true;
    int endcount = 0;
    int bytesread = 0;
    byte inbyte;
    //bool isascii = false;

    while (moretocome)
    {
      inbyte = Serial.read();

        delay(2);
        
      if (inbyte == 0xFF)
      {
        endcount++;
        if (endcount == 3)
        {
          moretocome = false;
          // Serial2.println("");
        }
      }
      else
      {
        endcount = 0;
      }
      buffer[bytesread] = inbyte;
      bytesread++;

    }

    for (int x = 0; x < bytesread; x++)
    {
      // Serial2.print(buffer[x], HEX);
      // Serial2.print(" ");
    }

    //// Serial2.println(bytesread, DEC);
    // Serial2.println("");

  }

  if (buffer[0] == 101) { //   
   backLightTime = millis(); //        
   if (backLight == false) { //    ,   
    // Serial2.println("Backlight 50%");
    Serial.print("dim=100"); //  
    sendToNextion();
    backLight = true; //    
   } else { //     
    
    if (buffer[1] == 0) { //    
      selectionTime = millis();
      if (buffer[2] < 8) { //    
      if (waveCounter < 4) { //    4 
        if (drawArray[buffer[2]-1] == false) { //    
          drawArray[buffer[2]-1] = true; //    ,   
          drawMark(1, buffer[2]-1);
          waveCounter = waveCounter + 1; //       
     //     // Serial2.print("Set button: "); // Serial2.println(buffer[2]);          
     //     // Serial2.print("Total buttons: "); // Serial2.println(waveCounter);
        } else {
          drawArray[buffer[2]-1] = false; //     
          drawMark(0, buffer[2]-1);
          if (waveCounter > 0) {
            waveCounter = waveCounter - 1;
          }
     //     // Serial2.print("Clear button: "); // Serial2.println(buffer[2]);          
     //     // Serial2.print("Total buttons: "); // Serial2.println(waveCounter);          
        }
      } else { //     
        if (drawArray[buffer[2]-1] == true) { //    ,  
          drawArray[buffer[2]-1] = false; //     
          drawMark(0, buffer[2]-1);
          waveCounter = waveCounter - 1; //   
     //     // Serial2.print("Clear button: "); // Serial2.println(buffer[2]);          
     //     // Serial2.print("Total buttons: "); // Serial2.println(waveCounter);          
        }
      }
    } else { //      
        currentPage = waveCounter;
        toPage(waveCounter);    
      }
    }
    else { 
      if (currentPage > 1) { //      ,    ID = 5    0
        if (buffer[2] == 5) {
          toPage(0);
        }
      }

      if (currentPage == 1) { //   1   ,    ID = 5    0
        if (buffer[2] == 5) {
          if (waveCounter == 1) {
            toPage(0);
          } else {
            toPage(waveCounter); //       
          }
        }
      }

      if (currentPage == 1) { //    1     ID = 6 -          
        if (buffer[2] == 6) {
          toPage(0);
        }
      }      
      
      //   

    if (currentPage > 1) { //    1, .   1
      if (buffer[2] > 5) { //     ID > 2, ..  
   //     // Serial2.print("Buffer[2]: ");
   //     // Serial2.println(buffer[2]);
   //     // Serial2.print("Normalized button: ");
        searchTarget = buffer[2] - 5; // ""  ,     ,   :  1 -   -  true   drawarray   1
        searchNumber = 0;
        searchCounter = 0;
   //     // Serial2.println(searchTarget);

        while ((searchCounter < 7) && (searchNumber < searchTarget)) {
          if (drawArray[searchCounter] == true) {
            searchNumber++;
          }
          searchCounter++;
        }
        
   //     // Serial2.print("searchCounter: "); // Serial2.println(searchCounter);
        toPage(1); //      
      }
    }


      
     }
    }
  } 

buffer[0] = 0;

//    *Status   1   
//    

//  :       ,    9
if ((millis() - statusTime) > statusTimeOut) {

 
 for (i = 0; i < 7; i++) { //   
  // Serial2.print("Status of "); // Serial2.print(i); // Serial2.print(" is: "); // Serial2.println(statusS[i]);
    if (statusS[i] == 0) {statusBoolean[i] = false;
    // Serial2.print("As StatusS "); // Serial2.print(i); // Serial2.print(" is "); // Serial2.print(statusS[i]); // Serial2.println(" StatusBoolean set to false");
    }
    statusS[i] = 0; //    
 }
  statusTime = millis();
  
}

if (currentPage == 0) { //       

 
//    
if ((millis() - updateTime) > updateTimeOut) {

  reDraw();
  updateTime = millis();
 }

 
 
}

//         
if ((millis() - backLightTime) > backLightTimeOut) {
 if (backLight == true) {
  backLight = false;
  // Serial2.println("Backlight 15%");
  //Serial.print("page 0");
  // sendToNextion();
  currentPage = 0;
  clearSelection();
  reDraw();
  Serial.print("dim=15");
  sendToNextion();
 }
  
 }

//   
if ((millis() - historyTime) > historyTimeOut) {
  updateHistory();

    historyCount++;
    // Serial2.print("History Q: "); // Serial2.println(historyCount);
 
  historyTime = millis();
  }

}  



نموذج الحالة (بعناية - يمكنك كسر الشاشة)

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


All Articles