summaryrefslogtreecommitdiff
path: root/lcd-ipaddress-display
diff options
context:
space:
mode:
authorSaumit Dinesan <justsaumit@protonmail.com>2023-04-22 23:31:40 +0530
committerSaumit Dinesan <justsaumit@protonmail.com>2023-04-22 23:31:40 +0530
commitc95424b6ecb771f57dbbacd59a69894c1150d4fd (patch)
treef53c721b839c1bcbe0accf418c435cdf31e78c18 /lcd-ipaddress-display
parent4633e624fdc4e61928b8c7743d9bbd50c5d75a6a (diff)
Adding 16x2 lcd drivers+IP Display script
Diffstat (limited to 'lcd-ipaddress-display')
-rw-r--r--lcd-ipaddress-display/dispip.py20
-rw-r--r--lcd-ipaddress-display/drivers/__init__.py1
-rw-r--r--lcd-ipaddress-display/drivers/i2c_dev.py272
3 files changed, 293 insertions, 0 deletions
diff --git a/lcd-ipaddress-display/dispip.py b/lcd-ipaddress-display/dispip.py
new file mode 100644
index 0000000..22b044c
--- /dev/null
+++ b/lcd-ipaddress-display/dispip.py
@@ -0,0 +1,20 @@
+#!/usr/bin/env python
+
+import drivers
+from time import sleep
+from subprocess import check_output
+
+display = drivers.Lcd()
+
+try:
+ # Retrieve the IP address
+ IP = check_output(["hostname", "-I"]).split()[0].decode()
+ print("Writing to display")
+ while True:
+ display.lcd_display_string("IP Address: ", 1)
+ display.lcd_display_string(str(IP), 2) # Display the IP address on the second line
+ # sleep(1) # Uncomment the following line to loop with 1 sec delay
+except KeyboardInterrupt:
+ # If there is a KeyboardInterrupt (when you press ctrl+c), exit the program and cleanup
+ print("Cleaning up!")
+ display.lcd_clear()
diff --git a/lcd-ipaddress-display/drivers/__init__.py b/lcd-ipaddress-display/drivers/__init__.py
new file mode 100644
index 0000000..f6fa541
--- /dev/null
+++ b/lcd-ipaddress-display/drivers/__init__.py
@@ -0,0 +1 @@
+from .i2c_dev import Lcd, CustomCharacters
diff --git a/lcd-ipaddress-display/drivers/i2c_dev.py b/lcd-ipaddress-display/drivers/i2c_dev.py
new file mode 100644
index 0000000..3a0a252
--- /dev/null
+++ b/lcd-ipaddress-display/drivers/i2c_dev.py
@@ -0,0 +1,272 @@
+from smbus import SMBus
+from RPi.GPIO import RPI_REVISION
+from time import sleep
+from re import findall, match
+from subprocess import check_output
+from os.path import exists
+
+# old and new versions of the RPi have swapped the two i2c buses
+# they can be identified by RPI_REVISION (or check sysfs)
+BUS_NUMBER = 0 if RPI_REVISION == 1 else 1
+
+# other commands
+LCD_CLEARDISPLAY = 0x01
+LCD_RETURNHOME = 0x02
+LCD_ENTRYMODESET = 0x04
+LCD_DISPLAYCONTROL = 0x08
+LCD_CURSORSHIFT = 0x10
+LCD_FUNCTIONSET = 0x20
+LCD_SETCGRAMADDR = 0x40
+LCD_SETDDRAMADDR = 0x80
+
+# flags for display entry mode
+LCD_ENTRYRIGHT = 0x00
+LCD_ENTRYLEFT = 0x02
+LCD_ENTRYSHIFTINCREMENT = 0x01
+LCD_ENTRYSHIFTDECREMENT = 0x00
+
+# flags for display on/off control
+LCD_DISPLAYON = 0x04
+LCD_DISPLAYOFF = 0x00
+LCD_CURSORON = 0x02
+LCD_CURSOROFF = 0x00
+LCD_BLINKON = 0x01
+LCD_BLINKOFF = 0x00
+
+# flags for display/cursor shift
+LCD_DISPLAYMOVE = 0x08
+LCD_CURSORMOVE = 0x00
+LCD_MOVERIGHT = 0x04
+LCD_MOVELEFT = 0x00
+
+# flags for function set
+LCD_8BITMODE = 0x10
+LCD_4BITMODE = 0x00
+LCD_2LINE = 0x08
+LCD_1LINE = 0x00
+LCD_5x10DOTS = 0x04
+LCD_5x8DOTS = 0x00
+
+# flags for backlight control
+LCD_BACKLIGHT = 0x08
+LCD_NOBACKLIGHT = 0x00
+
+En = 0b00000100 # Enable bit
+Rw = 0b00000010 # Read/Write bit
+Rs = 0b00000001 # Register select bit
+
+class I2CDevice:
+ def __init__(self, addr=None, addr_default=None, bus=BUS_NUMBER):
+ if not addr:
+ # try autodetect address, else use default if provided
+ try:
+ self.addr = int('0x{}'.format(
+ findall("[0-9a-z]{2}(?!:)", check_output(['/usr/sbin/i2cdetect', '-y', str(BUS_NUMBER)]).decode())[0]), base=16) \
+ if exists('/usr/sbin/i2cdetect') else addr_default
+ except:
+ self.addr = addr_default
+ else:
+ self.addr = addr
+ self.bus = SMBus(bus)
+
+ # write a single command
+ def write_cmd(self, cmd):
+ self.bus.write_byte(self.addr, cmd)
+ sleep(0.0001)
+
+ # write a command and argument
+ def write_cmd_arg(self, cmd, data):
+ self.bus.write_byte_data(self.addr, cmd, data)
+ sleep(0.0001)
+
+ # write a block of data
+ def write_block_data(self, cmd, data):
+ self.bus.write_block_data(self.addr, cmd, data)
+ sleep(0.0001)
+
+ # read a single byte
+ def read(self):
+ return self.bus.read_byte(self.addr)
+
+ # read
+ def read_data(self, cmd):
+ return self.bus.read_byte_data(self.addr, cmd)
+
+ # read a block of data
+ def read_block_data(self, cmd):
+ return self.bus.read_block_data(self.addr, cmd)
+
+
+class Lcd:
+ def __init__(self, addr=None):
+ self.addr = addr
+ self.lcd = I2CDevice(addr=self.addr, addr_default=0x27)
+ self.lcd_write(0x03)
+ self.lcd_write(0x03)
+ self.lcd_write(0x03)
+ self.lcd_write(0x02)
+ self.lcd_write(LCD_FUNCTIONSET | LCD_2LINE | LCD_5x8DOTS | LCD_4BITMODE)
+ self.lcd_write(LCD_DISPLAYCONTROL | LCD_DISPLAYON)
+ self.lcd_write(LCD_CLEARDISPLAY)
+ self.lcd_write(LCD_ENTRYMODESET | LCD_ENTRYLEFT)
+ sleep(0.2)
+
+ # clocks EN to latch command
+ def lcd_strobe(self, data):
+ self.lcd.write_cmd(data | En | LCD_BACKLIGHT)
+ sleep(.0005)
+ self.lcd.write_cmd(((data & ~En) | LCD_BACKLIGHT))
+ sleep(.0001)
+
+ def lcd_write_four_bits(self, data):
+ self.lcd.write_cmd(data | LCD_BACKLIGHT)
+ self.lcd_strobe(data)
+
+ # write a command to lcd
+ def lcd_write(self, cmd, mode=0):
+ self.lcd_write_four_bits(mode | (cmd & 0xF0))
+ self.lcd_write_four_bits(mode | ((cmd << 4) & 0xF0))
+
+ # put string function
+ def lcd_display_string(self, string, line):
+ if line == 1:
+ self.lcd_write(0x80)
+ if line == 2:
+ self.lcd_write(0xC0)
+ if line == 3:
+ self.lcd_write(0x94)
+ if line == 4:
+ self.lcd_write(0xD4)
+ for char in string:
+ self.lcd_write(ord(char), Rs)
+
+ # put extended string function. Extended string may contain placeholder like {0xFF} for
+ # displaying the particular symbol from the symbol table
+ def lcd_display_extended_string(self, string, line):
+ if line == 1:
+ self.lcd_write(0x80)
+ if line == 2:
+ self.lcd_write(0xC0)
+ if line == 3:
+ self.lcd_write(0x94)
+ if line == 4:
+ self.lcd_write(0xD4)
+ # Process the string
+ while string:
+ # Trying to find pattern {0xFF} representing a symbol
+ result = match(r'\{0[xX][0-9a-fA-F]{2}\}', string)
+ if result:
+ self.lcd_write(int(result.group(0)[1:-1], 16), Rs)
+ string = string[6:]
+ else:
+ self.lcd_write(ord(string[0]), Rs)
+ string = string[1:]
+
+ # clear lcd and set to home
+ def lcd_clear(self):
+ self.lcd_write(LCD_CLEARDISPLAY)
+ self.lcd_write(LCD_RETURNHOME)
+
+ # backlight control (on/off)
+ # options: lcd_backlight(1) = ON, lcd_backlight(0) = OFF
+ def lcd_backlight(self, state):
+ if state == 1:
+ self.lcd.write_cmd(LCD_BACKLIGHT)
+ elif state == 0:
+ self.lcd.write_cmd(LCD_NOBACKLIGHT)
+
+class CustomCharacters:
+ def __init__(self, lcd):
+ self.lcd = lcd
+ # Data for custom character #1. Code {0x00}.
+ self.char_1_data = ["11111",
+ "10001",
+ "10001",
+ "10001",
+ "10001",
+ "10001",
+ "10001",
+ "11111"]
+ # Data for custom character #2. Code {0x01}
+ self.char_2_data = ["11111",
+ "10001",
+ "10001",
+ "10001",
+ "10001",
+ "10001",
+ "10001",
+ "11111"]
+ # Data for custom character #3. Code {0x02}
+ self.char_3_data = ["11111",
+ "10001",
+ "10001",
+ "10001",
+ "10001",
+ "10001",
+ "10001",
+ "11111"]
+ # Data for custom character #4. Code {0x03}
+ self.char_4_data = ["11111",
+ "10001",
+ "10001",
+ "10001",
+ "10001",
+ "10001",
+ "10001",
+ "11111"]
+ # Data for custom character #5. Code {0x04}
+ self.char_5_data = ["11111",
+ "10001",
+ "10001",
+ "10001",
+ "10001",
+ "10001",
+ "10001",
+ "11111"]
+ # Data for custom character #6. Code {0x05}
+ self.char_6_data = ["11111",
+ "10001",
+ "10001",
+ "10001",
+ "10001",
+ "10001",
+ "10001",
+ "11111"]
+ # Data for custom character #7. Code {0x06}
+ self.char_7_data = ["11111",
+ "10001",
+ "10001",
+ "10001",
+ "10001",
+ "10001",
+ "10001",
+ "11111"]
+ # Data for custom character #8. Code {0x07}
+ self.char_8_data = ["11111",
+ "10001",
+ "10001",
+ "10001",
+ "10001",
+ "10001",
+ "10001",
+ "11111"]
+
+ # load custom character data to CG RAM for later use in extended string. Data for
+ # characters is hold in file custom_characters.txt in the same folder as i2c_dev.py
+ # file. These custom characters can be used in printing of extended string with a
+ # placeholder with desired character codes: 1st - {0x00}, 2nd - {0x01}, 3rd - {0x02},
+ # 4th - {0x03}, 5th - {0x04}, 6th - {0x05}, 7th - {0x06} and 8th - {0x07}.
+ def load_custom_characters_data(self):
+ self.chars_list = [self.char_1_data, self.char_2_data, self.char_3_data,
+ self.char_4_data, self.char_5_data, self.char_6_data,
+ self.char_7_data, self.char_8_data]
+
+ # commands to load character adress to RAM srarting from desired base adresses:
+ char_load_cmds = [0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78]
+ for char_num in range(8):
+ # command to start loading data into CG RAM:
+ self.lcd.lcd_write(char_load_cmds[char_num])
+ for line_num in range(8):
+ line = self.chars_list[char_num][line_num]
+ binary_str_cmd = "0b000{0}".format(line)
+ self.lcd.lcd_write(int(binary_str_cmd, 2), Rs)