Nextion et Orange PI Zéro

Nextion 2.4″ basic

Les écrans Nextion offrent la possibilité d’avoir un écran interactif facilement pilotable par une liaison série. Ici on le connecte à un orange pi zéro pour montrer les fonctionnalités de base. Ecrire un texte ou des valeurs et récupérer une information à chaque fois qu’un champ de l’écran est touché.

Préparation Orange PI Zéro

Dans un premier temps il faut charger le système d’exploitation Armbian sur l’Orange Pi Zéro comme expliqué dans l’article https://f1atb.fr/index.php/fr/2020/03/27/mise-en-route-orange-pi-zero/

Pour la liaison série on va connecter le Nextion à l’UART1 de l’Orange Pi. On alimente le Nextion par le 5v de l’Orange PI et on connecte les TX-RX dans chaque sens.

Orange PI Zéro – Nextion

Il faut activer l’UART1 en passant par le configurateur.

$ armbian-config

Sélectionnez la rubrique System puis Hardware et validez UART1.

Pour la liaison série, installez la bibliothèque python-serial ou/et python3-serial.

$ apt-get install python-serial
ou/et
$ apt-get install python3-serial

Editeur Nextion

Pour l’afficheur Nextion la programmation se passe en 2 temps:

  • une définition des différents champs de textes, valeurs, images.. souhaités grâce à un éditeur graphique
  • l’écriture d’un programme sur l’Orange Pi pour aller écrire les informations dans les champs et lire les actions manuelles sur l’écran.

Sur le site https://nextion.tech dans la section download vous pouvez télécharger l’éditeur graphique à mettre sur votre PC. Une fois installé, allez dans la rubrique « File » et « New » pour démarrer un nouveau projet.

Choisissez le modèle de votre écran
  • Dans l’onglet « Device », choisissez votre modèle d’écran
  • Dans l’onglet « Display », choisissez l’orientation de l’écran

Allez dans « Tools », « Font Generator » pour définir les fontes que vous souhaitez utiliser pour votre projet. Pour faire simple et ne pas générer des fichiers volumineux, choisissez un codage Ascii et la génération des fontes uniquement pour les caractères Ascii. Faites par exemple 2 jeux de fontes à utiliser par la suite.

Dans « Toolbox » choisissez « Text » et positionnez sur l’ecran la zone de texte. Donnez lui un nom, ici « titre » dans « objname ».

On y trouve un numéro d’identification « id » le numéro de la fonte crée visible dans l’onglet « Font » en bas à gauche, la couleur du fond et la couleur du texte. Les valeurs en vert pourront être changées par programmation depuis l’Orange Pi, les noires sont figées.

Créez un deuxième champ de type Number dont on gardera le nom « n0 » par defaut.

Si l’on souhaite être informé de l’appui sur un champ, sélectionnez le et cochez la case « Touch Press Event / Send Component ID ».

Une fois le design achevé, on lance une compilation du code , rubrique « File », « TFT output », qui génère un fichier .tft qu’il faut transférer sur une carte microSD de 32Go ou moins formattée initialement en « FAT32 ». Ensuite insérer la carte microSD sur le Nextion et le mettre sous tension pour transférer le fichier.

Une fois le transfert effectué, débranchez l’alimentation 5v, retirez la carte microSD et branchez le Nextion à l’Orange Pi Zéro comme expliqué ci-dessus.

Programmation Orange Pi Zero

Dans le dossier de votre choix, créez un fichier source en python3.

nano test1.py

Mettez le code ci dessous qui:

  • ouvre une liaison série: ‘ser’
  • définie une fonction de réception des données en provenance du nextion qui si rien n’est disponible rend la main après le timeout défini dans ‘ser’
  • écrit l’heure dans le champ ‘titre’
  • incrémente un compteur dans le champ numerique ‘n0’
import time
import serial


ser = serial.Serial(
  port='/dev/ttyS1',
  baudrate = 9600,
  parity=serial.PARITY_NONE,
  stopbits=serial.STOPBITS_ONE,
  bytesize=serial.EIGHTBITS,
  timeout=0.2 # timeout in reception in seconds
)

def serialReceive():
  received_data = ser.read() #read serial port
  data_left = ser.inWaiting() #check for remaining byte
  received_data += ser.read(data_left)
  print (received_data)


i = 0
while True:
  EndCom = b'\xff\xff\xff' #End of each command as bytes
  temp = 'titre.txt="'+time.strftime('%H%M%S')+'"' #local time
  temp = temp.encode('ascii') #conversion unicode in ascii
  ser.write(temp + EndCom) #write in text field 'titre'
  i=i+1
  ser.write(b'n0.val=') #write value in numeric field 'n0'
  ser.write(str(i).encode('ascii'))
  ser.write(EndCom)

Toutes les commandes à passer au Nextion sont sous forme de byte avec le code Ascii de chaque lettre s’il existe ou \xff par exemple. On remarque que chaque commande se termine par 3 bytes \xff,\xff,\xff.

Nextion + Orange Pi Zéro

Lancez le programme:

python3 test1.py

A chaque appui sur un des champs le Nextion retourne des bytes qui donnent ‘e’ pour évenement, l’ID du champ et le sens, touché ou relaché si au design on a coché les cases correspondantes. En fin, les 3 bytes \xff\xff\xff.

b'e\x00\x002\x001\xff\xff\xff'

Voila donc un moyen simple de créer une interface graphique pilotable simplement depuis un Orange Pi Zéro à moins de 20€ ou tout autre nano ordinateur.

Autorisation d’accès au port série

Les accès au GPIO ou ports série sont limités à l’utilisateur root. Si vous accédez par exemple depuis un script cgi lancé par une page web gérée par un serveur Apache2 vous aurez probablement une erreur comme:
Permission denied: ‘/dev/ttyS1

Allez dans le dossier /dev, vous verrez que ttyS1 appartient au group dialout. Rajoutez l’utilisateur d’Apache2 à ce groupe, à savoir ‘www-data’.

adduser www-data dialout

Upload fichier .tft via le port série

Une alternative plus rapide pour télécharger sur le Nextion le fichier de configuration .tft est d’utiliser directement l’Orange Pi sur lequel il est connecté. Ci- après un programme en python2 trouver sur le web qui facilite bien cette phase.

#
# Original: Python Upload script (historic), Bjoern Schrader
# See: http://support.iteadstudio.com/support/discussions/topics/11000007783
# and Omerbeg
# https://github.com/omerbeg/nextionupload/blob/master/nextionupload.py
# My small modification to support my nextion display connected on Orange PI Zero
# This version can upload a tft file to a nextion display connected on Orange PI Zero
# via Uart1
#

import threading, time, os, sys, serial

PORT = '/dev/ttyS1'
BAUDCOMM = 9600
BAUDUPLOAD = 115200

if len(sys.argv) != 2:
	print 'usage: python %s file_to_upload.tft' % sys.argv[0]
	exit(-2)

file_path = sys.argv[1]

if os.path.isfile(file_path):
	print 'uploading %s (%i bytes)...' % (file_path, os.path.getsize(file_path))
else:
	print 'file not found'
	exit(-1)

fsize = os.path.getsize(file_path)


ser = serial.Serial(PORT, BAUDCOMM, timeout=.1, )

waiting = False

def reader():
	global waiting
	while True:
		r = ser.read(128)
		if r == '': continue
		if waiting and '\x05' in r:
			waiting = False
			continue
		print '<%r>' % r

threader = threading.Thread(target = reader)
threader.daemon = True
threader.start()

ser.write([0xff, 0xff, 0xff])
ser.write('connect')
ser.write([0xff, 0xff, 0xff])
time.sleep(.5)

ser.write('whmi-wri %i,%i,res0' % (fsize, BAUDUPLOAD))
ser.write([0xff, 0xff, 0xff])
time.sleep(.1)

waiting = True
ser.baudrate = BAUDUPLOAD
print 'waiting hmi'
while waiting:
	pass

with open(file_path, 'rb') as hmif:
	dcount = 0
	while True:
		time.sleep(.1)
		data = hmif.read(4096)
		if len(data) == 0: break
		dcount += len(data)
		print 'writing %i...' % len(data)
		ser.write(data)
		sys.stdout.write('\rDownloading, %3.3f...        ' % (dcount/868631.0*100.0))
		sys.stdout.flush()
		waiting = True
		print 'waiting for hmi...'
		while waiting:
			pass


ser.close()