Jedes Wetter ist gut: ein Wetterindikator, der cosplay



Stellen wir uns vor, dass nach einem Gefecht mit Dave Bowman die Überreste der einst mächtigen Intelligenz von HAL 9000 ausreichten, um Discovery One zurück auf die Erde zu bringen und es unter dem Motto „Tod allen Menschen“ auf dem Planeten zu zerschlagen, damit es nicht mehr falsch wäre, dies mit Computern zu tun.

Die Katastrophe, die ausbrach, zerstörte natürlich die gesamte rationale Menschheit, und nur Individuen wie ich blieben mit einem Hammer in der einen und einem Arduino in der anderen Hand zurück. Daher ist es nicht verwunderlich, dass das mysteriöse Gerät, das von den immer noch mysteriösen Überresten des im Berg gefundenen Raumfahrzeugs gefunden wird, nur in einer Wetterstation verwendet werden kann. Nun, zu Recht!

Wenn wir die Romantik verwerfen, war die harte Wahrheit des Lebens, dass der berüchtigte ITEAD das Nextion HMI NX4832T035- Display zum Testen anbot .

Da Nextion-Produkte hier wiederholt beschrieben wurden, sind die Funktionen kurz gefasst. Dies ist ein Bildschirm mit einer eigenen einfachen API und einem Touchpanel, mit dem Sie Steuergeräte mit grafischen Menüs ohne großen Aufwand erstellen können.

Zu diesem Zweck verfügt Nextion über ein einfaches Befehlssystem zum Anzeigen von Bildern (und deren Teilen), Textelementen, Eingabefeldern und Grafiken. Außerdem gibt es eine Art Skriptsprache zum Ausführen von Aktionen, z. B. durch Drücken der Bildschirmtasten oder durch Timer. Gleichzeitig ein Anschluss zum Empfangen externer Befehle von Mikrocontrollern oder dergleichen und zum Zurückgeben von Daten über das Berühren des Bildschirms, um zu wissen, welche Tasten die spielerischen Hände des Besitzers haben und in welchem ​​Zustand sich diese Taste gerade befindet (gedrückt, losgelassen).

Grob gesagt besteht keine Notwendigkeit, zu leiden und Punktanordnungen zu sammeln oder eine Wolke aller Arten von Bibliotheken zu verbinden. Eine Zeile - und der Hintergrund auf dem Bildschirm hat sich geändert. Klicken Sie auf - ein Menü wird geöffnet. Wir haben Arduino angeschlossen - wir erstellen Diagramme anhand der Daten, die über die serielle Schnittstelle empfangen werden.

Das heißt, nach der Beschreibung zu urteilen, ist das Display so intelligent, dass es alles anzeigen und darauf reagieren kann (es gibt ein Touchpanel). Aber ich habe nichts zu Hause, aber Klimadaten fliegen regelmäßig durch die Luft. Zum Beispiel vom selben BDS-M oder vom PI-TV-2- Wettersensor .

Natürlich werden sie alle letztendlich an People's Monitoring übertragen , von wo aus ich das Glück habe, sie über einen Browser oder eine App auf meinem Smartphone anzusehen. Aber ich konnte der Idee nicht widerstehen, „eine weitere Wetterstation auf dem Arduino“ zu bauen.

Und um ehrlich zu sein, ging es nicht so sehr um Technologie als solche, sondern darum, dass ich mich hartnäckig für das Entwerfen von Schnittstellen interessierte. Wahrscheinlich zieht er mit der gleichen Kraft, mit der er zieht, um alle zu singen, denen der Bär auf sein Ohr getreten ist.

Deshalb entschuldige ich mich sofort dafür, dass es weniger Ausrüstung und mehr Fantasy-Fantasien geben wird. Aber zuerst eine kleine Demonstration des fertigen Produkts, anhand derer Sie entscheiden, weiterlesen oder mit dem nächsten Material fortfahren können.



Ich hatte also 3,5 Zoll, 480 x 320 Pixel, was eine ziemlich einfache API zu sein schien, und sieben Parameter, die angezeigt werden mussten (in Klammern sind die daran angebrachten Sensoren):

1) Die Temperatur innen und außen (BMP085 / DHT22)
2) Die Luftfeuchtigkeit innen und außen (DHT22 / DHT22)
4) Atmosphärendruck (BMP085)
5) Die Konzentration von nicht sehr nützlichen Gasen im Raum, insbesondere CO2 (MQ135)
6) Die Konzentration von Feststoffen in der Raumluft, insbesondere PM2.5 (Sharp GP2Y1010AU0F)

Hierbei ist zu beachten, dass Genossen, die sich mit den Eigenschaften der letzten beiden Sensoren vertraut gemacht haben, zu dem Schluss kommen, dass die größte Reaktion nur im Bereich CO2 bzw. PM2,5 erzielt wird. Dies erklärt in der Tat meine Wahl: Es ist nicht schade, zwei Cent auszugeben und zu sehen, was passiert, während spezialisierte Sensoren viel teurer sind und die Kröte im Fehlerfall immer etwas zu zeigen hat.

Es ist klar, dass ich von billigen Sensoren nicht viel Genauigkeit erwartet hatte - vielmehr erwartete ich, meine eigenen Gefühle mit ihren Messwerten zu korrelieren. Übrigens ist alles ganz offensichtlich: Es lohnt sich, das Fenster zu schließen, da gleichzeitig mit steigender Temperatur und Verstopfung die Gaskonzentrationswerte von MQ135 zu steigen beginnen.

Allerdings zu den Parametern. Es schien mir langweilig, nur sieben Ziffern anzuzeigen, daher wurde die technische Aufgabe für das Gerät erweitert: Ich habe für jeden Parameter eine grafische Darstellung der Änderungen im Zeitverlauf erstellt. Und so konnten auf einem Bildschirm bis zu vier Kurven gleichzeitig angezeigt werden, um Muster (falls vorhanden) in den Änderungen verschiedener Indikatoren visuell wahrzunehmen.

Ein aufmerksamer Leser und Besitzer eines tragbaren Geräts mit einer Diagonale von 3,5 Zoll oder mehr wird wahrscheinlich sagen, dass dies nichts Kompliziertes ist. Wie auf einem solchen Bildschirm und mehr Daten passen leicht.

Aber es gibt einen Trick: Bei einem Haushaltsgerät sollten Zahlen und Unterschriften so groß wie möglich sein, damit sie nicht lange in einer Lupe auf den Bildschirm schauen müssen, um den Geist des Schöpfers zu durchdringen.

Im Allgemeinen wollte ich die größte und nicht zu überfüllte Schnittstelle, deren Logik ohne eine höhere Ausbildung verstanden werden könnte. Mit einem solchen Bild im Kopf habe ich es in den Nextion-Editor übertragen und zwei Hauptbildschirmtypen erhalten.

Hauptbildschirm mit aktuellen Messwerten der Sensoren:




Zusätzlich zu den tatsächlichen Messwerten sehen Sie auch einen Hinweis auf den Änderungstrend (nach oben / unten) und Markierungen von Parametern, die für die Anzeige im Diagramm ausgewählt wurden. Durchscheinende Vierecke sind die sensorischen Bereiche, die in der Arbeit unsichtbar sind.

Bildschirm mit Grafiken. Tatsächlich gibt es vier davon, die von einem bis vier Graphen angezeigt werden können, aber tatsächlich sind sie alle identisch. Zum Beispiel ein Bildschirm mit einem und vier Diagrammen:




Hier werden für jeden Parameter auch dessen Maximum und Minimum angezeigt, um die Grenzen zu verstehen. Aber es gibt keine Zeitleiste: Erstens hat das Gerät keine Uhr, und zweitens gibt es einfach keinen Platz für die Waage. Zumindest habe ich nicht gefunden, wo ich es anhängen soll, da ich maximal vier Grafiken anzeigen wollte.

In diesem Fall sieht der Code vor, dass die erhaltenen Indikatoren alle halbe Stunde mit einer Gesamtarchivtiefe von 48 Werten, d. H. für etwa einen Tag. Ungefähr - weil die Daten über den 433-MHz-Funkkanal übertragen werden, der nicht vor Störungen geschützt ist, sind Lücken möglich.

Und bei diesen Lücken ist auch die Lebensdauer der Sensoren in derselben halben Stunde vorgesehen. Und wenn innerhalb einer halben Stunde kein Datenempfang stattgefunden hat, werden die Sensorwerte nicht angezeigt und nicht in das Archiv eingegeben.

Trends bei Indikatoren werden durch den ersten Algorithmus berechnet, der auf die letzten sechs Punkte in der Geschichte stößt , d. H. nach den sechs neuesten Angaben. Und da die Messungen in halbstündigen Intervallen durchgeführt werden, stellt sich heraus, dass der Trend Änderungen in den letzten drei Stunden widerspiegelt.

Wie jeder Designer musste ich "mit Schriftarten spielen". Beim Zeichnen der Optionen stellte sich heraus, dass meine Lieblingssymmetrie nicht nur durch die Kombination von Feuchtigkeitsindikatoren in der oberen rechten Ecke, sondern auch durch ein viel enttäuschenderes Phänomen in Form von negativen Temperaturen gebrochen werden musste.

Die Minuspunkte verdarben nämlich das ganze Bild. Deshalb habe ich auf meine eigene Weise gehandelt: Setzen Sie ein Minus über den Wert. Für Mathematiker wird dies natürlich wie eine barbarische Lösung erscheinen, und die Beteiligten werden natürlich unwillkürlich zurückschrecken und darüber nachdenken, warum Wetterstationen modulo bewertet werden sollten. Aber es stellte sich ziemlich ordentlich heraus und die Zahlen tanzen nicht.

Die Logik der Schnittstelle ist wie folgt. Die Hauptbetriebsart ist der Standby-Modus mit einer Bildschirmhelligkeit von 15% des Nennwerts und einer regelmäßigen Aktualisierung der Messwerte.

Überall berühren - mit 100% Helligkeit online gehen. Wenn Sie danach auf die Messwerte klicken, wählen Sie sie für die nachfolgende Anzeige in der Grafik aus, und klicken Sie auf das "Auge". HAL wechselt zum Bildschirm mit den Grafiken.

Dafür gibt es genau fünf Sekunden. Dann werden die Markierungen gelöscht und nach weiteren fünf Minuten Inaktivität wechselt das Gerät zurück in den Standby-Modus.

Auf dem Diagrammbildschirm ist der linke Teil ein Schritt zurück (der Hauptbildschirm oder der Bildschirm mit Diagrammen), und der rechte Teil ist eine Vergrößerung des ausgewählten Diagramms im Vollbildmodus oder wiederum der Übergang zum Hauptbildschirm, wenn nur ein Diagramm vorhanden ist.

Es schien mir, dass dieses Schema einfach genug ist, um keine zusätzlichen Schaltflächen hinzuzufügen, die ich hier nicht wirklich sehen möchte.

Hintergrundbilder können übrigens bei Bedarf geändert werden. Ich habe sogar einige zusätzliche Optionen vorbereitet.

Für Kolonisten:


Für Hobbits:


Für Romantiker:


Für Kaffeeliebhaber:


Im Konzept ist das gesamte Gerät weniger eine Wetterstation als vielmehr ein spezielles drahtloses Display. Daher ist das Design äußerst einfach: Nur der Bildschirm, der Arduino Pro Mini und der 433-MHz-Empfänger mit Amplitudenmodulation befinden sich im Inneren. Die Baugruppe enthält überhaupt keine Funktionen: Der Bildschirm ist für die Stromversorgung und die serielle Schnittstelle vorgesehen, der Empfänger für die Stromversorgung und Pin 2 des Controllers. Abgesehen von der Notwendigkeit kompatibler externer Sensoren - das ist alles.

Um die Einfachheit zu verstehen, zeige ich eine der Gehäuseoptionen mit einer fast installierten Füllung:





Natürlich bestehe ich nicht auf einer solchen Konfiguration, aber in meinem Fall war sie sowohl hinsichtlich der Mühsal als auch der Kompatibilität mit anderen Komponenten der Hausautomation optimal.

Durch die Trennung von Display und Sensoren können Sie dasselbe Display an der bequemsten Stelle platzieren - wie bei jeder Wetterstation mit externen Sensoren.

Damit all dies funktioniert und beim Anblick von Drahtklumpen, einer Reihe von Sensoren und Mikrocontrollern, die in der Luft hängen, kein tierisches Entsetzen hervorruft, sollten Sie die Fälle herausfinden.

Die harte Wahrheit des Lebens war, dass die Box, in der BDS-M bisher gelebt hatte, drei zusätzliche Sensoren nicht aufnehmen konnte. Deshalb habe ich den Gefühlen freien Lauf gelassen und eine atemberaubende Lampe von Markellov gedruckt .

Aus Sicht des Wettersensors ist es ideal, da es von allen Winden geblasen wird und gleichzeitig das Chaos im Inneren effektiv und effektiv verbirgt. Nach solchen Metamorphen gab es kein BDS-M mehr: Jetzt ist es glamourös (wenn Sie nicht in die Nähe kommen). Multisensor:

Shell:



Zusammengebaut und an Ort und Stelle:



Es stellte sich heraus, dass es mit der Anzeigeeinheit schwieriger war. Im Allgemeinen wollte ich ihn ziemlich massiv und brutal sehen. Natürlich, als ob der Ureinwohner, der einen Teil des Raumschiffs gefunden hatte, ihn in Stein gemeißelt hätte. Daher passte der Rahmen, dessen Modell bereits in Nextion angeboten wurde, in keiner Weise. Erstens war es beängstigend, und zweitens befand sich das Display dort in einer Aussparung, die mir kategorisch nicht zusagte - ich wollte mit der Oberfläche spülen.

Ich habe aber trotzdem mit Plastik angefangen - nur um die Form zu brechen. Die Zwischenoptionen sahen ungefähr so ​​aus:



Im Allgemeinen hat es mir gefallen (ich habe beschlossen, ein wenig Unzufriedenheit nicht zu bemerken), aber das Gewicht ist natürlich ziemlich lächerlich, kein Stein. Daher wird eines der Gebäude als Innenschalung für die Herstellung von Beton "Rahmen" verwendet.

Der Prozess schockierte mich bis ins Mark - ich habe zu Hause selten so viel Schmutz gezüchtet. Das Ergebnis ist das gleiche. Obwohl sich stellenweise herausstellte, dass es gar nichts war, stellte sich heraus, dass die verstärkte Reparaturmischung für solche Produkte nicht sehr geeignet ist.

Vielleicht wäre reiner Sandbeton ideal, aber zu diesem Zeitpunkt war ich bereits von meinen eigenen Baukünsten enttäuscht und machte mich wie mein Kollege auf den Weg. Und nachdem er ein wenig nachgedacht hatte, sagte er, dass er das Glück in seinem Leben hatte, mit Sprühfarbe unter dem Stein zu arbeiten.

Bingo, dachte ich mir und fing sofort an, die Details herauszufinden. Schließlich ist das Drucken und Malen eines Koffers viel ästhetischer als das Verwandeln eines Hauses in eine Baustelle in voller Größe. Im Allgemeinen war die Farbe unmenschlich teuer, aber sehr cool (für Interessierte - Rust-Oleum American Accents Stone).

Unterwegs kam ich auch zu dem Schluss, dass mir das Korps mit nichts gefiel (höchstwahrscheinlich mit dicken Rahmen um den gesamten Umfang), also riss ich mich zusammen und kam nach einem Verhör mit einer Sucht zu einer endgültigen Form.

Es war:



Es wurde:







Es ist leicht zu erkennen, dass es keine Spur von Massivität gibt, aber aus irgendeinem Grund gefällt mir diese Form am besten. Ich werde darauf eingehen. Tschüss.

Die Ansicht ist natürlich ein Amateur, da einige Innereien des Bildschirms (dieselbe Schleife des Touchpanels) in Sicht sind und damit auf vernünftige Weise nichts getan werden kann. Meiner Meinung nach unvernünftig - Überzüge, Farbe, Klebebänder.

Und da ich mit transparentem Kunststoff gedruckt habe, nachts im allgemeinen Raum:



Nun zu einigen, sagen wir, den Nuancen des Designs. Ich werde vielleicht vom selben Gebäude aus starten. Das Verlangen nach Schönheit war ein schlechter Scherz: Da ich wollte, dass der Bildschirm bündig mit der Oberfläche abschließt, wurde der Ausschnitt so weit wie möglich entsprechend den Außenabmessungen des Displays hergestellt. Und nach ungefähr einem Dutzend Armaturen hat er seine Arbeit erledigt - entweder das Touchpanel-Kabel gebrochen oder den Kontakt mit der Platine unterbrochen, aber jetzt ist es sehr schwierig, den Sensor zum Laufen zu bringen.

Daher kann ich ein solches Design wahrscheinlich nicht empfehlen. Nun, oder ich empfehle, aber denken Sie daran, dass dies eine der einfachsten und schönsten (ja, ich schmeichle mir dreist) Möglichkeiten ist, den Bildschirm zu brechen.

Außerdem musste ich einige Funktionen des Bildschirms selbst durchgehen, deren Beschreibung ich persönlich als "Sie können es nicht einfach nehmen und ..." bezeichnen kann.

Man kann also nicht einfach irgendeine Schriftart aufnehmen und anzeigen. Das heißt theoretisch - ja. Jede Windows-Schriftart kann in den in die Nextion-Umgebung integrierten Konverter heruntergeladen werden. Die Ausgabe ist ein ziemlich zahniges Raster, das nicht optimal aussieht.

Vergleichen Sie beispielsweise die konvertierte Schriftart mit dem Original:


Deshalb musste ich den trostlosen Weg gehen. Nämlich - um Zahlen und Signaturen aus grafischen Elementen zu erstellen, die zuvor in GIMP erstellt wurden.

Dann bin ich über die Charts gestolpert. Es stellte sich heraus, dass Sie nicht einfach einen beliebigen Datensatz aufnehmen und dem Wellenformelement zuführen können, das zum Zeichnen von Kurven bestimmt ist. Zuerst müssen Sie alles auf das gewünschte Format bringen - von 0 bis 255 - und die Zwischenpunkte beenden, wenn die Bildschirmbreite geringer ist.

Nun, dann habe ich herausgefunden, dass das nicht alles ist. Es stellt sich heraus, dass 255 logische Punkte von der Anzeige nicht skaliert werden, wenn sich die Höhe des Wellenform-Diagrammelements ändert. Daher ist es beim Ändern der Höhe des Wellenform-Diagrammelements erforderlich, die Skalierung der Werte proportional zu ändern, da sonst das Diagramm "abgeschnitten" wird.

Sie können jedoch keine Bilder mit transparentem Hintergrund verwenden, wodurch die nützliche Breite der Informationsfelder etwas eingeschränkt wurde, sodass im Verlaufsbereich des Hintergrundbilds keine hässliche Überlappung auftritt. Meiner Meinung nach hat das Nextion-Forum dies diskutiert, und es scheint, dass ITEAD versprochen hat, die Möglichkeit zur Arbeit mit transparenten Bildern hinzuzufügen, dies jedoch noch nicht getan hat.

Dies wird, wie meine Qual beim Umschalten der Portgeschwindigkeit (die für das schnelle Zeichnen von Grafiken erforderlich ist), erfahrenen Kameraden zweifellos lächerlich erscheinen. Ich kann jedoch nicht schweigen - ich habe anständig die Kräfte aufgewendet, um sie zu überwinden.

Aber insgesamt fühle ich mich wie ein Gewinner. Was ich wollte - ich tat es und die Sammlung von Haushaltsgeräten wurde mit einem anderen aufgefüllt. Darüber hinaus ist es nicht völlig nutzlos: Es ist praktisch, sofort zu sehen, was Heimsensoren anzeigen, ohne nach einem Smartphone zu greifen und keinen Computer einzuschalten.

Außerdem hängt dieses Ding nicht vom Internet ab und sieht in diesem Zusammenhang wie ein Anti-IoT-Gerät aus, da es alles in sich selbst speichert. Und dann stelle ich mir vor, als würde ein Hacker mit einem absurden Sinn für Humor meine Wetterstation abschneiden und sie die Tür abschließen lassen.

Ich würde dann draußen herumkratzen mit Anfragen wie:

- Öffne die Türen der Pod-Bucht, HAL

True, wäre es lustig?

PS Bei der Herstellung des Gerätes wurde von den Handbüchern geleitet:

" Nextion HMI Solution
" FLProg + Nextion HMI. Lektion 1
» FLProg + Nextion HMI. Lektion 2
» FLProg + Nextion HMI. Lektion 3

kann ich auch anbieten:

" Das Layout der Oberfläche zum Bearbeiten im Nextion Editor
"Download-Schnittstellendatei anzeigen

Teilecode für Arduino anzeigen
// 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();
  }

}  



Fallmodell (vorsichtig - Sie können den Bildschirm brechen)

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


All Articles