Skip to content

Instantly share code, notes, and snippets.

@pingud98
Created September 1, 2020 07:17
Show Gist options
  • Save pingud98/f3c9f4dbcc0d3860f89034f83c4e9702 to your computer and use it in GitHub Desktop.
Save pingud98/f3c9f4dbcc0d3860f89034f83c4e9702 to your computer and use it in GitHub Desktop.
I2C LCD display scripts for Friendlyelec NanoPi NEO2 based NAS
# -*- coding: utf-8 -*-
# Original code found at:
# https://gist.github.com/DenisFromHR/cc863375a6e19dce359d
"""
Compiled, mashed and generally mutilated 2014-2015 by Denis Pleic
Made available under GNU GENERAL PUBLIC LICENSE
# Modified Python I2C library for Raspberry Pi
# as found on http://www.recantha.co.uk/blog/?p=4849
# Joined existing 'i2c_lib.py' and 'lcddriver.py' into a single library
# added bits and pieces from various sources
# By DenisFromHR (Denis Pleic)
# 2015-02-10, ver 0.1
"""
# i2c bus (0 -- original Pi, 1 -- Rev 2 Pi)
I2CBUS = 0
# LCD Address
ADDRESS = 0x27
import smbus
from time import sleep
class i2c_device:
def __init__(self, addr, port=I2CBUS):
self.addr = addr
self.bus = smbus.SMBus(port)
# 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)
# 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 lcd:
#initializes objects and lcd
def __init__(self):
self.lcd_device = i2c_device(ADDRESS)
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_device.write_cmd(data | En | LCD_BACKLIGHT)
sleep(.0005)
self.lcd_device.write_cmd(((data & ~En) | LCD_BACKLIGHT))
sleep(.0001)
def lcd_write_four_bits(self, data):
self.lcd_device.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))
# write a character to lcd (or character rom) 0x09: backlight | RS=DR<
# works!
def lcd_write_char(self, charvalue, mode=1):
self.lcd_write_four_bits(mode | (charvalue & 0xF0))
self.lcd_write_four_bits(mode | ((charvalue << 4) & 0xF0))
# put string function with optional char positioning
def lcd_display_string(self, string, line=1, pos=0):
if line == 1:
pos_new = pos
elif line == 2:
pos_new = 0x40 + pos
elif line == 3:
pos_new = 0x14 + pos
elif line == 4:
pos_new = 0x54 + pos
self.lcd_write(0x80 + pos_new)
for char in string:
self.lcd_write(ord(char), Rs)
# clear lcd and set to home
def lcd_clear(self):
self.lcd_write(LCD_CLEARDISPLAY)
self.lcd_write(LCD_RETURNHOME)
# define backlight on/off (lcd.backlight(1); off= lcd.backlight(0)
def backlight(self, state): # for state, 1 = on, 0 = off
if state == 1:
self.lcd_device.write_cmd(LCD_BACKLIGHT)
elif state == 0:
self.lcd_device.write_cmd(LCD_NOBACKLIGHT)
# add custom characters (0 - 7)
def lcd_load_custom_chars(self, fontdata):
self.lcd_write(0x40);
for char in fontdata:
for line in char:
self.lcd_write_char(line)
start on runlevel [2345]
stop on runlevel [!2345]
exec sh /root/mystartupscript.sh
[Unit]
Description=LCDscreen service
[Service]
Type=simple
ExecStart=/usr/bin/python /root/neo2lcdthree.py
WorkingDirectory=/root/
Restart=on-failure
[Install]
WantedBy=multi-user.target
import socket
import fcntl
import struct
import psutil
import os
import sys
import time
home_dir = os.path.expanduser("~")
sys.path.append(home_dir)
import I2C_LCD_Driver
import SDL_DS1307
mylcd = I2C_LCD_Driver.lcd()
ds1307 = SDL_DS1307.SDL_DS1307(0, 0x68)
def get_ip_address(ifname):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
return socket.inet_ntoa(fcntl.ioctl(
s.fileno(),
0x8915,
struct.pack('256s', ifname[:15])
)[20:24])
#mylcd.lcd_display_string("hello",1)
#mylcd.lcd_display_string("IP Address:", 1)
#mylcd.lcd_display_string(get_ip_address('eth0'), 2)
# Return RAM information (unit=kb) in a list
# Index 0: total RAM
# Index 1: used RAM
# Index 2: free RAM
def getRAMinfo():
p = os.popen('free')
i = 0
while 1:
i = i + 1
line = p.readline()
if i==2:
return(line.split()[1:4])
mylcd.lcd_clear()
while True:
#CPU usage and time
CPU_usage = psutil.cpu_percent(interval = .5)
mylcd.lcd_display_string("CPU Load %s%% " % (CPU_usage), 1)
mylcd.lcd_display_string("%s" % ds1307.read_datetime(), 2)
time.sleep(3)
mylcd.lcd_clear()
#IP ADDRESS
mylcd.lcd_display_string("IP Address : ", 1)
mylcd.lcd_display_string(get_ip_address('eth0'), 2)
time.sleep(3)
mylcd.lcd_clear()
#RAM USAGE
RAM_stats = getRAMinfo()
RAM_used = round(int(RAM_stats[1]) / 1000,1)
RAM_free = round(int(RAM_stats[2]) / 1000,1)
mylcd.lcd_display_string("RAM Used %sMB" % (RAM_used),1)
mylcd.lcd_display_string("RAM Free %sMB" % (RAM_free),2)
time.sleep(3)
mylcd.lcd_clear()
mylcd.lcd_display_string("All your base",1)
mylcd.lcd_display_string("are belong to us",2)
time.sleep(3)
mylcd.lcd_clear()
#!/usr/bin/env python
# SDL_DS1307.py Python Driver Code
# SwitchDoc Labs 07/10/2014
# Shovic V 1.0
# only works in 24 hour mode
# original code from below (DS1307 Code originally - had issues with 24 hour mode. Removed 12 hour mode)
#encoding: utf-8
# Copyright (C) 2013 @XiErCh
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
from datetime import datetime
import smbus
def _bcd_to_int(bcd):
"""Decode a 2x4bit BCD to a integer.
"""
out = 0
for d in (bcd >> 4, bcd):
for p in (1, 2, 4 ,8):
if d & 1:
out += p
d >>= 1
out *= 10
return out / 10
def _int_to_bcd(n):
"""Encode a one or two digits number to the BCD.
"""
bcd = 0
for i in (n // 10, n % 10):
for p in (8, 4, 2, 1):
if i >= p:
bcd += 1
i -= p
bcd <<= 1
return bcd >> 1
class SDL_DS1307():
_REG_SECONDS = 0x00
_REG_MINUTES = 0x01
_REG_HOURS = 0x02
_REG_DAY = 0x03
_REG_DATE = 0x04
_REG_MONTH = 0x05
_REG_YEAR = 0x06
_REG_CONTROL = 0x07
def __init__(self, twi=1, addr=0x68):
self._bus = smbus.SMBus(twi)
self._addr = addr
def _write(self, register, data):
#print "addr =0x%x register = 0x%x data = 0x%x %i " % (self._addr, register, data,_bcd_to_int(data))
self._bus.write_byte_data(self._addr, register, data)
def _read(self, data):
returndata = self._bus.read_byte_data(self._addr, data)
#print "addr = 0x%x data = 0x%x %i returndata = 0x%x %i " % (self._addr, data, data, returndata, _bcd_to_int(returndata))
return returndata
def _read_seconds(self):
return _bcd_to_int(self._read(self._REG_SECONDS))
def _read_minutes(self):
return _bcd_to_int(self._read(self._REG_MINUTES))
def _read_hours(self):
d = self._read(self._REG_HOURS)
if (d == 0x64):
d = 0x40
return _bcd_to_int(d & 0x3F)
def _read_day(self):
return _bcd_to_int(self._read(self._REG_DAY))
def _read_date(self):
return _bcd_to_int(self._read(self._REG_DATE))
def _read_month(self):
return _bcd_to_int(self._read(self._REG_MONTH))
def _read_year(self):
return _bcd_to_int(self._read(self._REG_YEAR))
def read_all(self):
"""Return a tuple such as (year, month, date, day, hours, minutes,
seconds).
"""
return (self._read_year(), self._read_month(), self._read_date(),
self._read_day(), self._read_hours(), self._read_minutes(),
self._read_seconds())
def read_str(self):
"""Return a string such as 'YY-DD-MMTHH-MM-SS'.
"""
return '%02d-%02d-%02dT%02d:%02d:%02d' % (self._read_year(),
self._read_month(), self._read_date(), self._read_hours(),
self._read_minutes(), self._read_seconds())
def read_datetime(self, century=21, tzinfo=None):
"""Return the datetime.datetime object.
"""
return datetime((century - 1) * 100 + self._read_year(),
self._read_month(), self._read_date(), self._read_hours(),
self._read_minutes(), self._read_seconds(), 0, tzinfo=tzinfo)
def write_all(self, seconds=None, minutes=None, hours=None, day=None,
date=None, month=None, year=None, save_as_24h=True):
"""Direct write un-none value.
Range: seconds [0,59], minutes [0,59], hours [0,23],
day [0,7], date [1-31], month [1-12], year [0-99].
"""
if seconds is not None:
if seconds < 0 or seconds > 59:
raise ValueError('Seconds is out of range [0,59].')
self._write(self._REG_SECONDS, _int_to_bcd(seconds))
if minutes is not None:
if minutes < 0 or minutes > 59:
raise ValueError('Minutes is out of range [0,59].')
self._write(self._REG_MINUTES, _int_to_bcd(minutes))
if hours is not None:
if hours < 0 or hours > 23:
raise ValueError('Hours is out of range [0,23].')
self._write(self._REG_HOURS, _int_to_bcd(hours)) # not | 0x40 as in the orignal code
if year is not None:
if year < 0 or year > 99:
raise ValueError('Years is out of range [0,99].')
self._write(self._REG_YEAR, _int_to_bcd(year))
if month is not None:
if month < 1 or month > 12:
raise ValueError('Month is out of range [1,12].')
self._write(self._REG_MONTH, _int_to_bcd(month))
if date is not None:
if date < 1 or date > 31:
raise ValueError('Date is out of range [1,31].')
self._write(self._REG_DATE, _int_to_bcd(date))
if day is not None:
if day < 1 or day > 7:
raise ValueError('Day is out of range [1,7].')
self._write(self._REG_DAY, _int_to_bcd(day))
def write_datetime(self, dt):
"""Write from a datetime.datetime object.
"""
self.write_all(dt.second, dt.minute, dt.hour,
dt.isoweekday(), dt.day, dt.month, dt.year % 100)
def write_now(self):
"""Equal to DS1307.write_datetime(datetime.datetime.now()).
"""
self.write_datetime(datetime.now())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment