Clock with Nokia 5110 Display

All ESP32 boards running MicroPython.
Target audience: MicroPython users with an ESP32 board.
Post Reply
djairguilherme
Posts: 1
Joined: Fri Jan 26, 2018 7:33 pm

Clock with Nokia 5110 Display

Post by djairguilherme » Fri Jan 26, 2018 7:47 pm

Hello. I'm starting to program in Python. Recently I purchased two ESP-WROOM32 Dev Module. One is Wemos, with bluetooth and wifi and 18650 battery. I'm using the Loboris version on this board and made this script to learn how to use the board. It's a clock, using the Nokia PCD8544 display.

I used the library https://github.com/mcauser/micropython-pcd8544 and created a main.py file with the clock code. My boot.py file automatically starts Wi-fi and gets the time via NTP.

This is my first effort. I consulted extensively on the forum and documentation provided by Loboris. Thank you!

I hope this helps.

==

Code: Select all

#Nokia 5110 in Wemos ESP 32
# Pinout
# 3V3 or any Pin => VCC       3.3V logic voltage (0=off, 1=on)
# MOSI (23)      => DIN       data flow (Master out, Slave in)
# SCK  (18)      => CLK       SPI clock
# Pin  (0)       => RST       Reset pin (0=reset, 1=normal)
# Pin  (2)       => CE        Chip Enable (0=listen for input, 1=ignore input)
# Pin  (15)      => DC        Data/Command (0=commands, 1=data)
# Pin  (12)      => LIGHT     Light (0=on, 1=off)
# GND            => GND
# References:  https://github.com/mcauser/micropython-pcd8544
#              http://docs.micropython.org/en/latest/pyboard/library/machine.SPI.html
#              http://pedrominatel.com.br/pt/esp8266/utilizando-o-lcd-nokia-5110-no-esp8266/

import pcd8544
import framebuf
import utime
import machine
import _thread

from machine import Pin, SPI
from time import strftime

spi = SPI(1, baudrate=328125, bits=8, polarity=0, phase=1, sck=18, mosi=23, miso=19)
spi.init()
cs = Pin(2)
dc = Pin(15)
rst = Pin(0)

led = Pin(16)

# backlight on
bl = Pin(12, Pin.OUT, value=0)

lcd = pcd8544.PCD8544(spi, cs, dc, rst)
lcd.contrast(0x3c, pcd8544.BIAS_1_40, pcd8544.TEMP_COEFF_0)
lcd.reset()
lcd.init()
lcd.clear()


buffer = bytearray((lcd.height // 8) * lcd.width)
framebuf = framebuf.FrameBuffer1(buffer, lcd.width, lcd.height)

rtc = machine.RTC()
rtc.ntp_sync ('a.ntp.br')
rtc.init (rtc.now())

def watch():
    data = strftime('%d/%m/%y')
    relogio = strftime('%H:%M:%S')
    lcd.position(0, 0)
    while True:
	framebuf.text(data, 10, 12, 1)
	framebuf.text(relogio,10,24,1)
	lcd.data(buffer)
	agora = strftime('%H:%M:%S')
	
	if relogio != agora:
            relogio = agora	
	    framebuf.fill(0) # clear framebuffer
	    utime.sleep(1)
	    lcd.data(buffer)
	    
_thread.start_new_thread ("clock",watch, ())
Last edited by jimmo on Thu Feb 27, 2020 3:34 am, edited 2 times in total.
Reason: Add [code] formatting

stanely
Posts: 40
Joined: Fri Jan 17, 2020 5:19 am
Location: Ohio, USA

Re: Clock with Nokia 5110 Display

Post by stanely » Thu Feb 27, 2020 1:55 am

Did this really work for you? Running this didn't seem to work. First the lack of indents had to be fixed, then uP complained about no strtfime. There's no strftime() method in the time module, is there?

How did you get this to run on an ESP32?

User avatar
jimmo
Posts: 1465
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia
Contact:

Re: Clock with Nokia 5110 Display

Post by jimmo » Thu Feb 27, 2020 3:41 am

stanely wrote:
Thu Feb 27, 2020 1:55 am
First the lack of indents had to be fixed
The post had the formatting, just wasn't in a [ code ] block. I modified the post to add it in.
stanely wrote:
Thu Feb 27, 2020 1:55 am
then uP complained about no strtfime. There's no strftime() method in the time module, is there?

How did you get this to run on an ESP32?
The OP was using the Loboris port, which has all sorts of differences to upstream (including, as I discovered today, time.strftime) -- https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo

stanely
Posts: 40
Joined: Fri Jan 17, 2020 5:19 am
Location: Ohio, USA

Re: Clock with Nokia 5110 Display

Post by stanely » Thu Feb 27, 2020 6:01 pm

jimmo wrote:
Thu Feb 27, 2020 3:41 am
The OP was using the Loboris port, which has all sorts of differences to upstream (including, as I discovered today, time.strftime) -- https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo
Thanks, I had no idea. Threading seems different too, so it might take a bit of effort to make this work with MicroPython.

I was evaluating the Nokia 5110 for my project and ran into problems mapping pins from the Wemos D1 mini (re, mcauser) to the ESP32 DEVKIT. I found this thread and needless to say, this post confused me even more. :) But after sorting everything out, I thought this clock idea would make a good test for the display on a DEVKIT.

The code below starts with a connection to the WiFi network. Normally I put that in the boot.py file, that's why it's shown above everything else. Note, you'll need to edit the SSID & PASSWORD to match your network particulars.

The rest of the code is pretty simple and doesn't attempt to thread assuming there's not much else going on.

Code: Select all

import network

station = network.WLAN(network.STA_IF)
station.active(True)
station.connect("YOUR SSID", "YOUR PASSWORD")
station.isconnected()
station.ifconfig()

import pcd8544
import framebuf
import utime
import machine
import ntptime
import _thread
from machine import Pin, SPI

#ESP32 DEVKIT with Nokia 5110. Using SPI 2 hardware definition.
spi = SPI(2, baudrate=2000000, polarity=0, phase=0, bits=8, firstbit=0, sck=Pin(18), mosi=Pin(23), miso=Pin(19))
spi.init()
cs = Pin(16)
dc = Pin(5)
rst = Pin(21)
bl = Pin(17, Pin.OUT, value=1)
led = Pin(2, Pin.OUT, value=0)          # Turn off LED.
toggle = False

lcd = pcd8544.PCD8544(spi, cs, dc, rst)
lcd.reset()
lcd.init()
lcd.clear()
lcd.contrast(0x3c, pcd8544.BIAS_1_40, pcd8544.TEMP_COEFF_0)

days = ("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday")


buffer = bytearray((lcd.height // 8) * lcd.width)
framebuf = framebuf.FrameBuffer1(buffer, lcd.width, lcd.height)
framebuf.fill(0)        # clear screen framebuffer 

ntptime.settime()       # This library call sets RTC to ntp time.

while True:
    now = machine.RTC().datetime()
    now_day = str(days[now[3]])
    now_date = str(now[1]) + "/" + str(now[2]) + "/" + str(now[0])
    now_time = "%d:%2.2d:%2.2d" % (now[4], now[5], now[6])
    framebuf.text(now_day, 9, 2, 1)
    framebuf.text(now_date, 7, 16, 1)
    framebuf.text(now_time, 11, 0, 1)
    lcd.data(buffer)

    led.value(toggle)   # toggle the LED every .1 sec.
    toggle = not toggle

    time.sleep(0.1)     # wait 100 ms. & loop
    framebuf.fill(0)     # clear screen

stanely
Posts: 40
Joined: Fri Jan 17, 2020 5:19 am
Location: Ohio, USA

Re: Clock with Nokia 5110 Display

Post by stanely » Sat Feb 29, 2020 5:59 am

I couldn't resist rewriting this clock code using Peter Hinch's Writer class. I also used his font-to-py to generate the two fonts used in this script. The pictures show this script running on an ESP32 devkit. It imports the following files:

pcd8544_fb.py (https://github.com/mcauser/micropython- ... 8544_fb.py)
writer.py (https://github.com/peterhinch/micropyth ... /writer.py)
marrada30.py (https://github.com/the-stanely/Clock-ES ... rrada30.py) (only ' 0123456789:.')
arialn11.py (https://github.com/the-stanely/Clock-ES ... rialn11.py)

Here's what the clock looks like.

Image https://github.com/the-stanely/Clock-ES ... 5110-1.JPG

Image https://github.com/the-stanely/Clock-ES ... 5110-2.JPG

12/24 hour format and local timezone are supported. The clock pulls ntp time from the Internet, so a coonection is assumed. Here's the script...

Code: Select all

import pcd8544_fb
from machine import Pin, RTC, SPI
import ntptime
import sys
import utime
from writer import Writer

# Fonts
import marrada30 as clock   # This font only has ' 0123456789.:'
import arialn11 as small

#----------------------------------------------------------------------------------
# Mode of operation
timezone = -5
clockmode = 12  # 24 or 12
#----------------------------------------------------------------------------------

# Set up SPI 2 for hardware transfers.
spi = SPI(2, baudrate=4000000, polarity=0, phase=0, bits=8, firstbit=0, sck=Pin(18), mosi=Pin(23), miso=Pin(19))
spi.init()

# Setup up ESP32 DEVKIT with Nokia 5110. Using SPI .
cs = Pin(16)
dc = Pin(5)
rst = Pin(21)
bl = Pin(17, Pin.OUT, value=1)

# Constants
DAYS = ("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday")
scr_wd = 84     # Nokia 5110 width
scr_ht = 48     # Nokia 5110 height

# Check for network connection & exit if none.
if not station.isconnected():
    print('No network connection, exiting...')
    sys.exit()

# Get network time from ntp.
ntptime.settime()   # This sets the RTC to UTC.

# Get MicroPython UTC epoch time in seconds.
utc_time = utime.time()
# Offset UTC by timezone using 3600 seconds per hour.
local_time = utc_time + 3600 * timezone
# Get local time's datetime tuple.
yy, mo, dd, hh, mm, ss, wkd, yrd = [d for d in utime.localtime(local_time)]

# Set the RTC to local time.  (I don't think the uP docs are exactly right about this.)
RTC().datetime((yy, mo, dd, 0, hh, mm, ss, 0))

# Create a framebuf instance of display using SPI driver.
ssd = pcd8544_fb.PCD8544_FB(spi, cs, dc, rst)

# Create two Writer instances for two fonts.
wri_bcf = Writer(ssd, clock, verbose=False)     # Big Clock font.
wri_bcf.set_clip(True, True, False)             # Clip is on
wri_s = Writer(ssd, small, verbose=False)       # Small font line 2.
wri_s.set_clip(True, True, False)               # Clip is on


# Create blank strings to erase display lines to eol.
bcf_blank_wd = wri_bcf._charlen(' ')    # Width of a big font blank
px_to_eol = bcf_blank_wd                # Create big blanks to clear to eol 1.
bcf_clr_eol = ' '
while px_to_eol < scr_wd:
	bcf_clr_eol += ' '
	px_to_eol += bcf_blank_wd

s_blank_wd = wri_s._charlen(' ')        # Width of a small font blank
px_to_eol = s_blank_wd                  # Create small blanks to clear to eol 2.
s_clr_eol = ' '
while px_to_eol < scr_wd:
	s_clr_eol += ' '
	px_to_eol += s_blank_wd

if clockmode == 24:
    l2start = 10
else:
    l2start = 4

while True:
    now = RTC().datetime()

    now_day = str(DAYS[now[3]])[:3]
    now_date = '%2.2d/%2.2d/%2.2d' % (now[1], now[2], now[0])
    now_day_date = now_day + '. ' + now_date

    now4 = now[4]
    if clockmode == 24:
        am_pm = ''
    else:
        if now[4] >= 13:
            am_pm = '  PM'
            now4 = now[4] - 12
        elif now[4] == 0:
            now4 = 12
        else:
            am_pm = '  AM'

    now_time = "%2d:%2.2d:%2.2d" % (now4, now[5], now[6])

    wri_bcf.set_textpos(ssd, 0, 0)          # Clear line 1 to eol.
    wri_bcf.printstring(bcf_clr_eol)
    wri_bcf.set_textpos(ssd, 0, 0)          # Write the time.
    wri_bcf.printstring(now_time)
    
    wri_s.set_textpos(ssd, 33, 0)            # Clear line 2 to eol.
    wri_s.printstring(s_clr_eol)
    wri_s.set_textpos(ssd, 33, l2start)     # Write the date on line 2.
    wri_s.printstring(now_day_date+am_pm)
    ssd.show()

    utime.sleep(0.25)   # wait & loop

Post Reply