Last active
July 27, 2021 14:17
-
-
Save idriszmy/4cad5f2780d7da4c2ff76ac8f6f83565 to your computer and use it in GitHub Desktop.
Display Covid-19 Data Using Maker Pi Pico and CircuitPython
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# 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 16x2 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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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', | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment