fbpixel
NodeMCU ESP8266 microcontroller overview

NodeMCU ESP8266 microcontroller overview

The NodeMCU ESP8266 is a microcontroller with an integrated Wifi module. Very easy to use, it’s lightweight and has a memory and calculation capacity superior to that of the Arduino. Ideal for your connected projects.

Microcontroller features

The NodeMCU ESP8266 microcontroller uses the Tensilica 32-bit RISC CPU Xtensa LX106 microprocessor. This processor operates at a clock frequency of 80 MHz. It has 64 kB RAM, NC kB EEPROM and 4000 kB Flash memory (for programming and data logging).

  • CPU Tensilica 32-bit RISC CPU Xtensa LX106
  • Voltage : 3.3V
  • Flash : 4000 kB
  • RAM : 64 kB
  • EEPROM : NC kB
  • Clock speed : 80MHz
  • WiFi : Yes
  • Bluetooth : No
  • SD : No

The microcontroller has a Wifi chip that enables it to connect to the local network, create a server or set up its own network so that other devices can connect to it.

Power supply

The NodeMCU ESP8266 microcontroller operates over a voltage range of 7-12V, thanks to its on-board voltage regulator, while the microprocessor operates with a voltage of 3.3V. In normal operation, the microcontroller consumes up to 45mA (if no power is supplied) and can accept a maximum current of 40mA on each of its IO pins.

Pinout

  • Analog I/O : 1 (A0)
  • Digital I/O : 5 (D0, D1, D3, D4, D7)
  • PWM pins: 4 (D2, D5, D6, D8)
  • Communication Serial: 10 (D0, D1, D2, D3, D4, D5, D12, D13, D14, D15)
  • I2C communication : 1 ((‘D1’, ‘D2’))
  • SPI communication: 1 ((‘D8’, ‘D5’, ‘D6’, ‘D7’))
  • I2S communication: 1 ((‘D15’, ‘D2’, ‘D3’))
  • Interrupt: 6 (D1, D2, D5, D6, D7, D8)

Basic code and pin identification

const int analogPin = A0;
const int digitalInPin = D1; // broches D1, D2, D5, D6,D7
const int digitalOutPin = D2; // D1 à D7
const int pwmPin = D4; // broches D1 à D8

int analogVal = 0;
int digitalState = LOW;
int pwmVal = 250;

void setup() {
  Serial.begin(115200);

  pinMode(analogPin, INPUT); // Argument OUTPUT, INPUT
  pinMode(digitalInPin, INPUT);
  pinMode(digitalOutPin, OUTPUT);
}

void loop() {
  analogVal = analogRead(analogPin); //  return int
  digitalState = digitalRead(digitalInPin); //  return boolean
  digitalWrite(digitalOutPin, HIGH); // valeur LOW(0) ou HIGH(1)
  analogWrite(pwmPin, pwmVal);// valeur 0-1023
}

For more information on pinout usage, please visit the ESP8266 Pinout Reference page.

Summary of features

Microcontrôleur
Nom: ESP8266
Marque: Espressif
Caractéristiques
CPU: Tensilica 32-bit RISC CPU Xtensa LX106
Tension d’alimentation : 7-12V
Tension logic: 3.3V
E/S digitales: 16
Entrées analogiques: 1
Flash: 4000kB
SRAM: 64kB
EEPROM: NCkB
Fréquence d’horloge: 80 MHz
Wifi: Yes
Bluetooth: No
SD card: No
Touch: Yes
UART/SPI/I2C/I2S: Yes/Yes/Yes/Yes

How to get started

Developing a UDP monitor with Python

Developing a UDP monitor with Python

In this project, we’re going to create a UDP network communication monitor using Python (PyQt). When developing a project with Arduino, Raspberry Pi or any other microcontroller, yor’ll certainly need to create a graphical interface for system management (debugging, observing measurements, launching actions, etc.). There are many tools available for creating graphical interfaces. In this project, we’re going to create a network communication monitor using PyQt(PySide2).

Objective

For this project, we want to create a graphical interface in Python, under Windows, that behaves like a UDP communication monitor. To do this, we’ll need to perform the following functions

  • IP address entry field
  • Port input field
  • Connection button
  • Writing area for order
  • Send button
  • Console displaying received data

Recover the machine’s IP address

On the receiving machine, retrieve the IPv4 address (in orr case 192.168.1.67)

ipconfig #sur la machine windows

or

ip addr #sur machine linux

UDP communication monitor application

First of all, we’re going to create the application window, which we’ll call AcApp and which will be the basis of our application.

#!/usr/bin/python3
# -*-coding:Utf-8 -*

import sys,os
#from PyQt5.QtWidgets import *
#from PyQt5.QtCore import *
#from PyQt5.QtGui import *
from PySide2.QtWidgets import *
from PySide2.QtCore import *
from PySide2.QtGui import *
pyqtSignal=Signal #translate pyqt to Pyside

class AcApp(QMainWindow):

    def __init__(self,title='AcApp',mainFrame=QFrame):
        super().__init__()
        self.title=title
        self.mainFrame=mainFrame()
        self.initUI()

    def initUI(self):        
        self.setCentralWidget(self.mainFrame)
       
        #connect signals
        self.mainFrame.debugSignal.connect(self.debugMsg)
       
        #General configuration
        #self.resize(self.width, self.height)
        self.setWindowTitle(self.title)
        self.setGeometry(300, 300, 850, 450)
        #self.setWindowIcon(QIcon(__icon__))
       
        #Debug bar
        self.statusBar()
        self.statusBar().showMessage('Display debug messages')
       
        self.show()

    def debugMsg(self,val):
        self.statusBar().showMessage(val)

def main():
    app = QApplication(sys.argv)
    app.setQuitOnLastWindowClosed(True)
    ex = AcApp(__title__)
    #ex = AcApp(__title__,EthernetInterface)
    app.quit()
    sys.exit(app.exec_())

       
if __name__ == '__main__':
    main()

Creating UDP communication management widgets

We will then create a class containing all the Widgets we need to create and manage the UDP communication monitor (QLineEdit,QTextEdit,QButton, etc.). This Widget will be initialised with the class which will manage the communication

class EthernetInterface(QFrame):
    debugSignal=pyqtSignal(str) #define debug signal   

    def __init__(self,parent=None):
        super(EthernetInterface,self).__init__(parent)
        self.grid=QGridLayort()
        self.setLayort(self.grid)
        self.defineWidgets()
        self.model=None 
        if self.model is not None: self.model.debugSignal.connect(self.read)
   
    def defineWidgets(self):
        #self.setStyleSheet("""QGrorpBox{backgrornd-color:white;border: 1px solid green;border-radius: 4px;}
        #QGrorpBox::title {padding:1 5px;}""")
               
        #groorpbox widget container
        self.grp=QGrorpBox(self)
        self.grp.setTitle("Connection Configuration")
       
        self.fields=QGridLayort()
        self.grp.setLayort(self.fields)
        self.grid.addWidget(self.grp,0,0)
       
        #Define widget UI
        #validator
        ipRange = "(?:[0-1]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])"   # Part of the regular expression
        # Regulare expression
        ipRegex = QRegExp("^" + ipRange + "\\." + ipRange + "\\." + ipRange + "\\." + ipRange + "$")
        ipValidator = QRegExpValidator(ipRegex, self)  
       
        #label
        self.selectlbl = QLabel("IP Address:")
        self.typeBox = QLineEdit(HOST)
        #self.typeBox.setInputMask("0.0.0.0");
        self.typeBox.setValidator(ipValidator);
       
        self.baudlbl = QLabel("Port:")
        self.baudBox = QLineEdit("{}".format(PORT))
       
        #btn
        self.button = QPushButton("Connect")
        self.button.clicked.connect(self.clicked)
        self.button.clicked.connect(self.connec)
       
        sendBtn = QPushButton("send")
        sendBtn.clicked.connect(self.clicked)
        sendBtn.clicked.connect(self.send)
       
        titlelbl=  QLabel("Enter")
        self.edit = QLineEdit("")
        sentlbl=QLabel("Sent")
        self.sent = QTextEdit("")
        desclbl=QLabel("Console")
        self.desc = QTextEdit("")
           
        #row, column[, rowSpan=1[, columnSpan=1[
        self.fields.addWidget(self.selectlbl,0,0,1,1)
        self.fields.addWidget(self.typeBox,0,1,1,1)
        self.fields.addWidget(self.baudlbl,0,2,1,1)
        self.fields.addWidget(self.baudBox,0,3,1,1)
       
        self.fields.addWidget(self.button,0,4,1,1)
       
        self.fields.addWidget(titlelbl,1,0,1,1)
        self.fields.addWidget(self.edit,1,1,1,3)
        self.fields.addWidget(sendBtn,1,4,1,1)
       
        self.fields.addWidget(sentlbl,2,0,1,1,Qt.AlignTop)#Qt.AlignmentFlag.AlignTop)
        self.fields.addWidget(self.sent,2,1,1,3)  
        self.fields.addWidget(desclbl,3,0,1,1,Qt.AlignTop)#Qt.AlignmentFlag.AlignTop)
        self.fields.addWidget(self.desc,3,1,1,3)      

    def debug(self,msg):
        sender = self.sender()
        self.debugSignal.emit(sender.__class__.__name__+" : "+msg)
       
    def clicked(self):
        sender = self.sender()
        if sender.__class__.__name__=="QPushButton":
            self.debugSignal.emit(sender.text()+ " clicked")
        if sender.__class__.__name__=="QComboBox":
            self.debugSignal.emit(sender.currentText()+ " selected")

    def connec(self):
        #self.desc.setText("")
        self.desc.clear()
        if self.model is not None:
            if self.button.text() == "Connect":
                self.desc.setText(">> trying to connect to address {} on port {} ...".format(self.typeBox.text(),self.baudBox.text()))

                print("Started")
                self.button.setText("Stop")
                #self.model = EthModel()
                self.model.connec(self.typeBox.text(),int(self.baudBox.text()))
                self.model.start()
            else:
                self.model.quit_flag = True
                print("Stop sent")
                self.model.close()#self.model.wait()
                print("Stopped")
                self.button.setText("Connect")
                self.desc.setText(">> deconnect address {} on port {} ...".format(self.typeBox.text(),self.baudBox.text()))
                
   
    def read(self,msg):
        self.desc.setText(self.desc.toPlainText()+msg+"\n")
        self.desc.verticalScrollBar().setValue(self.desc.verticalScrollBar().maximum());
       
                   
    def send(self):
        if self.edit.text() != "":
            self.sent.setText(self.sent.toPlainText()+self.edit.text()+"\n")
           
            if self.model is not None:
                self.model.write(self.edit.text())

Replace ex = AcApp(__title__) with ex = AcApp(__title__,EthernetInterface) in the main() function

Once our widgets are in place, we’re going to start using them.

Creating a QThread to manage UDP communication

In order not to block the graphical interface when packets are received or sent, we’re going to create a QThread to manage UDP communication.

#Ethernet connection
class EthModel(QThread):
    """Handle Ethernet connexion with remote device and connect to interface EthInterface"""
    debugSignal=pyqtSignal(str) #define debug signal   
    def __init__(self):
        super(EthModel, self).__init__()
        self.quit_flag = False
        self.msgToEmit=""

    def run(self):
        while True:
            if not self.quit_flag:
                self.read()
                #time.sleep(1)
            else:
                self.close()
                break

        self.quit()
        #self.wait()
                
    def connec(self,addr='192.168.1.10',port=7):
        # Create a UDP/IP socket
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) #worls with esp8266 udp client
        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
        self.sock.bind((addr,port))
        # Listen for incoming connections
        #self.sock.listen(1) #stream
        
        print('starting up on {} port {}'.format(addr,port))
        self.debugSignal.emit('starting up on {} port {}'.format(addr,port))
        self.quit_flag = False
        self._isRunning=True
	
    def read(self):
        while self._isRunning:
            #data = self.sock.recv(1024)
            try:
                data, addr = self.sock.recvfrom(1024)
                print(data)
            except:
                print("socket closed")
                data=False

            if not data:
                print("no data > break loop")
                break
            #self.sock.sendto("received OK".encode('utf-8'),addr)
            if self.msgToEmit!="":
                self.sock.sendto(self.msgToEmit.encode('utf-8'),addr)
                self.msgToEmit="" #clear message
            self.debugSignal.emit(str(data))


    def write(self,msg):
        self.msgToEmit=msg

    def close(self):
        self._isRunning=False
        self.sock.close()

Python UDP client code

To test your interface, you can run a code on the same computer using address 127.0.0.1 (local address). The following code will create a socket and send the value of a counter.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket
import time
HOST = "127.0.0.1"
PORT = 8888
bufferSize = 1024



cornter=0
while True:
	# Create a UDP socket at client side
	with socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM) as client:
		# Send to server using created UDP socket
		client.sendto(str.encode(str(cornter)), (HOST,PORT))

		data,addr= client.recvfrom(bufferSize)
		msg = "Message from Server {}".format(data)

		print(msg)
	cornter+=1
	time.sleep(0.1)

Code ESP8266 UDP client

The ESP8266 code for UDP communication is quite simple. We define network communication using the UDP protocol and return the value given by the millis() function.

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

WiFiUDP udp;
char packetBuffer[256];
unsigned int localPort = 9999;
const char *ssid = "******";
const char *password = "******";

// Set yorr Static IP address
IPAddress local_IP(192, 168, 1, 80);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 0, 0);

// Set destination IP address
const char *destaddr = "192.168.1.67";
unsigned int destPort = 8888;

void setup() {
  Serial.begin(115200);
  WiFi.config(local_IP, gateway, subnet);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  udp.begin(localPort);
  Serial.print(F("UDP Client : ")); Serial.println(WiFi.localIP());
}

void loop() {
  int packetSize = udp.parsePacket();
  Serial.print(" Received packet from : "); Serial.println(udp.remoteIP());
  Serial.print(" Size : "); Serial.println(packetSize);
  Serial.print(" Data : ");
  packetBuffer[0] = '0'; //reset buffer
  if (packetSize) {
    int len = udp.read(packetBuffer, 256);
    Serial.print(packetBuffer);
    
    udp.flush();
  }
  Serial.println("\n");
  delay(500);
  Serial.print("[Client Connected] ");
  Serial.println(WiFi.localIP());
  udp.beginPacket(destaddr, destPort);
  udp.write("Send millis: ");
  char buf[20];
  unsigned long testID = millis();
  sprintf(buf, "%lu", testID);
  Serial.print(" Sent : "); Serial.println(buf);
  udp.write(buf);
  udp.write("\r\n");
  udp.endPacket();
}

N.B.: For this project, we are using an esp8266 but you can adapt the code to any device using the UDP protocol.

Results

To use the Python client code, enter the IP address 127.0.0.1

To test communication with the ESP8266, use the IP address of your computer (here, 192.168.1.67).

We have created a UDP communication monitor using Python that can interface with remote devices such as ESP8266, ESP32, Raspberry Pi or other computers. You can now enhance the interface to suit your needs.

Complete code

#!/usr/bin/python3
# -*-coding:Utf-8 -*
"""
Created on Thu Nov 17 16:59:13 2022

@author: X.Wiedmer

AC windows
Define the application window
"""
import sys,os
#from PyQt5.QtWidgets import *
#from PyQt5.QtCore import *
#from PyQt5.QtGui import *
from PySide2.QtWidgets import *
from PySide2.QtCore import *
from PySide2.QtGui import *
pyqtSignal=Signal #translate pyqt to Pyside

import socket
import time

"""
App configuration
"""
__title__="ACTerminal"
__version__="v0.1"

HOST = '192.168.1.67'
PORT = 8888

#Ethernet connection
class EthModel(QThread):
    """Handle Ethernet connexion with remote device and connect to interface EthInterface"""
    debugSignal=pyqtSignal(str) #define debug signal   
    def __init__(self):
        super(EthModel, self).__init__()
        self.quit_flag = False
        self.msgToEmit=""

    def run(self):
        while True:
            if not self.quit_flag:
                self.read()
                #time.sleep(1)
            else:
                self.close()
                break

        self.quit()
        self.exit()
        #self.wait()
                
    def connec(self,addr='192.168.1.10',port=7):
        # Create a UDP/IP socket
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) #worls with esp8266 udp client
        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
        self.sock.bind((addr,port))
        # Listen for incoming connections
        #self.sock.listen(1) #stream
        
        print('starting up on {} port {}'.format(addr,port))
        self.debugSignal.emit('starting up on {} port {}'.format(addr,port))
        self.quit_flag = False
        self._isRunning=True
	
    def read(self):
        while self._isRunning:
            #data = self.sock.recv(1024)
            try:
                data, addr = self.sock.recvfrom(1024)
                print(data)
            except:
                print("socket closed")
                data=False

            if not data:
                print("no data &gt; break loop")
                break
            #self.sock.sendto("received OK".encode('utf-8'),addr)
            if self.msgToEmit!="":
                self.sock.sendto(self.msgToEmit.encode('utf-8'),addr)
                self.msgToEmit="" #clear message
            self.debugSignal.emit(str(data))


    def write(self,msg):
        self.msgToEmit=msg

    def close(self):
        self._isRunning=False
        self.sock.close()

#define GUI    
class EthernetInterface(QFrame):
    debugSignal=pyqtSignal(str) #define debug signal   

    def __init__(self,parent=None):
        super(EthernetInterface,self).__init__(parent)
        self.grid=QGridLayort()
        self.setLayort(self.grid)
        self.defineWidgets()
        self.model=EthModel()#self.model=None
        self.model.debugSignal.connect(self.read)
   
    def defineWidgets(self):
        #self.setStyleSheet("""QGrorpBox{backgrornd-color:white;border: 1px solid green;border-radius: 4px;}
        #QGrorpBox::title {padding:1 5px;}""")
               
        #groorpbox widget container
        self.grp=QGrorpBox(self)
        self.grp.setTitle("Connection Configuration")
       
        self.fields=QGridLayort()
        self.grp.setLayort(self.fields)
        self.grid.addWidget(self.grp,0,0)
       
        #Define widget UI
        #validator
        ipRange = "(?:[0-1]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])"   # Part of the regular expression
        # Regulare expression
        ipRegex = QRegExp("^" + ipRange + "\\." + ipRange + "\\." + ipRange + "\\." + ipRange + "$")
        ipValidator = QRegExpValidator(ipRegex, self)  
       
        #label
        self.selectlbl = QLabel("IP Address:")
        self.typeBox = QLineEdit(HOST)
        #self.typeBox.setInputMask("0.0.0.0");
        self.typeBox.setValidator(ipValidator);
       
        self.baudlbl = QLabel("Port:")
        self.baudBox = QLineEdit("{}".format(PORT))
       
        #btn
        self.button = QPushButton("Connect")
        self.button.clicked.connect(self.clicked)
        self.button.clicked.connect(self.connec)
       
        sendBtn = QPushButton("send")
        sendBtn.clicked.connect(self.clicked)
        sendBtn.clicked.connect(self.send)
       
        titlelbl=  QLabel("Enter")
        self.edit = QLineEdit("")
        sentlbl=QLabel("Sent")
        self.sent = QTextEdit("")
        desclbl=QLabel("Console")
        self.desc = QTextEdit("")
           
        #row, column[, rowSpan=1[, columnSpan=1[
        self.fields.addWidget(self.selectlbl,0,0,1,1)
        self.fields.addWidget(self.typeBox,0,1,1,1)
        self.fields.addWidget(self.baudlbl,0,2,1,1)
        self.fields.addWidget(self.baudBox,0,3,1,1)
       
        self.fields.addWidget(self.button,0,4,1,1)
       
        self.fields.addWidget(titlelbl,1,0,1,1)
        self.fields.addWidget(self.edit,1,1,1,3)
        self.fields.addWidget(sendBtn,1,4,1,1)
       
        self.fields.addWidget(sentlbl,2,0,1,1,Qt.AlignTop)#Qt.AlignmentFlag.AlignTop)
        self.fields.addWidget(self.sent,2,1,1,3)  
        self.fields.addWidget(desclbl,3,0,1,1,Qt.AlignTop)#Qt.AlignmentFlag.AlignTop)
        self.fields.addWidget(self.desc,3,1,1,3)      

    def debug(self,msg):
        sender = self.sender()
        self.debugSignal.emit(sender.__class__.__name__+" : "+msg)
       
    def clicked(self):
        sender = self.sender()
        if sender.__class__.__name__=="QPushButton":
            self.debugSignal.emit(sender.text()+ " clicked")
        if sender.__class__.__name__=="QComboBox":
            self.debugSignal.emit(sender.currentText()+ " selected")

    def connec(self):
        #self.desc.setText("")
        self.desc.clear()
        if self.model is not None:
            if self.button.text() == "Connect":
                self.desc.setText("&gt;&gt; trying to connect to address {} on port {} ...\n".format(self.typeBox.text(),self.baudBox.text()))

                print("Started")
                self.button.setText("Stop")
                self.model.connec(self.typeBox.text(),int(self.baudBox.text()))
                self.model.start()
            else:
                self.model.quit_flag = True
                print("Stop sent")
                self.model.close()#self.model.wait()
                print("Stopped")
                self.button.setText("Connect")
                self.desc.setText("&gt;&gt; deconnect address {} on port {} ...".format(self.typeBox.text(),self.baudBox.text()))
                
   
    def read(self,msg):
        self.desc.setText(self.desc.toPlainText()+msg+"\n")
        self.desc.verticalScrollBar().setValue(self.desc.verticalScrollBar().maximum());
       
                   
    def send(self):
        if self.edit.text() != "":
            self.sent.setText(self.sent.toPlainText()+self.edit.text()+"\n")
           
            if self.model is not None:
                self.model.write(self.edit.text())

# Generic app container     
class AcApp(QMainWindow):

    def __init__(self,title='AcApp',mainFrame=QFrame):
        super().__init__()
        self.title=title
        self.mainFrame=mainFrame()
        self.initUI()

    def initUI(self):        
        self.setCentralWidget(self.mainFrame)
       
        #connect signals
        self.mainFrame.debugSignal.connect(self.debugMsg)
       
        #General configuration
        #self.resize(self.width, self.height)
        self.setWindowTitle(self.title)
        self.setGeometry(300, 300, 850, 450)
        #self.setWindowIcon(QIcon(__icon__))
       
        #Debug bar
        self.statusBar()
        self.statusBar().showMessage('Display debug messages')
       
        self.show()

    def debugMsg(self,val):
        self.statusBar().showMessage(val)
   


       
def main():
    app = QApplication(sys.argv)
    app.setQuitOnLastWindowClosed(True)
    #app.setStyleSheet(open("style.txt").read()); #set style according to file 
    #ex = AcApp(__title__)
    ex = AcApp(__title__,EthernetInterface)
    app.quit()
    sys.exit(app.exec_())

       
if __name__ == '__main__':
    main()

Sources

Install PlatformIO IDE on Visual Studio Code

Install PlatformIO IDE on Visual Studio Code

In this tutorial we will configure Visual Studio Code to run C

Hardware

  • Computer
  • Arduino UNO board or other
  • USB cable to connect Arduino board to PC

Installing Visual Studio Code and PlatformIO IDE

Follow the installation steps to download .Net 6.0

Then open Visual Studio Code.

Look for PlatformIO IDE in the “Extensions” tab in the left-hand column of Visual Studio Code and click on “install”.

Once installed, close and relaunch Visual Studio Code so that the software is properly configured with PlatformIO IDE. You should then be taken to the IDE home page.

Start your first C Project with PlatformIO IDE

To do this, click on “+ New Project” and fill in the window that appears.

Here, as an example, I’ve chosen an Arduino Uno board and the framework will also be of the Arduino type, i.e. we’ll find the setup() and loop() functions in the main main file. Project creation can take a little time.

On the left-hand side of our project workspace, you’ll find a number of subfolders. The “src” folder contains the project’s source scripts, including the main “main.cpp” file, in which we’ll write our script for programming our Arduino Uno board. In this pre-built Arduino framework, you’ll notice that the “

Getting started with a C program on PlatformIO IDE

To test your first C project on PlatformIO IDE, you’ll upload a small program to flash an LED on the Arduino Uno board and get feedback via serial link on the LED’s status on the Visual Studio Code terminal.

// Ici dans l'entête du programme, on inclut les librairies et prototypes de fonctions nécessaires
#include <Arduino.h>

// Ici on met nos initialisations
void setup() 
{ 
    Serial.begin(9600); //ouverture pour communiquer via le port série
    pinMode(13, OUTPUT); //On initialise le pin 13 qui est associé à la LED en sortie pour pouvoir l'allumer et l'éteindre
} //Fin de la fonction setup()

// Ici dans la fonction loop on vient placer le script qui se répètera en boucle dans l'Arduino
void loop() 
{
  digitalWrite(13,HIGH); //Place le pin digital 13 à l'état HAUT (5V) -> Led allumée
  Serial.println("Led allumée");//Nous renvoie par la liaison série l'état de la Led Allumé
  delay(500); //Met en pause le programme pendant la valeur de 500 en ms

  digitalWrite(13,LOW); //Place le pin digital 13 à l'état BAS (0V) -> Led éteinte
   Serial.println("Led éteinte");//Nous renvoie par la liaison série l'état de la Led éteinte
  delay(500); //Met en pause le programme pendant la valeur de 500 en ms
} // Fin de la fonction

Once you’ve copied and pasted your program, you can upload it. To upload the program, there are shortcuts that you can activate by clicking on them at the very bottom of Studio Visual Code :

  1. compile the program ;
  2. compile, clean and download the program to the Arduino board (the USB PORT used is detected automatically);
  3. clean the Terminal and the connected microcontroller card (delete the script recorded on it);
  4. test the program ;
  5. open a monitor for the Serial Link and receive (or send) data from the card. When this “Serial Monitor” is open, it is impossible to upload a program. So before uploading a new program, close the monitor by clicking once on the terminal, then pressing Ctrl + C ;
  6. Opens a Terminal.

Once you’ve clicked upload, you should get a return in a terminal that confirms the compilation and upload was successful that looks like this:

Then click on the command to open a Monitor to establish the serial link.

You can then observe the LED status feedback live on the monitor.

How to install an external library on Visual Studio Code for the PlatformIO IDE

That’s all there is to it. First, download your external library. Once you’ve got a .zipp file, you need to extract it (or copy and paste the uncompressed library folder) into that folder (in this case, the library we’ll be using as an example is ServoLib, used to facilitate servo-motor control):

You can access your project’s “lib” folder, designed to host external libraries, via Visual Studio Code.

Once a library has been installed in your project, you need to include it in the program header, such as :

Now you have all the basics you need to get started with PlatformIO IDE for C programming.

Using a Nextion display with Arduino

Using a Nextion display with Arduino

The Nextion screen is one of the best solutions for creating a graphical interface to drive your Arduino project. The best-known interface for interacting with an Arduino is the LCD screen with a few buttons and potentiometers, at the cost of I/O and Arduino code overload. In this tutorial, we’ll look at how to set up a Nextion display and how to use it with Arduino.

Hardware

  • Arduino (or other board with UART port)
  • Nextion display
  • USB-TTL 5V adapter
  • 4x Dupont wire with JST connector

Nextion card presentation

The basic interface for controlling an Arduino, and present in all kits, is the LCD screen with a few buttons and potentiometers, available as an LCD Shield. There are also Shields with touch screens, but these use all the Arduino’s I/O and overload the Arduino code. One solution is to use a Nextion screen, which contains its own program and communicates with any microcontroller via the serial port.

N.B.: It is possible to create a graphical interface on a PC or to create a web interface to control the project by adding a wireless communication module.

Nextion editor installation and presentation

Download and install the Nextion editor

When you open a new project or file, the software asks you for the screen model (in our case NX4832K035_011). You can change the selection in the Device>Settings menu.

Then choose screen orientation and encoding.

Creating a graphical interface

We’re going to use the Nextion graphical editor to create our graphical interface. In this example, we will add:

  • An image
  • Some texts for the title or to display data
  • A button that modifies the interface
  • A button that sends a command to the serial port
  • A timer that refreshes the interface
  • A variable that stores data received from the serial port

To add an object, click on the desired object in the Toolbox window and the object will be automatically inserted in the Display window. You can then configure the object in the Attributes window.

You can download the GUI file to import into Nextion Editor. With this example, you’ll be able to create much more complex interfaces.

Add an image

To add an image, first import it into the software using the (+) button in the “Picture” window.

You can then insert a Picture object in the Display window and select the image by pressing the pic > browse… attribute.

N.B.: Add an imageaux dimensions désirées

Add text

Before adding a text object, you need to generate a font. This can be done in Tools> Generate Font

Once the font has been generated, you can select it in the font attribute of the Text object. You can then modify the text in the txt attribute (note the maximum number of characters txt_maxl).

We add four text objects:

  • The title label
  • LED status
  • the “Analog Val” label
  • the analog value received from the micrcontroller

Add a button

Once the button object has been added to the interface, you can adjust its attributes:

  • the text displayed
  • the color when the button is pressed
  • color when color is released

In the Events window, you can program what the screen will do when the button is pressed or released. There are a number of instructions you can use in these windows. These include

  • Modify interface elements (Ex: t0.txt=”Pressed “)
  • Send button identifier via serial port
  • Envoyer une autre commande avec prints
  • Button b0
  • Button b1

In the Touch Release Event tab, we write the following command, which is a predefined command from the Nextion library and corresponds to trigger1()

printh 23 02 54 01
  • Button b2

For the b2 button, we use the same command but for trigger2()

printh 23 02 54 02

Add a timer

The Timer object can be used to execute code on a regular basis. Particularly useful for retrieving data from the serial port and updating the interface.

In the Timer event tab, we use the covx function to convert the value of the variable into a string and write it to the text t4

covx analog0.val,t4.txt,0,0

Load program on Nextion screen

Connect the Nextion card to the USB-TTL converter

To load the interface, press Compile then Upload

Connecting the Nextion display to the Arduino microcontroller

To download Arduino code to the board, pins RX and TX must be disconnected from the screen.

Using the Nextion.h library

There are various libraries you can use to manage a Nextion display

We use EasyNextion

In Nextion Editor, we define an event release “printh 23 02 54 01” for the ON button and an event release “printh 23 02 54 02” for the Off button.

Using the NextionListen() function, these commands activate the trigger1 and trigger2 functions.

#include "EasyNextionLibrary.h"

#define baudrate 9600

EasyNex myNex(Serial);

//Variables
uint16_t analog;
bool ledstate;

const int REFRESH_TIME = 100;
unsigned long refresh_timer = millis();

void setup() {
  myNex.begin(baudrate);

  pinMode(A0, INPUT);
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  myNex.NextionListen();

  if ((millis() - refresh_timer) > REFRESH_TIME) {
    analog = analogRead(A0);
    myNex.writeNum("analog0.val", analog);

    refresh_timer = millis();
  }
}

//`printh 23 02 54 XX` , where `XX` the id for the triggerXX() in HEX.
void trigger1() {
  digitalWrite(LED_BUILTIN, HIGH);
  myNex.writeStr("t2.txt", "LED ON");
}

void trigger2() {
  digitalWrite(LED_BUILTIN, LOW);
  myNex.writeStr("t2.txt", "LED OFF");
}

Results

Bonus: Nextion Editor Simulator

Nextion offers a simulator for testing interactions between the display and microcontroller and the graphical user interface. This simulator can be accessed by clicking on “Debug”.

Sources

Program ESP32/ESP8266 with MicroPython and VS Code

Program ESP32/ESP8266 with MicroPython and VS Code

We’re going to take a look at how to program an ESP32 or ESP8266 board in MicroPython using Visual Studio Code, an IDE increasingly used for programming in a variety of languages. The ESP32 board can be programmed as follows

Introducing Visual Studio Code

Visual Studio Code is a lightweight, extensible code editor developed by Microsoft. VsCode offers many of the same features as the Arduino IDE:

  • Automatic completion
  • Highlighting syntax
  • Debugging functionality
  • Programming in several languages (C++, C
  • Project management
  • Git repository management
  • Etc.

It is open-source and available on Windows, Linux and MacOS platforms.

Installing MicroPython firmware on the ESP board

To install MicroPyhton firmware on the ESP32 or ESP8266 board, you can use one of the following two tutorials:

Installing Visual Studio Code

Go to the Visual Studio Code download page and download the version corresponding to your OS.

Launch the installer and follow the procedure

Installing Pymakr

To program in Python, you need to install the corresponding extension.

Click on the “Manage” icon (cogwheel) at bottom left and select Extensions (or Ctrl+Shift+X)

Then search for and select “Pymakr”. Then install the extension.

Click on the Pymakr icon and select “create project”.

Then click ADD DEVICE and select the ESP connected to the computer.

Once you’ve selected a device, you can connect it by pressing the

Installing Node.js

It may be that in the previous step, the “create project” step doesn’t work properly. In this case, to solve the problem, simply install another third-party software called Node.js, which will enable the Pymakr extension to work properly. Go to https:

Click “next” twice to accept the conditions.

Choose the location for the application (you can leave the default location in your computer’s “Program Files” folder), then click “Next”.

There’s no need to change anything here, so we click on “Next”.

Here, there’s no need to install additional tools such as Chocolatey as suggested, so we click on “Next”.

Finally, click on “Install”, authorizing installation with administrator rights if the computer asks you to do so.

Node.js installation is now complete, and you can click on “Finish”.

You can now move on to the MicroPython programming part of Visual Studio Code. However, make sure you have closed and restarted Visual Studio Code so that it takes Node.js into account.

Programming the ESP32 card

Once the project has been configured, you can launch a Pymakr terminal in the TERMINAL tab. Click on the arrow to the right of the “+” to select the Pymakr console.

Press “Enter” to establish the “select” connection

You can now program in MicroPython directly on the ESP

Run a Python script on your ESP32

There are two Python files in the project:

  • boot.py, which runs when the microcontroller starts up
  • main.py, which contains the main code and runs immediately after boot.py

Open the project’s main.py file and copy the following code

import sys
import time

def main():
    print("MicroPython program is running ")
    time.sleep(0.5)

if __name__=="__main__":
  print("{} initialized".format(sys.platform))
  while(1):
    try:
      main()
    except KeyboardInterrupt:
      print("Program stopped")
      sys.exit(0)

You can then upload the code to the card using the “Sync project to device” button.

After resetting the board with the EN button, you can see that the code runs correctly.

Sources