Monday, December 19, 2022

Setup I2C LCD on Raspberry pi


I2C (inter-integrated circuit) uses two wires to send and receive data and two wires to Vcc and ground.

- install I2C-tools: sudo apt-get install i2c-tools.

- install SMBUS: sudo apt-get install python-smbus.

- reboot.

- connect the I2C LCD to Raspi

- in terminal: i2cdetect -y 1 . This will show a table of addresses for each I2C device connected to Pi.


- put the I2C address of your LCD in line 22 of the library code. For example, my I2C address is 21, so I’ll change line 22 to ADDRESS = 0x3f.

- in terminal: nano I2C_LCD_driver.py

# -*- 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 = 1
# LCD Address
ADDRESS = 0x3f
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)

- Now, we can test it with hello world, in terminal: nano test.py

import I2C_LCD_driver
mylcd = I2C_LCD_driver.lcd()
mylcd.lcd_display_string("Hello world", 1)

- make sure, you have python installed and between library and python files in one directory.

- run it in terminal: python test.py


Auto-renew Let’s Encrypt SSL certificates using crontab

Usually we renew certificates with certbot --apache in CentOS, and the problem is if you have ton of domains, then how to fix it. 

We can use an automatic code with cron job.

to try it, you can use these codes first:

(base) [root@diomain ~]# certbot renew --apache

Saving debug log to /var/log/letsencrypt/letsencrypt.log


- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Processing /etc/letsencrypt/renewal/diomain.fr.conf

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Certificate not yet due for renewal


- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

The following certificates are not due for renewal yet:

  /etc/letsencrypt/live/diomain.fr/fullchain.pem expires on 2023-03-20 (skipped)

No renewals were attempted.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

(base) [root@diomain ~]# certbot certificates

Saving debug log to /var/log/letsencrypt/letsencrypt.log


- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Found the following certs:

  Certificate Name: diomain.com

    Serial Number: 331cb1d6f8f48cf90e65992cd1c0fdc57b2

    Key Type: RSA

    Domains: diomain.fr

    Expiry Date: 2023-03-20 01:39:17+00:00 (VALID: 89 days)

    Certificate Path: /etc/letsencrypt/live/diomain.fr/fullchain.pem

    Private Key Path: /etc/letsencrypt/live/diomain.fr/privkey.pem

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


If you haven't problem, now you can create it with webmin or use this manual command

crontab -e

0 0 20 2,4,6,8,10,12 * certbot renew --apache

we can assume that validation of certificate is 90 days so we must renew it in two months.
The command description is Cron will work at time: 0 minutes: 0 date: 20 month: 2/4/6/8/10/12 weekdays: */all



Thursday, December 15, 2022

Solve error shaka player or DRM or Widevine at Chromium in Raspberry pi

 If you have ever tried to load streaming live tv (indihome tv) or Netflix, Amazon Prime, HBO, Spotify, or the many other streaming services on your Raspberry Pi, you will find that they fail to function. Such as shaka player not support .....

This is because the Raspberry Pi does not come with the Widevine DRM software installed by default.

So you must update first Raspi, and install libwidevinecdm0

pi@pi:~ $ sudo apt update

............

pi@pi:~ $ sudo apt full-upgrade

............

pi@pi:~ $ sudo apt install libwidevinecdm0

Reading package lists... Done

Building dependency tree       

Reading state information... Done

The following packages were automatically installed and are no longer required:

  lxplug-volume python-colorzero

Use 'sudo apt autoremove' to remove them.

The following NEW packages will be installed:

  libwidevinecdm0

0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.

Need to get 5,990 kB of archives.

After this operation, 8,901 kB of additional disk space will be used.

Get:1 http://archive.raspberrypi.org/debian buster/main armhf libwidevinecdm0 armhf 4.10.2252.0-1 [5,990 kB]

Fetched 5,990 kB in 37s (162 kB/s)                                             

Selecting previously unselected package libwidevinecdm0.

(Reading database ... 104862 files and directories currently installed.)

Preparing to unpack .../libwidevinecdm0_4.10.2252.0-1_armhf.deb ...

Unpacking libwidevinecdm0 (4.10.2252.0-1) ...

Setting up libwidevinecdm0 (4.10.2252.0-1) ...

pi@pi:~ $ 



How to check the free space of SD card in Raspberry Pi

 pi@pi:~ $ df -h

Filesystem      Size  Used Avail Use% Mounted on

/dev/root       7.0G  5.9G  773M  89% /

devtmpfs        406M     0  406M   0% /dev

tmpfs           438M     0  438M   0% /dev/shm

tmpfs           438M   45M  394M  11% /run

tmpfs           5.0M  4.0K  5.0M   1% /run/lock

tmpfs           438M     0  438M   0% /sys/fs/cgroup

/dev/mmcblk0p1  253M   28M  226M  11% /boot

tmpfs            88M     0   88M   0% /run/user/1000

/dev/sda1        15G   15G  373M  98% /media/pi/3633-6436