i2c 20 pin alternative python display for 2 drives

Post Reply
puremind
Posts: 40
Joined: Wed Nov 21, 2018 2:27 am
languages_spoken: english
ODROIDs: Odroid H2 Rev B
Has thanked: 2 times
Been thanked: 4 times
Contact:

i2c 20 pin alternative python display for 2 drives

Unread post by puremind » Mon Jul 01, 2019 12:48 am

Hi All:

If anybody has got the i2c 20 pin and installed 2 drives, I've modified the hello_world.py file to display the wake/sleep status for those. Original git from author https://github.com/djjproject/odroidh2_i2c_lcd

Also, I've modified the TX/RW Mbps to UP/DL and MB/s , plus some date time adjustment to EU vs US m-d format and removal of decimals for CPU and MEM % consumption.

See pic sample below if anyone interested simply update your /home/odroidlcd/hello_world.py file to the below code, then restart service ( service odroidlcd restart ) or reboot machine:
(it might help others to do their own)

If anybody has other options to share or other ideas on how to use this LCD display it would be great :)

Updated:
1. Start of the script will display your hostname on LCD
2. You can define what sdx drives you want displayed
3. CPU and MEM moved to left side lines 2 & 3 where Upload and DownLoad to the right so it's all easier to read


Code: Select all

# import modules
import lcddriver as lcd
import stat
import os
import psutil as ps
from time import time
from time import sleep
from datetime import datetime

sleep(10)

# test code
#lcd.display_string("11111111111111111111222222222222222222223333333333333333333344444444444444444444", 1)


# load lcd
lcd = lcd.lcd()

lcd.display_string("                    ",1)
lcd.display_string(str.center(str(os.popen('hostname').readline())[:-1],20,' '),2)
lcd.display_string("      STARTING      ",3)
lcd.display_string("                    ",4)



#change here to sda sdb sdc etc
#disk1_to_check="sda"
#disk2_to_check="sdb"

disk1_to_check="sda"
disk2_to_check="sdb"


sleep(1)





#check if disk exists function
def disk_exists(path):
     try:
             return stat.S_ISBLK(os.stat(path).st_mode)
     except:
             return False


# network status get function
def get_bytes(t, iface='enp2s0'):
    with open('/sys/class/net/' + iface + '/statistics/' + t + '_bytes', 'r') as f:
        data = f.read();
        return int(data)


while True:

  # foot powered coding
  #cpuUsage=str(round(float(os.popen('''grep 'cpu ' /proc/stat | awk '{usage=($2+$4)*100/($2+$4+$5)} END {print usage }' ''').readline()),2))
  #tot_m, used_m, free_m = map(int, os.popen('free -t -m').readlines()[-1].split()[1:])
  #percentMem=str(round(used_m/tot_m))


  # check if disk sda exists
  
  
  #hddexists1=str(os.popen('ls /dev/'+disk1_to_check).readline())[:][:-1]
  
  
  if disk_exists("/dev/"+disk1_to_check)!=True:
    hddstr1="NONE"
  else :

   # read hdd state from hdparm
   hddstate1=str(os.popen('hdparm -C /dev/'+disk1_to_check+' | grep state | cut -f 2 -d :').readline())[2:][:-1]

   if hddstate1=="standby":
    hddstr1="SLEEP"
   else :
    hddstr1="WAKE"


  

  if disk_exists("/dev/"+disk2_to_check)!=True:
    hddstr2="NONE"
  else :

   # read hdd state from hdparm
   hddstate2=str(os.popen('hdparm -C /dev/'+disk2_to_check+' | grep state | cut -f 2 -d :').readline())[2:][:-1]

   if hddstate2=="standby":
    hddstr2="SLEEP"
   else :
    hddstr2="WAKE"



 # line 1 print (hddstate, friendly name)
  lcd.display_string(disk1_to_check+":"+hddstr1.rjust(5)+"  "+disk2_to_check+":"+hddstr2.rjust(5), 1)





  # get network speed for 1sec
  tx1 = get_bytes('tx')
  rx1 = get_bytes('rx')
  sleep(1)
  tx2 = get_bytes('tx')
  rx2 = get_bytes('rx')
  tx_speed = (tx2 - tx1)/1000000.0
  rx_speed = (rx2 - rx1)/1000000.0



  # line 2 print (cpu, memory)
  # use psutil to get CPU usage and Memory Usage
  # line 3 print (network speed)
  # bps -> mpbs (*8)

  lcd.display_string("CPU:"+str(round(ps.cpu_percent())).rjust(3)+"%"+" UP:"+str(round(tx_speed*8*1.048/10)).rjust(3)+" MB/s", 2)
  lcd.display_string("MEM:"+str(round(ps.virtual_memory()[2])).rjust(3)+"%"+" DL:"+str(round(rx_speed*8*1.048/10)).rjust(3)+" MB/s", 3)

  # line 4 print (cputemp, date, time)
  # use lm-sensors to get cpu temp / get time data from python internal method
  dateString = datetime.now().strftime('%d-%b')
  timeString = datetime.now().strftime('%H:%M:%S')
  lcd.display_string("T"+os.popen('sensors | grep "temp1:" | cut -d+ -f2 | cut -c1-2').read()[:-1]+"C "+dateString+" "+timeString, 4)

  # line 4 print (cputemp, uptime)
  # use /proc/uptime and python divmod method
  #uptime=os.popen('cat /proc/uptime | cut -d " " -f1').read()
  #uptimeDay=divmod(float(uptime),86400)
  #uptimeHour=divmod(uptimeDay[1],3600)
  #uptimeMin=divmod(uptimeHour[1],60)
  #uptimeString=str(int(uptimeDay[0]))+"D:"+str(int(uptimeHour[0]))+"H:"+str(int(uptimeMin[0]))+"M"
  #lcd.display_string("TEMP:"+os.popen('sensors | grep "temp1:" | cut -d+ -f2 | cut -c1-2').read()[:-1]+"C "+uptimeString.zfill(3), 4)


  # sleep(1)


Image-1.jpg
Image-1.jpg (187.46 KiB) Viewed 744 times



ADDING NEW SCRIPT IN A NEW OPST ON THIS THREAD
Last edited by puremind on Sat Jul 13, 2019 4:49 am, edited 4 times in total.
These users thanked the author puremind for the post:
domih (Mon Jul 22, 2019 9:53 am)
Odroid H2 Rev B

User avatar
odroid
Site Admin
Posts: 31381
Joined: Fri Feb 22, 2013 11:14 pm
languages_spoken: English
ODROIDs: ODROID
Has thanked: 54 times
Been thanked: 184 times
Contact:

Re: i2c 20 pin alternative python display for 2 drives

Unread post by odroid » Mon Jul 01, 2019 1:55 pm

Thank you for sharing a very nice and useful Python code. :)

RomaT
Posts: 144
Joined: Thu Oct 23, 2014 4:48 pm
languages_spoken: Russian
ODROIDs: -H2 rev.B, -XU3, -XU4, -C1, -C2, -W, -VU, CloudShell
Location: Perm, Russia
Has thanked: 0
Been thanked: 8 times
Contact:

Re: i2c 20 pin alternative python display for 2 drives

Unread post by RomaT » Sat Jul 06, 2019 8:49 pm

In the absence of disk writes "wake"

puremind
Posts: 40
Joined: Wed Nov 21, 2018 2:27 am
languages_spoken: english
ODROIDs: Odroid H2 Rev B
Has thanked: 2 times
Been thanked: 4 times
Contact:

Re: i2c 20 pin alternative python display for 2 drives

Unread post by puremind » Sat Jul 06, 2019 9:51 pm

RomaT wrote:
Sat Jul 06, 2019 8:49 pm
In the absence of disk writes "wake"
correct
I am rewriting this with a nicer look and will post back
Odroid H2 Rev B

puremind
Posts: 40
Joined: Wed Nov 21, 2018 2:27 am
languages_spoken: english
ODROIDs: Odroid H2 Rev B
Has thanked: 2 times
Been thanked: 4 times
Contact:

Re: i2c 20 pin alternative python display for 2 drives

Unread post by puremind » Sat Jul 06, 2019 10:45 pm

First post updated with script and new picture to fix the no device detected also added:

1. Start of the script will display your hostname on LCD
2. You can define what sdx drives you want displayed
3. CPU and MEM moved to left side lines 2 & 3 where Upload and DownLoad to the right so it's all easier to read
Odroid H2 Rev B

RomaT
Posts: 144
Joined: Thu Oct 23, 2014 4:48 pm
languages_spoken: Russian
ODROIDs: -H2 rev.B, -XU3, -XU4, -C1, -C2, -W, -VU, CloudShell
Location: Perm, Russia
Has thanked: 0
Been thanked: 8 times
Contact:

Re: i2c 20 pin alternative python display for 2 drives

Unread post by RomaT » Sun Jul 07, 2019 12:25 am

Generally a good idea to use LCD ...
In my case, I had to connect power to +5V
from 3.3V as described in Wiki, the display (Winstar WH2004A-YYH-CT) did not show anything.
and there is an error in the description sudo apt install python3-psutil lm-sensor hdparm must be lm-sensors
.
P6290868s.JPG
P6290868s.JPG (113.86 KiB) Viewed 727 times

puremind
Posts: 40
Joined: Wed Nov 21, 2018 2:27 am
languages_spoken: english
ODROIDs: Odroid H2 Rev B
Has thanked: 2 times
Been thanked: 4 times
Contact:

Re: i2c 20 pin alternative python display for 2 drives

Unread post by puremind » Sun Jul 07, 2019 12:53 am

Lol, I see you've taken pieces from here and there ;)

Note the LCD I got has the blue background/white letters and yours have a green background with black letters, I wonder why the difference ?

This is the one I bought:
https://www.hardkernel.com/shop/i2c-lcd-module/
Odroid H2 Rev B

puremind
Posts: 40
Joined: Wed Nov 21, 2018 2:27 am
languages_spoken: english
ODROIDs: Odroid H2 Rev B
Has thanked: 2 times
Been thanked: 4 times
Contact:

Re: i2c 20 pin alternative python display for 2 drives

Unread post by puremind » Sun Jul 07, 2019 12:58 am

Ok, I see, there's a lot of them ... would be nice to see other alternatives that work with the H2, specially the OLED models look very nice.
Odroid H2 Rev B

RomaT
Posts: 144
Joined: Thu Oct 23, 2014 4:48 pm
languages_spoken: Russian
ODROIDs: -H2 rev.B, -XU3, -XU4, -C1, -C2, -W, -VU, CloudShell
Location: Perm, Russia
Has thanked: 0
Been thanked: 8 times
Contact:

Re: i2c 20 pin alternative python display for 2 drives

Unread post by RomaT » Sun Jul 07, 2019 1:11 am

I think you can use any LCD with interface 6800 or I2C ...
I bought the display in my country with the support of my language (in the first line LCD of my photo it can be seen).

puremind
Posts: 40
Joined: Wed Nov 21, 2018 2:27 am
languages_spoken: english
ODROIDs: Odroid H2 Rev B
Has thanked: 2 times
Been thanked: 4 times
Contact:

Re: i2c 20 pin alternative python display for 2 drives

Unread post by puremind » Sun Jul 07, 2019 9:47 pm

Would one of these work ?
https://www.ebay.com/itm/0-96-I2C-4PIN- ... SwKdZbYtEW

The look pretty damn cheap
Odroid H2 Rev B

RomaT
Posts: 144
Joined: Thu Oct 23, 2014 4:48 pm
languages_spoken: Russian
ODROIDs: -H2 rev.B, -XU3, -XU4, -C1, -C2, -W, -VU, CloudShell
Location: Perm, Russia
Has thanked: 0
Been thanked: 8 times
Contact:

Re: i2c 20 pin alternative python display for 2 drives

Unread post by RomaT » Sun Jul 07, 2019 10:35 pm

It will work, only it is a graphic, it will need another library of drivers and font library ...
In the subject we are considering a character LCD, already with a character set.

puremind
Posts: 40
Joined: Wed Nov 21, 2018 2:27 am
languages_spoken: english
ODROIDs: Odroid H2 Rev B
Has thanked: 2 times
Been thanked: 4 times
Contact:

Re: i2c 20 pin alternative python display for 2 drives

Unread post by puremind » Thu Jul 11, 2019 6:23 am

Everybody,
I've made some changes here and there if anybody wants to try...

Managed, Celsius vs Fahrenheit with custom chars
Moving Bars for CPU & RAM. Two drives status with storage capacity.

Same as the first post, simply update the hello_world.py as instructed, then edit the config section on the script for full customisation, including 3/4 characters for the first drive to monitor.

Animation really nice on the percentage section.

Code: Select all

# -*- coding: utf-8 -*-
"""
Compiled, mashed and generally REmutilated 2019 by puremind
Made available under GNU GENERAL PUBLIC LICENSE

# added bits and pieces from various sources
# 2019-07-07, ver 0.1
# Add your own custom stuff with custom characters

"""
from time import sleep
import lcddriver as lcd


lcd = lcd.lcd()

lcd.display_string("                    ",1)
lcd.display_string("                    ",2)
lcd.display_string("                    ",3)
lcd.display_string("                    ",4)


sleep(1)

lcd.clear()



#set to False for Celsius, True for Fahrenheit
fahrenheit=False


#change here to sda sdb sdc etc
#disk1_to_check="sda"
#disk2_to_check="sdb"

disk1_to_check="nvme0n1p3"

#change here to partition full name for pct usage, check with "df -h"
path_disk1="/"


disk2_to_check="sda"
path_disk2="/mnt/data"

#Time to sleep between checks. Defaults 3
delay=3


#offsets 1 char to the right if the first disk starts with "nvme"
if disk1_to_check[0:4]!="nvme":
 nvmeoffset=0
else :
 nvmeoffset=1




# import modules
#import RPi_I2C_driver
import stat
import os
import psutil as ps
import math
from time import time

from datetime import datetime

sleep(5)



# -*- coding: utf-8 -*-
"""
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

"""
#
#
import smbus
from time import *

class i2c_device:
   def __init__(self, addr, port=1):
      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)



# LCD Address
#ADDRESS = 0x3F
ADDRESS = 0x27

# I2C bus
BUS = 1

# 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, BUS)

      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.15)


   # 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
   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)

   # 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)         
         
         
   # define precise positioning (addition from the forum)
   def lcd_display_string_pos(self, string, line, pos):
    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)
      
      







#check if disk exists function
def disk_exists(path):
     try:
             return stat.S_ISBLK(os.stat(path).st_mode)
     except:
             return False


# network status get function
def get_bytes(t, iface='enp2s0'):
    with open('/sys/class/net/' + iface + '/statistics/' + t + '_bytes', 'r') as f:
        data = f.read();
        return int(data)






sleep(3)

# load lcd
lcd = lcd()

sleep(1)

# 5 by 8 custom char creation
#https://www.quinapalus.com/hd44780udg.html

#More info here with full char set
#http://www.electronic-engineering.ch/microchip/datasheets/lcd/charset.gif

# Define some static characters

fontdata = [
         # Char 0 - Celsius
        [ 0x8,0x14,0x8,0x3,0x4,0x4,0x4,0x3],
 		# Char 1 1/5 block 
 		[ 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10],
 		# Char 2 2/5 block 
 		[ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18],
 		# Char 3 3/5 block 
 		[ 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c],
 		# Char 4 4/5 block 
 		[ 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e],
        # Char 5 - Arrow up
        [ 0x0,0x4,0xe,0x1f,0x4,0x4,0x4,0x0],
        # Char 6 - Arrow down
        [ 0x0,0x4,0x4,0x4,0x1f,0xe,0x4,0x0],
        # Char 7 ZZ
        [ 0x1e,0x4,0x8,0x1e,0xf,0x2,0x4,0xf]

]


lcd.lcd_load_custom_chars(fontdata)

sleep(1)

lcd.lcd_display_string("                    ",1)
lcd.lcd_display_string(str.center(str(os.popen('hostname').readline())[:-1],20,' '),2)
lcd.lcd_display_string("      STARTING      ",3)
lcd.lcd_display_string("                    ",4)

sleep(2)

lcd.lcd_display_string(disk1_to_check[0:3+nvmeoffset]+" ? ??% "+disk2_to_check[0:3]+" ? ??%",1)

#Set 0 as speed for network first cycle
#Fixed elements
#TX / RX Arrows

lcd.lcd_display_string("CPU ??% "+chr(126)+"      "+chr(127)+" ??"+chr(6),2)
lcd.lcd_display_string("RAM ??% "+chr(126)+"      "+chr(127)+" ??"+chr(5),3)

#Celsius
if fahrenheit!=True:
 lcd.lcd_display_string_pos("??"+chr(0),4,17)
else:
 lcd.lcd_display_string_pos("??F",4,17)

sleep(1)
steps3 = [1, 2, 3]
steps = [0, 1, 2, 3, 4, 5]

while True:


  # check if disk  exists
  
  
  # get network speed for delay sec
  tx1 = get_bytes('tx')
  rx1 = get_bytes('rx')

  
  if disk_exists("/dev/"+disk1_to_check)!=True:
    hddstr1=chr(6)
  else :

   # read hdd state from hdparm
   hddstate1=str(os.popen('hdparm -C /dev/'+disk1_to_check+' | grep state | cut -f 2 -d :').readline())[2:][:-1]

   if hddstate1=="standby":
    hddstr1=chr(7)
   else :
    hddstr1=chr(5)


  

  if disk_exists("/dev/"+disk2_to_check)!=True:
    hddstr2=chr(6)
  else :

   # read hdd state from hdparm
   hddstate2=str(os.popen('hdparm -C /dev/'+disk2_to_check+' | grep state | cut -f 2 -d :').readline())[2:][:-1]

   if hddstate2=="standby":
    hddstr2=chr(7)
   else :
    hddstr2=chr(5)



 # line 1 print (hddstate, friendly name)

  #lcd.lcd_display_string(disk1_to_check+":"+hddstr1.rjust(5)+"  "+disk2_to_check+":"+hddstr2.rjust(5), 1)
  lcd.lcd_display_string_pos(hddstr1, 1,4+nvmeoffset)  
  lcd.lcd_display_string_pos(hddstr2, 1,15)  


  obj_Disk1 = ps.disk_usage(path_disk1)
  lcd.lcd_display_string_pos(str(round(obj_Disk1.percent)), 1,6+nvmeoffset)  

  obj_Disk2 = ps.disk_usage(path_disk2)
  lcd.lcd_display_string_pos(str(round(obj_Disk2.percent)), 1,17)  


  # line 2 print (cpu, memory)
  # use psutil to get CPU usage and Memory Usage
  # line 3 print (network speed)
  # bps -> mpbs (*8)


 

  for z in range(2) :
   sleep(delay/2)
   cpupct=ps.cpu_percent()
   rampct=ps.virtual_memory()[2]
  

   lcd.lcd_display_string_pos(str(math.floor(cpupct)).rjust(3),2,3)
   lcd.lcd_display_string_pos(str(math.floor(rampct)).rjust(3),3,3)

#  for y in range(101):
#    sleep(0.1)
#    cpupct=y
#    lcd.lcd_display_string_pos(str(y),3,10)

   for x in steps:
     if (math.floor(cpupct+1)>x*(100/6)) and (math.floor(cpupct)>(x+1)*(100/6)) or cpupct>98:
      lcd.lcd_display_string_pos(chr(255),2,9+x)
     else:
      if ((math.floor(cpupct)>x*(100/6)+1) and (math.floor(cpupct)<(x+1)*(100/6)) and cpupct>2):
       lcd.lcd_display_string_pos(chr(min(4,math.floor((cpupct-(x*100/6))/((100/6/4))+1))),2,9+x)
      else:  
       lcd.lcd_display_string_pos(" ",2,9+x)

     if (math.floor(rampct+1)>x*(100/6)) and (math.floor(rampct)>(x+1)*(100/6)) or rampct>98:
      lcd.lcd_display_string_pos(chr(255),3,9+x)
     else:
      if (math.floor(rampct)>x*(100/6)+1) and (math.floor(rampct)<(x+1)*(100/6)) :
       lcd.lcd_display_string_pos(chr(min(4,math.floor((rampct-(x*100/6))/((100/6/4))+1))),3,9+x)
      else:  
       lcd.lcd_display_string_pos(" ",3,9+x)




  # line 4 print (cputemp, date, time)
  # use lm-sensors to get cpu temp / get time data from python internal method
  dateString = datetime.now().strftime('%d-%b')
  timeString = datetime.now().strftime('%H:%M:%S')

#  lcd.lcd_write(0xC0)
#  lcd.lcd_write_char(1)	
  

#  lcd.lcd_display_string_pos(chr(0),4,0)
  
#  lcd.lcd_display_string_pos(os.popen('sensors | grep "temp1:" | cut -d+ -f2 | cut -c1-2').read()[:-1].rjust(3), 4,16)
  if fahrenheit!=True:
   lcd.lcd_display_string_pos(dateString+" "+timeString+" "+os.popen('sensors | grep "temp1:" | cut -d+ -f2 | cut -c1-2').read()[:-1].rjust(3), 4,0)
  else:
   lcd.lcd_display_string_pos(dateString+" "+timeString+" "+str(round(int(os.popen('sensors | grep "temp1:" | cut -d+ -f2 | cut -c1-2').read()[:-1])*9/5+32,0)).rjust(3)[0:3], 4,0)


 
  tx2 = get_bytes('tx')
  rx2 = get_bytes('rx')
  tx_speed = (tx2 - tx1)/1000000.0/delay
  rx_speed = (rx2 - rx1)/1000000.0/delay
  
  lcd.lcd_display_string_pos(str(round(rx_speed*8*1.048/10)).rjust(3),2,16)
  lcd.lcd_display_string_pos(str(round(tx_speed*8*1.048/10)).rjust(3),3,16)



  # line 4 print (cputemp, uptime)
  # use /proc/uptime and python divmod method
  #uptime=os.popen('cat /proc/uptime | cut -d " " -f1').read()
  #uptimeDay=divmod(float(uptime),86400)
  #uptimeHour=divmod(uptimeDay[1],3600)
  #uptimeMin=divmod(uptimeHour[1],60)
  #uptimeString=str(int(uptimeDay[0]))+"D:"+str(int(uptimeHour[0]))+"H:"+str(int(uptimeMin[0]))+"M"
  #lcd.lcd_display_string("TEMP:"+os.popen('sensors | grep "temp1:" | cut -d+ -f2 | cut -c1-2').read()[:-1]+"C "+uptimeString.zfill(3), 4)


  # sleep(1)



Samples:
Untitled.jpg
Untitled.jpg (54.47 KiB) Viewed 550 times
2019-07-10 at 22.16.30.jpg
2019-07-10 at 22.16.30.jpg (54.16 KiB) Viewed 550 times
Last edited by puremind on Sat Jul 13, 2019 5:24 am, edited 2 times in total.
These users thanked the author puremind for the post:
domih (Mon Jul 22, 2019 9:55 am)
Odroid H2 Rev B

User avatar
odroid
Site Admin
Posts: 31381
Joined: Fri Feb 22, 2013 11:14 pm
languages_spoken: English
ODROIDs: ODROID
Has thanked: 54 times
Been thanked: 184 times
Contact:

Re: i2c 20 pin alternative python display for 2 drives

Unread post by odroid » Thu Jul 11, 2019 10:22 am

It is beautiful and informative. :o
Especially I love the CGRAM generated font °C

puremind
Posts: 40
Joined: Wed Nov 21, 2018 2:27 am
languages_spoken: english
ODROIDs: Odroid H2 Rev B
Has thanked: 2 times
Been thanked: 4 times
Contact:

Re: i2c 20 pin alternative python display for 2 drives

Unread post by puremind » Thu Jul 11, 2019 2:16 pm

odroid wrote:
Thu Jul 11, 2019 10:22 am
It is beautiful and informative. :o
Especially I love the CGRAM generated font °C
Thanks :) That one is custom-made. :)
You could do your own chars very easily if you'd feel creative (or change the ones I got there), there's instructions in the script.

I've ordered one of those cheap OLED's 128x64 on eBay and will have some fun with it when it arrives. :twisted:
Odroid H2 Rev B

User avatar
odroid
Site Admin
Posts: 31381
Joined: Fri Feb 22, 2013 11:14 pm
languages_spoken: English
ODROIDs: ODROID
Has thanked: 54 times
Been thanked: 184 times
Contact:

Re: i2c 20 pin alternative python display for 2 drives

Unread post by odroid » Thu Jul 11, 2019 5:11 pm

I'm not creative at all. :oops:

BTW, ODROID-N2 users also enjoyed various display modules with CoreELEC OS image.
https://discourse.coreelec.org/t/odroid ... river/4995
These users thanked the author odroid for the post:
puremind (Thu Jul 11, 2019 6:37 pm)

puremind
Posts: 40
Joined: Wed Nov 21, 2018 2:27 am
languages_spoken: english
ODROIDs: Odroid H2 Rev B
Has thanked: 2 times
Been thanked: 4 times
Contact:

Re: i2c 20 pin alternative python display for 2 drives

Unread post by puremind » Thu Jul 11, 2019 6:37 pm

Nice. I’ll check those libs once I get the part
Odroid H2 Rev B

puremind
Posts: 40
Joined: Wed Nov 21, 2018 2:27 am
languages_spoken: english
ODROIDs: Odroid H2 Rev B
Has thanked: 2 times
Been thanked: 4 times
Contact:

Re: i2c 20 pin alternative python display for 2 drives

Unread post by puremind » Sat Jul 13, 2019 4:49 am

Edited the script to sleep(10) at start otherwise weird characters coming up, looks nice at restart now.
Odroid H2 Rev B

RomaT
Posts: 144
Joined: Thu Oct 23, 2014 4:48 pm
languages_spoken: Russian
ODROIDs: -H2 rev.B, -XU3, -XU4, -C1, -C2, -W, -VU, CloudShell
Location: Perm, Russia
Has thanked: 0
Been thanked: 8 times
Contact:

Re: i2c 20 pin alternative python display for 2 drives

Unread post by RomaT » Sat Jul 13, 2019 5:06 am

In BIOS, set the frequency of I2C - 100 KHz, base frequency I2C 400 kHz in the chip PCA8574
because The LCD Module has a chip PCF8574T base frequency I2C 100 kHz
.
20x4LCDboard.jpg
20x4LCDboard.jpg (75.27 KiB) Viewed 344 times
.
Although it works at 400KHz, but 100KHz is better.
.
pcf8574t.png
pcf8574t.png (82.62 KiB) Viewed 398 times

User avatar
odroid
Site Admin
Posts: 31381
Joined: Fri Feb 22, 2013 11:14 pm
languages_spoken: English
ODROIDs: ODROID
Has thanked: 54 times
Been thanked: 184 times
Contact:

Re: i2c 20 pin alternative python display for 2 drives

Unread post by odroid » Mon Jul 15, 2019 9:59 am

Yes! 100Khz must be more stable and enough to handle 20x4 characters.

RomaT
Posts: 144
Joined: Thu Oct 23, 2014 4:48 pm
languages_spoken: Russian
ODROIDs: -H2 rev.B, -XU3, -XU4, -C1, -C2, -W, -VU, CloudShell
Location: Perm, Russia
Has thanked: 0
Been thanked: 8 times
Contact:

Re: i2c 20 pin alternative python display for 2 drives

Unread post by RomaT » Sun Jul 21, 2019 8:07 pm

Strange you have actions:

Code: Select all

  tx_speed = (tx2 - tx1)/1000000.0
  rx_speed = (rx2 - rx1)/1000000.0
  ...
  # line 3 print (network speed)
  # bps -> mpbs (*8)
  ...tx_speed*8*1.048/10...
  ...rx_speed*8*1.048/10...
there is data already in bytes, not in bits - coefficient by 8 is not necessary.
strange some kind of coefficient = 8*1.048/10 = 0.8384
if in Bytes, when he should be = 1.048576, if in bits, then 8.388608
and 1KBytes = 1024 Bytes,
this implies 1MBytes = 1024 * 1024 = 1048576 Bytes
Respectively:

Code: Select all

tx_speed = (tx2 - tx1)/1048576.0
rx_speed = (rx2 - rx1)/1048576.0
and no further perversions are needed, simply:

Code: Select all

...str(round(rx_speed))...
...str(round(tx_speed))...
result in megabytes,
if you want in megabits, you can multiply by 8

Code: Select all

...str(round(rx_speed*8))...
...str(round(tx_speed*8))...
or

Code: Select all

tx_speed = (tx2 - tx1)/131072‬.0
rx_speed = (rx2 - rx1)/131072‬.0
Last edited by RomaT on Mon Jul 22, 2019 1:34 pm, edited 1 time in total.

fvolk
Posts: 268
Joined: Sun Jun 05, 2016 11:04 pm
languages_spoken: english
ODROIDs: C2, HC1, H2
Has thanked: 0
Been thanked: 2 times
Contact:

Re: i2c 20 pin alternative python display for 2 drives

Unread post by fvolk » Mon Jul 22, 2019 4:11 am

Would connecting two 20x4 displays to the H2 also work?
I see there are two I2C buses, but only one +3.3V pin - putting both displays on the same +3.3V for VCC is ok?

domih
Posts: 42
Joined: Mon Feb 11, 2019 4:48 pm
languages_spoken: English, French
ODROIDs: UX4, HC2, N2, H2.
Has thanked: 18 times
Been thanked: 8 times
Contact:

Re: i2c 20 pin alternative python display for 2 drives

Unread post by domih » Mon Jul 22, 2019 10:06 am

puremind wrote:
Thu Jul 11, 2019 6:23 am
Everybody,
I've made some changes here and there if anybody wants to try...

Managed, Celsius vs Fahrenheit with custom chars
Moving Bars for CPU & RAM. Two drives status with storage capacity.

Same as the first post, simply update the hello_world.py as instructed, then edit the config section on the script for full customisation, including 3/4 characters for the first drive to monitor.

Animation really nice on the percentage section.

Code: Select all

# -*- coding: utf-8 -*-
"""
Compiled, mashed and generally REmutilated 2019 by puremind
Made available under GNU GENERAL PUBLIC LICENSE

# added bits and pieces from various sources
# 2019-07-07, ver 0.1
# Add your own custom stuff with custom characters

"""
from time import sleep
import lcddriver as lcd


lcd = lcd.lcd()

lcd.display_string("                    ",1)
lcd.display_string("                    ",2)
lcd.display_string("                    ",3)
lcd.display_string("                    ",4)


sleep(1)

lcd.clear()



#set to False for Celsius, True for Fahrenheit
fahrenheit=False


#change here to sda sdb sdc etc
#disk1_to_check="sda"
#disk2_to_check="sdb"

disk1_to_check="nvme0n1p3"

#change here to partition full name for pct usage, check with "df -h"
path_disk1="/"


disk2_to_check="sda"
path_disk2="/mnt/data"

#Time to sleep between checks. Defaults 3
delay=3


#offsets 1 char to the right if the first disk starts with "nvme"
if disk1_to_check[0:4]!="nvme":
 nvmeoffset=0
else :
 nvmeoffset=1




# import modules
#import RPi_I2C_driver
import stat
import os
import psutil as ps
import math
from time import time

from datetime import datetime

sleep(5)



# -*- coding: utf-8 -*-
"""
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

"""
#
#
import smbus
from time import *

class i2c_device:
   def __init__(self, addr, port=1):
      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)



# LCD Address
#ADDRESS = 0x3F
ADDRESS = 0x27

# I2C bus
BUS = 1

# 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, BUS)

      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.15)


   # 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
   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)

   # 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)         
         
         
   # define precise positioning (addition from the forum)
   def lcd_display_string_pos(self, string, line, pos):
    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)
      
      







#check if disk exists function
def disk_exists(path):
     try:
             return stat.S_ISBLK(os.stat(path).st_mode)
     except:
             return False


# network status get function
def get_bytes(t, iface='enp2s0'):
    with open('/sys/class/net/' + iface + '/statistics/' + t + '_bytes', 'r') as f:
        data = f.read();
        return int(data)






sleep(3)

# load lcd
lcd = lcd()

sleep(1)

# 5 by 8 custom char creation
#https://www.quinapalus.com/hd44780udg.html

#More info here with full char set
#http://www.electronic-engineering.ch/microchip/datasheets/lcd/charset.gif

# Define some static characters

fontdata = [
         # Char 0 - Celsius
        [ 0x8,0x14,0x8,0x3,0x4,0x4,0x4,0x3],
 		# Char 1 1/5 block 
 		[ 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10],
 		# Char 2 2/5 block 
 		[ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18],
 		# Char 3 3/5 block 
 		[ 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c],
 		# Char 4 4/5 block 
 		[ 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e],
        # Char 5 - Arrow up
        [ 0x0,0x4,0xe,0x1f,0x4,0x4,0x4,0x0],
        # Char 6 - Arrow down
        [ 0x0,0x4,0x4,0x4,0x1f,0xe,0x4,0x0],
        # Char 7 ZZ
        [ 0x1e,0x4,0x8,0x1e,0xf,0x2,0x4,0xf]

]


lcd.lcd_load_custom_chars(fontdata)

sleep(1)

lcd.lcd_display_string("                    ",1)
lcd.lcd_display_string(str.center(str(os.popen('hostname').readline())[:-1],20,' '),2)
lcd.lcd_display_string("      STARTING      ",3)
lcd.lcd_display_string("                    ",4)

sleep(2)

lcd.lcd_display_string(disk1_to_check[0:3+nvmeoffset]+" ? ??% "+disk2_to_check[0:3]+" ? ??%",1)

#Set 0 as speed for network first cycle
#Fixed elements
#TX / RX Arrows

lcd.lcd_display_string("CPU ??% "+chr(126)+"      "+chr(127)+" ??"+chr(6),2)
lcd.lcd_display_string("RAM ??% "+chr(126)+"      "+chr(127)+" ??"+chr(5),3)

#Celsius
if fahrenheit!=True:
 lcd.lcd_display_string_pos("??"+chr(0),4,17)
else:
 lcd.lcd_display_string_pos("??F",4,17)

sleep(1)
steps3 = [1, 2, 3]
steps = [0, 1, 2, 3, 4, 5]

while True:


  # check if disk  exists
  
  
  # get network speed for delay sec
  tx1 = get_bytes('tx')
  rx1 = get_bytes('rx')

  
  if disk_exists("/dev/"+disk1_to_check)!=True:
    hddstr1=chr(6)
  else :

   # read hdd state from hdparm
   hddstate1=str(os.popen('hdparm -C /dev/'+disk1_to_check+' | grep state | cut -f 2 -d :').readline())[2:][:-1]

   if hddstate1=="standby":
    hddstr1=chr(7)
   else :
    hddstr1=chr(5)


  

  if disk_exists("/dev/"+disk2_to_check)!=True:
    hddstr2=chr(6)
  else :

   # read hdd state from hdparm
   hddstate2=str(os.popen('hdparm -C /dev/'+disk2_to_check+' | grep state | cut -f 2 -d :').readline())[2:][:-1]

   if hddstate2=="standby":
    hddstr2=chr(7)
   else :
    hddstr2=chr(5)



 # line 1 print (hddstate, friendly name)

  #lcd.lcd_display_string(disk1_to_check+":"+hddstr1.rjust(5)+"  "+disk2_to_check+":"+hddstr2.rjust(5), 1)
  lcd.lcd_display_string_pos(hddstr1, 1,4+nvmeoffset)  
  lcd.lcd_display_string_pos(hddstr2, 1,15)  


  obj_Disk1 = ps.disk_usage(path_disk1)
  lcd.lcd_display_string_pos(str(round(obj_Disk1.percent)), 1,6+nvmeoffset)  

  obj_Disk2 = ps.disk_usage(path_disk2)
  lcd.lcd_display_string_pos(str(round(obj_Disk2.percent)), 1,17)  


  # line 2 print (cpu, memory)
  # use psutil to get CPU usage and Memory Usage
  # line 3 print (network speed)
  # bps -> mpbs (*8)


 

  for z in range(2) :
   sleep(delay/2)
   cpupct=ps.cpu_percent()
   rampct=ps.virtual_memory()[2]
  

   lcd.lcd_display_string_pos(str(math.floor(cpupct)).rjust(3),2,3)
   lcd.lcd_display_string_pos(str(math.floor(rampct)).rjust(3),3,3)

#  for y in range(101):
#    sleep(0.1)
#    cpupct=y
#    lcd.lcd_display_string_pos(str(y),3,10)

   for x in steps:
     if (math.floor(cpupct+1)>x*(100/6)) and (math.floor(cpupct)>(x+1)*(100/6)) or cpupct>98:
      lcd.lcd_display_string_pos(chr(255),2,9+x)
     else:
      if ((math.floor(cpupct)>x*(100/6)+1) and (math.floor(cpupct)<(x+1)*(100/6)) and cpupct>2):
       lcd.lcd_display_string_pos(chr(min(4,math.floor((cpupct-(x*100/6))/((100/6/4))+1))),2,9+x)
      else:  
       lcd.lcd_display_string_pos(" ",2,9+x)

     if (math.floor(rampct+1)>x*(100/6)) and (math.floor(rampct)>(x+1)*(100/6)) or rampct>98:
      lcd.lcd_display_string_pos(chr(255),3,9+x)
     else:
      if (math.floor(rampct)>x*(100/6)+1) and (math.floor(rampct)<(x+1)*(100/6)) :
       lcd.lcd_display_string_pos(chr(min(4,math.floor((rampct-(x*100/6))/((100/6/4))+1))),3,9+x)
      else:  
       lcd.lcd_display_string_pos(" ",3,9+x)




  # line 4 print (cputemp, date, time)
  # use lm-sensors to get cpu temp / get time data from python internal method
  dateString = datetime.now().strftime('%d-%b')
  timeString = datetime.now().strftime('%H:%M:%S')

#  lcd.lcd_write(0xC0)
#  lcd.lcd_write_char(1)	
  

#  lcd.lcd_display_string_pos(chr(0),4,0)
  
#  lcd.lcd_display_string_pos(os.popen('sensors | grep "temp1:" | cut -d+ -f2 | cut -c1-2').read()[:-1].rjust(3), 4,16)
  if fahrenheit!=True:
   lcd.lcd_display_string_pos(dateString+" "+timeString+" "+os.popen('sensors | grep "temp1:" | cut -d+ -f2 | cut -c1-2').read()[:-1].rjust(3), 4,0)
  else:
   lcd.lcd_display_string_pos(dateString+" "+timeString+" "+str(round(int(os.popen('sensors | grep "temp1:" | cut -d+ -f2 | cut -c1-2').read()[:-1])*9/5+32,0)).rjust(3)[0:3], 4,0)


 
  tx2 = get_bytes('tx')
  rx2 = get_bytes('rx')
  tx_speed = (tx2 - tx1)/1000000.0/delay
  rx_speed = (rx2 - rx1)/1000000.0/delay
  
  lcd.lcd_display_string_pos(str(round(rx_speed*8*1.048/10)).rjust(3),2,16)
  lcd.lcd_display_string_pos(str(round(tx_speed*8*1.048/10)).rjust(3),3,16)



  # line 4 print (cputemp, uptime)
  # use /proc/uptime and python divmod method
  #uptime=os.popen('cat /proc/uptime | cut -d " " -f1').read()
  #uptimeDay=divmod(float(uptime),86400)
  #uptimeHour=divmod(uptimeDay[1],3600)
  #uptimeMin=divmod(uptimeHour[1],60)
  #uptimeString=str(int(uptimeDay[0]))+"D:"+str(int(uptimeHour[0]))+"H:"+str(int(uptimeMin[0]))+"M"
  #lcd.lcd_display_string("TEMP:"+os.popen('sensors | grep "temp1:" | cut -d+ -f2 | cut -c1-2').read()[:-1]+"C "+uptimeString.zfill(3), 4)


  # sleep(1)



Samples:

Untitled.jpg

2019-07-10 at 22.16.30.jpg
:o :mrgreen: :P

Oh my, very nice, you are way ahead with the LC 20 x 4. I had just started to do some research on documents. In case it helps, I noticed these:

- https://github.com/johnrickman/LiquidCrystal_I2C
- https://en.wikipedia.org/wiki/Hitachi_H ... controller
- https://www.sparkfun.com/datasheets/LCD/HD44780.pdf

Best,

Dominique

User avatar
odroid
Site Admin
Posts: 31381
Joined: Fri Feb 22, 2013 11:14 pm
languages_spoken: English
ODROIDs: ODROID
Has thanked: 54 times
Been thanked: 184 times
Contact:

Re: i2c 20 pin alternative python display for 2 drives

Unread post by odroid » Mon Jul 22, 2019 7:19 pm

fvolk wrote:
Mon Jul 22, 2019 4:11 am
Would connecting two 20x4 displays to the H2 also work?
I see there are two I2C buses, but only one +3.3V pin - putting both displays on the same +3.3V for VCC is ok?
Yes, it must be okay.

Post Reply

Return to “Hardware and peripherals”

Who is online

Users browsing this forum: No registered users and 0 guests