Display Covid-19 Data Using Maker Pi Pico and CircuitPython

Introduction

Let’s try to build a device to display Covid-19 data in Malaysia. 😊

Video

Hardware Preparation

This is the list of items used in the video.

Sample Program

This is CircuitPython sample program and have been tested with CircuitPython 6.3.0. Before that, please include the following additional libraries:

  • adafruit_bus_device
  • adafruit_esp32spi
  • adafruit_requests.mpy

You may download the CircuitPython Libraries Bundle πŸ‘‰ here.

#
# Display Covid-19 Data Using Maker Pi Pico and CircuitPython
#
# Tutorial
# – https://tutorial.cytron.io/2021/07/27/display-covid-19-data-using-maker-pi-pico-and-circuitpython/
#
# Raspberry Pi Pico
# – [Maker Pi Pico] https://my.cytron.io/p-maker-pi-pico?tracking=idris
# – Node32 Lite https://my.cytron.io/p-node32-lite-wifi-and-bluetooth-development-kit?tracking=idris
# – Grove 16×2 LCD https://my.cytron.io/p-grove-16-x-2-lcd-white-on-blue?tracking=idris
#
# Additional Libraries
# – adafruit_bus_device
# – adafruit_esp32spi
# – adafruit_requests.mpy
# Download CircuitPython Libraries Bundle – https://circuitpython.org/libraries
#
# Update:
# 27 Jul 2021 – Tested with CircuitPython Pico 6.3.0
#
# SPDX-FileCopyrightText: Brent Rubell for Adafruit Industries
# SPDX-License-Identifier: MIT
import time
import board
import busio
from digitalio import DigitalInOut
from grove_lcd_i2c import Grove_LCD_I2C
import adafruit_requests as requests
from adafruit_esp32spi import adafruit_esp32spi
import adafruit_esp32spi.adafruit_esp32spi_socket as socket
COVID_URL = "https://jhucoronavirus.azureedge.net/api/v1/regions/my.json"
# Get wifi details and more from a secrets.py file
try:
from secrets import secrets
except ImportError:
print("WiFi secrets are kept in secrets.py, please add them there!")
raise
LCD_SDA = board.GP4
LCD_SCL = board.GP5
LCD_ADDR = 0x3E
i2c = busio.I2C(scl=LCD_SCL, sda=LCD_SDA)
lcd = Grove_LCD_I2C(i2c, LCD_ADDR)
lcd.home()
lcd.print("Data Covid-19\ndi Malaysia")
print("Data Covid-19 di Malaysia")
# Raspberry Pi RP2040
esp32_cs = DigitalInOut(board.GP13)
esp32_ready = DigitalInOut(board.GP14)
esp32_reset = DigitalInOut(board.GP15)
spi = busio.SPI(board.GP10, board.GP11, board.GP12)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
requests.set_socket(socket, esp)
if esp.status == adafruit_esp32spi.WL_IDLE_STATUS:
print("ESP32 found and in idle mode")
print("Firmware vers.", esp.firmware_version)
print("MAC addr:", [hex(i) for i in esp.MAC_address])
prev_total = 0
while True:
while not esp.is_connected:
print("Connecting to AP…")
try:
esp.connect_AP(secrets["ssid"], secrets["password"])
print("Connected to", str(esp.ssid, "utf-8"), "\tRSSI:", esp.rssi)
print("My IP address is", esp.pretty_ip(esp.ip_address))
print()
except RuntimeError as e:
print("could not connect to AP, retrying: ", e)
continue
try:
#print("Fetching json from", COVID_URL)
response = requests.get(COVID_URL)
#print()
#print(response.json())
#print()
daily_case = int(response.json()["confirmed_cases"]["day"])
total = response.json()["confirmed_cases"]["all"]
response.close()
print("Kes baru: {}\tJumlah: {}".format(daily_case, total))
if total != prev_total:
prev_total = total
print("Display on LCD…")
lcd.clear()
lcd.print("Kes baru: {} \nJumlah: {} ".format(daily_case, total))
except:
print("{} retrying…".format(response))
lcd.clear()
lcd.print("{}\nRetrying…".format(response))
time.sleep(60)

view raw
code.py
hosted with ❤ by GitHub

from board import *
import digitalio
import busio
import time
from adafruit_bus_device.i2c_device import I2CDevice
# Command values
LCD_CLEAR_DISPLAY = 0x01
LCD_RETURN_HOME = 0x02
LCD_ENTRY_MODE_SET = 0x04
LCD_DISPLAY_CONTROL = 0x08
LCD_CURSOR_SHIFT = 0x10
LCD_FUNCTION_SET = 0x20
LCD_SET_CG_RAM_ADDR = 0x40
LCD_SET_DD_RAM_ADDR = 0x80
# Flags for display entry mode
LCD_ENTRY_RIGHT = 0x00
LCD_ENTRY_LEFT = 0x02
LCD_ENTRY_SHIFT_INCREMENT = 0x01
LCD_ENTRY_SHIFT_DECREMENT = 0x00
# Flags for display on/off control
LCD_DISPLAY_ON = 0x04
LCD_DISPLAY_OFF = 0x00
LCD_CURSOR_ON = 0x02
LCD_CURSOR_OFF = 0x00
LCD_BLINK_ON = 0x01
LCD_BLINK_OFF = 0x00
# Flags for display/cursor shift
LCD_DISPLAY_MOVE = 0x08
LCD_CURSOR_MOVE = 0x00
LCD_MOVE_RIGHT = 0x04
LCD_MOVE_LEFT = 0x00
# Flags for function set
LCD_8_BIT_MODE = 0x10
LCD_4_BIT_MODE = 0x00
LCD_2_LINE = 0x08
LCD_1_LINE = 0x00
LCD_5x10_DOTS = 0x04
LCD_5x8_DOTS = 0x00
class Grove_LCD_I2C():
def __init__(self, i2c_bus, lcd_address, cols=16, lines=2, dotsize=LCD_5x8_DOTS):
self.lcd = I2CDevice(i2c_bus, lcd_address)
self._displayfunction = 0
self._displaycontrol = 0
self._displaymode = 0
self._initialized = 0
self._numlines = lines
self._currline = 0
if lines > 1:
self._displayfunction |= LCD_2_LINE
if (not dotsize == 0) and lines == 1:
self._displayfunction |= LCD_5x10_DOTS
time.sleep(0.05)
self.command(LCD_FUNCTION_SET | self._displayfunction)
time.sleep(0.0045) #wait more than 4.1 ms
self.command(LCD_FUNCTION_SET | self._displayfunction)
time.sleep(0.00015)
self.command(LCD_FUNCTION_SET | self._displayfunction)
self.command(LCD_FUNCTION_SET | self._displayfunction)
self._displaycontrol = LCD_DISPLAY_ON | LCD_CURSOR_OFF | LCD_BLINK_OFF
self.display()
self.clear()
self._displaymode = LCD_ENTRY_LEFT | LCD_ENTRY_SHIFT_DECREMENT
self.command(LCD_ENTRY_MODE_SET | self._displaymode)
def clear(self):
self.command(LCD_CLEAR_DISPLAY)
time.sleep(0.002)
def home(self):
self.command(LCD_RETURN_HOME)
time.sleep(0.002)
def cursor_position(self, col, row):
position = col | 0x80 if row == 0 else col | 0xc0
data = bytearray(2)
data[0] = 0x80
data[1] = position
#print(data)
self.i2c_send_bytes(data)
def noDisplay(self):
self._displaycontrol &= (0xff LCD_DISPLAY_ON)
self.command(LCD_DISPLAY_CONTROL | self._displaycontrol)
def display(self):
self._displaycontrol |= LCD_DISPLAY_ON
self.command(LCD_DISPLAY_CONTROL | self._displaycontrol)
def noCursor(self):
self._displaycontrol &= (0xff LCD_CURSOR_ON)
self.command(LCD_DISPLAY_CONTROL | self._displaycontrol)
def cursor(self):
self._displaycontrol &= (0xff LCD_CURSOR_ON)
self.command(LCD_DISPLAY_CONTROL | self._displaycontrol)
def noBlink(self):
self._displaycontrol |= LCD_CURSOR_ON
self.command(LCD_DISPLAY_CONTROL | self._displaycontrol)
def blink(self):
self._displaycontrol |= LCD_BLINK_ON
self.command(LCD_DISPLAY_CONTROL | self._displaycontrol)
def scrollDisplayLeft(self):
self.command(LCD_CURSOR_SHIFT | LCD_DISPLAY_MOVE | LCD_MOVE_LEFT)
def scrollDisplayRight(self):
self.command(LCD_CURSOR_SHIFT | LCD_DISPLAY_MOVE | LCD_MOVE_RIGHT)
def rightToLeft(self):
self._displaymode |= LCD_ENTRY_LEFT
self.command(LCD_ENTRY_MODE_SET | self._displaymode)
def autoscroll(self):
self._displaymode |= LCD_ENTRY_SHIFT_INCREMENT
self.command(LCD_ENTRY_MODE_SET | self._displaymode)
def noAutoscroll(self):
self._displaymode &= (0xff LCD_ENTRY_SHIFT_INCREMENT)
self.command(LCD_ENTRY_MODE_SET | self._displaymode)
def createChar(self, location, charmap):
location &= 0x7
self.command(LCD_SET_CG_RAM_ADDR | (location << 3))
data = bytearray(9)
data[0] = 0x40
for i in range(8):
data[i+1] = charmap[i]
self.i2c_send_bytes(data)
def command(self, value):
data = bytearray(2)
data[0] = 0x80 #command register address
data[1] = value #command byte
self.i2c_send_bytes(data)
def write(self, value):
data = bytearray(2)
data[0] = 0x40
data[1] = value
self.i2c_send_bytes(data)
return 1
def i2c_send_bytes(self, data):
with self.lcd as wire:
wire.write(data)
def print(self, text):
string = str(text)
for char in string:
if char == '\n':
self.cursor_position(0, 1)
else:
self.write(ord(char))

view raw
grove_lcd_i2c.py
hosted with ❤ by GitHub

# This file is where you keep secret settings, passwords, and tokens!
# If you put them in the code you risk committing that info or sharing it
secrets = {
'ssid' : 'Your WiFi SSID',
'password' : 'Your WiFi Password',
}

view raw
secrets.py
hosted with ❤ by GitHub

Thank You

References:

Thanks for reading this tutorial. If you have any technical inquiries, please post at Cytron Technical Forum.

Please be reminded, this tutorial is prepared for you to try and learn.
You are encouraged to improve the code for a better application.

Leave a Comment

Your email address will not be published.

Share this Tutorial

Share on facebook
Share on whatsapp
Share on email
Share on print
Share on twitter
Share on pinterest
Share on facebook
Share on whatsapp
Share on email
Share on print
Share on twitter
Share on pinterest

Latest Tutorial

DIY Digital Alarm Clock Using REKA:BIT With Micro:bit
Display Internet Time (NTP) on micro:bit
DIY Interactive Robot Using REKA:BIT With Micro:bit
BLTouch Installation for Ender 3 with 32-bit V4.2.2 Board
Pick and Send Random Meal’s Option and Locations through Telegram Bot Using Grove WiFi 8266 on micro:bit
Tutorials of Cytron Technologies Scroll to Top