Pantalla Nextion como control remoto para IoT


          Las pantalla Nextion es una Human Machine Interface (HMI) que proporciona una interfaz de control y visualización. Puede reemplazar la pantalla LCD tradicional con ventaja porque no consume recursos del procesador ya que su interface se diseña previamente con un software que es el editor de Nextion. La pantalla Nextion sólo utiliza un puerto serie para hacer la comunicación.
          El editor Nextion tiene componentes como botones, cajas de texto, barra de progreso, slider, panel de instrumentos, fotos, etc. para enriquecer el diseño de su interfaz.

Características:

    -Varios tamaños y resoluciones. La usada en este proyecto es de 3,5'' y 480x320
    -RGB 65K
    -Panel táctil resistivo.
    -Interfaz de 2 pines Serial compatible con cualquier microprocesador con UART.
    -Memoria Flash para código de usuario, aplicaciones y datos.
    -Permite multiples pantallas anidadas y por tanto menús complejos.
    -Actualización de firmware que diseñemos por serie del ordenador o por tarjeta micro-SD.
    -Consumo 5V 65mA. (según tamaño)
    -Precio razonable.
           Asi pues, la pantalla la diseñamos en nuestro ordenador con el programa gratuito proporcionado por el fabricante. Colocamos botones, barras de progreso, slider, instrumentos de medida de aspecto analógico o digital, etc.
           A los controles botones, slider, etc. se les asigna un valor de salida por el puerto serie que recibido por el Arduino actúa en consecuencia y de forma recíproca el Arduino puede enviar datos al control de Nextion que queramos. Por tanto el procesador no tiene ninguna carga de trabajo ya que no se hace cargo de dibujar nada en la pantalla, solo manda y recibe datos.

           Abajo vemos el editor de Nextion con el diseño de la pantalla de este brico. No añado mas información porque en Internet hay más que suficientes tutoriales de esta pantalla Nextion.
          En este proyecto he aprovechado el de comunicación bidireccional con dos nRF24L10 sustituyendo el pobre display LCD de 16x2 por la pantalla Nextion.
          Desde esta, y con la barra Slider enviamos por serie al Arduino los valores que queramos de PWM, las transmite con el nRF24L10 al segundo Arduino que las manda al ventilador y simultáneamente lee las RPM y re retransmite al primero y actua sobre la barra de deslizamiento y el valor en una caja de texto. Con el botón del Nextion puede encenderse y apagarse un LED de Arduino que tiene el ventilador.

          Una foto del montaje, un video y el código. En el video, primero Nextion y Arduino solos y en la segunda parte comunicación entre los nRF24L10.
/*
El código que tiene la pantalla Nextion
Emisor de datos en Arduino con NRF24L01 y
comunicación bidireccional
http://www.jopapa.me  
Alicante. España. 2018

  NRF24L01  Arduino pin
  VCC       3.3 V
  GND       GND
  CS        8
  CE        7
  MOSI      11
  MISO      12
  SCK       13
*/
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <SPI.h>
#include "RF24.h"
#include <MillisTimer.h>  //libreria Millis para no usar delay()
LiquidCrystal_I2C lcd(0x20, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);//Direccion de LCD
MillisTimer timer(1100); //envia datos cada ''
float data[1];   //los datos a emitir
float orden[1]; //Ordenes que se reciben
int sensorPin0 = A0;
int sensorValue = 0;        // valor leido del potenciometro
int pwm = 0;        // valor de PWM (analog out)
boolean led13=0;

RF24 NRF24L01 (7, 8);//crea objecto NRF24L01. pin CE y CSN usados en Arduino
byte address[] [6] = {"pipe1", "pipe2"};//set addresses of the 2 pipes for read and write


void setup() {                   
  Serial.begin(9600);
  Serial1.begin(9600);
//  lcd.begin(16,2);// Indicamos medidas de LCD 
//  lcd.clear();//Elimina todos los simbolos del LCD 
//  lcd.setCursor(0,0);//Posiciona la primera letra despues del segmento 5 en linea 1  
//  lcd.setCursor(0, 0);
//  lcd.print("PWM:");
//  lcd.setCursor(0, 1);
//  lcd.print("RPM:");
  pinMode(13, OUTPUT);
  timer.setTimer();
  NRF24L01.begin();
  NRF24L01.openReadingPipe(1, address[0]);//canal de lectura para dirección pipe 1
  NRF24L01.openWritingPipe(address[1]);//abre canal de escritura para address pipe 2

// Emisión al mínimo RF24_PA_MIN o máximo RF24_PA_MAX)
  NRF24L01.setPALevel(RF24_PA_MAX); 
  NRF24L01.setDataRate(RF24_250KBPS);//set datarate to 250kbps
  NRF24L01.setChannel(110);//set frecuencia canal 110
}

void loop() {
                            //TRANSMITE analógico0 (pwm) al otro Arduino
  delay(10);
  NRF24L01.stopListening();
  delay(10);
  if(timer.checkTimer()){  //Transmite los datos cada 5''   
   readDataSimple2(); 
   data[0]=pwm;
// Serial.println(data[0]);
   NRF24L01.write(data, sizeof(data));//Envia dato al otro Arduino
   delay(20);
  }



                     //RECIBE ordenes desde el Arduino

  NRF24L01.startListening();
  delay(10);
  if (NRF24L01.available()){          //¿Hay transmision desde el otro Arduino?
    NRF24L01.read(orden,sizeof(orden));
    int rpm=orden[0];  //para quitar decimales
   Serial1.write(0xff);Serial1.write(0xff);Serial1.write(0xff);        
   Serial1.print("t0.txt=");  //actualiza txt en Nextion
   Serial1.write(0x22);
   Serial1.print(orden[0]);
   Serial1.write(0x22);
   Serial1.write(0xff);Serial1.write(0xff);Serial1.write(0xff);   
   int rp=map(orden[0], 400, 2500, 0, 100);  //mapea a valores del Progress bar
   Serial1.print("j0.val="); //variable de la pantalla que se modificará en Progress bar
   Serial1.print(rp);
 
    NRF24L01.stopListening();
  }
}



void readDataSimple2 () {
int array[16];
while (Serial1.available() > 0) {
  for (int i = 1 ; i < 16; i++) {
   array[i] =  Serial1.read();
   delay(20);
  }
  array[16] = '\0'; 
  int pageNumber = array[2];
  int componentNumber = array[3];
  int pressEvent = array[4]; 
  int numericalData = array[9]; 
  if (pageNumber<20){ 
   Serial.print("pageNumber: ");
   Serial.println(pageNumber);
   Serial.print("componentNumber: ");
   Serial.println(componentNumber);
   Serial.print("pressEvent: ");
   Serial.println(pressEvent);
   Serial.print("numericalData: ");
   Serial.println(numericalData);
    if (componentNumber==2){       //Simula ON/OFF calefacción
     led13=!led13;
     digitalWrite(13, led13);
    }
                    
    if (componentNumber==10){
     pwm=map(numericalData, 0, 100, 0, 255);
    }
   }
  }
}
/*
Receptor de datos en Arduino con NRF21L01 y
comunicación bidireccional
http://www.jopapa.me  
Alicante. España. 2018
  Partes:
  2 X Arduinos
  2 X NRF24L01
  2 X LEDs rojos (indican recepción de datos)
  2 X LEDs amarillos (indican envio de datos)
  4 X 220 ohm resistors

  NRF24L01  Arduino pin
  VCC       3.3 V
  GND       GND
  CS        8
  CE        7
  MOSI      11 or ICSP-4
  MISO      12 or ICSP-1
  SCK       13 or ICSP-3
*/

#include <SPI.h>
#include "RF24.h"
#include <MillisTimer.h>  //libreria par aevitar uso de delay()
const int analogOutPin = 3; // Salida control PWM
byte outputValue = 0;        // valor del PWM

MillisTimer timer(1000); //envia datos cada 2''
float data[1];
float orden[2];

//Medir RPM ventilador PC 4 hilos
// pin 2 cable azul rpm
unsigned long lastPulseTime;
unsigned long pulseInterval;
unsigned long lastUpdateTime;

//objecto NRF24L01. specifying the CE and CSN pins to be used on the Arduino

RF24 NRF24L01 (7, 8);
byte address[] [6] = {"pipe1", "pipe2"};//addresses of the 2 pipes for read and write


//  Falling edge detection pulse rotation
void senseRotation( void ) {
unsigned long cur = micros ();
unsigned long dif = cur - lastPulseTime; //  difference between the previous edge
pulseInterval = (pulseInterval - (pulseInterval >> 2)) + (dif >> 2);  // smooth
lastPulseTime = cur;
}



void setup() {
  Serial.begin(9600);
  timer.setTimer();
  lastPulseTime = 0; pulseInterval = 0;
  attachInterrupt (0, senseRotation, FALLING ); //0 = D2, FALLING = falling
  NRF24L01.begin();
  //Abre "the pipes" para recibir y emitir desde placa 1
  NRF24L01.openWritingPipe(address[0]);//abre escritura pipe 1
  NRF24L01.openReadingPipe(1, address[1]);//abre lectura pipe 2

  NRF24L01.setPALevel(RF24_PA_MAX);
  NRF24L01.setDataRate(RF24_250KBPS);//set data rate to 250kbps
  NRF24L01.setChannel(110);//set frequency to channel 110
}


void loop() {
unsigned long cur = millis ();
if (cur - lastUpdateTime > 60){ // 60ms update interval LED
  uint16_t rpm = 60000000 / (pulseInterval * 2); // RPM find
  orden[0]=rpm;
  Serial.print("---");Serial.println(rpm);
  lastUpdateTime = cur; lastUpdateTime = cur;
}

                        //TRANSMITE button change to the other Arduino
delay(10);
NRF24L01.stopListening();
if(timer.checkTimer()){  //Transmite los datos cada x''
   delay(10);
//  orden[0]=rpm;
   orden[1]=02;
   NRF24L01.write(orden, sizeof(orden));//send LOW state to other Arduino board
  }



                     //RECIBE cambios desde el Arduino que genera datos de pwm
  NRF24L01.startListening();
  delay(10);
  if (NRF24L01.available()){//transmision desde el otro Arduino
    NRF24L01.read(data,sizeof(data));
    outputValue=data[0];
    analogWrite(analogOutPin, outputValue);
    Serial.print("PWM= " );
    Serial.print(data[0]);
//   Serial.print("Dato1= " );
//   Serial.print(data[1]);
    Serial.println("");   
    NRF24L01.stopListening();
  }
}

           En consecuencia, si juntamos una pantalla, un Arduino mini, nRF24L y una batería nos queda un mando compacto con menús mas o menos complejos que pueden transmitir y recibir datos de uno o multiples elementos IoT equipados con otros Arduino (u otros µP) y nRF24L10.
Menu