article

laurenceh avatar image
laurenceh posted

How to: Quickly update RPI Touch Screen configuration on new SD card or after version update.

I have created a scripted menu to enable me to quickly update a new Venus OS SD image installed on an SD card. I thought the community might find it useful.

What's the use case?

If I am going to test new release or intermediate version of Venus OS on my RPI 3B+ I want to be able to quickly configure the touch screen and other interfaces when I set up a new card. It is possible to store changes you want on the /data partition of a Venus OS Rpi SD card but getting at SD cards mounted in the touch screen case is tricky as it involves disassembling the Rpi and screen case. So I wanted to do this using an USB memory stick which is easy to insert and remove.

Also I'm dreadful at typing accurately when I'm eager to try out a new feature so this script does all the typing for me and checks the errors that might occur and tells me about them.

What does this do ?

It enables quick configuration of a new Venus OS install to support:

  • 7" Touch screen (800x480 or 480x272)
  • Screen rotation dependent on how you are going to mount it
  • Headless on and off (needed for calibration)
  • Calibrate touch screen
  • Enable mcp3208 analogue interface on Sio (as per Venus GX)
  • Screen backlight dimming
  • Screen auto power off
  • Enable i2c interface
  • Enable the inbuilt Venus OS Web server to serve python scripts

The script is interactive and incorporates everything I have gleaned from other posts in this forum and in other places on the internet. I have written most of the logic out long hand and using if-then-else and case statements without too many obscure code contractions - it could easily be significantly reduced in size but would probably be less readable or maintainable by others if It was.

Here's an example of what it looks like:


The full script is included below. Quite a bit of it works stand alone and uses the necessary wget and opkg installs to pull the right modules and packages from the internet. There are some items I have not been able to find on the internet and these need to be in a directory called 'restore' in the same directory as the script.

These resources are:

/restore/mcp3208-overlay.dtb

/restore/rpi-backlight-overlay.dtb

/restore/dbus-adc

/restore/start-gui-800x480.sh

/restore/start-gui-480x272.sh

The script has been tested as I use it, so I have confirmed that no other lines, programmes, commands or resources are needed for this work on a Venus OS Rpi.

I have created a zip file with these resources and including the script file, the zip file is available on my own web server here. (the version of the script in the zip image is out of date the version in the article her is up to date (5/5/2020).

How to use it:

Download the zip file put it on a USB memory stick.

Plug this into your Venus OS RPi and locate the memory stick which will be something like : /run/media/sda1

the exact device will depend on where you plug it in.

Open the storage device:

cd /run/media/sda1
unzip venus-rpi.zip

Unzipping on the target machine (not on a MAC or windows PC) should preserve the file setting and attributes well enough for the purpose here.

cd venus-rpi-setup

Run the script

./setup-menu.sh


#!/bin/sh
# sample.mnu
# Menu to allow selected setup of rasperry pi features on Venus os install. 
# This currently assumes you want to use the official Raspberry pi 7" screen
#
# this is written in a structured manner but is written long hand
# without fancy lopps, arrays, or constructions the rational for this is
# to enable others to extend, modify and debug it without too much obscure code
#
#------------------------------------------------------
# MENU FUNCTION DEFINITIONS
#------------------------------------------------------  
# define a function to highlight the choice
#
# funtion defined to mark the chosen function in the menu display
mark () {
if [ "${answer^}" = "$1" ] ; then echo -n "* " ; marked=1 ; else echo -n "  " ; fi }
#
# Define a function for invalid menu picks
# The function loads an error message into a variable
badchoice () { MSG="Invalid Selection ... Please Try Again" ; } 
  
# For each prompt displayed, there is a list of 
# commands to execute in response to the user picking the 
# associated letter. Each is defined as a function.
# Eech function defines the list of actions to be executed,
# and attempts to catch possible common errors.

execute () {
#echo "execute entered with" $1
   case $1 in
      H) headless;;
      O) headlessoff;;
      D) displayDrivers;;
      U) upsidedown ;;
      8) changeto800;;
      4) changeto480;;
      S) dimming;;
      T) timer;;
      A) analogue;;
      I) i2c;;
      R) systemreboot;;
      P) webpython ;;
      C) calibrate;;
      Q) exit;;

        *) badchoice;;
esac
echo "action complete press any key to continue"
read -rsn 1 jim
MSG=""
}

headless () { 
if [ -f /etc/venus/headless.off ]; then
  echo "headless is off - switching to headless"
  mv /etc/venus/headless.off /etc/venus/headless
  REBOOT=1
else
  if [ -f /etc/venus/headless ]; then
  echo "headless already configured - no change made"
  else
  echo "no headless configuration found - enabling headless"
  touch /etc/venus/headless
  REBOOT=1
  fi
fi ; }

headlessoff () {
if [ -f /etc/venus/headless ]; then
  echo "headless is enabled - switching to headless off"
  mv /etc/venus/headless /etc/venus/headless.off
  REBOOT=1
else
  if [ -f /etc/venus/headless.off ]; then
  echo "headless already off - no change made"
  else
  echo "no headless configuration found	- switching headless off"
  touch	/etc/venus/headless.off
  REBOOT=1
  fi
fi ; }

displayDrivers () { 
echo "This will execute opkg commands, an internet connection is required do you have one (y/n)?"
read -s -N 1 key
case $key in
   y|Y) 
   echo "Package install will continue"
   echo "opkg update"
     opkg update 2>&1
   echo "install mousedriver"
     opkg install qt4-embedded-plugin-mousedriver-tslib 2>&1
   echo "install-tslib-calibrate"
     opkg install tslib-calibrate	2>&1
   echo "install tslib-conf"
     opkg install tslib-conf 2>&1
   echo "install tslib-tests"
     opkg install tslib-tests 2>&1
# update config.txt
   echo "Upating config.txt"
     grep -q 'framebuffer_width=[0-9][0-9][0-9]' /u-boot/config.txt
     if [ $? -eq 0 ] ; then
       echo "Frame buffer already configured in config.txt no change made"
     else
       echo 'framebuffer_width=800' >> /u-boot/config.txt
       echo 'framebuffer_height=480' >> /u-boot/config.txt
       echo "Config.txt file updated"
     fi
   REBOOT=1
   ;;
   *)
   echo "Cannot proceed without internet connection"
   ;;
esac ; }

changeto800 () {
   echo "install replacement start GUI file"
     cp -p $dir/restore/start-gui-800x480.sh /opt/victronenergy/gui/start-gui.sh 2>&1
     if [ $? -eq 0 ] ; then
       echo "installed modified strat-gui.sh file"
     else
       echo "failed to install modified start-gui.sh file"
     fi
   echo "Upating config.txt"
     grep -q 'framebuffer_width=[0-9][0-9][0-9]' /u-boot/config.txt
     if [ $? -eq 0 ] ; then 
       sed -i 's/framebuffer_width=[0-9][0-9][0-9]/framebuffer_width=800/' /u-boot/config.txt
       sed -i 's/framebuffer_height=[0-9][0-9][0-9]/framebuffer_height=480/' /u-boot/config.txt
       echo "Config.txt file updated"
     else
      echo "Frame buffer config not found in config.txt no change made"
     fi
     echo "remember to recalibrate the touch screen if you have changed screen size"
     REBOOT=1 ; }


changeto480 () {
   echo "install replacement start GUI file"
     cp -p $dir/restore/start-gui-480x272.sh /opt/victronenergy/gui/start-gui.sh 2>&1
       if [ $? -eq 0 ] ; then
          echo "Installed modified start-gui.sh file"
       else
          echo "failed to install modified start-gui.sh file"
       fi
   echo "Upating config.txt"
     grep -q 'framebuffer_width=[0-9][0-9][0-9]' /u-boot/config.txt
     if [ $? -eq 0 ] ; then
       sed -i 's/framebuffer_width=[0-9][0-9][0-9]/framebuffer_width=480/' /u-boot/config.txt
       sed -i 's/framebuffer_height=[0-9][0-9][0-9]/framebuffer_height=272/' /u-boot/config.txt
       echo "Config.txt file updated"
     else
      echo "Frame buffer configuration not found in config.txt no change made"
     fi 
      echo "remember to recalibrate the touch screen if you have changed screen size"
     REBOOT=1 ; }

calibrate () { 
  echo "Make sure headless is enable and the system rebooted - you can't calibrate a screen with the GUI on"
  echo "If the screen blanking time has switched off the screen."
  echo "You can still change this by accessing the Venus OS GUI remote console with a browser"
  echo "ready to start calbration (y/n)?"
  read -s -N 1 key
  case $key in
  y|Y)
    TSLIB_FBDEVICE=/dev/fb1
    TSLIB_TSDEVICE=/dev/input/touchscreen0 ts_calibrate
  ;;
  *)
  echo "Calibration aborted - no changes made"
  ;;
esac ; }

dimming () {
echo "This will execute wget and opkg commands, an internet connection is required do you have one (y/n)?"
read -s -N 1 key
case $key in
   y|Y)
   echo "Overlay install will continue"
   echo "/sys/class/backlight/rpi_backlight" > /etc/venus/backlight_device
   if [ -f /u-boot/overlays/rpi-backlight-overlay.dtb ] ; then
     echo "backlight dtb overlay already exists - this will not be replaced"
   else 
     echo "fetching overlay file"
     wget https://github.com/PiNet/PiNet-Boot/raw/master/boot/overlays/rpi-backlight-overlay.dtb 2>&1
     echo $dir/rpi-backlight-overlay.dtb
     mv $dir/rpi-backlight-overlay.dtb /u-boot/overlays
    fi
    echo "fetching kernel module"
     opkg install kernel-module-rpi-backlight 2>&1
   REBOOT=1
   ;;
   *)
   echo "No changes made without internet connection"
   # an alternatie might be to install a copy of the overlay from the /data/recover directory
   ;;
esac ; }

timer () {
echo "/sys/class/backlight/rpi_backlight/bl_power" > /etc/venus/blank_display_device
}

analogue () {
   if [ -f /u-boot/overlays/mcp3208-overlay.dtb ]; then
      echo "mcp3208 overlay file already exists no change made"
   else
      cp -p $dir/restore/mcp3208-overlay.dtb /u-boot/overlays
      if [ $? -eq 0 ] ; then
        echo "mcp3208 overlay file installed"
      else
        echo "Failed to install mcp3208 overlay file"
      fi
   REBOOT=1
   fi
   if [ -d //opt/victronenergy/dbus-adc ]; then
      echo "dbus-adc device interfaces already exist no changes made to drivers"
   else
      cp -pr $dir/restore/dbus-adc /opt/victronenergy
      if [ $? -eq 0 ] ; then
         echo "dbus-adc service files installed in /opt/victronenergy"
      else
         echo "Failed install dbus-service files"
      fi
   REBOOT=1
   fi

   grep -q 'dtoverlay=mcp3208:spi0-0-present' /u-boot/config.txt
   if [ $? -eq 0 ] ; then
       echo "config.txt alread configured for MCP3208 analogue interface no changes made to config.txt"
   else
       echo 'dtoverlay=mcp3208:spi0-0-present' >> /u-boot/config.txt
       echo "Config.txt updated for analogue interface"
   fi
   touch /var/log/dbus-adc
   ln -s /opt/victronenergy/dbus-adc/service /service/dbus-adc
   REBOOT=1 ; }   

i2c () {
   grep -q 'dtparam=i2c_arm=on' /u-boot/config.txt
   if [ $? -eq 0 ] ; then
       echo "config.txt alread configured for i2c interface no changes made to config.txt"
   else
       echo 'dtparam=i2c_arm=on' >> /u-boot/config.txt
       echo "Config.txt updated for i2c interface"
   REBOOT=1
   fi

   grep -q 'modprobe i2c-dev' /data/rc.local
   if [ $? -eq 0 ] ; then
       echo "rc.local already configured to start i2c interface no changes made to rc.local"
   else
       echo 'modprobe i2c-dev' >> /data/rc.local
       chmod +x /data/rc.local
       echo "/data/rc.local updated for i2c interface"
   REBOOT=1
   fi ;  }

systemreboot () {
#crafty way of shutting down the script while rebooting
exec reboot
 }

upsidedown () {
   grep -q "lcd_rotate=2" /u-boot/config.txt
   if [ $? -eq 0 ] ; then
     echo "Screen is already inverted reverto no normal (y/n)"
     read -s -N 1 key
     case $key in
       y|Y)
       sed -i 's/lcd_rotate=2//' /u-boot/config.txt
     ;;
     *)
       echo "No change made"
     ;;   
     esac
   else
     echo "Configureing /u-boot/config.txt to invert screen"
     echo "lcd_rotate=2" >> /u-boot/config.txt
    fi ; }

webpython () {
   grep -q "CGIhandler = /usr/bin/python:py" /etc/hiawatha/hiawatha.conf
   if [ $? -eq 0 ] ; then
     sed -i 's%#CGIhandler = /usr/bin/python:py%CGIhandler = /usr/bin/python:py%' /etc/hiawatha/hiawatha.conf
     echo "/usr/bin/python:py updated to enable python"
   else
     echo "File or CGIhandler configuration missing in /etc/hiawatha/hiawatha.conf - no changes made"
   fi
REBOOT=1 ; }

#------------------------------------------------------
# DISPLAY MENU
#------------------------------------------------------
# This function displays the menu.
# The routine clears the screen, echoes
# the menu prompts and any additional messages.
# Note that this definition does not cause the menu to
# be executed, it just defines, it ready to be executed.

themenu () {
# clear the screen
clear
echo `date`
echo
echo -e "\t Venus os Raspberry pi configure functions"
echo
echo -e "\t\t\t Please Select"
echo -e $(dirname $0)
marked=0
#
# this line is a placeholder for a function which calls most of the other functions - not yet implemented
#echo -en "\t\t\t" ; mark E ; echo "(E)verything (i2c, Analogue, Headless, 800x400, except calibrate screen) " ;
#
echo -en "\t\t\t" ; mark H ; echo "(H)eadless         - used when calibrating ";        
echo -en "\t\t\t" ; mark O ; echo "(O) Headless (O)ff - enable RPI Screen  ";
echo -en "\t\t\t" ; mark D ; echo "(D)isplay drivers 800x480  ";
echo -en "\t\t\t" ; mark C ; echo "(C)alibrate touch screen   ";
echo -en "\t\t\t" ; mark U ; echo "(U)pside down touch screen ";
echo -en "\t\t\t" ; mark 8 ; echo "(8) change to 800x480 resolution  ";
echo -en "\t\t\t" ; mark 4 ; echo "(4) change to 480x272 resolution  ";
echo -en "\t\t\t" ; mark S ; echo "(S)creen dimming interface        ";
echo -en "\t\t\t" ; mark T ; echo "(T)imer display shut off          ";
echo -en "\t\t\t" ; mark A ; echo "(A)nalogue mcp3208 spi interface drivers ";
echo -en "\t\t\t" ; mark I ; echo "(I)2c enable i2c interfaces       ";
echo -en "\t\t\t" ; mark R ; echo "(R)eboot Venus OS                 ";
echo -en "\t\t\t" ; mark P ; echo "(P) Web server: enable (P)ython scripts  ";
echo -en "\t\t\t" ; mark Q ; echo "(Q)uit                     ";
echo
((!marked)) &&  badchoice # flag up bad selections
echo $MSG
((REBOOT)) && echo "A reboot will be required to implement changes" || echo

echo
echo "Select by pressing the letter and then ENTER to execute commands";
}
  
#------------------------------------------------------
# MAIN EXECUTION
#------------------------------------------------------
 
# Clear out the error
MSG=
# changes to true iff we do somthoing that needs a reboot
REBOOT=0
# find out where we are
dir=$(dirname $0)
# Repeat the menu over and over
# Steps are:
# 1. Display the menu
# 2. 'read' a key of input from the key board
# 3. Clear the error message
# 4. if the user pressed return dispatch valid entries for execution
#    to the appropriate function or exit
# 5. Set error message for invalid options

while  true
do
# 1. display the menu by calling the function
#    this includes display the last error mesaage if ther is one
  themenu

# 2. read a character of input from the keyboard by a command
read -s -N 1 key

# 3. Clear any error message
   MSG=
#
#if they press [ENTER]  then go and do it
 if [[ "$key" == $'\x0a' ]] ; then
  execute "$answer"

else
#
# They did not press return so remember the key they pressed
#
 answer=${key^} # make sure answer is upper case to aid case statements
#     Do it again until the user selects the exit option
fi
done

This was developed against Venus OS 2.42 and test against Venus OS 2.51 today 2nd March 2020.

Venus OSRaspberry Pi
23 comments
2 |3000

Up to 8 attachments (including images) can be used with a maximum of 190.8 MiB each and 286.6 MiB total.

pau1phi11ips avatar image pau1phi11ips commented ·

Excellent work!

I think this should be included in the Victron image as standard.

0 Likes 0 ·
pau1phi11ips avatar image pau1phi11ips pau1phi11ips commented ·

Not sure how possible it would be, but could this script save what settings had been applied and build those into the rc.local file so they survived an update?

Could maybe save the screen calibration settings too?

0 Likes 0 ·
laurenceh avatar image laurenceh pau1phi11ips commented ·

Paul - the answer is probably -

As a next step I was going to look at giving the program a command line interface something like :

Setup-menu.sh -dh8stia

Then this single line added to the rc.local would invoke the setting you want to implement (the interactive version could even add the line to rc.local). Doing it this way would ensure there was only one code base to fix bugs in. I also wanted to keep the interactive interface for the calibration steps and when I want to check for any changes in behaviour new Venus releases.

I was however thinking that if something like this was going to be added to the venus image then I would re-write it as a python web interface (with a similar overall design). This would mean that you could configure by simply going to [Venus IP address]/rpi-config.py. This avoids the root access, ssh, and cli steps which are the things most likely to trip up a linux novice when they want to configure a Venus Rpi. But that's a whole new project.

BTW there are a couple of bugs in the script (text not logic) I'm just going to edit in the fixes.

0 Likes 0 ·
Mark avatar image Mark commented ·

Thats awesome thank you.

0 Likes 0 ·
laurenceh avatar image laurenceh Mark commented ·

Following use of the script through a couple of firmware updates I have just corrected a minor bug in the timer section in the listing above.

echo "/sys/class/backlight/bl_power" > /etc/venus/blank_display_device

should read

echo "/sys/class/backlight/rpi_backlight/bl_power" > /etc/venus/blank_display_device

This has been corrected in the version of the script in the article above.

0 Likes 0 ·
Mark avatar image Mark laurenceh commented ·

@Laurence Thanks.

Have you see my post on previous thread where you link to your article? I'm loosing my marbles lol trying to do the rc.local way so its automated but just can't seem to get it to work grrr

0 Likes 0 ·
Mark avatar image Mark laurenceh commented ·
0 Likes 0 ·
laurenceh avatar image laurenceh Mark commented ·

Mark: OK i'll divert some cycles to modifying the script so that it is executable from a command line and confirm that it works from rc.local.

I have just posted my work on creating a dbus AJAX type interface as I am now moving forward on creating a customisable UI - as I have given up on trying to understand the motorhome/boat pages supplied with Venus. I need to add or modify the tank and temperature interfaces and just can't see how to do it the Venus way.

0 Likes 0 ·
Show more comments
mp1234 avatar image mp1234 commented ·

Hello.

i have problems to install the MCP3208 on the pi.

Ich have test it manually, und now also with your script. but i can´t see the analog valus in the menu. i got always this message:

root@raspberrypi2:~# opkg install kernel-module-mcp320x
no packages installed or removed

Can someone give me information what is wrong?


Thank You

0 Likes 0 ·
Rob Duthie avatar image Rob Duthie mp1234 commented ·

Hi

You will have to install this package as well as the analog setting screen gets updated with missing files etc.

Normal operation it will be there, do you have the mcp3208 overlay installed the correct version with the 12 bit conversion done to it.

What ver of venus are you running? as ver >2.60.66 you can't use the analog anymore all being changed when they updated from Rocko to Zeus.

Ver <2.6.66 is still OK and all runs OK.

https://github.com/stgnet/victron-gui-qml/blob/main/PageSettingsIo.qml

Regards

Rob D

NZ

0 Likes 0 ·
mp1234 avatar image mp1234 Rob Duthie commented ·

i have install this Version:

venus-image-raspberrypi2-20200906135923-v2.60.rootfs.rpi-sdimg.zip 2020-09-06 20:10 95M

where i can see the different version. i only can see V2.60.

When i select the script to install the mcp3208 then the pakage will automaticaly installed? or i must do it by my self?

it is important that the mcp3208 is right connected to the PI?? When there is a problem the values are 0. or there are no Signal at he analog input menu?

0 Likes 0 ·
Rob Duthie avatar image Rob Duthie mp1234 commented ·

In the firmware page, for the correct mcp to load you must install the correct dtb overlay file in the overlay folder.

Attached txt file file information for checking the raw analog inputs etc.ADC _GPIO_ Relay ports config notes for Raspi Venus.txt

0 Likes 0 ·
Show more comments
Show more comments
interestingfellow avatar image interestingfellow commented ·

First, THANK YOU!
But also, I can't get the slider to come up in my gui. I can go to /sys/devices/platform/rpi_backlight/backlight/rpi_backlight and manually change the value in "brightness" and the screen responds; I just don't have the handy dandy slider on my rpi venusos screen. What did I do wrong? V2.73

0 Likes 0 ·
w15p avatar image w15p commented ·

Just wanted to thank you for this. I installed and ran this against a venus-image-raspberrypi2-20220215233923-v2.84.rootfs.wic.gz install on a rasp-pi3 and it works fabulously. I haven't yet experimented with the spi/i2c or python web interface but will shortly.

0 Likes 0 ·

Article

Contributors

LaurenceH contributed to this article