FLProg + Nextion HMI. Lección 2



En la última lección, hablé sobre el panel Nextion HMI y sobre la creación de proyectos para este panel en el Editor de Nextion.
En este tutorial, le mostraré cómo controlar este panel utilizando el programa FLProg desde una placa Arduino. Por ejemplo, recopilemos la estación meteorológica más simple, que leerá los datos del sensor de temperatura y humedad DHT-22 y los mostrará en el panel. También se dibujará un gráfico de cambios en estos parámetros. El brillo de la luz de fondo de la pantalla del panel cambiará utilizando una resistencia variable.

Diseño de banco de pruebas.


Primero debe cargar el proyecto en el panel (el archivo del proyecto en el archivo es un enlace al que al final del artículo está Lesson2.hmi).
Este proyecto consta de tres pantallas.
La primera pantalla se usa para mostrar la temperatura (página “página0” índice - 0).



Se compone de los siguientes elementos:
1 - Imagen con la imagen de un termómetro de alcohol.
2 - El elemento "Barra de progreso". Con su ayuda, el termómetro es simulado.

Configuración del artículo.


Recomiendo aquellos elementos con los que se planea hacer siempre global a través de UART (el atributo "vccope" se establece en "global") y, en consecuencia, asignarles nombres únicos (el atributo "objname") durante todo el proyecto. Esto acelera el trabajo del controlador Arduino y reduce el código para ello. Explicaré por qué.
Al intentar escribir el atributo de un elemento local, primero debe solicitar la página actual desde el panel (esta es una solicitud separada que demora al menos 20 ms). Si la página es a la que pertenece el elemento, el valor se envía al panel; de lo contrario, el valor destinado al envío se escribe en la variable (para la cual se necesita el mismo espacio de memoria). Cuando va a una página con un elemento, debe actualizar inmediatamente sus atributos con los últimos valores reales, ya que al representar una página, las variables locales se inicializan con los valores especificados al crear el proyecto. Y si hay muchos elementos administrados desde el controlador en la página, al cambiar a este, este controlador estará ocupado durante mucho tiempo con la actualización de todos los elementos.
Para un elemento global, todo es mucho más simple. Puede registrar valores de atributo para él en cualquier momento, y los últimos valores se utilizan al representar la página. Esto significa que no es necesario solicitar un número de página antes de enviarlo y no es necesario cambiarlo para almacenar el valor.
Pero, por supuesto, todo depende del proyecto. Si el proyecto para el panel es muy grande y no hay suficiente espacio para elementos globales, entonces, por así decirlo, puede tomar memoria del controlador y hacerlos locales.
3. Cuadro de texto para mostrar la temperatura.

Parámetros del artículo.


La imagen cortada se selecciona como fondo (atributo "sta" valor "imagen recortada"). Y como la imagen que se usa para cortar, se usa la misma que se usa para el fondo de toda la página (el atributo "picc" es el índice de la imagen de la biblioteca de imágenes). Gracias a esto, el tex se obtiene con un fondo transparente.
Como ya escribí en la última lección, el panel no sabe cómo trabajar con números fraccionarios y negativos, y para la temperatura es posible. Por lo tanto, para mostrar el valor de temperatura, se utiliza un campo de texto, en el cual la línea terminada se enviará inmediatamente desde el controlador.
4. La imagen cortada.

Parámetros del artículo.


Con la ayuda de este elemento, el sol se mostrará cuando la temperatura exceda un límite predeterminado. En realidad, era posible usar una imagen ordinaria y cambiar su visibilidad, pero desde el ejemplo de entrenamiento, decidí usar este elemento en particular. Yo mismo he entendido por mucho tiempo la ideología de este elemento, intentaré mostrar cómo funciona. Para su trabajo, hice dos fotos, una con el sol y la otra sin el sol.





El elemento muestra la parte de la imagen adjunta (el atributo "picc" es el índice de la imagen en la biblioteca de imágenes). La esquina superior izquierda de esta sección está en las coordenadas de inserción del elemento (atributos "x" e "y") y tiene el ancho y la altura del elemento (atributos "w" y "h"). Durante la operación del programa controlador, si es necesario, la unión del elemento a la imagen cambiará.

5. Botón.

Parámetros del artículo.


Cuando hace clic en el botón, pasa a la página siguiente. Usé una imagen como fondo para el botón. Usé la misma imagen para ambos estados (los atributos "pic" y "pic2" son los índices de las imágenes en la biblioteca de imágenes) ya que el estado presionado nunca será visible, cuando hace clic en el botón, va directamente a la página siguiente. Como no cambiaremos nada en este botón, lo dejé local y el nombre predeterminado.

Código en el evento "Touch Press Event".


La segunda pantalla se utiliza para mostrar la humedad (página "página1" índice - 1).


Para el fondo de la página, utilicé una imagen con una imagen preparada de la escala del higrómetro.


Considere los elementos incluidos en la página.

1. El elemento "Gaude", que simulará el funcionamiento de un higrómetro.

Parámetros del artículo.


Como lo controlaremos desde el controlador, se hace global. La imagen cortada (el atributo "sta") se selecciona como fondo y la imagen de fondo de la página (el atributo "picc") se selecciona como fondo.

2. Campo numérico.

Parámetros del artículo.


El valor de humedad se mostrará en este campo. Dado que el panel no admite trabajar con números fraccionarios, mostraremos el valor de humedad sin una parte fraccional. La imagen cortada se selecciona como fondo (atributo "sta" valor "imagen recortada"). Y como la imagen que se usa para cortar, se usa la misma que se usa para el fondo de toda la página (el atributo "picc" es el índice de la imagen de la biblioteca de imágenes). En aras de la belleza de la pantalla, configuré la alineación a la derecha (atributo "xcen" valor - 2), y al lado puse un campo de texto (3) con el valor "%". La configuración de fondo es similar a la configuración del campo de número.

Opciones de campo de texto (3).


4 y 5. Botones página anterior y página siguiente. Cuando presiona el botón 4, va a la primera página, y cuando hace clic en el botón 5, pasa a la siguiente. La configuración de visualización de los botones es similar a la de la primera página.

Configuración del botón 4 (“Página anterior”)


Código en el “Evento de prensa táctil” para el Botón 4 (“Página anterior”).


Configuración del botón 5 (“Página siguiente”)


Código en el “Evento de prensa táctil” para el Botón 5 (“Página siguiente”).


Tercera página - Gráfico de cambios en temperatura y humedad (índice "página2" - 2).


En esta página se mostrará un gráfico de cambios en temperatura y humedad. Considere los elementos incluidos en la página.

1. El elemento de forma de onda.

Parámetros del artículo.


En la última lección, ya escribí que este elemento no puede (espero que hasta ahora) se vuelva global, es decir, el valor del atributo puede cambiarse, pero esto no conducirá a nada. Así que lo dejé local (quién sabe, pero de repente todavía se come la memoria de las variables globales). Habrá dos canales de visualización en este elemento (valor del atributo "ch" - 2).

2 y 3 son simplemente campos de texto que muestran el eje de los gráficos.

4 - Botón de regreso. Es similar al mismo botón en la pantalla anterior, con la excepción del código en el controlador de eventos.

El código en el "Evento de prensa táctil" para el botón 4 ("Página anterior").


Hemos descubierto el panel, ahora cuidemos el controlador. No diré cómo abrir el programa FLProg, crear un proyecto y dibujar un diagrama. Todo esto lo conté en lecciones anteriores (lección 1 , lección 2 ), y además, hay mucha información sobre esto en el centro de capacitación en el sitio web del proyecto. Por lo tanto, mostraré de inmediato las placas de circuitos ya hechas y contaré lo que está sucediendo en ellas.

Tablero 1. Lectura de datos del sensor.


Para obtener valores de temperatura y humedad con el sensor DHT-22, se utiliza el bloque B1: “DHT11, DHT21, DHT22” (biblioteca de elementos, carpeta “Sensores”).

Configuración de bloque (llamada haciendo doble clic en él).


En la configuración, se asigna el pin al que está conectada la salida "Datos" del sensor, el tipo de sensor y la presencia de salidas de temperatura y humedad. El modo de sondeo del sensor también está seleccionado. Configuro sondear el sensor una vez cada 5 segundos.

Dado que los controladores Arduino no funcionan muy bien con números de coma flotante, y trabajar con ellos consume mucha memoria, traduzco inmediatamente todos los valores al formato Integer. Para hacer esto, use los bloques B3 y B4 - "Convertir flotante a entero" (biblioteca de elementos, carpeta "Conversión de tipo"), que cortan la parte fraccionaria del número. Para no perder décimas de grado, el valor de temperatura obtenido del sensor se multiplica primero por 10 usando el bloque B2 - "MUL (*)" (biblioteca de elementos, carpeta "Matemáticas").
Luego, los valores obtenidos en el formato Entero se ingresan en las variables correspondientes.

Tablero 2. Muestra el valor de temperatura en el panel.


En este proyecto, uso conexiones con nombre. Puedes aprender más sobre ellos en la lección correspondiente .
Para limitar la carga en el controlador, tiene sentido enviar datos al panel solo cuando los datos han cambiado. Por lo tanto, primero determinamos que los datos han cambiado. Para hacer esto, use el bloque B5 - "Detector de cambio de número" (biblioteca de elementos, carpeta - "Bloques base"). Esta unidad controla el número "Valor" en su entrada y, cuando se cambia, genera un pulso de salida de un ciclo de ejecución del programa en la salida.
Después de eso, preparamos una cadena para enviar al campo de texto del panel. Primero, divida el valor de la temperatura, multiplicado por 10, por una constante de tipo Float con un valor de 10. Por lo tanto, obtenemos el valor de la temperatura con una parte fraccional. Hacemos esto usando el bloque B6 - "DIV (/)" (biblioteca de elementos, carpeta "Matemáticas"). Luego convertimos el valor obtenido en el formato Float en una cadena usando el bloque B7 - "Conversión de cadenas" (biblioteca de elementos, carpeta "Conversión de tipos"). Luego conectamos la cadena resultante con la constante de cadena "C" usando el bloque B8 - "Adición de líneas" (biblioteca de elementos, carpeta "Líneas"). La línea resultante se alimenta a la entrada de la unidad para escribir el valor del atributo en el panel Nextion HMI B9 - "Establecer parámetro" (biblioteca de elementos -> carpeta "Panel Nextion HMI" -> carpeta "Elementos").
Este bloque escribe el valor en el atributo especificado.

Bloqueo de parametrización.

Al hacer doble clic en el bloque, se abre la ventana del editor de bloques.


Si todavía no se han creado paneles en el proyecto, debe crear un panel. Si ya se ha creado el panel necesario, se puede seleccionar de la lista desplegable presionando el botón 3. El panel seleccionado se puede cambiar usando el botón "Cambiar panel" (2). Para crear un panel, haga clic en el botón "Agregar panel" (1). Se abrirá la ventana de creación del panel.


En este cuadro de diálogo, seleccione el puerto para conectar el panel (en nuestra lección - SoftwareSerial). Si selecciona SoftwareSerial, también debe seleccionar los pines asignados como señales RX y TX del puerto UART (en nuestro caso, 2 y 3). También es necesario asignar un nombre de panel. Debe ser único. Se pueden conectar varios paneles en un proyecto, siempre que haya suficientes puertos UART libres. El nombre de cada panel debe ser único dentro del proyecto. En el mismo cuadro de diálogo puede agregar las páginas incluidas en el panel. Que haremos Haz clic en el botón Agregar página. Se abre la ventana de creación de página.


En esta ventana necesitamos ingresar el nombre de la página y su ID. Esta información se puede aprender del proyecto en el Editor de Nextin.


Por defecto, la página de inicio (abierta cuando se inicia el controlador) será una página con un ID de 0, pero puede marcar la casilla "Página de inicio" en las propiedades de cualquier página y se convertirá en la página de inicio.
En esta ventana, puede agregar los elementos de interés para nosotros que se encuentran en esta página. Haga clic en el botón "Agregar elemento".
Se abre la ventana de creación de elementos.


Aquí debemos seleccionar el tipo y el tipo del elemento, ingresar su nombre, índice y, si el elemento es global, establecer la casilla correspondiente. Todos estos datos se pueden ver en el proyecto en el Editor Nextin.


Después de completar todos los datos, haga clic en "Finalizar" y luego, en la ventana de creación de la página, agregue todos los elementos de interés para nosotros en esta página.


Después de crear todos los elementos en la página, también hacemos clic en el botón "Finalizar" en la ventana de creación de la página y en la ventana para crear un panel usando el mismo escenario, cree el resto de la página.






Terminamos de crear el panel con el conocido botón "Finalizar".
En el editor de bloques, seleccione el elemento "Texto" de la página "página0" con el nombre "tnt" y su atributo "Texto (txt)". Como valor, seleccione la entrada.


El bloque está configurado.
Consideramos el esquema más allá.
Empíricamente, se determinó definitivamente que un valor de -40 grados de un termómetro dibujado corresponde a un valor de 10 en el elemento "Barra de progreso" ubicado en él, y un valor de 50 grados a un termómetro corresponde a un valor de progreso de 91 barras. De acuerdo con esto, escalamos el valor con la variable “Temperatura x10” usando el bloque B10 - “Escala” (Biblioteca de elementos, la carpeta “Escala”) sin olvidar que tenemos el valor de temperatura multiplicado por 10. Parámetros de este bloque.


El valor de temperatura escalado se envía al panel utilizando el bloque B11 - "Establecer parámetro" (biblioteca de elementos -> carpeta "Panel Nextion HMI" -> carpeta "Elementos"). Configuraciones para este bloque.


El siguiente bloque B12 - "Comparador" (biblioteca de elementos, carpeta "Comparación") determina si la temperatura actual excede el punto de ajuste por el valor predeterminado de la variable "Punto de ajuste - Caliente". Es 290 (no olvides que en todos lados tenemos temperaturas multiplicadas por 10).


El bloque B12 está configurado para generar una unidad lógica en su salida cuando el valor en la entrada "I1" excede el valor en la entrada "I2".


Los bloques B13, B14 y B15 forman circuitos discretos de detección de cambio de señal. Los bloques B13 y B14 - Rtrig (biblioteca de elementos, carpeta "Disparadores"), cuando aparece un borde delantero de una señal discreta, emiten un pulso de salida con una duración de 1 ciclo del programa. El bloque B14, debido a la inversión en su entrada, detecta el borde posterior de la señal "Superando el umbral". Bloque B15 –OR (biblioteca de elementos, carpeta “Elementos básicos”), si hay una unidad lógica en cualquiera de las entradas, envía una unidad lógica a su salida. Por lo tanto, se forma una señal "Envío de datos cuando se supera el umbral". En el borde de ataque de esta señal, se envía un comando para cambiar el color de fuente del campo de texto que muestra la temperatura actual. El envío se realiza utilizando el bloque B17– "Establecer parámetro" (biblioteca de elementos -> carpeta "Panel Nextion HMI" ->Carpeta de elementos). Configuraciones para este bloque.


El valor transmitido en el comando se selecciona utilizando el bloque B16 - "Interruptor" (biblioteca de elementos, carpeta "Interruptor"). Este bloque con un nivel lógico bajo en su entrada transfiere el valor de la entrada "0" a la salida, y con un nivel alto, de la entrada "1". Los valores de color suministrados a las entradas del interruptor se configuran utilizando los bloques B44 y B45 - “Color constante Alto Color” (biblioteca de elementos -> carpeta “Panel HMI Nextion” -> carpeta “Color”). El color se selecciona en el editor de bloques (haga doble clic en el bloque).


Para seleccionar un color, haga clic en el botón "Cambiar". Se abre el selector de color.


En él, configurando el valor de los componentes R (rojo), G (verde) y B (azul), se selecciona el color necesario.
Además, en el borde de ataque de la señal "Envío de datos cuando se excede el umbral", se envía un comando para cambiar la unión de la imagen recortada. Esto sucede utilizando el bloque B19 - "Establecer parámetro" (biblioteca de elementos -> carpeta "Panel HMI Nextion" -> carpeta "Elementos").
Configuraciones para este bloque.


El índice de la imagen se selecciona usando el bloque B18 - "Interruptor" (biblioteca de elementos, carpeta "Interruptor"). Su trabajo ha sido descrito anteriormente. El valor del índice de la imagen requerida se puede ver en el proyecto del Editor de Nextion en la biblioteca de imágenes.

Con la transferencia de datos de temperatura terminada. Pasemos a la humedad.

Tabla 3. Conclusión de la humedad.


Como en el caso de la temperatura, en primer lugar, creamos una señal "Enviando datos cuando la humedad cambia". Hacemos esto usando el bloque B20 - "Detector de cambio de número" (biblioteca de elementos, carpeta - "Bloques base"). El funcionamiento de esta unidad se ha descrito anteriormente. Esta señal envía el valor a un campo numérico que muestra la humedad. Esto se realiza utilizando el bloque B21– “Establecer parámetro” (biblioteca de elementos -> carpeta “Panel HMI Nextion” -> carpeta “Elementos”).
Configuraciones para este bloque.


Empíricamente, se determinó definitivamente que para el valor de humedad del 0% de la escala del higrómetro dibujado en el diseño del panel, el elemento "Gayge" que dibuja la flecha es 314 y para el 100% de humedad es 226. Al mismo tiempo, la flecha pasa al valor 0. Cuando se convierte a valores lineales, obtenemos continuamente rango de -46 (0%) a 226 (100%). De acuerdo con estos datos, configuramos el bloque B22 - "Escala".
Parámetros de bloque.


Dado que los valores para el elemento "Indicador" no pueden ser negativos, para calcular el ángulo de flecha en estos valores, en el caso de un valor negativo, se le agrega el valor 360. Hacemos esto usando el bloque B23- "SUMM (+)" (biblioteca de elementos, Carpeta de matemáticas). Determinamos que el número es menor que 0 usando el bloque B26 - "Comparador" (biblioteca de elementos, carpeta "Comparación"). Su salida controla el interruptor B24 - "Interruptor" (biblioteca de elementos, carpeta "Interruptor") y el valor seleccionado se envía al panel utilizando el bloque B25 - "Establecer parámetro" (biblioteca de elementos -> carpeta "Panel HMI Nextion" -> carpeta "Elementos" )
Configuraciones para este bloque.


La siguiente tabla muestra un gráfico de los cambios de temperatura y humedad.


Como escribí al comienzo de la lección, el elemento Waveform no sabe cómo ser un elemento global y se vuelve a dibujar cada vez que abre la página en la que se encuentra. Tenemos que sortear esta limitación. Primero, determine el número de la página que está cargada actualmente en el panel. Para hacer esto, use el bloque B27 - “Obtener Id. De la página actual” (biblioteca de elementos -> carpeta “Panel HMI Nextion” -> carpeta “Página”). En la configuración de este bloque solo necesita seleccionar el panel al que accederemos con esta solicitud.


El número de página obtenido de este bloque se compara con el índice de la página que necesitamos (2) usando el bloque B28 - "Comparador" (biblioteca de elementos, carpeta "Comparación"). Si la página deseada está abierta, la unidad lógica se escribe en la variable "Abrir página del gráfico", si no, entonces un cero lógico.
Usando el bloque B29 - "Generador" (biblioteca de elementos, carpeta "Temporizadores"), se genera una señal para registrar el siguiente punto en el gráfico. Este bloque genera pulsos con una duración y pausa de pulso dada.
Bloquear configuraciones.


El tipo de generador seleccionado es "Multivibrador simétrico", lo que significa que la duración del pulso es igual a la duración de la pausa. Al configurar la duración del pulso a 5 segundos, respectivamente, la pausa será la misma de 5 segundos. El borde de ataque del pulso vendrá cada 10 segundos. Este frente está resaltado por el bloque B30 - "Rtrig" (biblioteca de elementos, carpeta "Disparadores"), y está escrito en la variable "Comando para registrar el siguiente punto".
En el borde delantero de la señal "Abrir página de gráfico", que se seleccionará usando el bloque B31 - "Rtrig" (biblioteca de elementos, carpeta "Activadores"), se generará la señal "Enviar historial de gráfico". Con esta señal, el contenido de las matrices se enviará al panel en el gráfico, en el que se almacenan los valores de los puntos que muestran el gráfico de cambio. Para la temperatura, esto se realizará utilizando el bloque B32 - "Envío de la matriz al gráfico" (biblioteca de elementos -> carpeta "Panel HMI Nextion" -> carpeta "Gráfico"). El bloque se configura con el editor de bloques.


Primero debe crear una matriz en la que se almacenará el historial del gráfico de temperatura. Para hacer esto, haga clic en el botón "Crear". Se abre la ventana de creación de matriz.


En este océano, debe ingresar el nombre de la matriz, tipo (use Byte, ya que el elemento Waveform toma un valor máximo de 255). El tamaño se toma igual al ancho del gráfico (330).
Después de crear, seleccione el panel, página, elemento y canal en el que se dibujará el gráfico.


Del mismo modo, configuramos el bloque para enviar una matriz con datos de humedad al panel B33: “Envío de la matriz al gráfico” (biblioteca de elementos -> carpeta “Panel Nextion HMI” -> carpeta “Gráfico”). En su configuración, creamos otra matriz para almacenar estos datos.


Ahora necesita preparar los datos para el gráfico de temperatura. Este gráfico tendrá una línea a lo largo de su eje a una altura de 160 puntos desde la parte inferior del gráfico. Para hacer que los cambios de temperatura sean más visibles, dividimos el valor de la variable "Temperatura x10" por 5 (es decir, como si multiplicara el valor de temperatura real por 2) usando el bloque B35 y agreguemos el desplazamiento usando el bloque B36. El resultado se ingresará en la variable "Temperatura con un cambio para el gráfico".
Usando el bloque B37 - "Pila" (biblioteca de elementos, carpeta "matrices"), el pulso de la variable "Comando para registrar el siguiente punto" se escribe en la matriz por la temperatura con un cambio para el gráfico usando el principio de la pila (se elimina el primer elemento de la matriz, el resto se desplaza por uno y se escribe el último valor). El bloque se parametriza con el editor de bloques.


En el editor, seleccione la matriz deseada haciendo clic en el botón "Seleccionar".
Del mismo modo, configuramos el bloque B34 - "Pila" (biblioteca de elementos, carpeta "matrices") para escribir valores de humedad en la matriz seleccionando en la matriz correspondiente.
Si la página del gráfico está abierta, se completa la transferencia de matrices al gráfico y se recibe el comando para registrar el siguiente punto, entonces los valores de los nuevos puntos se envían a los gráficos correspondientes. Esto es necesario para que los gráficos se sigan construyendo mientras se muestra la página. El cumplimiento de estas condiciones se supervisa mediante el bloque B38 - "Y" (biblioteca de elementos, carpeta "Elementos básicos"). Este bloque emite una unidad en su salida si hay una unidad lógica en todas sus entradas. El siguiente valor de temperatura con un cambio se envía al gráfico utilizando el bloque B40 - "Agregar un punto al gráfico" (biblioteca de elementos -> carpeta "Panel HMI Nextion" -> carpeta "Gráfico").
Bloquear configuraciones.


El bloque para enviar el siguiente valor de humedad al gráfico B39 también está configurado: "Agregar un punto al gráfico" (biblioteca de elementos -> carpeta "Panel Nextion HMI" -> carpeta "Gráfico").


Terminado con la conclusión del horario.

Tablero 5. Ajuste el brillo de la luz de fondo.


El valor de la luz de fondo establecida con una resistencia variable se lee con el bloque de entrada analógica "Brillo". Dado que el valor de brillo de la luz de fondo del panel se establece dentro del rango de 0 a 100, escalamos el valor de lectura del rango 0-1023 al rango 0-100 usando el bloque B41 - "Escala".
Bloquear configuraciones.


Luego determinamos el hecho de un cambio en este valor usando el bloque B42 - "Detector para cambiar el número". Este bloque tiene una pequeña configuración no estándar.


Para no cambiar el brillo de cada movimiento de la resistencia variable, la banda muerta se establece en la unidad con un valor de 5. Es decir, la unidad funcionará cuando el valor de entrada cambie más de 5 en cualquier dirección. Cuando se activa la unidad, se enviará un comando al panel para establecer un nuevo brillo de retroiluminación utilizando el bloque B43 - "Establecer nivel de retroiluminación" (biblioteca de elementos -> carpeta "Panel Nextion HMI" -> carpeta "Sistema").
Configuración de bloque


Se completa el trabajo en el programa para el controlador.

Para aquellos que estén interesados ​​en el código para el skoller de croquis resultante.
#include <SoftwareSerial.h>
#include "DHT.h"
DHT _dht1(4, DHT22);

SoftwareSerial Serial100(2, 3);

byte _FLPArray142003126[330] = {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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
byte _FLPArray239384258[330] = {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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int _SUETFLPATemp = 0;
byte _nextionSaveDataVAL_P0_E2;
long _nextionSaveDataPCO_P0_E3;
String _nextionSaveDataTXT_P0_E3;
byte _nextionSaveDataPICC_P0_E4;
int _nextionSaveDataVAL_P1_E2;
long _nextionSaveDataVAL_P1_E4;
String _nextionCommandTempString;
struct _nextionLissenStruct {
  char code;
  String result;
  long number;
};
_nextionLissenStruct _nextionTempLissen;
int nextionGetPageIdTempVar = 0;
int NextionPanel_47525121_PageIdOut = 0;
int _hasNumberChangeInTemp = 0;
int _gtv1;
int _gtv2;
int _gtv3 = 290;
bool _gtv4 = 0;
bool _gtv5 = 0;
int _gtv6;
unsigned long _dht1Tti = 0UL;
float _dht1t = 0.00;
float _dht1h = 0.00;
bool _changeNumber1_Out = 0;
int _changeNumber1_OLV;
bool _nextionSetAttr1_isNU = 0;
bool _nextionSetAttr1_oldState = 0;
bool _nextionSetAttr2_isNU = 0;
bool _nextionSetAttr2_oldState = 0;
bool _trgrt1 = 0;
bool _trgrt1I = 0;
bool _trgrt2 = 0;
bool _trgrt2I = 0;
bool _nextionSetAttr3_isNU = 0;
bool _nextionSetAttr3_oldState = 0;
long _swi1;
bool _nextionSetAttr4_isNU = 0;
bool _nextionSetAttr4_oldState = 0;
byte _swi2;
bool _nextionSetAttr5_isNU = 0;
bool _nextionSetAttr5_oldState = 0;
bool _changeNumber2_Out = 0;
int _changeNumber2_OLV;
int _swi3;
bool _nextionSetAttr6_isNU = 0;
bool _nextionSetAttr6_oldState = 0;
bool _trgrt3 = 0;
bool _trgrt3I = 0;
bool _gen1I = 0;
bool _gen1O = 0;
unsigned long _gen1P = 0UL;
bool _trgrt5 = 0;
bool _trgrt5I = 0;
bool _nextionAddPointToWave1_OldState = 0;
bool _nextionAddPointToWave2_OldState = 0;
bool _SFLPAS1;
bool _SFLPAS2;
bool _nextionSendArraytToWave1_OldState = 0;
bool _nextionSendArraytToWave2_OldState = 0;
bool _nextionSetLighting1_OldStae = 0;
bool _changeNumber3_Out = 0;
int _changeNumber3_OLV;
void setup()
{
  Serial100.begin(9600);
  _dht1.begin();
  nextionSendCommand("", 100);
  nextionAck(100);
  nextionSendCommand("page 0", 100);
  delay(100);
  nextionAck(100);
}
void loop()
{ nextionGetPageIdTempVar = nextionAskPageNamper(100);
  if ( ! (nextionGetPageIdTempVar < 0) ) {
    NextionPanel_47525121_PageIdOut = nextionGetPageIdTempVar;
  };
  if (_isTimer(_dht1Tti, 5000)) {
    _dht1Tti = millis();
    float tempDht4;
    tempDht4 = _dht1.readTemperature();
    if (!(isnan(tempDht4))) {
      _dht1t = tempDht4;
    }
    tempDht4 = _dht1.readHumidity();
    if (!(isnan(tempDht4))) {
      _dht1h = tempDht4;
    }
  }



  _gtv1 = (int((_dht1t) * (10)));
  _gtv2 = (int(_dht1h));
  if ((_gtv1) > (_gtv3)) {
    if (_trgrt1I) {
      _trgrt1 = 0;
    } else {
      _trgrt1 = 1;
      _trgrt1I = 1;
    }
  } else {
    _trgrt1 = 0;
    _trgrt1I = 0;
  };
  if ((_gtv1) > (_gtv3))
  {
    _swi1 = 63488;
  }
  else
  {
    _swi1 = 2016;
  }
  if (!((_gtv1) > (_gtv3))) {
    if (_trgrt2I) {
      _trgrt2 = 0;
    } else {
      _trgrt2 = 1;
      _trgrt2I = 1;
    }
  } else {
    _trgrt2 = 0;
    _trgrt2I = 0;
  };
  if ((_gtv1) > (_gtv3))
  {
    _swi2 = 2;
  }
  else
  {
    _swi2 = 0;
  }
  if (_changeNumber1_Out) {
    _changeNumber1_Out = 0;
  } else {
    _hasNumberChangeInTemp = _gtv1;
    if (_hasNumberChangeInTemp != _changeNumber1_OLV) {
      _changeNumber1_OLV = _hasNumberChangeInTemp;
      _changeNumber1_Out = 1;
    }
  }
  if (_changeNumber1_Out) {
    if (! _nextionSetAttr1_oldState ) {
      _nextionSetAttr1_oldState = 1;
      _nextionSetAttr1_isNU = 1;
      _nextionSaveDataTXT_P0_E3 =  ((( _floatToStringWitRaz((_gtv1) / (10.00), 1))) + (String(" C"))) ;
    }
  } else {
    _nextionSetAttr1_oldState = 0;
  } if (_nextionSetAttr1_isNU) {
    _nextionCommandTempString = String("page0.tnt.txt=\"") + _nextionSaveDataTXT_P0_E3 + String("\"");
    nextionSendCommand(_nextionCommandTempString.c_str(), 100);  nextionAck(100);
    _nextionSetAttr1_isNU = 0;
  } if (_changeNumber1_Out) {
    if (! _nextionSetAttr2_oldState ) {
      _nextionSetAttr2_oldState = 1;
      _nextionSetAttr2_isNU = 1;
      _nextionSaveDataVAL_P0_E2 =  (map((_gtv1), (-400), (500), (10), (91))) ;
    }
  } else {
    _nextionSetAttr2_oldState = 0;
  } if (_nextionSetAttr2_isNU) {
    _nextionCommandTempString = String("page0.tpb.val=") + String(_nextionSaveDataVAL_P0_E2);
    nextionSendCommand(_nextionCommandTempString.c_str(), 100);  nextionAck(100);
    _nextionSetAttr2_isNU = 0;
  } if (( (_trgrt1) || (_trgrt2) )) {
    if (! _nextionSetAttr3_oldState ) {
      _nextionSetAttr3_oldState = 1;
      _nextionSetAttr3_isNU = 1;
      _nextionSaveDataPCO_P0_E3 =  _swi1 ;
    }
  } else {
    _nextionSetAttr3_oldState = 0;
  }
  if (nextionAskPageNamper(100) == 0) {
    if (_nextionSetAttr3_isNU) {
      _nextionCommandTempString = String("page0.tnt.pco=") + String(_nextionSaveDataPCO_P0_E3);
      nextionSendCommand(_nextionCommandTempString.c_str(), 100);  nextionAck(100);
      _nextionCommandTempString = "ref tnt";
      nextionSendCommand(_nextionCommandTempString.c_str(), 100);  nextionAck(100);
      _nextionSetAttr3_isNU = 0;
    }
  } else {
    _nextionSetAttr3_isNU = 1;
  }
  if (( (_trgrt1) || (_trgrt2) )) {
    if (! _nextionSetAttr4_oldState ) {
      _nextionSetAttr4_oldState = 1;
      _nextionSetAttr4_isNU = 1;
      _nextionSaveDataPICC_P0_E4 =  _swi2 ;
    }
  } else {
    _nextionSetAttr4_oldState = 0;
  }
  if (nextionAskPageNamper(100) == 0) {
    if (_nextionSetAttr4_isNU) {
      _nextionCommandTempString = String("page0.tci.picc=") + String(_nextionSaveDataPICC_P0_E4);
      nextionSendCommand(_nextionCommandTempString.c_str(), 100);  nextionAck(100);
      _nextionCommandTempString = "ref tci";
      nextionSendCommand(_nextionCommandTempString.c_str(), 100);  nextionAck(100);
      _nextionSetAttr4_isNU = 0;
    }
  } else {
    _nextionSetAttr4_isNU = 1;
  }
  if (((map((_gtv2), (0), (100), (-46), (226)))) < (0))
  {
    _swi3 = ((map((_gtv2), (0), (100), (-46), (226)))) + (360);
  }
  else
  {
    _swi3 = (map((_gtv2), (0), (100), (-46), (226)));
  }
  if (_changeNumber2_Out) {
    _changeNumber2_Out = 0;
  } else {
    _hasNumberChangeInTemp = _gtv2;
    if (_hasNumberChangeInTemp != _changeNumber2_OLV) {
      _changeNumber2_OLV = _hasNumberChangeInTemp;
      _changeNumber2_Out = 1;
    }
  }
  if (_changeNumber2_Out) {
    if (! _nextionSetAttr5_oldState ) {
      _nextionSetAttr5_oldState = 1;
      _nextionSetAttr5_isNU = 1;
      _nextionSaveDataVAL_P1_E4 =  _gtv2 ;
    }
  } else {
    _nextionSetAttr5_oldState = 0;
  } if (_nextionSetAttr5_isNU) {
    _nextionCommandTempString = String("page1.humN.val=") + String(_nextionSaveDataVAL_P1_E4);
    nextionSendCommand(_nextionCommandTempString.c_str(), 100);  nextionAck(100);
    _nextionSetAttr5_isNU = 0;
  } if (_changeNumber2_Out) {
    if (! _nextionSetAttr6_oldState ) {
      _nextionSetAttr6_oldState = 1;
      _nextionSetAttr6_isNU = 1;
      _nextionSaveDataVAL_P1_E2 =  _swi3 ;
    }
  } else {
    _nextionSetAttr6_oldState = 0;
  } if (_nextionSetAttr6_isNU) {
    _nextionCommandTempString = String("page1.humG.val=") + String(_nextionSaveDataVAL_P1_E2);
    nextionSendCommand(_nextionCommandTempString.c_str(), 100);  nextionAck(100);
    _nextionSetAttr6_isNU = 0;
  } if (1) {
    if (! _gen1I) {
      _gen1I = 1;
      _gen1O = 1;
      _gen1P = millis();
    }
  } else {
    _gen1I = 0 ;
    _gen1O = 0;
  }
  if (_gen1I) {
    if ( _isTimer ( _gen1P , 5000 )) {
      _gen1P = millis();
      _gen1O = ! _gen1O;
    }
  }
  if (_gen1O) {
    if (_trgrt5I) {
      _trgrt5 = 0;
    } else {
      _trgrt5 = 1;
      _trgrt5I = 1;
    }
  } else {
    _trgrt5 = 0;
    _trgrt5I = 0;
  };
  if (_gtv4) {
    if (_trgrt3I) {
      _trgrt3 = 0;
    } else {
      _trgrt3 = 1;
      _trgrt3I = 1;
    }
  } else {
    _trgrt3 = 0;
    _trgrt3I = 0;
  };
  _gtv4 = (NextionPanel_47525121_PageIdOut) == (2);
  _gtv5 = _trgrt5;
  if (_trgrt3) {
    if ( ! _nextionAddPointToWave1_OldState) {
      _nextionAddPointToWave1_OldState = 1;
      if (nextionAskPageNamper(100) == 2) {
        for (int nextionSATWTemp = 0;  nextionSATWTemp < 330;  nextionSATWTemp ++) {
          _nextionCommandTempString = String ("add 1,1,") + String (_FLPArray142003126[nextionSATWTemp]);
          nextionSendCommand(_nextionCommandTempString.c_str(), 100);
        } delay (50);
      }
    }
  } else {
    _nextionAddPointToWave1_OldState = 0;
  }

  if (_trgrt3) {
    if ( ! _nextionAddPointToWave2_OldState) {
      _nextionAddPointToWave2_OldState = 1;
      if (nextionAskPageNamper(100) == 2) {
        for (int nextionSATWTemp = 0;  nextionSATWTemp < 330;  nextionSATWTemp ++) {
          _nextionCommandTempString = String ("add 1,0,") + String (_FLPArray239384258[nextionSATWTemp]);
          nextionSendCommand(_nextionCommandTempString.c_str(), 100);
        } delay (50);
      }
    }
  } else {
    _nextionAddPointToWave2_OldState = 0;
  }

  if (_gtv5) {
    if (!_SFLPAS1) {
      _SFLPAS1 =  1;
      for (_SUETFLPATemp = 0; _SUETFLPATemp < 329; _SUETFLPATemp = _SUETFLPATemp + 1 ) {
        _FLPArray239384258[_SUETFLPATemp ] = _FLPArray239384258[_SUETFLPATemp + 1];
      }  _FLPArray239384258[329] = _gtv2;
    }
  }  else {
    _SFLPAS1 = 0;
  }
  _gtv6 = ((_gtv1) / (5)) + (160);
  if (_gtv5) {
    if (!_SFLPAS2) {
      _SFLPAS2 =  1;
      for (_SUETFLPATemp = 0; _SUETFLPATemp < 329; _SUETFLPATemp = _SUETFLPATemp + 1 ) {
        _FLPArray142003126[_SUETFLPATemp ] = _FLPArray142003126[_SUETFLPATemp + 1];
      }  _FLPArray142003126[329] = _gtv6;
    }
  }  else {
    _SFLPAS2 = 0;
  }
  if (( (_gtv5) && (!(_trgrt3)) && (_gtv4) )) {
    if ( ! _nextionSendArraytToWave1_OldState) {
      _nextionSendArraytToWave1_OldState = 1;
      if (nextionAskPageNamper(100) == 2) {
        _nextionCommandTempString = String ("add 1,0,") + String (_gtv2);
        nextionSendCommand(_nextionCommandTempString.c_str(), 100); delay (50);
      }
    }
  } else {
    _nextionSendArraytToWave1_OldState = 0;
  }

  if (( (_gtv5) && (!(_trgrt3)) && (_gtv4) )) {
    if ( ! _nextionSendArraytToWave2_OldState) {
      _nextionSendArraytToWave2_OldState = 1;
      if (nextionAskPageNamper(100) == 2) {
        _nextionCommandTempString = String ("add 1,1,") + String (_gtv6);
        nextionSendCommand(_nextionCommandTempString.c_str(), 100); delay (50);
      }
    }
  } else {
    _nextionSendArraytToWave2_OldState = 0;
  }

  if (_changeNumber3_Out) {
    _changeNumber3_Out = 0;
  } else {
    _hasNumberChangeInTemp = (map(( (analogRead (0))), (0), (1023), (0), (100)));
    if (((_hasNumberChangeInTemp > _changeNumber3_OLV) && ((_hasNumberChangeInTemp - _changeNumber3_OLV ) > 5)) || ((_hasNumberChangeInTemp < _changeNumber3_OLV) && ((_changeNumber3_OLV - _hasNumberChangeInTemp ) > 5) ))
    {
      _changeNumber3_OLV = _hasNumberChangeInTemp;
      _changeNumber3_Out = 1;
    }
  }
  if (_changeNumber3_Out) {
    if (!(_nextionSetLighting1_OldStae)) {
      _nextionSetLighting1_OldStae = 1;
      _nextionCommandTempString = String("dim=") + String((map(( (analogRead (0))), (0), (1023), (0), (100))));
      nextionSendCommand(_nextionCommandTempString.c_str(), 100);
    }
  } else {
    _nextionSetLighting1_OldStae = 0;
  }




}
bool _isTimer(unsigned long startTime, unsigned long period )
{
  unsigned long currentTime;
  currentTime = millis();
  if (currentTime >= startTime) {
    return (currentTime >= (startTime + period));
  } else {
    return (currentTime >= (4294967295 - startTime + period));
  }
}
String  _floatToStringWitRaz(float value, int raz)
{
  float tv;
  int ti = int(value);
  String ts = String(ti);
  if (raz == 0) {
    return ts;
  }
  ts += ".";
  float tf = abs(value - ti);
  for (int i = 1; i <= raz; i++ )
  {
    tv = tf * 10;
    ti = int(tv);
    ts += String(ti);
    tf = (tv - ti);
  }
  return ts;
}
void nextionSendCommand(const char* cmd, byte port )
{
  while (Serial100.available()) {
    Serial100.read();
  }
  Serial100.print(cmd);
  Serial100.write(0xFF);
  Serial100.write(0xFF);
  Serial100.write(0xFF);
}
boolean nextionAck( byte port )
{
  uint8_t bytes[4] = {0};
  Serial100.setTimeout(20); if (sizeof(bytes) != Serial100.readBytes((char *)bytes, sizeof(bytes))) {
    return 0;
  }

  if ((bytes[1] == 0xFF) && (bytes[2] == 0xFF) && (bytes[3] == 0xFF)) {
    switch (bytes[0]) {
      case 0x00:
        return false; break;
      case 0x01:
        return true; break;
      default:
        return false;
    }
  }
}
struct _nextionLissenStruct nextionListen( byte port )
{
  char _bite;
  char _end = 0xff;
  String cmd;
  _nextionLissenStruct temp;
  int countEnd = 0;
  delay(10);
  while (Serial100.available() > 0) {
    if (Serial100.available() > 0) {
      _bite = Serial100.read();
      cmd += _bite;
      if (_bite == _end) {
        countEnd++;
      }
      if (countEnd == 3) {
        break;
      }
    }
  }
  temp.result = "";
  temp.code = 'z';
  temp.number = 0;
  switch (cmd[0]) {
    case 'e':
      temp.code = 'e';
      countEnd = 0;
      for (uint8_t i = 0; i < cmd.length(); i++) {
        if (cmd[i] == _end) {
          countEnd++;
        }
        temp.result += String(cmd[i], HEX);
        if (countEnd == 3) {
          return temp;
        }
        temp.result += " ";
      }
      break;
    case 'f':
      temp.code = 'f';
      temp.result = String(cmd[1], DEC);
      return temp;
      break;
    case 'g':
      temp.code = 'g';
      temp.result = String(cmd[2], DEC) + "," + String(cmd[4], DEC) + "," + String(cmd[5], DEC);
      return temp;
      break;
    case 'h':
      temp.code = 'h';
      temp.result = String(cmd[2], DEC) + "," + String(cmd[4], DEC) + "," + String(cmd[5], DEC);
      temp.result = "68 " + temp.result;
      return temp;
      break;
    case 'p':
      temp.code = 'p';
      temp.result = cmd.substring(1, cmd.length() - 3);
      return temp;
      break;
    case 'q':
      temp.code = 'q';
      temp.number = (cmd[4] << 24) | (cmd[3] << 16) | (cmd[2] << 8) | (cmd[1]);
      return temp;
      break;
    default:
      return temp;
      break;
  }
  return temp;
}
int nextionAskPageNamper(byte port)
{
  int result;
  _nextionLissenStruct temp;
  nextionSendCommand("sendme", port);
  temp = nextionListen(port);
  if ((temp.code == 'f') && (temp.result != "")) {
    result = temp.result.toInt();
  } else {
    result = -1;
  }
  return result;
}


Un video corto con una demostración.


Archivar con el proyecto para el panel y el proyecto para el controlador.
En la próxima lección, aprenderemos cómo controlar el controlador Arduino desde el panel.

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


All Articles