Salut M. Vincent Leboulou.
Ma question cerne les accès aux GPIO de la raspberry.
Y-a-t-il une différence d'approche, s'il s'agit de la RPi 1A, RPi 1B, RPi 2B, RPi 3A,RPi 3B, RPi 3B+, RPi 4B ?
Cordialement.
Artemus24.
@+
Faire clignoter une led !
Modérateur : Francois
Faire clignoter une led !
RPI4B/8GB + Argon FanHAt
Rpi3A+, Rpi3B+
RPi 2B + Joy-It I2C Serial 20x4 2004 LCD Module
RPi 2B + PIM273 Unicorn HAT HD 16x16 Leds RGB
RPi0v1.3, RPi0W + LibreElec/Kodi, Rpi0WH + Tuner TV HAT
NodeMCU ESP32
Rpi3A+, Rpi3B+
RPi 2B + Joy-It I2C Serial 20x4 2004 LCD Module
RPi 2B + PIM273 Unicorn HAT HD 16x16 Leds RGB
RPi0v1.3, RPi0W + LibreElec/Kodi, Rpi0WH + Tuner TV HAT
NodeMCU ESP32
-
- Messages : 35
- Enregistré le : jeu. 19 oct. 2017 10:11
Re: Faire clignoter une led !
re bonjour.
Au niveau de la programmation des fonctions du GPIO il n'y a pas de différence entre les modèles 1,2 et 3 , par contre l’adresse de base du GPIO est différente : 0x 3F003000 à la place de 0x20003000.
Pour rpi4, je l'ignore car je n'ai pas ce modèle !!
Je suis entrain de regarder la documentation du nouveau microcontroleur rpi pico car ne faisant pas appel à Linux, il doit être intéressant de programmer en assembleur surtout qu'il s'agit d'un processeur ARM 2 coeurs et donc beaucoup de concepts à découvrir.
Au niveau de la programmation des fonctions du GPIO il n'y a pas de différence entre les modèles 1,2 et 3 , par contre l’adresse de base du GPIO est différente : 0x 3F003000 à la place de 0x20003000.
Pour rpi4, je l'ignore car je n'ai pas ce modèle !!
Je suis entrain de regarder la documentation du nouveau microcontroleur rpi pico car ne faisant pas appel à Linux, il doit être intéressant de programmer en assembleur surtout qu'il s'agit d'un processeur ARM 2 coeurs et donc beaucoup de concepts à découvrir.
Re: Faire clignoter une led !
Salut M. Vincent Leboulou.
Grande question concernant les microcontrôleurs.
Je me suis dit qu'il serait intéressant d'utiliser des arduino.
Sauf qu'ils sont chers, et il y a tout un tas de HAT et autres composants à acheter pour réaliser un simple montage.
J'ai préféré me contenter de l'ESP32 qui répond plus à ma problématique, celle de la domotique.
Je ne vais pas me procurer, pour l'instant, un Raspberry Pico.
@+
Grande question concernant les microcontrôleurs.
Je me suis dit qu'il serait intéressant d'utiliser des arduino.
Sauf qu'ils sont chers, et il y a tout un tas de HAT et autres composants à acheter pour réaliser un simple montage.
J'ai préféré me contenter de l'ESP32 qui répond plus à ma problématique, celle de la domotique.
Je ne vais pas me procurer, pour l'instant, un Raspberry Pico.
Peux-tu préciser la raspberry qui est concerné par ce changement d'adresse ?VincentLeboulou a écrit :par contre l’adresse de base du GPIO est différente : 0x 3F003000 à la place de 0x20003000.
@+
RPI4B/8GB + Argon FanHAt
Rpi3A+, Rpi3B+
RPi 2B + Joy-It I2C Serial 20x4 2004 LCD Module
RPi 2B + PIM273 Unicorn HAT HD 16x16 Leds RGB
RPi0v1.3, RPi0W + LibreElec/Kodi, Rpi0WH + Tuner TV HAT
NodeMCU ESP32
Rpi3A+, Rpi3B+
RPi 2B + Joy-It I2C Serial 20x4 2004 LCD Module
RPi 2B + PIM273 Unicorn HAT HD 16x16 Leds RGB
RPi0v1.3, RPi0W + LibreElec/Kodi, Rpi0WH + Tuner TV HAT
NodeMCU ESP32
Re: Faire clignoter une led !
Salut à tous.
Je viens de terminer mon premier programme assembleur de type "Bare Metal".
J'ai fait mes tests sur la raspberry Pi Zero W.
En quoi consiste-t-il ? Rien de très extraordinaire, je fais clignoter deux leds :
--> celle que je dois installer sur une breadboard, reliée à la GPIO21 (Broche 40).
--> celle qui se nomme LED ACT, dont la couleur est verte, et qui indique l'activité de la raspberry. Elle se trouve sur la GPIO47.
Attention, ce programme ne fonctionne que sur la Raspberry Pi Zero W.
Quelques remarques avant de donner les sources :
1) voici ce dont j'ai besoin :
--> une nouvelle carte Micro SD genre celle de 4Go pour démarrer la RPi 2.
--> une raspberry Pi Zero W pour le test.
--> une breadboard.
--> des cavaliers mâle/femelle pour les jonctions.
--> une led rouge.
--> un transistor NPN.
--> une résistance de 1k ohms pour la led.
--> une résistance de 10k ohms pour le transistor.
--> prendre l'alimentation sur la Raspberry Pi Zero : GND (broche 6) et 3.3Vcc (broche 1).
--> branchement sur la GPIO 21 (broche 40).
Il n'est pas nécessaire d'utiliser un transistor.
2) dans le source assembleur, j'ai indiqué le type de processeur qui est utilisé :
--> Raspberry Pi Zero W : cortex-a7
--> Raspberry Pi 2B & 3B+ : cortex-a53
--> Raspberry Pi 4B : cortex-a72
Pour cela, il faut utiliser la pseudo instruction ".cpu" en début du programme.
3) Avant la partie "main", j'ai déclaré "bootstrap".
Cette partie sert à l'initialisation du processeur, ainsi que du programme avant son démarrage.
Dans cet exemple, j'initialise l'adresse de la pile (push & pop).
4) L'adresse de la base des GPIO est différente selon la version de la raspberry que vous utilisez.
--> RPi zero W : 0x20200000
--> RPi 2B & 3B+ : 0x3F200000
--> RPi 4B : 0xFE200000
C'est la même adresse pour les RPi 2B, 3A, 3B, 3A+ et 3B+.
5) il fait en premier sélectionner une GPIO.
Il y a cinquante-trois GPIO pour la Raspberry Pi Zero W.
Il faut trois bits pour sélectionner une GPIO.
Pour un registre de 32 bits, on ne peut gérer que 10 GPIO à la fois.
Soit au total six registres qui sont : GPSEL0, GPSEL1, GPSEL2, GPSEL3, GPSEL4 et GPSEL5.
Dans le bloc de trois bits, c'est le premier bit qui est positionné à 1 pour indiquer que la GPIO est en OUTPUT.
Voire la documentation sur le broadcom 2835.
6) Puis faire un ON ou un OFF de la GPIO.
Pour faire le ON, on sélectionne le registre GPSET et pour le OFF, on sélectionne le registre GPCLR.
Il faut seulement deux registres pour contenir nos cinquante-trois GPIO.
Le premier registre va gérer les 32 premiers GPIO, et le second, les 21 suivants.
Ils sont notés GPSET0 & GPSET1 pour le ON, et GPCLR0 & GPCLR1 pour le OFF.
7) à quoi correspond la LED ACT de couleur verte, selon le type de Raspberry utilisé ?
--> Pour la RPi A & B, c'est la GPIO16.
--> Pour la RPi A+ & B+, c'est la GPIO47.
--> Pour la RPi zero v1.3 & W, c'est aussi la GPIO47.
--> Pour la RPi 2B, c'est encore la GPIO47.
--> Pour la RPi 3B, ce n'est pas géré par les GPIO, mais par un extenseur du port I2C.
--> Pour la RPi 3A+ et 3B+, c'est la GPIO29.
Je n'ai testé que sur la Raspberry Pi zero W.
8) nous avons besoin d'un éditeur de liens pour créer le programme "Bare Metal".
Celui-ci va indiquer où mettre chaque section dans la mémoire.
Pour ce programme, j'utilise une section pour la pile (.stack) et une autre section pour le programme (.text).
En principe, j'ai aussi deux autres sections (.data & .bss) que je n'utilise pas ici.
9) j'ai aussi besoin du fichier makefile pour créer le fichier objet et l'exécutable.
Donc aupréalable, je dois installer l'outil pour faire l'assemblage en mode "Bare Metal" :
10) j'ai besoin de ces trois outils :
--> AS = @arm-none-eabi-as
--> LD = @arm-none-eabi-ld
--> CPY = @arm-none-eabi-objcopy
11) sur la carte micro SD, vous devez recopier aupréalable les fichiers suivants :
--> bootcode.bin
--> start.elf
--> fixup.dat
Pour la raspberry Pi 4B, vous devez mettre ceux-ci ;
--> bootcode.bin
--> start4.elf
--> fixup4.dat
Pour le fichier exécutable, il doit se nommer :
--> kernel.img
Pour la raspberry Pi 4B, en 32 bits, il doit se nommer :
--> kernel71.img
12) je me suis créé un script bash qui réaliser la création de la carte micro SD, celle que je vais introduire dans la raspberry pi zero W.
@+
Je viens de terminer mon premier programme assembleur de type "Bare Metal".
J'ai fait mes tests sur la raspberry Pi Zero W.
En quoi consiste-t-il ? Rien de très extraordinaire, je fais clignoter deux leds :
--> celle que je dois installer sur une breadboard, reliée à la GPIO21 (Broche 40).
--> celle qui se nomme LED ACT, dont la couleur est verte, et qui indique l'activité de la raspberry. Elle se trouve sur la GPIO47.
Attention, ce programme ne fonctionne que sur la Raspberry Pi Zero W.
Quelques remarques avant de donner les sources :
1) voici ce dont j'ai besoin :
--> une nouvelle carte Micro SD genre celle de 4Go pour démarrer la RPi 2.
--> une raspberry Pi Zero W pour le test.
--> une breadboard.
--> des cavaliers mâle/femelle pour les jonctions.
--> une led rouge.
--> un transistor NPN.
--> une résistance de 1k ohms pour la led.
--> une résistance de 10k ohms pour le transistor.
--> prendre l'alimentation sur la Raspberry Pi Zero : GND (broche 6) et 3.3Vcc (broche 1).
--> branchement sur la GPIO 21 (broche 40).
Il n'est pas nécessaire d'utiliser un transistor.
2) dans le source assembleur, j'ai indiqué le type de processeur qui est utilisé :
--> Raspberry Pi Zero W : cortex-a7
--> Raspberry Pi 2B & 3B+ : cortex-a53
--> Raspberry Pi 4B : cortex-a72
Pour cela, il faut utiliser la pseudo instruction ".cpu" en début du programme.
3) Avant la partie "main", j'ai déclaré "bootstrap".
Cette partie sert à l'initialisation du processeur, ainsi que du programme avant son démarrage.
Dans cet exemple, j'initialise l'adresse de la pile (push & pop).
4) L'adresse de la base des GPIO est différente selon la version de la raspberry que vous utilisez.
--> RPi zero W : 0x20200000
--> RPi 2B & 3B+ : 0x3F200000
--> RPi 4B : 0xFE200000
C'est la même adresse pour les RPi 2B, 3A, 3B, 3A+ et 3B+.
5) il fait en premier sélectionner une GPIO.
Il y a cinquante-trois GPIO pour la Raspberry Pi Zero W.
Il faut trois bits pour sélectionner une GPIO.
Pour un registre de 32 bits, on ne peut gérer que 10 GPIO à la fois.
Soit au total six registres qui sont : GPSEL0, GPSEL1, GPSEL2, GPSEL3, GPSEL4 et GPSEL5.
Dans le bloc de trois bits, c'est le premier bit qui est positionné à 1 pour indiquer que la GPIO est en OUTPUT.
Voire la documentation sur le broadcom 2835.
6) Puis faire un ON ou un OFF de la GPIO.
Pour faire le ON, on sélectionne le registre GPSET et pour le OFF, on sélectionne le registre GPCLR.
Il faut seulement deux registres pour contenir nos cinquante-trois GPIO.
Le premier registre va gérer les 32 premiers GPIO, et le second, les 21 suivants.
Ils sont notés GPSET0 & GPSET1 pour le ON, et GPCLR0 & GPCLR1 pour le OFF.
7) à quoi correspond la LED ACT de couleur verte, selon le type de Raspberry utilisé ?
--> Pour la RPi A & B, c'est la GPIO16.
--> Pour la RPi A+ & B+, c'est la GPIO47.
--> Pour la RPi zero v1.3 & W, c'est aussi la GPIO47.
--> Pour la RPi 2B, c'est encore la GPIO47.
--> Pour la RPi 3B, ce n'est pas géré par les GPIO, mais par un extenseur du port I2C.
--> Pour la RPi 3A+ et 3B+, c'est la GPIO29.
Je n'ai testé que sur la Raspberry Pi zero W.
8) nous avons besoin d'un éditeur de liens pour créer le programme "Bare Metal".
Celui-ci va indiquer où mettre chaque section dans la mémoire.
Pour ce programme, j'utilise une section pour la pile (.stack) et une autre section pour le programme (.text).
En principe, j'ai aussi deux autres sections (.data & .bss) que je n'utilise pas ici.
9) j'ai aussi besoin du fichier makefile pour créer le fichier objet et l'exécutable.
Donc aupréalable, je dois installer l'outil pour faire l'assemblage en mode "Bare Metal" :
Code : Tout sélectionner
sudo apt-get install gcc-arm-none-eabi
--> AS = @arm-none-eabi-as
--> LD = @arm-none-eabi-ld
--> CPY = @arm-none-eabi-objcopy
11) sur la carte micro SD, vous devez recopier aupréalable les fichiers suivants :
--> bootcode.bin
--> start.elf
--> fixup.dat
Pour la raspberry Pi 4B, vous devez mettre ceux-ci ;
--> bootcode.bin
--> start4.elf
--> fixup4.dat
Pour le fichier exécutable, il doit se nommer :
--> kernel.img
Pour la raspberry Pi 4B, en 32 bits, il doit se nommer :
--> kernel71.img
12) je me suis créé un script bash qui réaliser la création de la carte micro SD, celle que je vais introduire dans la raspberry pi zero W.
@+
Modifié en dernier par Artemus24 le mer. 3 févr. 2021 10:52, modifié 1 fois.
RPI4B/8GB + Argon FanHAt
Rpi3A+, Rpi3B+
RPi 2B + Joy-It I2C Serial 20x4 2004 LCD Module
RPi 2B + PIM273 Unicorn HAT HD 16x16 Leds RGB
RPi0v1.3, RPi0W + LibreElec/Kodi, Rpi0WH + Tuner TV HAT
NodeMCU ESP32
Rpi3A+, Rpi3B+
RPi 2B + Joy-It I2C Serial 20x4 2004 LCD Module
RPi 2B + PIM273 Unicorn HAT HD 16x16 Leds RGB
RPi0v1.3, RPi0W + LibreElec/Kodi, Rpi0WH + Tuner TV HAT
NodeMCU ESP32
Re: Faire clignoter une led !
Salut à tous.
Et voici les fichiers :
1) le source assembleur :
2) le fichier makefile :
3) voici le résultat après avoir fait "make" :
C'est le désassemblage du programme !
On ne dit pas déassemblage (il manque le s) mais bien désassemblage.
3) le fichier "linker.ld" :
4) le script bash qui va créer ma carte micro SD :
Il est bien plus simple de lancer ce script, que de le faire à chaque fois à la main.
Et c'est tout !
Dernière remarque concerant l'exécution du programme "Bare Metal".
Je n'ai pas compris pourquoi la rapidité du clignotement est plus lente avec les autres raspberry.
En fait, c'est la RPi Zero W qui est la plus rapide avec une vitesse du processeur qui est le plus lent.
J'espère que cela va servir à quelqu'un !
@+
Et voici les fichiers :
1) le source assembleur :
Code : Tout sélectionner
@ ======================================================== @
@ Blink a led in GPIO21 (PIN40) & Led Green ACT in GPIO 47 @
@ -------------------------------------------------------- @
@ Raspberry PI Zero / BCM2835 (Cortex-a7) @
@ ======================================================== @
.cpu cortex-a7 @ RPi zero W
@ ---------------- @
@ Storage Sections @
@ ---------------- @
.section .data
.section .bss
.section .stack
@ ----------@
@ BootStrap @
@ --------- @
.section .text
.global _start
_start: ldr r0,=_stack_end_
mov sp,r0 @ Address Stack Pointer
b main
.ltorg
@ ---- @
@ Main @
@ ---- @
main: ldr r0,=0x20200000 @ GPIO Base for RPi Zero W
mov r1,#1
lsl r1,#21 @ 7 x 3
str r1,[r0,#0x10] @ GPFSEL4 : GPIO 47
mov r1,#1
lsl r1,#3 @ 1 x 3
str r1,[r0,#0x08] @ GPFSEL2 : GPIO 21
mov r1,#1
lsl r1,#15 @ Offset 1 for GPIO 47 (47-32=15)
mov r2,#1
lsl r2,#21 @ Offset 0 for GPIO 21
loop: str r1,[r0,#0x2C] @ GPCLR1 : GPIO 47
str r2,[r0,#0x28] @ GPCLR0 : GPIO 21
bl delay @ To put on hold
str r1,[r0,#0x20] @ GPSET1 : GPIO 47
str r2,[r0,#0x1C] @ GPSET0 : GPIO 21
bl delay @ To put on hold
b loop @ Loop Infinity
.ltorg
@ ------------------ @
@ Subroutine : delay @
@ ------------------ @
delay: push {r0,lr}
ldr r0,=0x00280000 @ Counter
delay1: sub r0,r0,#1
cmp r0,#0
bgt delay1
pop {r0,lr}
bx lr
.ltorg
Code : Tout sélectionner
# ----------------------------- #
# Déclaration des Commandes #
# ----------------------------- #
RM = @rm -rf
CPY = @arm-none-eabi-objcopy
LD = @arm-none-eabi-ld
AS = @arm-none-eabi-as
EX = @chmod +x
# -------------------------- #
# Déclaration des Objets #
# -------------------------- #
SRC = main.asm
OBJ = main.o
ELF = kernel.elf
BIN = kernel.img
LNK = linker.ld
# ------------------------------------ #
# Compilation et Edition des liens #
# ------------------------------------ #
all: clean $(BIN) after
.PHONY: clean
clean:
clear
$(RM) $(OBJ)
$(RM) $(ELF)
$(RM) $(BIN)
$(BIN): $(ELF)
$(CPY) $(ELF) -O binary $(BIN)
$(ELF): $(OBJ)
$(LD) $(OBJ) -T $(LNK) -o $(ELF)
$(OBJ): $(SRC)
$(AS) $(SRC) -o $(OBJ)
after:
$(RM) $(OBJ)
$(EX) $(BIN)
objdump -d $(ELF)
$(RM) $(ELF)
Code : Tout sélectionner
objdump -d kernel.elf
kernel.elf: format de fichier elf32-littlearm
Déassemblage de la section .text :
00000100 <_start>:
100: e59f0004 ldr r0, [pc, #4] ; 10c <_stack_end_+0xc>
104: e1a0d000 mov sp, r0
108: ea000000 b 110 <main>
10c: 00000100 .word 0x00000100
00000110 <main>:
110: e59f0040 ldr r0, [pc, #64] ; 158 <loop+0x1c>
114: e3a01001 mov r1, #1
118: e1a01a81 lsl r1, r1, #21
11c: e5801010 str r1, [r0, #16]
120: e3a01001 mov r1, #1
124: e1a01181 lsl r1, r1, #3
128: e5801008 str r1, [r0, #8]
12c: e3a01001 mov r1, #1
130: e1a01781 lsl r1, r1, #15
134: e3a02001 mov r2, #1
138: e1a02a82 lsl r2, r2, #21
0000013c <loop>:
13c: e580102c str r1, [r0, #44] ; 0x2c
140: e5802028 str r2, [r0, #40] ; 0x28
144: eb000004 bl 15c <delay>
148: e5801020 str r1, [r0, #32]
14c: e580201c str r2, [r0, #28]
150: eb000001 bl 15c <delay>
154: eafffff8 b 13c <loop>
158: 20200000 .word 0x20200000
0000015c <delay>:
15c: e92d4001 push {r0, lr}
160: e3a0070a mov r0, #2621440 ; 0x280000
00000164 <delay1>:
164: e2400001 sub r0, r0, #1
168: e3500000 cmp r0, #0
16c: cafffffc bgt 164 <delay1>
170: e8bd4001 pop {r0, lr}
174: e12fff1e bx lr
>
On ne dit pas déassemblage (il manque le s) mais bien désassemblage.
3) le fichier "linker.ld" :
Code : Tout sélectionner
ENTRY(_start)
MEMORY
{
/* mem1 (rwx) : ORIGIN = 0x0000, LENGTH = 0x0100 */
mem2 (rwx) : ORIGIN = 0x0000, LENGTH = 0x0100
mem3 (rx) : ORIGIN = 0x0100, LENGTH = 0x0100
}
SECTIONS
{
/* .data : { *(.data) } > mem1
.bss : { *(.bss) } > mem1 */
.stack : { _stack_start_ = .;
. += 0x0100;
_stack_end_ = .; } > mem2
.text : { *(.text) *(.rodata) } > mem3
}
Code : Tout sélectionner
#!/bin/bash
UUID="2D91-464A"
clear
echo -e "\t\t*==============================*"
echo -e "\t\t* *"
echo -e "\t\t* Recopie \"Kernel.img\" *"
echo -e "\t\t* *"
echo -e "\t\t*==============================*\n"
echo -e "\t\tUUID\t\t: $UUID\n"
# ======================================== #
# Vérification l'existence de la partition #
# ======================================== #
if [ -L "/dev/disk/by-uuid/$UUID" ]
then
DEVICE="$(blkid -U $UUID)"
DIRECTORY="$(lsblk -n -o MOUNTPOINT $DEVICE)"
echo -e "\t\tRépertoire\t: $DIRECTORY"
echo -e "\t\tPériphérique\t: $DEVICE\n"
if [ "$DIRECTORY" == "/mnt/boot" ]
then
echo -e "\t\t\e[31mPartition déjà montée\e[0m\n"
else
if [ "$DIRECTORY" != "" ]
then
echo -e "\t\t\e[32mPartition a démonter !\e[0m"
umount $DEVICE
if [[ $? == 0 ]]
then
echo -e "\t\t\e[32mPartition démontée\e[0m"
else
echo -e "\t\t\e[31mPartition non démontée\e[0m\n"
exit 3
fi
fi
mount -t vfat $DEVICE /mnt/boot
if [[ $? == 0 ]]
then
echo -e "\t\t\e[32mPartition a été montée\e[0m\n"
else
echo -e "\t\t\e[31mPartition non montée\e[0m\n"
exit 2
fi
# =========================== #
# Recopie des fichiers Kernel #
# =========================== #
cd /mnt/boot
rm -r *
cp /boot/bootcode.bin .
cp /boot/start.elf .
cp /boot/start4.elf .
cp /boot/fixup.dat .
cp /boot/fixup4.dat .
cp /warehouse/Prog_Asm/04.Bare_Metal/kernel.img .
cp /warehouse/Prog_Asm/04.Bare_Metal/kernel.img kernel71.img
sync
cd
echo -e "\t\t\e[32mCopie effectuée !\e[0m\n"
fi
# ========================= #
# Démontage de la partition #
# ========================= #
echo -e "\t\t\e[32mPartition démontée\e[0m\n"
umount $DEVICE
else
echo -e "\t\t\e[32mLa carte Micro SD \"$UUID\" (carte N°3) n'est pas installée !\e[0m\n"
exit 1
fi
exit 0
Et c'est tout !
Dernière remarque concerant l'exécution du programme "Bare Metal".
Je n'ai pas compris pourquoi la rapidité du clignotement est plus lente avec les autres raspberry.
En fait, c'est la RPi Zero W qui est la plus rapide avec une vitesse du processeur qui est le plus lent.
J'espère que cela va servir à quelqu'un !
@+
RPI4B/8GB + Argon FanHAt
Rpi3A+, Rpi3B+
RPi 2B + Joy-It I2C Serial 20x4 2004 LCD Module
RPi 2B + PIM273 Unicorn HAT HD 16x16 Leds RGB
RPi0v1.3, RPi0W + LibreElec/Kodi, Rpi0WH + Tuner TV HAT
NodeMCU ESP32
Rpi3A+, Rpi3B+
RPi 2B + Joy-It I2C Serial 20x4 2004 LCD Module
RPi 2B + PIM273 Unicorn HAT HD 16x16 Leds RGB
RPi0v1.3, RPi0W + LibreElec/Kodi, Rpi0WH + Tuner TV HAT
NodeMCU ESP32