Histoires de petit sapin de Noël
Figure 1: Les histoires d'arbres
Le contenu:
- La liste des composants
- Les logiciels
- On construit le petit arbre et on le câble
- Une illumination ciblée
- L'écran OLED pour des informations en texte clair
- Un éclairage étagé
- Le petit arbre enchanté
- Qui fait tant de bruit ?
- Sur la piste du vol de petits arbres
- Un bon séjour pour l'ESP32 et le DHT22/DHT11
- Un tirage au sort de Noël pas comme les autres
- L'application du sapin de Noël
1. La liste des composants
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
Kit RFID RC522 avec lecteur, puce et carte pour Raspberry Pi |
1 |
|
1 |
|
1 |
|
1 |
GY-521 MPU-6050 Gyroscope 3 axes et accéléromètre alternative GY-61 ADXL335 |
1 |
|
3 |
Résistance 1.0KΩ |
(*) L'utilisation des contacts vibrants ou du module GY-51 nécessitent une programmation différente.
2. Le logiciel
Pour le flashage et la programmation de l'ESP32 :
Tôt ou
pacetender Pour tester ESP32 / ESP8266 en tant que serveur UDP
Navigateur: Opéra ou Chrome
Firmware usagé:
Veuillez choisir une version stable
Les programmes Microptron pour le projet:
Pilote de périphérique:
Fichiers de projet Microptron:
Fichiers de projet Arduino IDE :
Pour utiliser l'ESP32 Core, vous devez saisir ce lien dans les préférences comme URL supplémentaire de l'administrateur de la carte :
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_dev_index.json
Ensuite, via le menu Outils -> Board -> Boardverwalter, chercher ESP32 et l'installer.
Les bibliothèques utilisées, comme LittleFS, n'ont été intégrées que tardivement dans le core. Il est donc important de le mettre à jour si nécessaire.
optionnel noisy_tinker_h.ino (avec ticker.h bibliothek)
MicroPython - Langage - Modules et programmes
Vous trouverez ici des instructions détaillées sur l'installation de Thonny. Vous y trouverez également une description de la manière dont le MicropythonFirmware est gravé sur la puce ESP.
MicroPython est un langage d'interprétation. La principale différence avec l'IDE Arduino, où vous flashez toujours et exclusivement des programmes entiers, est que vous ne devez flasher le firmware MicroPython qu'une seule fois au début sur l'ESP32, avant que le contrôleur ne comprenne les instructions MicroPython. Vous pouvez utiliser Thonny, µPyCraft ou esptool.py pour cela. Pour Thonny, j'ai décrit le processus ici.
Dès que le firmware est flashé, vous pouvez dialoguer avec votre contrôleur, tester des instructions individuelles et voir immédiatement la réponse, sans devoir compiler et transférer un programme entier. C'est précisément ce qui me dérange dans l'IDE Arduino. On gagne tout simplement énormément de temps lorsqu'on peut tester la syntaxe et le matériel, voire essayer et affiner des fonctions et des parties entières de programme via la ligne de commande avant de tricoter un programme. C'est dans ce but que j'aime créer de petits programmes de test. Ils constituent une sorte de macro regroupant des instructions récurrentes. Il arrive que des applications entières se développent à partir de ces fragments de programme.
Autostart
Si vous souhaitez que le programme démarre de manière autonome à la mise sous tension du contrôleur, copiez le texte du programme dans un fichier vierge que vous venez de créer. Enregistrez ce fichier sous boot.py dans l'espace de travail et téléchargez-le vers la puce ESP. Lors de la prochaine réinitialisation ou mise sous tension, le programme démarrera automatiquement.
Programmes de test
Les programmes sont lancés manuellement à partir de la fenêtre d'édition actuelle dans l'IDE Thonny en appuyant sur la touche F5. C'est plus rapide que de cliquer sur le bouton Start de la souris ou de passer par le menu Run. Seuls les modules utilisés dans le programme doivent se trouver dans la mémoire flash de l'ESP32.
Vous voulez utiliser l'IDE Arduino de temps en temps ?
Si vous souhaitez réutiliser le contrôleur avec l'IDE Arduino, il suffit de flasher le programme de la manière habituelle. Cependant, l'ESP32/ESP8266 aura alors oublié qu'il a déjà parlé MicroPython. Inversement, n'importe quelle puce Espressif contenant un programme compilé à partir de l'IDE Arduino, ou le firmware AT, ou LUA, ou ... peut sans problème être dotée du firmware MicroPython. Le processus est toujours le même que celui décrit ici.
3. On construit le petit sapin et on le câble
Il existe une video pour l'assemblage du petit sapin.
Bien sûr, une fois le petit arbre assemblé, on peut se détendre et admirer son œuvre. Pour plus de plaisir, nous pouvons modifier le processus de montage à certains endroits. À trois endroits dans la vidéo, nous devons procéder différemment pour notre projet. Les résistances de 4,7kΩ qui y sont mentionnées sont celles de 10kΩ dans le paquet de pièces. Et ces trois résistances par platine A et B ne sont soudées qu'aux endroits de la platine, comme le montrent les figures 2 et 3, l'autre extrémité de ces résistances reste pour l'instant libre. Nous souderons plus tard à ces extrémités libres des petits câbles fins (par exemple du ruban plat) pour la connexion à l'ESP32. Cela vaut pour les deux platines, A et B. Les condensateurs électrolytiques sont laissés de côté.
Figure 2 : Partie A
Figure 3: Partie B
Le reste du montage peut se faire exactement selon le modèle vidéo. Une fois la plaque de base en place, nous soudons les câbles aux extrémités libres des résistances 10kΩ. La longueur doit être comprise entre 25 et 30 cm. A l'autre extrémité du câble, nous soudons un morceau de barrette à broches pour que le tout soit enfichable.
Figure 4 : The Tree-Connection
L'affectation des connexions sur l'arbre aux GPIO de l'ESP32 est visible dans le tableau 1. L'index se réfère à la liste des objets pin. Cette liste, nommée schicht, sert à l'adressage des couches de DEL par des boucles, comme nous le verrons plus loin. Les connexions sont réparties de manière à ce qu'un index pair soit toujours suivi de la couche de DEL de même rang sur la platine B. Bien entendu, il est toujours possible de procéder à des réaffectations à volonté.
Sapins |
A1 |
B1 |
A2 |
B2 |
A3 |
B3 |
GPIO |
32 |
26 |
33 |
27 |
25 |
12 |
index |
0 |
1 |
2 |
3 |
4 |
5 |
Tableau 1 : Liens entre les arbres et l'ESP32
Figure 5 : Câblage de base
Figure 6 : Résistances de base sur la partie B - détail, extrémités libres en haut
Figure 7 : Câblé sur la partie A
4. illumination ciblée
Le câblage est terminé ? Alors nous allons déjà allumer les LED sur le petit sapin. Nous alimentons le petit sapin soit par les piles, soit par le câble fourni à partir d'un port USB. Une fois allumé, il reste dans l'obscurité. Bien sûr, car les bornes de base des transistors sont libres, ce qui empêche le courant de base de circuler et, comme il n'y a pas non plus de courant de collecteur, les LED restent sombres.
Figure 8 : Un des 6 étages de transistors
Cela change lorsque les GPIO sont programmés comme sorties et que le niveau du potentiel GND est augmenté à 3,3V. Nous y parvenons en attribuant un 1 comme valeur. Dans le terminal de Thonny, nous entrons les lignes suivantes.
>>> from machine import Pin
>>> a1=Pin(32,Pin.OUT,value=0)
>>> a1.value(1)
Si le câblage est correct, les LED du niveau A1 commencent alors à s'allumer, pour s'éteindre après l'entrée de
>>> a1.value(0)
s'éteindre. Contrairement à la version précédente du kit de l'arbre, la nouvelle version est équipée de LED scintillantes. Auparavant, il s'agissait de simples LED multicolores. Cela a un certain inconvénient, car il n'est plus possible de faire varier l'intensité des "flashing LEDs". Néanmoins, il est amusant de faire des expériences avec. Grâce aux six transistors, nous sommes désormais en mesure de démarrer ou d'éteindre les six niveaux exactement comme nous le souhaitons. Cela nous permet également d'influencer la luminosité globale.
La disposition des lumières est illustrée dans la figure 9. Elle est valable aussi bien pour la partie A que pour la partie B.
Figure 9 : La répartition des LED se fait à tour de rôle.
La disposition des DEL, le câblage vers l'ESP32 et les connexions à l'ESP32 sont considérés comme acquis pour toutes les autres expériences. Ils n'apparaissent donc plus explicitement dans les descriptions et les schémas des circuits partiels.
5. L'écran OLED
L'écran OLED peut nous fournir des informations en texte clair, mais il peut aussi afficher des graphiques en noir et blanc. La programmation est simple si nous utilisons les modules logiciels MicroPython correspondants. Le pilote matériel SH1106 est directement responsable de l'écran 1,3'' et ne peut être utilisé que pour cela. Le module framebuf intégré dans le noyau MicroPython met à disposition des commandes graphiques et textuelles simples et le module oled.py nous fournit des commandes confortables pour la sortie de texte.
L'écran est commandé uniquement par les deux lignes du bus I2C. On crée un objet I2C et on le transmet au constructeur de la classe OLED. L'adresse de l'appareil matériel de l'écran est fixe et ancrée dans OLED comme une constante. Néanmoins, nous commençons par regarder ce qui est présent sur le bus. Ensuite, nous effaçons l'écran et affichons quelques lignes.
Le graphique de la figure 10 et le programme suivant en démontrent l'utilisation. Nous saisissons le programme dans l'éditeur Thonny, l'enregistrons et le lançons ensuite avec la touche de fonction F5.
Figure 10 : L'OLED sur l'ESP32
# OLED-Display-Demo
#
from machine import Pin, I2C
from time import sleep
from oled import OLED
# Initialisieren der Schnittstelle **********************
i2c=I2C(-1,scl=Pin(22),sda=Pin(21))
print(i2c.scan())
d=OLED(i2c)
d.clearAll()
d.writeAt("Der",0,0,False)
d.writeAt("kleine",0,1,False)
d.writeAt("Weihnachts-",0,2,False)
d.writeAt("baum",0,3)
sleep(4)
d.clearFT(0,2,15,2,False)
d.writeAt("Christ-",0,2)
Sortie:
[60]
this is the constructor of OLED class
Size:128x64
L'adresse de l'appareil de l'écran est en décimal 60 ou en hexadécimal 0x3C. Le constructeur de la classe OLED sait également que l'écran possède 128 x 64 pixels. Après l'édition des quatre lignes, 4 secondes plus tard, "Noël-" est remplacé par "Chist-". Auparavant, nous devons bien sûr supprimer cette ligne. N'hésitez pas à essayer les différentes commandes individuellement via REPL, la console de terminal de Thonny.
Pour Arduino IDE:
La bibliothèque U2G8 est utilisée pour l'affichage. Vous pouvez l'installer via la gestion des bibliothèques.
Télécharger oledtest.ino
6. Un éclairage étagé
Figure 11: Niveau1
Figure 12: Niveau2
Comme on peut commander séparément les différents niveaux de LED sur le petit arbre, nous en profitons pour monter et descendre du niveau le plus bas - OFF - jusqu'à la luminosité maximale. Nous n'avons pas besoin de modifier le circuit. L'écran nous informe du niveau actif.
# steigerung.py
#
import sys
from machine import Pin, I2C
from oled import OLED
from time import sleep,ticks_ms, ticks_us, sleep_ms
# Initialisieren der Schnittstellen **********************
i2c=I2C(-1,scl=Pin(22),sda=Pin(21))
d=OLED(i2c)
# LED-Schichten einrichten *******************************
#schichtPin = [32,33,25,27,26,12] # sortiert
schichtPin = [32,26,33,27,25,12] # verteilt
schicht=[0]*6
for i in range(6): # Ausgaenge erzeugen und auf 0
schicht[i]=Pin(schichtPin[i],Pin.OUT)
schicht[i].value(0)
# Funktionen defnieren ***********************************
def switch(n,val): # Ebene n ein-/ausschalten
schicht[n].value(val)
def stop(): # alle LED-Ebenen aus
d.writeAt("GOOD BYE",4,3)
for i in range(6):
switch(i,0)
def alle(): # alle LED-Ebenen ein
for i in range(6):
sleep_ms(300)
switch(i,1)
# Hauptprogramm ******************************************
d.clearAll()
d.rect(4,16,123,40,1) # Rechteck in Pixelwerten
for j in range(3):
for i in range(6):
d.writeAt("Ebene: {} ein".format(i),2,3)
switch(i,1)
sleep_ms(3000)
for i in range(5,-1,-1):
d.writeAt("Ebene: {} aus".format(i),2,3)
switch(i,0)
sleep_ms(3000)
d.clearFT(2,3,14,3,False)
stop()
On définit l'ordre des couches dans la liste schichtPin. Les objets pin sont créés selon ce modèle dans la boucle for suivante. Les fonctions switch(), stop() et alle() nous aident à rendre le programme plus clair. De plus, nous les utiliserons plusieurs fois dans les chapitres suivants.
Dans le programme principal, nous effaçons l'écran et dessinons un cadre. 4 et 16 sont les coordonnées en pixels du coin supérieur gauche, 123 et 40 la largeur et la hauteur en pixels et 1 la couleur blanche, il n'y a pas plus de couleurs. La boucle for externe compte le nombre total de passages. La première boucle for interne compte i en haut à des intervalles de 3 secondes et active les calques. La deuxième boucle compte à rebours et éteint à nouveau les LED.
La dernière sortie est supprimée et la fonction stop() éteint toutes les LED de manière fiable et prend congé avec un "GOOD BYE" cordial.
La longueur de l'intervalle et le nombre de passages nous permettent de définir nous-mêmes le comportement des LED.
Pour Arduino IDE
Télécharger steigerung.ino
7. Le petit sapin enchanté
N'importe qui pourrait venir et vouloir allumer notre petit arbre. Mais non, ce n'est possible que grâce à nos mains magiques. Bien sûr, nous ne disons pas que nous avons caché une petite tige magnétique en néodyme dans chaque main. Pourquoi en avons-nous besoin ? Pour "faire de la magie", justement. Car nous avons entre-temps modifié notre circuit. Un contact Reed est désormais relié à la masse sur la broche GPIO 13. Dans le petit tube en verre se trouve un contact de commutation qui se ferme à l'approche d'un aimant.
Figure 13 : Les Muggles n'ont pas d'aimant, l'arbre reste sombre
Figure 14 : Dans le repère jaune : contact et aimant.
Attention:
Le verre est très fragile et les fils sont très rigides. Ne les plie pas, sinon le verre se fend et on risque d'enterrer le composant.
Figure 15 : Le contact Reed aide à faire de la magie
Il ne faut pas oublier autre chose, à savoir que l'OLED et l'arbre restent connectés comme décrit ci-dessus.
from os import uname
import sys
from machine import Pin, I2C
from oled import OLED
from time import sleep_ms
# Initialisieren der Schnittstellen **********************
i2c=I2C(-1,scl=Pin(22),sda=Pin(21))
d=OLED(i2c)
taste=Pin(0,Pin.IN,Pin.PULL_UP)
reed=Pin(13,Pin.IN,Pin.PULL_UP)
# LED-Schichten einrichten *******************************
schichtPin = [32,33,25,26,27,12]
schicht=[0]*6
for i in range(6):
schicht[i]=Pin(schichtPin[i],Pin.OUT)
schicht[i].value(0)
# Funktionen defnieren ***********************************
def switch(n,val):
schicht[n].value(val)
def stop():
d.writeAt(" MUGGLE ",1,3)
for i in range(6):
switch(i,0)
def alle():
d.writeAt(" DUMBLEDOR ",1,3)
for i in range(6):
sleep_ms(300)
switch(i,1)
# Hauptprogramm ******************************************
d.clearAll()
d.writeAt("Kannst du ...",0,0)
d.writeAt("ZAUBERN???",0,1)
while 1:
if reed()==0:
alle()
else:
stop()
Le contact Reed doit être placé de manière à ce que nous puissions facilement l'approcher avec notre aimant lorsque nous posons un petit arbre ou un breadboard sur la paume de notre main. Un gant noir fin nous aide à garder l'aimant invisible. Il est probable que tous ceux qui vous entourent soient des moldus.
Le programme est très simple. Jusqu'au programme principal, on connait déjà tout. La boucle while fonctionne sans fin jusqu'à la coupure du courant. Si le contact au voisinage de l'aimant est fermé, alors GPIO13 est au potentiel GND et toutes les lumières s'allument. Dans le cas contraire, la résistance intégrée au module tire le GPIO13 vers Vcc=3,3V et les lumières s'éteignent.
Pour que la magie opère mieux, le petit sapin avec breadboard doit être alimenté par la pile. La borne positive de la batterie doit être reliée à la broche Vin / 5V de l'ESP32. De plus, le programme doit être téléchargé en tant que boot.py sur l'ESP32 afin que le contrôleur démarre de manière autonome après la mise sous tension. La manière de procéder est décrite en détail dans le chapitre 2 - Autostart.
Pour Arduino IDE
Télécharger enchanté.ino
8. Avent et Noël, la période "staade".
Traduit dans le langage courant allemand, "Staad" signifie "calme", "contemplatif". Mais la vie quotidienne nous apprend que la période précédant Noël peut aussi être agitée. Lorsque les choses deviennent trop turbulentes, le petit arbre nous invite à baisser de quelques décibels. Comment fait-il ? Eh bien, il y a un module sonore qui capte le son et délivre le signal numérisé à l'ESP32.
Figure 16 : Volume OK
Figure 17 : trop fort
Figure 18 : Moteur de son sur ESP32
# noisy.py
import esp32
from os import uname
from machine import Timer, Pin, I2C
from oled import OLED
from time import time, sleep,
i2c=I2C(-1,scl=Pin(22),sda=Pin(21))
d=OLED(i2c)
# IRQ-Steuerung durch Soundmodul
ST=Timer(1)
sound=Pin(17,Pin.IN)
#
# LED-Schichten einrichten *******************************
schichtPin = [32,33,25,27,26,12]
L=len(schichtPin)
schicht=[0]*L
for i in range(L):
schicht[i]=Pin(schichtPin[i],Pin.OUT)
schicht[i].value(0)
# Funktionen defnieren ***********************************
def switch(n,val):
schicht[n].value(val)
def stop():
d.clearAll()
d.writeAt("ALLES GUT",4,2)
for i in range(L):
switch(i,0)
def alle():
d.clearAll()
d.writeAt("ZU LAUT!!",0,0)
for i in range(L):
sleep(0.5)
switch(i,1)
def soundDetected(pin):
global n
if pin==Pin(17):
sound.irq(handler=None)
if n:
return
n=True
ST.init(period=15000, mode=Timer.ONE_SHOT, callback=soundDone)
print("begin",time())
alle()
def soundDone(t):
global n
n=False
print("ende",time())
stop()
sound.irq(handler=soundDetected, trigger=Pin.IRQ_FALLING)
n=False
sound.irq(handler=soundDetected, trigger=Pin.IRQ_FALLING)
Le son est transmis par des variations rapides de la pression de l'air. Un signal sonore se propage à une vitesse d'environ 340 m/s. Dans une pièce, il ne subit pratiquement aucun retard perceptible. Le microphone du module sonore transforme les variations de pression en un signal électrique. Mais contrairement au contact Reed, il n'est plus possible de détecter ces oscillations en interrogeant le port GPIO, ce procédé est trop lent. C'est pourquoi on utilise ici une autre technique, la programmation par interruption. Une interruption est l'interruption d'un programme par un événement spécifique. Nous allons utiliser deux sources d'interruption différentes. L'une déclenche une interruption lorsque le niveau sur une broche GPIO change, de 0 à 1 ou inversement. L'autre source d'IRQ est une minuterie matérielle de l'ESP32. Elle déclenche l'IRQ lorsque le réveil sonne.
Les deux se passent maintenant la balle à tour de rôle. Le GPIO17 attend un signal du module son. Si un front descendant arrive, la fonction soundDetected() démarre et vérifie d'abord si elle est signifiée en raison du paramètre pin passé. Si n est True, un cycle est déjà en cours et il n'y a rien d'autre à faire. Si au contraire n est False, alors il s'agit d'une commande fraîche. L'IRQ pin-change est désactivée et n est mis à True afin de supprimer les impulsions immédiatement suivantes sur GPIO17. Ensuite, le timer est lancé, qui définit la durée de fonctionnement de l'éclairage de l'arbre. L'éclairage est allumé en appelant alle().
Si le timer est écoulé, l'interruption correspondante est déclenchée, ce qui lance la fonction soundDone(). n est mis à False, les lumières s'éteignent et l'IRQ Pin-Change est réarmé.
Le programme principal ne comporte que deux lignes. n est défini sur False pour que l'IRQ Pin-Change activée ensuite puisse être déclenchée
Ce qui est intéressant, c'est que les IRQ restent actives, même si le programme principal est déjà terminé. Pour désactiver cela, l'ESP32 doit être réinitialisé avec le bouton STOP/RESTART.
Pour Arduino Ide
Télécharger noisy.ino ou optionnellement noisy_ticker_h.ino (avec la librairie Ticker.h)
Deux variantes ont été utilisées ici pour implémenter les interruptions du timer. Dans le noisy.ino, seules des variables binaires sont commutées dans chacune des deux routines de service d'interruption. Le changement est ensuite détecté dans la boucle principale normale. Une alternative consiste à intégrer la bibliothèque Ticker.h. Ses réglages sont un peu plus faciles à effectuer. Elle est incluse dans le ESP32 Core. Il n'est pas nécessaire de l'installer séparément. Si elle n'est pas trouvée lors de la compilation, vous devrez éventuellement mettre à jour le noyau ESP32.
9. Sur la piste du vol de sapins
Il paraît qu'il y a des gens qui volent les sapins de Noël - dans la forêt. Eh bien, chers gardes forestiers, faites comme nous et installez dans vos petits arbres un gardien comme celui que nous allons décrire.
OK, ce sera certainement aussi difficile que pour la surveillance d'autres interdictions, si le personnel manque. Pourquoi interdire quelque chose si on ne peut pas le contrôler ? Quoi qu'il en soit.
Notre petit arbre se voit attribuer un surveillant, à savoir lui-même ! Il est aidé par un capteur qui vient d'un tout autre monde. Le module GY-521 utilisé avec le composant MPU6050 est un accéléromètre avec gyroscope. Il permet de mesurer les accélérations, les forces et les rotations. Oui, et si l'on veut enlever quelque chose, il faut le soulever et le mettre en mouvement. Dans les deux cas, on accélère l'objet, même en le faisant basculer.
Figure 19 : Un léger basculement suffit à déclencher l'alarme.
Même de très faibles changements de lieu produisent des forces et donc font réagir notre capteur. Le reste est simple : le déclenchement est suivi de l'éclairage du petit arbre et le voleur potentiel prend la fuite, espérons-le. La durée de l'alarme est à nouveau déterminée par une interruption de la minuterie.
Figure 20 : Unité antivol
# alarm.py
# RED-ALLERT by movement
import esp32
from os import uname
from machine import Timer, Pin, I2C
from oled import OLED
from time import sleep,ticks_ms, ticks_us, sleep_ms
from gy521rc import GY521
# Initialisieren der Schnittstellen **********************
i2c=I2C(-1,scl=Pin(22),sda=Pin(21))
d=OLED(i2c)
AT=Timer(0)
acc=GY521(i2c)
limit=36
dauer=5000
schichtPin = [32,33,25,27,26,12]
L=len(schichtPin)
schicht=[0]*L
for i in range(L):
schicht[i]=Pin(schichtPin[i],Pin.OUT)
schicht[i].value(0)
# Funktionen defnieren ***********************************
def TimeOut(t):
start=ticks_ms()
def compare():
return int(ticks_ms()-start) >= t
return compare
def switch(n,val):
schicht[n].value(val)
def stop():
d.clearAll()
d.writeAt("ALLES GUT",4,2)
for i in range(L):
switch(i,0)
def alle():
d.clearAll()
d.writeAt("DIEBSTAHL",0,0)
for i in range(L):
sleep(0.5)
switch(i,1)
def hasMoved(delay):
xs,ys,zs=0,0,0
for i in range(100):
x,y,z=acc.getXYZ()
xs+=x
ys+=y
zs+=z
xs//=100
ys//=100
zs//=100
#print(xs,ys,zs)
n=0
while 1:
x,y,z=acc.getXYZ()
x=abs(xs-x)
y=abs(ys-y)
z=abs(zs-z)
#print(x,xs//limit)
if x > abs(xs//limit) :
print("*******",n)
n+=1
alle()
# Optional Nachricht via UDP
AT.init(period=delay, mode=Timer.ONE_SHOT, callback=alertDone)
sleep(0.3)
def alertDone(t):
stop()
print("Diebstahlschutz gestartet")
hasMoved(dauer)
On retrouve à nouveau de bonnes connaissances dans le programme. Mais la nouveauté réside dans l'initialisation du GY521. Pour le module, nous devons télécharger un autre module vers l'ESP32, gy521rc.py. La classe qu'il contient porte le même nom que le module.
Comme l'écran OLED, le GY521 est commandé par le bus I2C. Nous transmettons au constructeur le même objet I2C, définissons le seuil de déclenchement de l'alarme et sa durée en millisecondes.
Le seuil est la valeur absolue de l'écart de la valeur mesurée par rapport à la valeur moyenne de la mesure d'accélération dans la direction x. Le capteur est orienté de manière à ce que l'axe x positif soit orienté verticalement vers le haut. La valeur mesurée se situe autour de 16000 counts et correspond dans ce cas à l'accélération de la pesanteur g=9,81m/s².
La fonction hasMoved() représente ici la boucle principale. A l'entrée, la valeur moyenne est déterminée par 100 mesures. Il est évident que le capteur ne doit pas bouger.
Ensuite, on passe à la boucle principale. L'accélération actuelle est mesurée et les écarts par rapport aux valeurs moyennes sont calculés. Si la différence dépasse la limite prédéfinie, l'alarme est déclenchée et la minuterie activée. L'alarme signifie que l'arbre passe en pleine luminosité.
La routine de service de l'IRQ de la minuterie éteint les lumières. La solution via l'IRQ fait en sorte que le circuit soit à nouveau armé immédiatement après le déclenchement de l'alarme. Si la durée de l'alarme était fixée par une instruction sleep dans la boucle principale, le circuit serait mort pendant cette durée.
Les contacts vibrants mentionnés dans la liste des pièces seraient raccordés à l'ESP32 de manière similaire au contact Reed, mais ne permettent pas de régler la sensibilité.
Pour Arduino IDE
Télécharger alarm.ino
Pour le capteur gyroscopique, la bibliothèque GY521 est intégrée ici. Celle-ci peut également être installée via la gestion des bibliothèques. De plus, la bibliothèque Ticker.h est également utilisée ici. Contrairement au modèle MicroPython, tous les axes du capteur sont considérés ici.
Si vous n'êtes pas sûr de l'adresse I2C utilisée par le capteur, vous pouvez charger le programme I2C_Scanner.ino sur l'ESP. Dans ce cas, deux adresses devraient être affichées dans le moniteur série (pour l'écran et le capteur). Sur le capteur lui-même, vous avez la possibilité de choisir entre les adresses 0x68 et 0x69. Pour cela, vous devez relier la broche A0 soit à GND, soit à 3.3V de l'ESP.
10. Séjour agréable ESP32 et DHT22
Un climat ambiant agréable fait partie de l'ambiance des fêtes. Dans cette application simple, l'ESP32 ne peut pas modifier le climat ambiant, mais il peut en rendre compte. Les valeurs exactes de la température et de l'humidité de l'air sont affichées sur l'écran OLED, les valeurs approximatives nous sont communiquées par le petit arbre. Il indique les valeurs de la température ambiante par paliers de 2 degrés grâce à différents niveaux de LED activés.
Figure 21 : température moyenne - demi-éclairage
Figure 22 : Mesure de la température et de l'humidité de l'air dans un module.
Il existe deux variantes du DHT22, alias AM2302. Le module de l'illustration de gauche contient déjà la résistance pull-up nécessaire pour le bus One-Wire, qui ne doit d'ailleurs pas être confondu avec le système du module Dallas DS18B20. Le bus Dallas a un timing très différent. Pour la version nue de l'illustration de droite, il faut installer une résistance de 4,7kΩ à 10kΩ contre Vcc.
L'utilisation dans le programme est très simple. Les trois commandes nécessaires sont fournies par le module dht déjà intégré dans MicroPython..
import esp32, dht
from os import uname
import sys
from machine import Pin, I2C
from oled import OLED
from time import sleep
# Initialisieren der Schnittstellen **********************
i2c=I2C(-1,scl=Pin(22),sda=Pin(21))
d=OLED(i2c)
taste=Pin(0,Pin.IN,Pin.PULL_UP)
dhtPin=Pin(13)
dht22=dht.DHT22(dhtPin)
# LED-Schichten einrichten *******************************
schichtPin = [32,33,25,26,27,12]
schicht=[0]*6
for i in range(6):
schicht[i]=Pin(schichtPin[i],Pin.OUT)
schicht[i].value(0)
# Funktionen defnieren ***********************************
def switch(n,val):
schicht[n].value(val)
def stop():
d.writeAt("TEMP TO LOW",4,2)
for i in range(6):
switch(i,0)
def alle():
for i in range(6):
sleep_ms(300)
switch(i,1)
def tree(n):
for i in range(6):
if i <=n:
switch(i,1)
else:
switch(i,0)
# Hauptprogramm ******************************************
d.clearAll()
d.writeAt("***RAUMKLIMA***",0,0)
while True:
sleep(0.3)
dht22.measure()
t=dht22.temperature()
h=dht22.humidity()
d.rect(0,10,126,38,1)
d.clearFT(1,2,14,3)
d.writeAt("TEMP: {:.1f} *C".format(t),1,2)
d.writeAt("HUM : {:.1f} %".format(h),1,3)
tree(int(((t-15)//2)%6))
sleep(2.7)
Outre les suspects habituels, le programme ne propose comme nouveautés que l'importation du module dht, l'instanciation de l'objet dht22 et la boucle principale avec l'ordre de mesure dht22.measure() et la lecture de la valeur de température et d'humidité. Nous connaissons déjà la sortie à l'écran et l'affichage de l'arbre. Ce qui est peut-être intéressant et peu visible, c'est la conversion de la température de °C en indice de niveau d'éclairage. par le terme int(((t-15)//2)%6). A partir de la valeur du quotient de la division entière de l'écart de la température de 15 °C vers le haut et 2, on détermine le reste de la division par 6 et, pour plus de sécurité, on le représente sous forme d'un nombre entier. Encore une fois, très lentement.
pour 28°C, on obtiendrait : 28-15=13 ; 13//2=6 ; 6%6 = 0 ; La dernière étape est nécessaire parce qu'il n'y a pas de niveau avec le numéro 6.
Pour Arduino IDE
Télécharger roomclimate.ino
Pour ce capteur, veuillez installer la DHT sensor library et la Adafruit Unified Sensor Library via la gestion des bibliothèques. Contrairement à Python, il faut faire très attention aux types de données en C/C++. Les valeurs de mesure du capteur sont retournées de type float. En conséquence, il faut configurer la sortie formatée et le calcul pour la commande des LEDs peut également être erroné si l'on fait abstraction du type de données.
11. Le tirage au sort de Noël (un peu différent)
Je me souviens de cette pratique à l'école. Chacun apportait un paquet pendant la période de l'Avent et la semaine avant les vacances, on lançait la tombola - chaque billet était gagnant.
J'ai choisi des cartes RFID neutres comme lots recyclables. Le tirage au sort est effectué par l'ESP32 en même temps que le kit RFID. Il n'y a que les gains dont il faut s'occuper soi-même. Bien entendu, le petit arbre est également de la partie. Grâce à sa luminosité, il annonce son gain à chaque joueur. Pour qu'il n'y ait aucun doute quant à l'interprétation, l'écran indique sans équivoque le lieu de chaque tirage : Fribourg, Berlin, Hambourg ... Six cartes de tirage et une carte maîtresse sont nécessaires.
Figure 23 : La hauteur du numéro d'impact détermine l'intensité lumineuse
Figure 24 : Loterie
Figure 25 : Lecteur de carte RFID
En raison du bus SPI, le câblage est un peu plus complexe que pour le bus I2C avec ses deux lignes. Les appareils du bus SPI n'ont pas d'adresse d'appareil matériel, mais ils ont une connexion Chip-select qui doit être sur LOW si l'appareil doit être adressé. Le transfert de données est également un peu différent, l'envoi et la réception se font toujours simultanément. Il n'est pas nécessaire de préciser la procédure ici, car la classe MFRC522 s'en charge pour nous. Nous indiquons seulement au constructeur l'affectation des ports et la vitesse de transfert. Le transfert fonctionne à une vitesse de 3,2 MHz. À titre de comparaison, l'I2C fonctionne à 400 kHz.
La fonction readUID() lit l'identifiant unique de la carte et le renvoie sous forme de valeur hexadécimale et de nombre décimal. Les cartes sont demandées via l'écran OLED. Pour que la fonction ne bloque pas l'ensemble du processus, un timeout assure un retrait ordonné. Dans ce cas, la valeur None est renvoyée au lieu de l'ID de la carte.
Figure 26 : Cartes RFID et puce
Pour que les cartes de tirage au sort entrent en jeu, nous avons besoin d'une carte maîtresse. Pour ce faire, nous prenons une carte ou une puce quelconque dans la pile, lisons son ID et l'utilisons pour attribuer la valeur décimale à la variable dès le début du programme :
MasterID=4217116188.
Lors du premier démarrage, l'ESP32 constate qu'il n'existe pas encore de fichier contenant les données de la carte de lot et demande la carte maître. Une fois celle-ci reconnue, une carte de lot est demandée. Après la lecture de l'ID, celle-ci est écrite dans le fichier et la carte maître est à nouveau demandée. La lecture se poursuit jusqu'à la dernière carte de lot. Si aucune carte de jeu n'est proposée pendant 10 secondes après la demande de la carte maîtresse, le système redémarre de lui-même. Pour cela, il faut que le programme rfid.py ait été envoyé à l'ESP32 en tant que boot.py. Le chapitre 2 - Autostart explique exactement comment procéder. Pour repartir complètement à zéro, nous pouvons supprimer le fichier slavecards.txt contenant les ID des cartes de lot via la console Thonny. Après une réinitialisation, les cartes de lot peuvent alors être lues à nouveau.
# rfid.py
# workes with RC522 13,2MHz
import mfrc522
import esp32, dht
from os import uname
from machine import Timer, Pin, I2C, ADC, reset
from oled import OLED
from time import sleep,ticks_ms, ticks_us, sleep_ms
from gy521 import GY521
# Initialisieren der Schnittstellen **********************
if uname()[0] == 'esp32':
# sck, mosi, miso, cs=sda
rdr = mfrc522.MFRC522(14, 16, 15, 5, baudrate=3200000)
elif uname()[0] == 'esp8266':
# sck, mosi, miso, cs=sda
# D3 D4 D2 D5
rdr = mfrc522.MFRC522(0, 2, 4, 14, baudrate=100000)
else:
raise RuntimeError("Unsupported platform")
MasterID=4217116188 # 0XFB5C161C
i2c=I2C(-1,scl=Pin(22),sda=Pin(21))
d=OLED(i2c)
schichtPin = [32,33,25,27,26,12]
schicht=[0]*6
for i in range(6):
schicht[i]=Pin(schichtPin[i],Pin.OUT)
schicht[i].value(0)
gewinn=[
"Freiburg",
"Berlin",
"Hamburg",
"Augsburg",
"Ratzeburg",
"Erfurt",
"Essen",
"Bonn",
]
# Funktionen defnieren ***********************************
def TimeOut(t):
start=ticks_ms()
def compare():
return int(ticks_ms()-start) >= t
return compare
def readUID(display,kartentyp,timeout):
display.clearFT(0,1,15,show=False)
display.writeAt("Put on "+kartentyp,0,1)
readTimeOut=TimeOut(timeout)
while not readTimeOut():
(stat, tag_type) = rdr.request(rdr.REQIDL)
if stat == rdr.OK:
(stat, raw_uid) = rdr.anticoll()
if stat == rdr.OK:
display.clearFT(0,2,15,show=False)
display.writeAt("Card OK",0,2)
sleep(1)
userID=0
for i in range(4):
userID=(userID<<8) | raw_uid[i]
userIDS="{:#X}".format(userID)
print(userIDS)
return userID,userIDS
return None
def addUID(display):
display.clearAll()
m=readUID(display,"Master",3000)
if m is not None:
mid,_= m
if mid==MasterID:
sleep(3)
u=readUID(display,"Slavecard",3000)
if u is not None:
uid,uids=u
if uid is not None and uid != MasterID:
with open("slavecards.txt","a") as f:
f.write("{}\n".format(uids))
display.writeAt("New slave written",0,3)
sleep(3)
return True
else:
display.writeAt("ERROR!!!",0,3)
display.writeAt("Card not added!",0,4)
return False
else:
display.writeAt("ERROR!!!",0,3)
display.writeAt("Not mastercard",0,4)
sleep(3)
return False
def switch(n,val):
schicht[n].value(val)
def stop():
d.writeAt("GOOD BYE",4,2)
for i in range(6):
switch(i,0)
def alle():
for i in range(6):
sleep_ms(300)
switch(i,1)
def tree(n):
for i in range(6):
if i <=n:
switch(i,1)
else:
switch(i,0)
# ******************* Hauptprogramm *********************
d.clearAll()
d.writeAt("*XMAS LOTTERIE*",0,0)
d.rect(0,20,127,28,1)
cards=[]
try:
with open("slavecards.txt","r") as f:
for line in f:
cards.append(line.strip("\n"))
closed=TimeOut(60000)
while not closed():
u=readUID(d,"LOSKARTE",5000)
d.clearFT(1,3,14,4,False)
if u is not None:
uid,uids=u
try:
n=cards.index(uids)
d.writeAt("TREFFER {}".format(n),1,3, False)
d.writeAt(gewinn[n],1,4)
except ValueError as e:
d.writeAt("TROSTPREIS",1,3)
n=-1
tree(n)
closed=TimeOut(60000)
sleep(10)
stop()
except OSError as e:
print("keine Datei, keine Daten!")
allRead=TimeOut(10000)
while not allRead():
if addUID(d):
allRead=TimeOut(10000)
print("Alle Karten eingelesen und gespeichert")
d.clearFT(0,3,15,4,False)
d.writeAt(" ALL CARDS READ",0,3)
d.writeAt("**R E B O O T**",0,4)
reset()
d.clearFT(0,1,15,3,False)
d.writeAt("Lotterie neu",0,2)
d.writeAt("starten",0,3)
Pour un cycle de jeu, 6 gains sont déterminés, les 6 cartes sont mélangées et distribuées et le nouveau cycle est lancé avec la touche PROG de l'ESP32.
Pour Arduino IDE
Télécharger rfid.ino
Remarque : dans ce cas, les connexions aux broches du ESP32 doivent être modifiées. La raison en est que l'interface matérielle SPI est utilisée. Ses broches ne peuvent pas être modifiées.
MOSI = 23
MISO = 19
SCK = 18
SDA = 5
RST = 17
Pour le scanner RFID, veuillez installer la bibliothèque MFRC522.
Pour une comparaison directe avec MicroPython, vous pouvez modifier cette ligne afin de ne pas déplacer les broches à chaque fois :
rdr = mfrc522.MFRC522(14, 16, 15, 5, baudrate=3200000)
dans
rdr = mfrc522.MFRC522(18, 23, 19, 5, baudrate=3200000)
Pour enregistrer le fichier texte avec les identifiants, un système de fichiers est créé dans la mémoire flash de l'ESP à l'aide de la bibliothèque LittleFS (le successeur de SPIFS). Des fichiers peuvent alors y être déposés. La bibliothèque fait désormais partie du cœur de l'ESP32. Il n'est pas non plus nécessaire de l'installer séparément. Le programme est écrit de manière à ce que vous n'ayez pas à traiter le fichier texte sur le PC.
Si vous souhaitez tout de même le faire, vous pouvez installer le plugin ESP32 Upload. L'échange de données ne fonctionne alors que dans un sens (comme son nom l'indique).
La structure du programme a été quelque peu modifiée ici. Le comportement du programme devrait toutefois rester le même. Quelques fonctions ont encore été ajoutées. Il est possible de lire la carte maître au démarrage du programme. De plus, il est possible de supprimer le fichier texte de la flash. Pour cela, vous pouvez relier un câble ou un bouton à la broche indiquée (voir code source) à GND. Maintenez-le enfoncé et redémarrez l'ESP. Le fichier est alors supprimé, s'il existe. Ensuite, coupez la connexion et relisez les cartes gagnantes. Le nombre maximal de cartes gagnantes correspond aux niveaux de LED du sapin de Noël. Si vous souhaitez utiliser moins de cartes, vous pouvez attendre le timeout lors du processus de lecture.
12. Le petit sapin sur le LAN/WLAN
Complétons la douzaine et connectons le petit sapin au réseau. En effet, si un ESP32 est utilisé pour la commande, il faut aussi un accès LAN ou WLAN pour la commande. J'ai opté pour la réalisation d'un serveur web sur l'ESP32, car les niveaux du petit arbre peuvent alors être contrôlés avec presque n'importe quel navigateur. Un serveur UDP sur le contrôleur et une application pour téléphone portable auraient pu être envisagés comme alternatives. Mais cela aurait dépassé le cadre de ce blog et j'y ai donc renoncé. Pour les personnes intéressées, j'ai déjà décrit un tel type de contrôle dans d'autres articles, par exemple ici et ici.
Pour le circuit, nous avons besoin du montage du chapitre 5, auquel nous ajoutons une LED RGB et trois résistances de 1,0 kΩ.
Figure 27: Structure du site web
Après avoir importé les modules nécessaires, nous définissons les broches pour la LED RGB, qui nous indique l'état du réseau de manière visible à grande distance. Vient ensuite le choix du mode de fonctionnement du réseau, WLAN ou point d'accès propre à ESP32. Le WLAN est préréglé par défaut. Pour accéder au routeur WLAN, il faut également indiquer ici les données d'accès. La définition des couches est complétée par trois listes, texte en clair pour on/off, couleur de fond pour le tableau dans la page web et les états de commutation des couches.
Dans les services, les fonctions bloquantes ont été supprimées : seuils(), seuils de sortie(), vague() et arbre(). Les nouvelles fonctions sont hexMac(), blink(), ledsOff() et web_page(). hexMac donne l'adresse MAC de l'ESP32 en mode station, blink() signale l'état du réseau et du serveur. ledsOff() éteint la LED RGB et web_page() décortique les requêtes du navigateur, exécute les ordres et renvoie une réponse sous forme de texte de page web.
La demande du navigateur est envoyée au serveur sous la forme d'une chaîne de requête. La chaîne a la forme ?a, ?p ou ?e=x&v=y. Dans cette chaîne, x représente le numéro de niveau et y l'état de commutation, 0 ou 1.
web_page() convertit la requête en majuscules, vérifie d'abord la présence de "A" et de "P". Si la requête contient plus de 2 caractères, elle essaie de déterminer le niveau et l'état de commutation. Si une erreur se produit, aucune action n'est déclenchée et la page d'accueil nue est appelée. Cela se produit également si aucune chaîne de requête n'est indiquée. Ensuite, la page web est construite sous forme de chaîne de caractères et renvoyée à la boucle principale.
Après les définitions de fonctions, la connexion au réseau est établie, soit comme point d'accès propre, soit comme connexion au routeur WLAN. Cela est contrôlé par les deux variables ownAP et WLANconnect. Dans les deux cas, une adresse IP fixe (10.0.1.181) est attribuée, puisqu'il s'agit d'un serveur. Les adresses dynamiques du routeur WLAN ne sont pas appropriées, car elles peuvent changer d'une fois à l'autre. L'établissement de la connexion avec le routeur est marqué par le clignotement de la LED bleue. L'écran nous informe que la connexion est établie et que le socket de connexion s est également prêt à recevoir des demandes.
Dans la boucle principale, la boucle de réception de la méthode accept() attend une demande. Si rien n'arrive avant le timeout, accept() lance une exception que nous interceptons avec le try précédent.
S'il y a une demande, accept() renvoie un socket de communication c et l'adresse de la machine qui a fait la demande. c sert à gérer l'échange de données entre le client et le serveur, tandis que s est à nouveau libre pour accepter d'autres requêtes entrantes. La méthode c.recv() renvoie le texte de la requête, dont seuls les premiers caractères nous intéressent. Pendant la phase de développement, il est possible d'entrer des requêtes à la main pour tester l'analyseur web_page(). ownAP et WLANconnect doivent alors tous deux être définis sur False.
L'objet octet request du texte reçu est maintenant décodé en une chaîne de caractères r, plus facile à manipuler. Nous recherchons un "GET /" au tout début de la chaîne r et la position à laquelle " HTTP" suit. Si les deux sont trouvés, nous isolons le texte après le "/" de "GET" jusqu'à l'espace de " HTML" et l'envoyons comme chaîne de requête à l'analyseur syntaxique web_page(). Nous recevons sa réponse dans la variable response. Ensuite, nous renvoyons l'en-tête HTML et le texte de la page HTML avec la réponse contenue à l'appelant. Les deux else et except qui suivent servent à intercepter et à traiter les éventuelles erreurs. Le dernier c.close(), qui ferme le socket de communication c, est important.
Après une demande de touche pour l'interruption du programme, la LED verte nous indique par son bref clignotement comme un battement de cœur que le système est encore en vie.
# webcontrol.py
# Fernsteuerung vom Browser via TCP
# (C) 2021 Jürgen Grzesina
# released under MIT-License (MIT)
# http://www.grzesina.de/az/weihnachtsbaum/MIT-License.txt
#
from machine import Pin, I2C
from oled import OLED
# ******************** Network stuff ********************
from time import sleep,ticks_ms, sleep_ms
try:
import usocket as socket
except:
import socket
import ubinascii
import network
statusLed=Pin(18,Pin.OUT,value=0) # blau=2
onairLed=Pin(19,Pin.OUT,value=0) # gruen=1
errorLed=Pin(23,Pin.OUT,value=0) # rot=0
led=[errorLed,onairLed,statusLed ]
red,green,blue=0,1,2
request = bytearray(50)
response=""
taste=Pin(0,Pin.IN,Pin.PULL_UP)
# Auswahl der Betriebsart Netzwerk oder Tastatur:
# --------------------------------------------------------
# Netzwerk: Setzen Sie genau !_EINE_! Variable auf True
WLANconnect=True # Netzanbindung ueber lokales WLAN
ownAP=False # Netzanbindung ueber eigenen Accessppoint
# beide False ->> Befehlseingabe ueber PC + USB in Testphase
# Falls WLANconnect=True:
# Geben Sie hier die Credentials Ihres WLAN-Accesspoints an
mySid = 'YOUR_SSID'; myPass = "YOUR_PASSWORD"
myIP="10.0.1.181"
myPort=9002
# Initialisieren der Schnittstellen **********************
i2c=I2C(-1,scl=Pin(22),sda=Pin(21))
d=OLED(i2c)
#schichtPin = [32,33,25,27,26,12] # sortiert
schichtPin = [32,26,33,27,25,12] # verteilt
schicht=[0]*6
for i in range(6):
schicht[i]=Pin(schichtPin[i],Pin.OUT)
schicht[i].value(0)
zustand=["aus","an "]
color=["red","lightgreen"]
eState=[0,0,0,0,0,0]
connectStatus = {
1000: "STAT_IDLE",
1001: "STAT_CONNECTING",
1010: "STAT_GOT_IP",
202: "STAT_WRONG_PASSWORD",
201: "NO AP FOUND",
5: "GOT_IP"
}
# Funktionen defnieren ***********************************
def TimeOut(t):
start=ticks_ms()
def compare():
return int(ticks_ms()-start) >= t
return compare
def switch(n,val):
schicht[n].value(val)
def stop():
d.writeAt("ALL LEDS OFF",2,5)
for i in range(6):
switch(i,0)
def alle():
d.writeAt("ALL LEDS ON ",2,5)
for i in range(6):
sleep_ms(300)
switch(i,1)
def tree(n):
d.writeAt("TREE PROGR. ",2,5)
for i in range(6):
if i <=n:
switch(i,1)
else:
switch(i,0)
def hexMac(byteMac):
"""
Die Funktion hexMAC nimmt die MAC-Adresse im Bytecode
entgegen und bildet daraus einen String fuer die Rueckgabe
"""
macString =""
for i in range(0,len(byteMac)): # Fuer alle Bytewerte
macString += hex(byteMac[i])[2:] # ab Position 2 bis Ende
if i <len(byteMac)-1 : # Trennzeichen
macString +="-"
return macString
def blink(pulse,wait,col,inverted=False):
if inverted:
led[col].off()
sleep(pulse)
led[col].on()
sleep(wait)
else:
led[col].on()
sleep(pulse)
led[col].off()
sleep(wait)
def ledsOff():
for i in range(3):
led[i].value(0)
def web_page(q):
global eState
q=q.upper()
print("Anfrage: ",q)
if q=="?A":
alle()
for i in range(6):
eState[i]=1
elif q=="?P":
stop()
for i in range(6):
eState[i]=0
elif len(q)>2:
try:
ebene,state=q[1:].split("&")
_,ebene= ebene.split("=")
_,state= state.split("=")
ebene=(int(ebene) if 0<=int(ebene)<=5 else 0)
state=(int(state) if 0<=int(state)<=1 else 0)
switch(ebene,state)
eState[ebene]=state
except:
pass
else:
pass
antwort="<tr>"
for i in range(6):
h="<td bgcolor={}><H3>E{} {}.</H3></td>".format(color[eState[i]],i, zustand[eState[i]])
antwort=antwort+h
antwort=antwort+"</tr>"
html1 = """<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<h2>Hallo, <br>ich bin dein Weihnachtsbäumchen</h2>"""
html2="""<table border=2 cellspacing=2>
"""
html3="""
<tr>
<td>
<a href='http://10.0.1.181:9002/?e=0&v=1'><H3>E0 An </H3> </a>
</td>
<td>
<a href='http://10.0.1.181:9002/?e=1&v=1'><H3>E1 An </H3> </a>
</td>
<td>
<a href='http://10.0.1.181:9002/?e=2&v=1'><H3>E2 An </H3> </a>
</td>
<td>
<a href='http://10.0.1.181:9002/?e=3&v=1'><H3>E3 An </H3> </a>
</td>
<td>
<a href='http://10.0.1.181:9002/?e=4&v=1'><H3>E4 An </H3> </a>
</td>
<td>
<a href='http://10.0.1.181:9002/?e=5&v=1'><H3>E5 An </H3> </a>
</td>
<td>
<a href='http://10.0.1.181:9002/?a'><H3>ALLE AN </H3> </a>
</td>
</tr>
<tr>
<td>
<a href='http://10.0.1.181:9002/?e=0&v=0'><H3>E0 Aus</H3> </a>
</td>
<td>
<a href='http://10.0.1.181:9002/?e=1&v=0'><H3>E1 Aus</H3> </a>
</td>
<td>
<a href='http://10.0.1.181:9002/?e=2&v=0'><H3>E2 Aus</H3> </a>
</td>
<td>
<a href='http://10.0.1.181:9002/?e=3&v=0'><H3>E3 Aus</H3> </a>
</td>
<td>
<a href='http://10.0.1.181:9002/?e=4&v=0'><H3>E4 Aus</H3> </a>
</td>
<td>
<a href='http://10.0.1.181:9002/?e=5&v=0'><H3>E5 Aus</H3> </a>
</td>
<td>
<a href='http://10.0.1.181:9002/?p'><H3>ALLE AUS</H3> </a>
</td>
</tr>
"""
html9 = "</table> </body> </html>"
html=html1+html2+antwort+html3+html9
return html
if taste.value()==0:
print("Mit Flashtaste abgebrochen")
ledsOff()
d.writeAt("Abbruch d. User ",0,5)
sys.exit()
# ********************************************************
# Netzwerk einrichten
# ********************************************************
# Eigener ACCESSPOINT
# ********************************************************
if ownAP and (not WLANconnect):
#
nic = network.WLAN(network.AP_IF)
nic.active(True)
ssid="christbaum"
passwd="don't_care"
# Start als Accesspoint
nic.ifconfig((myIP,"255.255.255.0",myIP,\
myIP))
print(nic.ifconfig())
# Authentifizierungsmodi ausser 0 werden nicht unterstuetzt
nic.config(authmode=0)
MAC=nic.config("mac") # liefert ein Bytes-Objekt
# umwandeln in zweistellige Hexzahlen
MAC=ubinascii.hexlify(MAC,"-").decode("utf-8")
print(MAC)
nic.config(essid=ssid, password=passwd)
while not nic.active():
print(".",end="")
sleep(0.5)
print("Unit1 listening")
# *************** Setup accesspoint end *****************
# ********************************************************
# WLAN-Connection
# ********************************************************
if WLANconnect and (not ownAP):
nic = network.WLAN(network.STA_IF) # erzeuge WiFi-Objekt
nic.active(True) # Objekt nic einschalten
#
MAC = nic.config('mac') # binaere MAC-Adresse abrufen +
myMac=hexMac(MAC) # in Hexziffernfolge umwandeln
print("STATION MAC: \t"+myMac+"\n") # ausgeben
# Verbindung mit AP im lokalen Netzwerk aufnehmen,
# falls noch nicht verbunden, dann
# connect to LAN-AP
if not nic.isconnected():
nic.connect(mySid, myPass)
# warten bis die Verbindung zum Accesspoint steht
print("connection status: ", nic.isconnected())
while not nic.isconnected():
blink(0.8,0.2,0)
print("{}.".format(nic.status()),end='')
sleep(1)
# zeige Verbindungsstatus & Config-Daten
print("\nconnected: ",nic.isconnected())
print("\nVerbindungsstatus: ",connectStatus[nic.status()])
print("Weise neue IP zu:",myIP)
nic.ifconfig((myIP,"255.255.255.0",myIP, \
myIP))
STAconf = nic.ifconfig()
print("STA-IP:\t\t",STAconf[0],"\nSTA-NETMASK:\t",\
STAconf[1],"\nSTA-GATEWAY:\t",STAconf[2] ,sep='')
# *********** Setup Router connection end ***************
# ********************************************************
# TCP-Web--Server
# ********************************************************
# ----------------- Server starten --------------------------
if WLANconnect or ownAP:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
s.bind(('', myPort))
print("Socket established, waiting on port",myPort)
d.clearAll()
# 0123456789012345
d.writeAt("SOCK ESTABLISHED",0,0)
d.writeAt("LISTENING AT",0,1)
d.writeAt(myIP+":"+str(myPort),0,2)
s.settimeout(0.9)
s.listen(2)
if taste.value()==0:
print("Mit Flashtaste abgebrochen")
ledsOff()
d.writeAt("Abbruch d. User ",0,5)
sys.exit()
# ------------------- Serverschleife ----------------------
while True:
try: # wegen timeout
r=""
if WLANconnect or ownAP:
c, addr = s.accept()
print('Got a connection from {}:{}\n'.\
format(addr[0],addr[1]))
request=c.recv(1024)
else:
request=input("Kommando:")
addr="999.999.999.999:99999"
try: # decodieren und parsen
r=request.decode("utf8")
getPos=r.find("GET /")
if r.find("favicon")==-1:
print("***********************************")
print("Position:",getPos)
print("Request:")
print(r)
print("***********************************")
pos=r.find(" HTTP")
if getPos == 0 and pos != -1:
query=r[5:pos] # nach ? bis HTTP
print("*********QUERY:{}*********\n\n".\
format(query))
response = web_page(query)
print("---------------\n",response,\
"\n----------------")
c.send('HTTP/1.1 200 OK\n'.encode())
c.send('Content-Type: text/html\n'.encode())
c.send('Connection: close\n\n'.encode())
c.sendall(response.encode())
else:
print("##########\nNOT HTTP\n###########")
c.send('HTTP/1.1 400 bad request\n'.encode())
else:
print("favicon request found")
c.send('HTTP/1.1 200 OK\n'.encode())
except: # decodieren und parsen
request = rawRequest
c.send('HTTP/1.1 200 OK\n'.encode())
c.close()
except: # wegen timeout
pass
if taste.value()==0:
print("Mit Flashtaste abgebrochen")
ledsOff()
d.writeAt("Abbruch d. User ",0,5)
sys.exit()
blink(0.05,0.05,1)
Figure 28 : En direct depuis le navigateur
Voici à quoi ressemble le site web en réalité sur Google Chrome. Opera offre une image similaire après avoir saisi l'URL 10.0.1.181:9002. Firefox fait des siennes parce que ses créateurs se sont mis en tête de devoir brider les utilisateurs en n'acceptant que les adresses https dans leur navigateur. Mais il existe des alternatives. Si les choses tournent mal, on pourrait même écrire son propre front-end pour le PC avec CPython.
Eh bien, je pense que vous avez suffisamment à faire jusqu'à Noël avec les projets de sapins. Il y en a certainement un ou deux pour chacun. L'important est que vous ayez du plaisir à les réaliser et que j'aie pu éveiller votre intérêt. Je vous souhaite en tout cas une bonne période de l'Avent.
Pour Arduino IDE
Télécharger webcontrol.ino
Die Oberfläche im Browser sieht hier etwas anders aus. Die Funktion ist dabei die gleiche.
Je nachdem, ob Sie einen eigenen Accesspoint, oder das heimische WLAN verwenden wollen, müssen Sie die jeweils nicht verwendete Option im Quellcode zu Beginn in den #defines auskommentieren.
// #define WLANconnect true
#define ownAP true
N'oubliez pas de saisir vos données d'accès si vous choisissez l'option WLAN.
Nous profitons de l'occasion pour vous souhaiter un joyeux 1er Avent.
6 commentaires
Jürgen
@ Niko Germer
Natürlich können Sie die Flacker-LEDs gegen normale Kandidaten austauschen. Aber Sie haben recht, für unterschiedliche Farben brauchen Sie unterschiedliche Widerstände. Das liegt einerseits an den unterschiedlichen Durchlassspannungen, rote LEDs haben eine niedrigere als blaue. Aber entscheidender ist die Helligkeit der LEDs. Geringe Helligkeit bei rot und gelb steht der blendenden Helligkeit der blauen und vor allem grünen LEDs gegenüber. Ich beziehe mich hier auf auf die LED aus dem LED Assortment Kit. Für die roten schlage ich 150 Ohm vor, blau 560 Ohm und grün 1,5kOhm für jeweils sechs parallele LEDs am Bäumchen. Die normalen LEDs lassen sich dann auch dimmen, wenn an die Basiswiderstände ein PWM-Signal gelegt wird. Der ESP32 kann das Signal an allen digitalen Ausgängen zur Verfügung stellen.
Niko Germer
Hallo,
ich würde das Bäumchen gerne mit normale LEDs bestücken. Kann man dann die LEDs dimmen? Was muss ich beachten, bei die Vorwiderstände? Bleiben die gleich?
Andreas Wolter
Die Aktion für das Bundle ist leider abgelaufen. Danke für den Hinweis. Den Link haben wir entfernt.
Michael Beckmann
Hallo
wenn man auf das Bild zur Teileliste klickt kommt ein HTTP 404 :-(
Miguel Torres
Un articulo muy bueno con muchos ejemplos con un elemento común.
bit.picker
Sehr schöner Artikel. Besonders interessant finde ich das Kapitel mit der Web-Steuerung. Dannke!