Chaque temps est bon: un indicateur météo qui cosplay



Imaginons qu'après une escarmouche avec Dave Bowman, les vestiges de l'intelligence jadis puissante de HAL 9000 aient suffi à ramener Discovery One sur Terre et, sous le slogan «la mort à tous les peuples», à l'écraser sur la planète, afin qu'il ne soit plus mauvais de le faire avec les ordinateurs.

Le cataclysme qui a éclaté, bien sûr, a détruit toute l'humanité rationnelle, et seuls des individus comme moi sont restés, avec un marteau dans une main et un Arduino dans l'autre. Par conséquent, il n'est pas surprenant que l'appareil mystérieux trouvé par les restes encore mystérieux du vaisseau spatial trouvé dans la montagne ne puisse être utilisé que dans une station météorologique. Eh bien, à juste titre!

Si nous rejetons la romance, alors la dure vérité de la vie était que le célèbre ITEAD a offert l' écran Nextion HMI NX4832T035 pour les tests .

Étant donné que les produits Nextion ont été décrits à plusieurs reprises ici, il est concis sur ses capacités. Il s'agit d'un écran avec sa propre API simple et son écran tactile pour créer des unités de contrôle avec des menus graphiques sans trop de tracas.

À cet effet, Nextion dispose d'un système de commande simple pour afficher des images (et leurs parties), des éléments de texte, des champs de saisie, des graphiques. De plus, il existe une sorte de langage de script pour effectuer des actions, par exemple, en appuyant sur les boutons à l'écran ou par minuterie. Et en même temps, un port pour recevoir des commandes externes de microcontrôleurs ou similaires et renvoyer des données sur le toucher de l'écran pour savoir quels boutons les mains ludiques du propriétaire sont arrivés et dans quel état ce bouton est (pressé, relâché) pour le moment.

En gros, il n'est pas nécessaire de souffrir et de collecter des tableaux de points ou de connecter un nuage de toutes sortes de bibliothèques. Une ligne - et l'arrière-plan a changé à l'écran. Cliqué - un menu s'ouvre. Nous avons connecté Arduino - nous construisons des graphiques en fonction des données reçues via le port série.

Autrement dit, à en juger par la description, l'écran est si intelligent qu'il peut montrer et répondre (il y a un écran tactile) à tout. Mais je n'ai rien chez moi, mais les données climatiques volent périodiquement dans l'air. À partir du même BDS-M , par exemple, ou du capteur météo PI-TV-2 .

Bien sûr, tous sont finalement transférés vers People’s Monitoring , d'où j'ai la chance de les regarder via un navigateur ou une application sur mon smartphone. Mais je n'ai pas pu résister à l'idée de faire "une autre station météo sur l'Arduino".

Et, pour être honnête, ce n'était pas tant une question de technologie en tant que telle, mais du fait que j'étais obstinément attiré par la conception d'interfaces. Probablement, il tire avec la même force avec laquelle il tire pour chanter tous ceux à qui l'ours a marché sur son oreille.

Par conséquent, je m'excuse immédiatement pour le fait qu'il y aura encore moins d'équipement et plus de fantasmes fantastiques. Mais d'abord, une petite démonstration du produit fini, selon laquelle vous pouvez décider, lire ou passer au matériau suivant.



Donc, j'avais 3,5 pouces, 480x320 pixels, ce qui semblait une API assez simple et sept paramètres qui devaient être affichés (entre parenthèses, les capteurs y sont attachés):

1) La température à l'intérieur et à l'extérieur (BMP085 / DHT22)
2) L'humidité à l'intérieur et extérieur (DHT22 / DHT22)
4) Pression atmosphérique (BMP085)
5) La concentration de gaz peu utiles dans la pièce, en particulier le CO2 (MQ135)
6) La concentration de solides dans l'air ambiant, en particulier les PM2,5 (Sharp GP2Y1010AU0F)

Il convient de noter ici que les camarades qui se sont familiarisés avec les caractéristiques des deux derniers capteurs concluent que la meilleure réponse est obtenue uniquement dans le domaine du CO2 et des PM2,5, respectivement. En fait, cela explique mon choix: ce n'est pas dommage de dépenser deux sous et de voir ce qui se passe, alors que les capteurs spécialisés sont beaucoup plus chers et en cas d'échec, le crapaud a toujours quelque chose à montrer.

Il est clair que je ne m'attendais pas à beaucoup de précision de la part de capteurs bon marché - je m'attendais plutôt à corréler mes propres sentiments avec leurs lectures. Et, au fait, tout est assez évident: cela vaut la peine de fermer la fenêtre, car en même temps que la température et la congestion augmentent, les valeurs de concentration de gaz du MQ135 commencent à grimper.

Cependant, aux paramètres. Il m'a semblé ennuyeux de ne montrer que sept chiffres, par conséquent, la tâche technique de l'appareil s'est étendue: j'ai trouvé pour chaque paramètre un graphique des changements dans le temps. Et de sorte que sur un écran, il était possible de visualiser jusqu'à quatre courbes en même temps pour la perception visuelle des motifs (s'il y en a) dans les changements de divers indicateurs.

Un lecteur attentif et propriétaire de tout appareil portable d'une diagonale de 3,5 pouces ou plus, dira probablement qu'il n'y a rien de compliqué à ce sujet. Par exemple, sur un tel écran et plus de données s'adapteront facilement.

Mais il y a une astuce: pour un appareil électroménager, les chiffres et les signatures doivent être aussi grands que possible afin qu'ils n'aient pas à regarder l'écran longtemps dans une loupe, essayant de percer l'esprit de l'esprit du créateur.

En général, je voulais l'interface la plus large et pas trop encombrée, dont la logique pouvait se comprendre sans un enseignement supérieur. Ayant une telle image dans ma tête, je l'ai transférée vers l'éditeur Nextion et j'ai obtenu deux principaux types d'écran.

Écran principal avec lectures actuelles des capteurs:




En plus des lectures réelles, vous pouvez également voir une indication de la tendance du changement (haut / bas) et des marqueurs des paramètres sélectionnés pour l'affichage sur le graphique. Les quadrangles translucides sont les zones sensorielles invisibles dans l'œuvre.

Écran avec graphiques. En fait, il y en a quatre à afficher d'un à quatre graphiques, mais en fait ils sont tous identiques. Par exemple, un écran avec un et quatre graphiques:




Ici, pour chaque paramètre, son maximum et son minimum sont également affichés afin de comprendre les limites. Mais il n'y a pas de chronologie: premièrement, l'appareil n'a pas d'horloge, et deuxièmement, il n'y a tout simplement pas de place pour la balance. Au moins, je n'ai pas trouvé où le joindre, étant donné que je voulais montrer un maximum de quatre graphiques.

Dans ce cas, le code prévoit l'ajout des indicateurs obtenus à l'archive toutes les demi-heures avec une profondeur d'archivage totale de 48 valeurs, c'est-à-dire pendant environ une journée. Approximativement - parce que les données sont transmises via le canal radio 433 MHz, qui n'est pas protégé contre les interférences, des écarts sont donc possibles.

Et dans le cas de ces écarts, la durée de vie des capteurs est également prévue dans la même demi-heure. Et s'il n'y a pas eu de réception de données dans une demi-heure, les relevés du capteur ne sont pas affichés et ne sont pas entrés dans l'archive.

Les tendances des indicateurs sont calculées par le premier algorithme qui rencontre les six derniers points de l'histoire, à savoir selon les six dernières indications. Et puisque les lectures sont faites à intervalles d'une demi-heure, il s'avère que la tendance reflète les changements au cours des trois dernières heures.

Comme tout designer, je devais "jouer avec les polices". En train de dessiner les options, il s'est avéré que ma symétrie préférée a été forcée d'être brisée non seulement par la combinaison d'indicateurs d'humidité dans le coin supérieur droit, mais aussi par un phénomène beaucoup plus décevant sous la forme de températures négatives.

À savoir, les inconvénients ont gâché toute l'image. J'ai donc agi à ma façon: mettre un moins sur la valeur. Pour les mathématiciens, cela, bien sûr, semblera être une solution barbare, et les personnes impliquées, bien sûr, tressailliront involontairement, réfléchissant aux raisons pour lesquelles les stations météorologiques devraient être modulo-évaluées. Mais ça s'est bien passé et les chiffres ne dansent pas.

La logique de l'interface est la suivante. Le principal mode de fonctionnement est le mode veille avec une luminosité de l'écran de 15% de la valeur nominale et une mise à jour régulière des relevés.

Touchez n'importe où - allez en ligne avec une luminosité de 100%. Après cela, en cliquant sur les lectures, sélectionnez-les pour un affichage ultérieur sur le graphique, et en cliquant sur le "œil" HAL passe à l'écran avec des graphiques.

Il y a exactement cinq secondes pour cela. Ensuite, les marques sont effacées et après cinq autres minutes d'inactivité, l'appareil repasse en mode veille.

Sur l'écran du graphique, la partie gauche est un pas en arrière (l'écran principal ou l'écran avec les graphiques), et la partie droite est une augmentation du graphique sélectionné en plein écran ou, encore une fois, allez à l'écran principal s'il y a un graphique.

Il m'a semblé que ce schéma est assez simple pour ne pas ajouter de boutons supplémentaires, ce que je ne veux pas vraiment voir ici.

Soit dit en passant, les images d'arrière-plan peuvent être modifiées si vous le souhaitez. J'ai même préparé quelques options supplémentaires.

Pour les colons:


Pour les hobbits:


Pour les romantiques:


Pour les amateurs de café:


Dans son concept, l'ensemble de l'appareil n'est pas tant une station météo qu'un écran sans fil spécialisé. Par conséquent, la conception est extrêmement simple: seuls l'écran, l'Arduino Pro Mini et le récepteur 433 MHz avec modulation d'amplitude sont à l'intérieur. Il n'y a aucune fonctionnalité dans l'assemblage: l'écran est pour l'alimentation et le port série, le récepteur est pour l'alimentation et la broche 2 du contrôleur. Et, outre le besoin de capteurs externes compatibles - c'est tout.

Pour comprendre la simplicité, je montre une des options de logement avec un remplissage presque installé:





Bien sûr, je n'insiste pas sur une telle configuration, mais dans mon cas, elle était optimale à la fois en termes de pénibilité et de compatibilité avec d'autres composants de la domotique.

Eh bien, la séparation de l'écran et des capteurs vous permet de placer ce même écran à l'endroit le plus pratique - comme, en fait, n'importe quelle station météo avec des capteurs externes.

Bien sûr, pour que tout cela fonctionne et ne provoque pas l'horreur des animaux à la vue de blocs de fils, d'un tas de capteurs et de microcontrôleurs suspendus dans l'air, vous devez comprendre les cas.

La dure vérité de la vie était que la boîte où BDS-M avait vécu jusqu'à présent n'était pas en mesure d'accueillir trois capteurs supplémentaires. Par conséquent, j'ai donné libre cours à mes sentiments et j'ai imprimé une superbe lampe de Markellov .

Du point de vue du capteur météo, il est idéal, car il est soufflé par tous les vents et cache en même temps efficacement et efficacement le désordre à l'intérieur. Après de tels métamorphes, BDS-M a cessé d'exister: maintenant il est glamour (si vous ne vous en approchez pas) Multisensor:

Shell:



Assemblé et en place:



Il s'est avéré plus difficile avec l'unité d'affichage. En général, je voulais le voir plutôt massif et brutal. Eh bien, bien sûr, comme si l'aborigène qui avait trouvé une partie du vaisseau spatial l'avait encadrée dans la pierre. Par conséquent, le cadre, dont le modèle était déjà proposé dans Nextion, ne correspondait en aucune façon. Premièrement, c'était effrayant, et deuxièmement, l'affichage était dans une niche là-bas, ce qui ne me convenait absolument pas - je voulais rincer la surface.

J'ai quand même commencé de toute façon avec du plastique - juste pour casser la forme. Les options intermédiaires ressemblaient à ceci:



En général, j'ai bien aimé (j'ai décidé de ne pas remarquer un peu de mécontentement), mais le poids, bien sûr, est assez ridicule, pas de pierre. Par conséquent, l'un des bâtiments utilisé comme coffrage interne pour la fabrication de "ossature" en béton.

Le processus m'a profondément choqué - j'ai rarement apporté autant de saleté à la maison. Le résultat est le même. Bien que, par endroits, il se soit avéré ne rien être, il s'est avéré que le mélange de réparation renforcé n'était pas très approprié pour de tels produits.

Peut-être que le béton de sable pur serait idéal, mais à ce moment-là, j'étais déjà déçu de mes propres compétences en construction et je suis parti comme mon collègue. Et lui, après avoir réfléchi un peu, a dit qu'il avait le bonheur dans sa vie de travailler avec de la peinture en aérosol sous la pierre.

Bingo, je me suis dit, et j'ai immédiatement commencé à fouiller les détails. Après tout, imprimer un boîtier et le peindre est beaucoup plus esthétique que de transformer une maison en un chantier de construction en taille réelle. En général, la peinture était inhumainement chère, mais très cool (pour les intéressés - Rust-Oleum American Accents Stone).

En cours de route, j'ai également conclu que je n'aimais pas le corps avec quelque chose (très probablement, avec des cadres épais sur tout le périmètre), alors je me suis ressaisi et, après un interrogatoire avec une dépendance, j'ai pris une forme apparemment définitive.

C'était:



C'est devenu:







Il est facile de voir qu'il n'y a aucune trace de massivité, mais pour une raison quelconque, cette forme me plaît le plus. Je m'y attarderai. Au revoir.

La vue, bien sûr, est un amateur, car certains abats de l'écran (la même boucle de l'écran tactile) sont en vue, et rien ne peut être fait avec cela de manière raisonnable. Déraisonnable, à mon avis, - superpositions, peinture, rubans adhésifs.

Et depuis que j'ai imprimé avec du plastique transparent, la nuit dans l'espace général:



Maintenant, à propos de, disons, les nuances du design. Je vais peut-être partir du même bâtiment. Le désir de beauté a joué une mauvaise blague: comme je voulais que l'écran affleure la surface, la découpe a fait autant que possible correspondre aux dimensions extérieures de l'écran. Et après environ une douzaine de raccords, il a fait son travail - soit rompu le câble de l'écran tactile, soit rompu le contact avec la carte, mais maintenant, il est très difficile de faire fonctionner le capteur.

Par conséquent, je ne peux probablement pas recommander une telle conception. Eh bien, ou je le recommande, mais gardez à l'esprit que c'est l'un des moyens les plus simples et les plus beaux (oui, je me flatte effrontément) de briser l'écran.

De plus, je devais passer en revue plusieurs fonctionnalités de l’écran lui-même, dont je peux personnellement décrire la description comme «vous ne pouvez pas simplement le prendre et ...».

Donc, on ne peut pas simplement prendre et afficher n'importe quelle police. C'est, théoriquement - oui. N'importe quelle police Windows peut être téléchargée dans le convertisseur intégré à l'environnement de Nextion et la sortie sera un raster plutôt costaud qui ne sera pas le meilleur.

Par exemple, comparez la police convertie avec l'original:


Par conséquent, j'ai dû suivre la voie morne. A savoir - pour composer des nombres et des signatures à partir d'éléments graphiques préalablement préparés dans GIMP.

Puis je suis tombé sur les graphiques. Il s'est avéré que vous ne pouvez pas simplement prendre et alimenter un ensemble de données arbitraires vers l'élément Waveform destiné à dessiner des courbes. Tout d'abord, vous devez tout mettre au format requis - de 0 à 255 et terminer les points intermédiaires, s'il y a moins que la largeur de l'écran.

Eh bien, j'ai découvert que ce n'était pas tout. Il s'avère que 255 points logiques ne sont pas mis à l'échelle par l'affichage lorsque la hauteur de l'élément de graphique Waveform change. Par conséquent, lorsque vous modifiez la hauteur de l'élément de graphique Waveform, il est nécessaire de modifier proportionnellement l'échelle des valeurs, sinon le graphique sera "coupé".

Cependant, vous ne pouvez pas utiliser d'images avec un arrière-plan transparent, ce qui a quelque peu limité la largeur utile des champs d'information - de sorte qu'il n'y a pas de chevauchement laid dans la zone de dégradé de l'image d'arrière-plan. À mon avis, le forum Nextion en a discuté et il semble que ITEAD a promis d'ajouter la possibilité de travailler avec des images transparentes, mais ne l'a pas encore fait.

Cela, comme mon tourment avec la commutation de la vitesse du port (qui est nécessaire pour dessiner rapidement des graphiques), sans aucun doute, semblera ridicule aux camarades expérimentés. Cependant, je ne peux pas rester silencieux - j'ai dépensé décemment les forces à vaincre.

Mais dans l'ensemble, je me sens comme un gagnant. Ce que je voulais - je l'ai fait, et la collection d'appareils électroménagers a été reconstituée avec une autre. De plus, ce n'est pas tout à fait inutile: il est pratique de voir immédiatement ce que les capteurs domestiques montrent sans atteindre un smartphone et sans allumer un ordinateur.

De plus, cette chose ne dépend pas d'Internet et dans ce contexte, elle ressemble à un appareil anti-IoT, car elle stocke tout en soi. Et puis j'imagine, comme si un pirate avec un sens de l'humour absurde couperait ma station météo et la ferait fermer la porte.

Je raclerais ensuite dehors avec des demandes comme:

- Ouvrir les portes de la baie Pod, HAL

True, serait-ce drôle?

PS Dans la fabrication de l'appareil a été guidé par les manuels:

" Nextion HMI Solution
" FLProg + Nextion HMI. Leçon 1
» FLProg + Nextion HMI. Leçon 2
» IHM FLProg + Nextion. Leçon 3,

je peux également proposer:

" La disposition de l'interface pour l'édition dans Nextion Editor
"Afficher le fichier d'interface de téléchargement

Afficher le code de pièce pour Arduino
// 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();
  }

}  



Modèle de boîtier (soigneusement - vous pouvez casser l'écran)

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


All Articles