NodeMCU Projects

From Network Security Wiki



Small Projects

LED ON/OFF

from machine import Pin

led = Pin(2, Pin.OUT)

led.value()
led.value(1)
led.value(0)

Toggle GPIO

import machine
import time
import urandom

pin = machine.Pin(2, machine.Pin.OUT)

def toggle(p):
   p.value(not p.value())

while True:
   time.sleep_ms(urandom.getrandbits(8))
   toggle(pin)


Fading an LED

import time, math
import machine

led = machine.PWM(machine.Pin(2), freq=1000)

def pulse(l, t):
    for i in range(20):
        l.duty(int(math.sin(i / 10 * math.pi) * 500 + 500))
        time.sleep_ms(t)

while True:
    pulse(led, 20)


Control a hobby servo

  1. Hobby servo motors can be controlled using PWM.
  2. They require a frequency of 50Hz and a duty between about 40 and 115, with 77 being the center value.
  • Manual Movements
servo = machine.PWM(machine.Pin(12), freq=50)
servo.duty(40)
servo.duty(115)
servo.duty(77)
  • Random movements:
servo = machine.PWM(machine.Pin(12), freq=50)
while True:
   servo.duty(urandom.getrandbits(8))
   time.sleep(1)

One Wire DS18B20 Temp Sensor

import time
import machine
import onewire, ds18x20

# the device is on GPIO12
dat = machine.Pin(12)

# create the onewire object
ds = ds18x20.DS18X20(onewire.OneWire(dat))

# scan for devices on the bus
roms = ds.scan()
print('found devices:', roms)

# loop 10 times and print all temperatures
for i in range(10):
    print('temperatures:', end=' ')
    ds.convert_temp()
    time.sleep_ms(750)      # delay should be atleast 750ms between 2 readings
    for rom in roms:
        print(ds.read_temp(rom), end=' ')
    print()

LM35 Temp Sensor

        This section is under construction.

DHT11 Temp Sensor

Source: github.com

  • Use DHT11 Module driectly, Do not use Sensor board with Pull Up resistor.
  • Testing Sensor:
>>> from machine import Pin
>>> from dht import DHT11
>>> d = DHT11(Pin(14))    # Pin D5
>>> d.measure()
>>> d.temperature()
28
>>> d.humidity()
16
  • Printing Temperature to I2C LCD
import time
from machine import I2C, Pin
from dht import DHT11
from esp8266_i2c_lcd import I2cLcd

time.sleep(1)

d = DHT11(Pin(14))                              # Pin D5

i2c = I2C(scl=Pin(5), sda=Pin(4), freq=400000)  # Pin D1 & D2
lcd = I2cLcd(i2c, 63, 2, 16)

while True:
  try:
    d.measure()
    print("temp: ", d.temperature(), "humidity: ", d.humidity())
    lcd.putstr("Temperature: " + str(d.temperature()) + "C")
    lcd.putstr("Humidity:    " + str(d.humidity()) + "%")
    time.sleep(10)
    lcd.clear()
  except OSError:
    print("Sensor read error!!")
    lcd.putstr("Sensor read error!!")
    time.sleep(5)
    lcd.clear()

Deep-sleep mode

  • This shut down the ESP8266 and all its peripherals & also WiFi.
  • But not including the real-time-clock, which is used to wake the chip.
  • This drastically reduces current consumption and is a good way to make devices that can run for a while on a battery.
  • You Must connect GPIO16 to the reset pin.
import machine

# configure RTC.ALARM0 to be able to wake the device
rtc = machine.RTC()
rtc.irq(trigger=rtc.ALARM0, wake=machine.DEEPSLEEP)

# check if the device woke from a deep sleep
if machine.reset_cause() == machine.DEEPSLEEP_RESET:
    print('woke from a deep sleep')

# set RTC.ALARM0 to fire after 10 seconds (waking the device)
rtc.alarm(rtc.ALARM0, 10000)

# put the device to sleep
machine.deepsleep()

Analog Temperature Meter

Requirements:

DS18B20 Temperature sensor
Servo Motor
Micropython based NodeMCU

Wiring details:

Servo motor = D4 => GPIO 2
DS18B20     = D7 => GPIO 13
import time
import machine
import onewire, ds18x20

# the device is on GPIO13
dat = machine.Pin(13)

# create the onewire object
ds = ds18x20.DS18X20(onewire.OneWire(dat))

# scan for devices on the bus
roms = ds.scan()
print('found devices:', roms)

# servo is connected to GPIO2
servo = machine.PWM(machine.Pin(2), freq=50)

# Function for mapping range
def translate(value, leftMin, leftMax, rightMin, rightMax):
    # Figure out how 'wide' each range is
    leftSpan = leftMax - leftMin
    rightSpan = rightMax - rightMin

    # Convert the left range into a 0-1 range (float)
    valueScaled = float(value - leftMin) / float(leftSpan)

    # Convert the 0-1 range into a value in the right range.
    return rightMin + (valueScaled * rightSpan)
 
# print all temperatures
while True:
    ds.convert_temp()
    time.sleep_ms(1000)
    for rom in roms:
        print(ds.read_temp(rom))
    temp = ds.read_temp(rom)
    srv = translate(temp, 20, 35, 115, 40)
    print(int(srv))
    if (temp>=20) & (temp<=35):
        servo.duty(int(srv))
    else:
        print("Out of Range")

NeoPixel

import machine
import neopixel
import time
import urandom

pin = machine.Pin(14, machine.Pin.OUT)     # WS2812 data pin connected to GPIO 14 or Pin D5
np = neopixel.NeoPixel(pin, 16)            #16 Pixels or LEDs in strip

def rand():
    return urandom.getrandbits(7)

def cycle():
    for i in range(16):
        np[i] = (128,0,0)
        np.write()
        time.sleep_ms(25)

    for i in range(16):
        np[i] = (0,128,0)
        np.write()
        time.sleep_ms(25)

    for i in range(16):
        np[i] = (0,0,128)
        np.write()
        time.sleep_ms(25)

def circle():
    for j in range(10):
        x,y,z = rand(),rand(),rand()
        for i in range(16):
            np[i] = (x,y,z)
            np.write()
            time.sleep_ms(25)

def circle_rainbow():
    for j in range(10):
        for i in range(16):
            np[i] = (rand(),rand(),rand())
            np.write()
            time.sleep_ms(25)

def fade():
    for i in range(0, 4 * 256, 8):
            for j in range(16):
                if (i // 256) % 2 == 0:
                    val = i & 0xff
                else:
                    val = 255 - (i & 0xff)
                np[j] = (val, 0, 0)
            np.write()

    for i in range(0, 4 * 256, 8):
            for j in range(16):
                if (i // 256) % 2 == 0:
                    val = i & 0xff
                else:
                    val = 255 - (i & 0xff)
                np[j] = (0, val, 0)
            np.write()

    for i in range(0, 4 * 256, 8):
            for j in range(16):
                if (i // 256) % 2 == 0:
                    val = i & 0xff
                else:
                    val = 255 - (i & 0xff)
                np[j] = (0, 0, val)
            np.write()

def clock():
    for k in range(10):
        for i in range(16):
            if i%2 == 0:
                np[i] = (64,0,10)
                np.write()
            else:
                np[i] = (10,64,0) 
                np.write()
        time.sleep_ms(200)

        for j in range(16):
            if j%2 == 0:
                np[j] = (10,64,0)
                np.write()
            else:
                np[j] = (64,10,0)
                np.write()
        time.sleep_ms(200)

def bounce():
    for i in range(3):
        x,y,z = rand(),rand(),rand()
        for i in range(4 * 16):
            for j in range(16):
                np[j] = (x,y,z)
            if (i // 16) % 2 == 0:
                np[i % 16] = (0, 0, 0)
            else:
                np[16 - 1 - (i % 16)] = (0, 0, 0)
            np.write()
            time.sleep_ms(60)

def off():
    for i in range(16):
        np[i] = (0,0,0)
        np.write()

cycle()
off()
time.sleep(1)

circle()
off()
time.sleep(1)

circle_rainbow()
off()
time.sleep(1)

fade()
off()
time.sleep(1)

clock()
off()
time.sleep(1)

bounce()
off()

Morse Code

import machine
import sys
import time

CODE = {'A': '.-',     'B': '-...',   'C': '-.-.', 
        'D': '-..',    'E': '.',      'F': '..-.',
        'G': '--.',    'H': '....',   'I': '..',
        'J': '.---',   'K': '-.-',    'L': '.-..',
        'M': '--',     'N': '-.',     'O': '---',
        'P': '.--.',   'Q': '--.-',   'R': '.-.',
     	'S': '...',    'T': '-',      'U': '..-',
        'V': '...-',   'W': '.--',    'X': '-..-',
        'Y': '-.--',   'Z': '--..',   ' ': ' ',
        
        '0': '-----',  '1': '.----',  '2': '..---',
        '3': '...--',  '4': '....-',  '5': '.....',
        '6': '-....',  '7': '--...',  '8': '---..',
        '9': '----.' 
        }

pin = machine.Pin(14, machine.Pin.OUT)        # Laser Module connected to GPIO 14 or Pin D5
pin.off()
a = 300

def morse(x):
    c = []
    for i in x:
        c.append(CODE[i.upper()])
        c.append(" ")

    for i in range(len(c)):
        for j in c[i]:
            if j == ".":
                pin.on()
                print("DOT")
                time.sleep_ms(a)
                pin.off()
                time.sleep_ms(a*2)
            elif j == "-":
                pin.on()
                print("DASH")
                time.sleep_ms(a*3)
                pin.off()
                time.sleep_ms(a*2)
            elif j == " ":
                pin.off()
                print(" ")
                time.sleep_ms(a*4)
            else:
                print("ERROR")
    pin.off()
    print("END")

morse("amandeep")

I2C LCD

Source: forum.micropython.org & forum.micropython.org

  • Download the below library files from below link & upload them to NodeMCU:
https://github.com/dhylands/python_lcd/tree/master/lcd
- esp8266_i2c_lcd.py
- lcd_api.py
  • Connect the NodeMCU to I2C LCD-1602 as below:
D1 SCL ------------ SCL
D2 SDA ------------ SDA
GND --------------- GND
5V ---------------- VCC


  • There are many versions of this device - the difference is the controller IC.
  • If you have the PCF8574T. the default I2C bus address is 0x27.
  • If you have the PCF8574AT the default I2C bus address is 0x3F(63).
  • Defining Address:
lcd=I2cLcd(i2c, 0x27, 2, 16)
lcd=I2cLcd(i2c, 39, 2, 16)
  • An i2c.scan() should reveal which address to use:
>>> from machine import I2C
>>> i2c = I2C(scl=Pin(5), sda=Pin(4), freq=400000)
>>> print(i2c.scan())
[63]
>>> lcd=I2cLcd(i2c, 63, 2, 16)
  • Print the output on the LCD:
import time
from machine import I2C, Pin
from esp8266_i2c_lcd import I2cLcd

i2c = I2C(scl=Pin(5), sda=Pin(4), freq=400000)

lcd = I2cLcd(i2c, 63, 2, 16)
while True:
  lcd.putstr("Hello Tester..\nIt's working!")
  time.sleep(2)
  lcd.clear()
  lcd.putstr("Test 2\nMicropython_lcd")
  time.sleep(2)
  lcd.clear()

MAX7219 based 8x8 LED Matrix

Source: github.com

  • Download below Library and upload it to NodeMCU:
https://github.com/vrialland/micropython-max7219/blob/master/max7219.py
  • Connections:
ESP8266 	MAX7219
5V 	        VCC
GND 	        GND
D7 (GPIO13) 	DIN
D8 (GPIO15) 	CS
D5 (GPIO14) 	CLK
  • Static Testing:
from machine import Pin, SPI
import max7219

spi = SPI(1, baudrate=10000000)
screen = max7219.Max7219(32, 8, spi, Pin(15))
screen.text('ABCD', 0, 0, 1)    #
screen.show()
  • Command explaination
screen.text("ABCD",x,y,z)
ABCD = Text to be displayed
x = Horizontal Position
y = Vertical Position
  • Scroll Text:
def disp(txt,n,t):
    for i in range(-n,n):
        screen.text(txt,-i,0,1)
        screen.show()
        time.sleep(t)
        screen.init_display()


Auto Marque Library

Source: github.com

  • Download below Library and upload it to NodeMCU:
https://github.com/jgbrown32/ESP8266_MAX7219/blob/master/max7219.py
from machine import Pin, SPI
import max7219, utime

spi = SPI(1, 10000000)
d = max7219.Max7219(32, 8, spi, Pin(15), False)
d.text("Aman", 0, 0)
d.show()
utime.sleep(5)

while True:
    d.marquee("This code is working fine now...")
  • Flash all the LEDs
def flash(x,y,z):
  for i in range(x):
    d.fill(1)
    d.show()
    time.sleep(y)
    d.fill(0)
    d.show()
    time.sleep(z)

flash(3,0.2,0.2)

Display Info using Urequests

import machine
import max7219, utime
import urequests as requests
import time

 
# LCD Config
spi = machine.SPI(1, 10000000)
d = max7219.Max7219(32, 8, spi, machine.Pin(15), False)

cntry = ["India", "Canada", "Ireland", "USA", "Germany", "Italy", "France", "Spain", "Pakistan", "Korea"]


# Flash all LEDs
for i in range(3):
    d.fill(1)
    d.show()
    time.sleep(0.2)
    d.fill(0)
    d.show()
    time.sleep(0.2)


# Print Global Data
try:
    res = requests.get(url='http://coronavirus-19-api.herokuapp.com/all')
    if res.status_code == 200:
        flash_led(1,0.1,0.1)
    else:
        flash_led(2,0.5,0.1)
    data = res.json()
    print("Global: " + str(data["cases"]))
    d.marquee("Global: " + str(data["cases"]))
except OSError:
    print("Global: Error")
    d.marquee("Global: Error")
    time.sleep(5)


# Print Country Data
for i in cntry:
    link = 'http://coronavirus-19-api.herokuapp.com/countries/%s' %i
    try:
        res = requests.get(url=link)
        if res.status_code == 200:
            flash_led(1,0.1,0.1)
        else:
            flash_led(2,0.5,0.1)
        data = res.json()
        print(str(data["country"]) + ": " + str(data["cases"]) + " Today: " + str(data["todayCases"]))
        d.marquee(str(data["country"]) + ": " + str(data["cases"]) + " Today: " + str(data["todayCases"]))
    except OSError:
        print(i, ": Error")
        d.marquee(i + ": Error")
        time.sleep(5)
        continue


# Sleep for 30 minutes
sleep = 5
d.marquee("Sleep " + str(sleep) + " min")
flash_led(5,0.1,0.1)
deep_sleep(sleep)

TM1637 CLock

Download Library:

https://github.com/mcauser/micropython-tm1637/blob/master/tm1637.py
        This section is under construction.



References





{{#widget:DISQUS |id=networkm |uniqid=NodeMCU Projects |url=https://aman.awiki.org/wiki/NodeMCU_Projects }}