Archive

Archive for November, 2016

A minimal LCD (HD44780) library for MicroPython

November 25th, 2016 No comments

This post demonstrates a minimal LCD library for MicroPython, used on an ESP8266. This is a small collection of commands that I put together (mostly ported) to have simple control over an HD44780 compatible LCD. There are a couple of existing LCD libraries for MicroPython so make sure to check them out first, since this is a minimalistic approach and may be limiting for you project. The post is merely a reference to the code rather than full explanation on how HD44780 LCD works. There are plenty of sources about that as well as the post of the code’s original author.

I am using the NodeMCU board so make sure to adjust the connections according to the board you are using. The LCD uses an 8-bit data bus but it also supports 4-bit mode. That means we can break a byte to two nibbles (4 bits) and save up 4 wired connections.

Let’s take a look at the code. Credit goes to Matt Hawkins over raspberrypi-spy.co.uk who is the original author of the code. I just ported it over to MicroPython and made a couple of simple changes.

import machine
import time
 
LCD_RS = 16
LCD_E = 5
LCD_D4 = 4
LCD_D5 = 0
LCD_D6 = 2
LCD_D7 = 14
 
LCD_WIDTH = 16
LCD_CHR = True
LCD_CMD = False
 
LCD_LINE_1 = 0x80
LCD_LINE_2 = 0xC0
 
E_PULSE = 0.0005
E_DELAY = 0.0005
 
pin_lcd_e = machine.Pin(LCD_E, machine.Pin.OUT)
pin_lcd_rs = machine.Pin(LCD_RS, machine.Pin.OUT)
pin_lcd_d4 = machine.Pin(LCD_D4, machine.Pin.OUT)
pin_lcd_d5 = machine.Pin(LCD_D5, machine.Pin.OUT)
pin_lcd_d6 = machine.Pin(LCD_D6, machine.Pin.OUT)
pin_lcd_d7 = machine.Pin(LCD_D7, machine.Pin.OUT)
 
def main():
    lcd_init()
    lcd_string("HD44780 LCD", LCD_LINE_1)
    lcd_string("with MicroPython", LCD_LINE_2)
 
def lcd_init():
    lcd_byte(0x33, LCD_CMD)
    lcd_byte(0x32, LCD_CMD)
    lcd_byte(0x0C, LCD_CMD)
    lcd_byte(0x01, LCD_CMD)
    lcd_byte(0x28,LCD_CMD)
    lcd_byte(0x06,LCD_CMD)
    time.sleep(E_DELAY)
 
def lcd_byte(bits, mode):
    pin_lcd_rs.value(mode)
    pin_lcd_d4.low()
    pin_lcd_d5.low()
    pin_lcd_d6.low()
    pin_lcd_d7.low()
    if bits & 0x10 == 0x10:
        pin_lcd_d4.high()
    if bits & 0x20 == 0x20:
        pin_lcd_d5.high()
    if bits & 0x40 == 0x40:
        pin_lcd_d6.high()
    if bits & 0x80 == 0x80:
        pin_lcd_d7.high()
    lcd_toggle_enable()
    pin_lcd_d4.low()
    pin_lcd_d5.low()
    pin_lcd_d6.low()
    pin_lcd_d7.low()
    if bits & 0x01 == 0x01:
        pin_lcd_d4.high()
    if bits & 0x02 == 0x02:
        pin_lcd_d5.high()
    if bits & 0x04 == 0x04:
        pin_lcd_d6.high()
    if bits & 0x08 == 0x08:
        pin_lcd_d7.high()
    lcd_toggle_enable()
 
def lcd_toggle_enable():
    time.sleep(E_DELAY)
    pin_lcd_e.high()
    time.sleep(E_PULSE)
    pin_lcd_e.low()
    time.sleep(E_DELAY)
 
def lcd_string(message, line):
    lcd_byte(line, LCD_CMD)
    for c in message: # Print out the message
        lcd_byte(ord(c), LCD_CHR)
    for i in range(LCD_WIDTH - len(message)): # Fill the rest of the line with empty characters
        lcd_byte(32, LCD_CHR)
 
main()

Copy the above code in a file, for example lcd.py and then use the following command to give it a test run (assuming your port is /dev/ttyUSB0)

ampy --port /dev/ttyUSB0 run lcd.py

Here is how it should look like 🙂

hd44780-lcd-with-micropython

I did some changes in the lcd_string function in order to support multi length strings. So what it does, it first prints the contents of the message and then fills the rest of the line with empty characters in order to delete any remains from the previous refresh.

Hope this helps you out. Let me know in the comments.

Categories: general Tags:

Flashing MicroPython on ESP8266

November 15th, 2016 No comments

This post is a summary on how to install and use MicroPython on ESP8266. MicroPython is a Python 3 implementation, optimized to run on microcontrollers. Due to resource restrictions, it contains a subset of the original standard library. Nevertheless, it allows us to use our beloved Python language and rapid prototype our projects.

First, we need to flash the MicroPython firmware. Goto https://micropython.org/download and download the latest firmware for ESP8266. At the time of writing, this is esp8266-20161110-v1.8.6.bin. Connect your ESP8266 to the USB port and figure out the port name. I am using Linux so I use dmesg. In my case, the port is /dev/ttyUSB0. If your module powers up but does not connect to a port the are a couple of possibilities. Make sure you are using a normal USB cable with data connections. In other words, make sure that your cable is not for charging only; usually the cables coming with power banks are power only, connecting only the power pins of the USB to the module. Another possibility, is that not enough power goes through to keep the connection alive. In this case, try another cable, or try connecting the cable to another USB port.

For flahsing the firmware we need the esptool.py script. Install it using pip:

sudo pip install esptool

Once the installation is finished and the module is connected, run the following command:

esptool.py --port /dev/ttyUSB0 --baud 115200 write_flash --flash_size=8m 0 esp8266-20161110-v1.8.6.bin

and here is what it should look like:

esp8266_micropython_flashing

By the way, you can try higher baud rates if you want to speed up the process but 115200 is a safe one.

Next, disconnect and reconnect the USB cable. Check again the port name and use a serial terminal application to connect to the module which now expects 115200 baud rate communication. I use picoterm using the following:

picocom /dev/ttyUSB0 -b 115200

Press ENTER once and you will be prompted with the familiar >>> Your module is now flahsed and you can start typing away in Python. Before closing, lets see a couple of commands to see how this works. We will flash the LED on the ESP8266 a couple of times. To do this, we need to import machine in order to manipulate the values on the pins.

import machine
import time
 
led_pin = machine.Pin(2, machine.Pin.OUT)
 
def flash_led(lp):
    lp.low()
    time.sleep(1)
    lp.high()
    time.sleep(1)
    lp.low()
    time.sleep(1)
    lp.high()
    time.sleep(1)

With the above snippet, we created a function `flash_led` that takes as an argument a pin from the ESP8266 module and toggles its value. At the start, we assign pin 2 to `led_pin`. So finally, run

flash_led(led_pin)

to flash the LED on the board.

Hope this was useful to you. Let me know of your comments.

Reference: http://docs.micropython.org/en/latest/esp8266/esp8266/tutorial/index.html

Categories: general Tags: