Todo clima é bom: um indicador de clima que cosplay



Imaginemos que, depois de uma briga com Dave Bowman, os remanescentes da inteligência outrora poderosa do HAL 9000 foram suficientes para trazer o Discovery One de volta à Terra e, sob o slogan "morte a todas as pessoas", esmagá-lo no planeta, para que não fosse mais errado fazer isso com computadores.

O cataclismo que eclodiu, é claro, destruiu toda a humanidade racional, e apenas indivíduos como eu permaneceram, com um martelo em uma mão e um Arduino na outra. Portanto, não é de surpreender que o misterioso dispositivo encontrado pelos ainda misteriosos remanescentes da nave espacial encontrada na montanha possa ser usado apenas em uma estação meteorológica. Bem, com razão!

Se descartamos o romance, a dura realidade da vida é que o notório ITEAD ofereceu o monitor Nextion HMI NX4832T035 para teste .

Como os produtos Nextion foram descritos repetidamente aqui, é conciso sobre seus recursos. Esta é uma tela com sua própria API simples e painel de toque para criar unidades de controle com menus gráficos sem muito aborrecimento.

Para esse fim, o Nextion possui um sistema de comando simples para exibir imagens (e suas partes), elementos de texto, campos de entrada, gráficos. Além disso, existe um tipo de linguagem de script para executar ações, digamos, pressionando os botões na tela ou pelo timer. E, ao mesmo tempo, uma porta para receber comandos externos de microcontroladores ou similares e retornar dados ao tocar na tela para saber quais botões as mãos brincalhonas do proprietário chegaram e em que estado esse botão está (pressionado, liberado) no momento.

Grosso modo, não há necessidade de sofrer e coletar matrizes de pontos ou conectar uma nuvem de todos os tipos de bibliotecas. Uma linha - e o fundo mudou na tela. Clicado - um menu é aberto. Conectamos o Arduino - construímos gráficos de acordo com os dados recebidos pela porta serial.

Ou seja, a julgar pela descrição, a tela é tão inteligente que pode mostrar e responder (existe um painel de toque) a qualquer coisa. Mas não tenho nada em casa, mas os dados climáticos voam periodicamente pelo ar. Do mesmo BDS-M , por exemplo, ou do sensor climático PI-TV-2 .

Obviamente, todos eles são transferidos para o People's Monitoring , de onde tenho a sorte de assisti-los por meio de um navegador ou aplicativo no meu smartphone. Mas não pude resistir à ideia de fazer "outra estação meteorológica no Arduino".

E, para ser sincero, não se tratava tanto de tecnologia, mas do fato de que eu era teimosamente atraído pelo design de interfaces. Provavelmente, ele puxa com a mesma força com que puxa para cantar todos para quem o urso pisou em sua orelha.

Portanto, peço desculpas imediatamente pelo fato de que haverá menos equipamento adicional e mais fantasias de fantasia. Mas primeiro, uma pequena demonstração do produto acabado, segundo a qual você pode decidir, ler ou seguir para o próximo material.



Então, eu tinha 3,5 polegadas, 480x320 pixels, que parecia uma API bastante simples e sete parâmetros que precisavam ser mostrados (entre parênteses estão os sensores anexados a isso):

1) A temperatura interna e externa (BMP085 / DHT22)
2) A umidade interna e externa fora (DHT22 / DHT22)
4) Pressão atmosférica (BMP085)
5) A concentração de gases não muito úteis na sala, especialmente CO2 (MQ135)
6) A concentração de sólidos no ar ambiente, especialmente PM2.5 (Sharp GP2Y1010AU0F)

Aqui deve-se notar que os camaradas que se familiarizaram com as características dos dois últimos sensores concluem que a maior resposta é alcançada apenas no campo de CO2 e PM2,5, respectivamente. Isso, de fato, explica minha escolha: não é uma pena gastar dois centavos e ver o que acontece, enquanto sensores especializados são muito mais caros e, em caso de falha, o sapo sempre tem algo a mostrar.

É claro que eu não esperava muita precisão de sensores baratos - pelo contrário, esperava correlacionar meus próprios sentimentos com as leituras deles. E, a propósito, tudo é bastante óbvio: uma vez que você fecha a janela, ao mesmo tempo em que a temperatura e o congestionamento aumentam, a concentração de gás do MQ135 começa a aumentar.

No entanto, para os parâmetros. Pareceu-me entediante mostrar apenas sete dígitos; portanto, a tarefa técnica do dispositivo se expandiu: criei cada parâmetro para exibir um gráfico de alterações ao longo do tempo. E para que em uma tela fosse possível visualizar até quatro curvas ao mesmo tempo para a percepção visual dos padrões (se houver) nas alterações em vários indicadores.

Um leitor atento e proprietário de qualquer dispositivo portátil com uma diagonal de 3,5 polegadas ou mais provavelmente dirá que não há nada de complicado nisso. Assim, nessa tela, mais dados cabem facilmente.

Mas há um truque: para um eletrodoméstico, números e assinaturas devem ser tão grandes quanto possível, para que eles não precisem olhar a tela por muito tempo em uma lupa, tentando perfurar a mente da mente do criador.

Em geral, eu queria a interface maior e não muito confusa, cuja lógica poderia ser entendida sem um ensino superior. Tendo essa imagem em minha cabeça, eu a transferi para o editor Nextion e obtive dois tipos principais de tela.

Tela principal com leituras atuais de sensores:




Além das leituras reais, você também pode ver uma indicação da tendência de mudança (para cima / para baixo) e marcadores de parâmetros selecionados para exibição no gráfico. Quadrângulos translúcidos são as áreas sensoriais invisíveis no trabalho.

Tela com gráficos. Na verdade, existem quatro para mostrar de um a quatro gráficos, mas na verdade são todos idênticos. Por exemplo, uma tela com um e quatro gráficos:




Aqui, para cada parâmetro, seu máximo e mínimo também são exibidos para entender os limites. Mas não há linha do tempo: em primeiro lugar, o dispositivo não possui um relógio e, em segundo lugar, simplesmente não há lugar para a balança. Pelo menos não encontrei onde anexá-lo, pois queria mostrar no máximo quatro gráficos.

Nesse caso, o código prevê a adição dos indicadores obtidos ao arquivo a cada meia hora, com uma profundidade total de 48 valores, ou seja, por cerca de um dia. Aproximadamente - porque os dados são transmitidos pelo canal de rádio de 433 MHz, que não é protegido contra interferências, possibilitando lacunas.

E, no caso dessas lacunas, o tempo de vida dos sensores também é fornecido na mesma meia hora. E se não houver recepção de dados em meia hora, as leituras do sensor não serão exibidas e não serão inseridas no arquivo.

As tendências nos indicadores são calculadas pelo primeiro algoritmo que se depara com os últimos seis pontos do histórico, ou seja, de acordo com as seis novas indicações. E como as leituras são feitas em intervalos de meia hora, verifica-se que a tendência reflete mudanças nas últimas três horas.

Como qualquer designer, eu tive que "brincar com fontes". No processo de desenhar as opções, minha simetria favorita foi forçada a ser quebrada não apenas pela combinação de indicadores de umidade no canto superior direito, mas também por um fenômeno muito mais decepcionante na forma de temperaturas negativas.

Nomeadamente, os negativos estragaram todo o cenário. Portanto, eu agi da minha maneira: coloque menos o valor. Para os matemáticos, isso, é claro, parecerá uma solução bárbara, e os envolvidos, é claro, recuarão involuntariamente, refletindo sobre por que as estações meteorológicas devem ser valorizadas em módulos. Mas acabou bem e os números não dançam.

A lógica da interface é a seguinte. O principal modo de operação é o modo de espera, com um brilho da tela de 15% do valor nominal e atualização regular das leituras.

Toque em qualquer lugar - fique on-line com 100% de brilho. Depois disso, clicando nas leituras, selecione-as para exibição subsequente no gráfico e clique no HAL "olho" para a tela com gráficos.

Há exatamente cinco segundos para isso. Em seguida, as marcas são apagadas e, após mais cinco minutos de inatividade, o dispositivo volta ao modo de espera.

Na tela do gráfico, a parte esquerda está um passo atrás (a tela principal ou a tela com gráficos) e a parte direita é um aumento no gráfico selecionado em tela cheia ou, novamente, a transição para a tela principal se houver apenas um gráfico.

Pareceu-me que esse esquema é simples o suficiente para não adicionar botões extras, o que eu realmente não quero ver aqui.

A propósito, as imagens de fundo podem ser alteradas, se desejado. Eu até preparei algumas opções adicionais.

Para os colonos:


Para hobbits:


Para românticos:


Para os amantes do café:


Em conceito, todo o dispositivo não é tanto uma estação meteorológica como um monitor sem fio especializado. Portanto, o design é extremamente simples: somente a tela, o Arduino Pro Mini e o receptor de 433 MHz com modulação de amplitude estão dentro. Não há nenhum recurso na montagem: a tela é para energia e porta serial, o receptor é para energia e o pino 2 do controlador. E, além da necessidade de sensores externos compatíveis - isso é tudo.

Para entender a simplicidade, mostro uma das opções de caixa com um recheio quase instalado:





é claro que não insisto em tal configuração, mas, no meu caso, foi ideal tanto em termos de laboriosa quanto de compatibilidade com outros componentes da automação residencial.

Bem, a separação da tela e dos sensores permite que você coloque essa mesma tela no local mais conveniente - como, de fato, qualquer estação meteorológica com sensores externos.

Obviamente, para que tudo isso funcione e não cause horror aos animais ao ver pedaços de fios, um monte de sensores e microcontroladores pairando no ar, você deve descobrir os casos.

A dura realidade da vida era que a caixa onde o BDS-M morava até agora não conseguia acomodar três sensores adicionais. Por isso, dei vazão a sentimentos e imprimi uma lâmpada impressionante de Markellov .

Do ponto de vista do sensor climático, é ideal, pois é soprado por todos os ventos e, ao mesmo tempo, esconde a bagunça de maneira eficaz e eficaz. Após essas metamorfos, o BDS-M deixou de existir: agora é fascinante (se você não se aproxima) Multissensor:

Shell:



Montado e no lugar:



acabou sendo mais difícil com a unidade de exibição. Em geral, eu queria vê-lo bastante massivo e brutal. Bem, é claro, como se o aborígene que havia encontrado parte da espaçonave o enquadrasse em pedra. Portanto, o quadro, cujo modelo já foi oferecido no Nextion, não se encaixava de forma alguma. Em primeiro lugar, foi assustador e, em segundo lugar, a tela estava em um recesso lá, o que categoricamente não era adequado para mim - eu queria nivelar com a superfície.

Comecei, no entanto, de qualquer maneira com plástico - apenas para quebrar a forma. As opções intermediárias eram mais ou menos assim:



em geral, eu gostei (decidi não notar um pouco de descontentamento), mas o peso, é claro, é bastante ridículo, não pedra. Portanto, um dos edifícios utilizados como cofragem interna para a fabricação de "estrutura" de concreto.

O processo me chocou profundamente - raramente produzia tanta sujeira em casa. O resultado é o mesmo. Embora em alguns lugares parecesse ser nada, a mistura reforçada de reparo não é muito adequada para esses produtos.

Talvez o concreto de areia pura seja o ideal, mas nesse momento eu já estava decepcionado com minhas próprias habilidades de construção e parti como está meu colega. E ele, pensando um pouco, disse que teve a felicidade de sua vida ao trabalhar com tinta spray embaixo da pedra.

Bingo, pensei comigo mesmo, e imediatamente comecei a investigar os detalhes. Afinal, imprimir uma caixa e pintar é muito mais estético do que transformar uma casa em um canteiro de obras em tamanho real. Em geral, a tinta era desumanamente cara, mas muito legal (para os interessados ​​- Rust-Oleum American Accents Stone).

Ao longo do caminho, cheguei à conclusão de que, no entanto, não gostava do corpo com algo (provavelmente, com molduras grossas em todo o perímetro), então me recompus e, após interrogatório com um vício, cheguei à forma aparentemente final.

Foi:



Tornou-se:







É fácil ver que não há vestígios de massividade, mas, por alguma razão, essa forma é muito do meu agrado. Eu vou insistir nisso. Tchau.

A vista, é claro, é amadora, já que alguns miudezas da tela (o mesmo loop do painel de toque) estão à vista e nada pode ser feito com isso de maneiras razoáveis. Não razoável, na minha opinião, - sobreposições, tintas, fitas adesivas.

E desde que eu imprimi com plástico transparente, à noite no espaço geral:



Agora, sobre algumas, digamos, as nuances do design. Talvez eu comece do mesmo prédio. O desejo de beleza era uma piada de mau gosto: como eu queria que a tela estivesse nivelada com a superfície, o recorte era o máximo possível, correspondendo às dimensões externas da tela. E após cerca de uma dúzia de acessórios, ele alcançou seu objetivo - quebrou o cabo do painel de toque ou quebrou o contato com a placa, mas agora é muito difícil fazer o sensor funcionar.

Portanto, provavelmente não posso recomendar esse design. Bem, ou eu recomendo, mas lembre-se de que essa é uma das maneiras mais fáceis e bonitas (sim, eu me gabo descaradamente) de quebrar a tela.

Além disso, eu tive que revisar vários recursos da tela em si, uma descrição que eu pessoalmente posso destacar como "você não pode simplesmente pegar e ...".

Portanto, não se pode apenas pegar e exibir qualquer fonte. Ou seja, teoricamente - sim. Qualquer fonte do Windows pode ser baixada no conversor incorporado no ambiente do Nextion e a saída será uma varredura bastante complicada que não parece a melhor.

Por exemplo, compare a fonte convertida com a original:


Então eu tive que seguir o caminho sombrio. Ou seja - para compor números e assinaturas a partir de elementos gráficos previamente preparados no GIMP.

Então eu tropecei nas paradas. Acontece que você não pode simplesmente pegar e alimentar um conjunto de dados arbitrário para o elemento Waveform destinado a desenhar curvas. Primeiro, você precisa trazer tudo para o formato necessário - de 0 a 255 e finalizar os pontos intermediários, se houver menos que a largura da tela.

Bem, então eu descobri que isso não é tudo. Acontece que 255 pontos lógicos não são redimensionados pela exibição quando a altura do elemento gráfico da forma de onda é alterada. Portanto, ao alterar a altura do elemento gráfico Waveform, é necessário alterar proporcionalmente a escala dos valores, caso contrário, o gráfico será "cortado".

Ainda assim, não é possível usar imagens com fundo transparente, o que limita um pouco a largura útil dos campos de informações - para que não haja sobreposição feia na área de gradiente da imagem de fundo. Na minha opinião, o fórum do Nextion discutiu isso e parece que o ITEAD prometeu adicionar a capacidade de trabalhar com imagens transparentes, mas ainda não o fez.

Isso, como meu tormento ao mudar a velocidade da porta (necessária para o desenho rápido de gráficos), sem dúvida, parecerá ridículo para camaradas experientes. No entanto, não consigo ficar calado - gastei decentemente as forças para superar.

Mas no geral me sinto um vencedor. O que eu queria - eu fiz, e a coleção de eletrodomésticos foi reabastecida com outra. Além disso, não é totalmente inútil: é conveniente ver imediatamente o que os sensores domésticos mostram sem procurar um smartphone e não ligar o computador.

Além disso, isso não depende da Internet e, nesse contexto, parece um dispositivo anti-IoT, pois armazena tudo em si. E então imagino, como se algum hacker com um absurdo senso de humor cortasse minha estação meteorológica e a fizesse trancar a porta.

Em seguida, eu rastejava do lado de fora com pedidos como:

- Abra as portas do compartimento de pods, HAL

True, seria engraçado?

PS Na fabricação do dispositivo foi orientado pelos manuais:

" Nextion HMI Solution
" FLProg + Nextion HMI. Lição 1
» FLProg + Nextion HMI. Lição 2
» FLProg + Nextion HMI. Lição 3

: também posso oferecer:

" O layout da interface para edição no Nextion Editor
"Exibir arquivo de interface de download

Exibir código de peça para 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();
  }

}  



Modelo de caso (com cuidado - você pode quebrar a tela)

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


All Articles