This section contains loose pieces of interesting Raspberry Pi information.
Raspberry Pi is an enormous popular embedded system running Linux on an ARM processor.
Introduced in 2012 as an initiative to support the dwindling interest in computers in Britain in a very cheap way so that it's accessible to everyone in the society, it has in the meantime conquered the world at lightning speed and is used in all sorts of disciplines (even air space related programs).
Its popularity also makes that this embedded system is supported in many different ways. A zillion HAT (Hardware At the TOP) shields are available to do the most simple and most complex things, lots of different languages are supported (C/C++, Java, Python,... to name a few) and a huge user group (fora) is available on the internet.
Below is a collection of possibly interesting things I faced along the way using the Raspberry Pi. I hope they will be useful for at least some people somewhere on this planet.
In the past, at times where the trees were still speaking and the leaves were still green, logging in into the Raspberry Pi was a "piece of cake". pi was the username and raspberry was the password. That simple. Period.
But nowadays, thanks to so many friendly people on the internet, all with good intentions, we have to better protect the access to all devices. And the Raspberry Pi is no exception, certainly not when you use it in a way that it's accessible from "outside" (that is, internet access instead of intranet access).
Therefore, the login process has changed drastically since April, 2022.
When you use the graphical tools to setup the Raspberry Pi, then the steps to take are not so drastic. But when you're a command line addict like me, things are a bit different. But still, doable.
Below is a summary of the process to follow to successfully log in into the Raspberry Pi for the first time when you're using the command line approach. If you want more in-depth explanations about the new login process, pls. see this page.
You still have to put a file called ssh on the SD card. You should do this while the SD card is still attached to your computer. This gives you a one-time opportunity to access the Raspberry Pi with e.g. putty by setting up an SSH connection. This is because the startup process of the Raspberry Pi checks if there's a file called ssh available and if so, it will start the SSH daemon once. Once the SSH daemon is started, the Raspberry Pi wipes out the file ssh from the boot partition on the SD card.
Once connected, then you should activate the SSH daemon "forever" through the raspi-config tool so that with the next boot the SSH daemon is started automatically instead of checking if there's a file called ssh on the boot partition of the SD card.
New is that you also have to create a file named userconf or userconf.txt on the boot partition that must contain the following:
The configuration file must contain only one line of text with the following layout <user_name>:<encrypted_password>
The user name is the name you want to use: it can still be pi if you want.
The encrypted password must be generated. You can do it on a Windows machine if openssl is installed like so:
openssl passwd -6
You will be asked to give a password and to confirm that password. After you've confirmed your password, you will see a very long encrypted password like so (example given):
openssl passwd -6
Password:
Verifying - Password:
$6$m.VC...z3S/ (shortened for security reasons...)
Once you have the above info, your userconf or userconf.txt should look like this (if you still want to use pi as a user):
pi:$6$m.VC...z3S/
If you now put the card into the Raspberry Pi and boot, it will ask for the credentials:
fill in pi as user name
fill in your_password_given as password (in this example given, of course use the password you've chosen)
You should now be able to log in into the Raspberry Pi and then run the raspi-config configuration file to defintively activate, among other things, the SSH daemon.
To login into a Raspberry Pi that only has WiFi (e.g. Raspberry Pi Zero) another file has to be changed on top of the ones mentioned in the chapter above.
There's also a need for a file called wpa_supplicant.conf. The file should have the following content:
country=BE
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
scan_ssid=1
ssid="<SSID of your access point>"
psk="<password of your access point>"
}
Once the above data is filled incorrectly, put the card in the Raspberry Pi Zero W and start up the board. After some time the connection with the access point should be established.
If you're tired of typing the password each and every time you log in into the Raspberry Pi, fear no more. Rescue is on its way!
When using the mechanism of public/private keys, you don't have to give the password anymore when starting up the Raspberry Pi. Not only is this very handy, it's in some situations just needed. Suppose you want to start up the Raspberry Pi without human interference, there's no other option than having this start-up to happen autonomously.
To prepare the Raspberry Pi to start up autonomously, the following steps are needed:
On a Windows machine, open PuttyGEN and generate a new private key. I'm using as key type SSH-2 to generate the key and the number of bits is set to 2048
Save the private key somewhere on your PC and copy the public key
Go to your Raspberry Pi and create a folder .ssh. Change the permissions of the folder to 700
In that folder, create a file authorized_keys
Open the file with the editor of choice (in my case, I'm using the good'ol vi editor) and paste the complete public key in that file
Save the file and change the permissions to 644
Open the session in Putty and do the following:
Type in the IP address of the Raspberry Pi
Create a new session
On the left, select Connection -> Data and fill in pi in the Auto-login username field
Select Connection -> SSH -> Auth and point to the location of the private key
Save the Putty session under a name
If you now select the newly saved Putty session and you press the Open button, you should be able to auto-login into the Raspberry Pi.
To know what Raspberry Pi you have you can run the following command:
cat /proc/cpuinfo
At the end of the output you should see a line with the name Revision. Next to this, there's a number.
Output example of the above command for a Raspberry Pi 2B:
pi@rpi2B-garage:~ $ cat /proc/cpuinfo
processor : 0
model name : ARMv7 Processor rev 5 (v7l)
BogoMIPS : 38.40
Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x0
CPU part : 0xc07
CPU revision : 5
processor : 1
model name : ARMv7 Processor rev 5 (v7l)
BogoMIPS : 38.40
Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x0
CPU part : 0xc07
CPU revision : 5
processor : 2
model name : ARMv7 Processor rev 5 (v7l)
BogoMIPS : 38.40
CPU architecture: 7
CPU variant : 0x0
CPU part : 0xc07
CPU revision : 5
processor : 3
model name : ARMv7 Processor rev 5 (v7l)
BogoMIPS : 38.40
Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x0
CPU part : 0xc07
CPU revision : 5
Hardware : BCM2709
Revision : a01041
Serial : 00000000aafd0004
To know the connection between the revision number and the Raspberry Pi you have, you can consult the following web page:
Overview Raspberry Pi revision codes
You will see the following for the revision code a01041:
Pi 2 Model B v1.1 1GB a01041 (Sony, UK)
To see the Raspberry Pi model on the command line, run the following command:
cat /sys/firmware/devicetree/base/model
For a Raspberry Pi 2B, the following info is given:
Raspberry Pi 2 Model B Rev 1.1
Two possibilities:
uname -a
Shows you the following line:
Linux rpi4immc 6.1.21-v7+ #1642 SMP Mon Apr 3 17:20:52 BST 2023 armv7l GNU/Linux
If the line contains armv7l, it's a 32 bit system. If the line contains armv8, it's a 64 bit system.
getconf LONG_BIT
Returns a number 32 or 64 depending on the OS running.
file /lib/systemd/systemd
gives the following output:
pi@rpi4immc:~ $ file /lib/systemd/systemd
/lib/systemd/systemd: ELF 32-bit LSB pie executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, BuildID[sha1]=b0ae9c01730fd62f33a7a5da3681528ae4b65982, for GNU/Linux 3.2.0, stripped
When you want to do I2C communication, you have to perform at least the following action: activate I2C.
How?
Run sudo raspi-config on the command line
Select Interfacing Options
Select I2C and confirm you want to activate it.
No need to restart.
After you activated I2C, install i2c-tools. This can be done running the command sudo apt install i2c-tools.
i2ctools is a handy command-based tool to quickly test I2C on the Raspberry Pi without the need of other packages installed.
The following commands are part of the i2c-tools package:
i2cdetect: to check for available I2C busses or to see what I2C devices are detected on one of the I2C busses
i2cset: to write values to an I2C device
i2cget: to read values from an I2C device
i2cdump: to dump the complete register content of an I2C device
i2ctransfer: TBE (to be explained)
To run one of the above commands, you have to run it as sudo. This is the default behaviour, but can be changed (see one of the articles below).
Some popular commands are (see the chapter below on how to get rid of the sudo command):
i2cdetect -l: shows all available busses (to sort the output numerically: i2cdetect -l | sort -k 3 (sort on the 3rd column of the output)
i2cdetect -y 0x1: shows all available I2C devices connected to I2C bus 1
i2cset -y 1 0x20 0x00 0xFF: writes 0xFF (all pins as input) into register 0x00 (IODIRA) of the MCP23017 IO expander with address 0x20.
i2cdump dumps a certain amount of registers for a given device. Example for the MCP23017:
i2cdump -y -r 0x00-0x15 0 0x21
This will dump all 22 registers of the MCP23017 connected to I2C bus 0 and having an address of 0x20
pi@librecomputer:~ $ i2cdump -y -r 0x00-0x15 0 0x21
No size specified (using byte-data access)
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
10: 00 00 00 00 00 00 ......
This is the same as running the command i2cdump -y -r 0x00-0x15 0 0x21 b (mind the b at the end)
So, by default the result is shown in byte mode. If you want to see the result written in word mode, add the parameter w at the end like so:
pi@librecomputer:~ $ i2cdump -y -r 0x00-0x15 0 0x21 w
0,8 1,9 2,a 3,b 4,c 5,d 6,e 7,f
00: 0000 0000 0000 0000 0000 0000 0000 0000
08: 0000 0000 0000 0000 0000 0000 0000 0000
10: 0000 0000 0000 0000 0000 0000
After installing I2C tools you will experience you can't do anything with it without using the sudo rights. This is very annoying but can luckily be solved in a very easy way. This small article explains how.
the i2ctools package is installed in /usr/sbin. When you search for the I2C tools that are part of the package, using ls -als | grep i2c, you will see the group and owner is set to root. That in itself is not an issue. The problem is that the correct path can only be found when you prepend the tools with the sudo command. Else, you will get a message that i2cdetect (or one of the other programs part of the i2ctools package) is not found.
To solve this, you have to extend the PATH variable. One way of doing this, is by letting your .bashrc file know there's another file containing one or more path extensions.
Therefore, perform the following steps:
Open your ~/.bashrc file
At the end of the file, add the following line: [ -f ~/.bash_path ] && . ~/.bash_path. What this does, is the following:
it looks for the existence of a file called ~/.bash_path
if the file exists, it will source (execute) the content of the file
Create a new file called ~/.bash_path
Add the following content to the file: PATH=/usr/sbin:$PATH. This will prepend the current PATH variable with the path location of the i2ctools programs. This way, there's no need anymore to start the commands using sudo.
Re-run your ~/.bashrc file: . ~/.bashrc (yes, the command starts with a dot!).
From now on, you can just type i2cdetect (or any other program that is part of the i2ctools package) without the need for sudo.
By default, the I2C speed is set to 100 kHz. However, nowadays almost all I2C devices can run at 400 kHz (at least). To change the default I2C speed on the Raspberry Pi, one has to do the following:
Edit /boot/config.txt as root (sudo)
Add the following lines
core_freq=250
dtparam=i2c_baudrate=400000
This will set the I2C speed to exactly 400 kHz. For a speed of 100kHz, replace 400000 with 100000.
You have to reboot before the changes will take effect.
To get extra I2C busses, one can use an I2C switch or multiplexer.
One of such devices is the PCA9548, a 1-to-8 I2C switch. One I2C input can be sent out to 1 to 8 I2C output busses. More than one output bus can be selected which makes this device indeed a switch and not a multiplexer: a multiplexer selects one output while a switch can select one or more outputs.
There are different types of I2C muxes/switches. More information and a nice overview about I2C multiplexers/switches can be found here.
The PCA9548 I2C switch has 3 address pins. This means, you can have a maximum of 8 such devices on the I2C bus. The lowest address is 0x70 (A0 = A1 = A2 = 0), the highest address is 0x77 (A0 = A1 = A2 = 1).
The good news is: you don't have to do a lot to get the I2C switch up and running. Since a couple of years, the Linux kernel has an internal module available that allows transparent I2C bus selection without the user having something to do for it.
To activate this mechanism, the following line has to be put in the /boot/config.txt file on the Raspberry Pi:
dtoverlay=i2c-mux,pca9548,addr=0x70
This assumes the address of the external I2C switch is 0x70. If not, pls. adapt.
Once you added the above configuration, the Linux kernel will check if there's an I2C device connected to the Raspberry Pi each time the Raspberry Pi is started up.
If it found such device, then an extra of 8 (!!!) I2C busses will be available to the user. To check this, run the command i2cdetect -l on the command line (make sure you installed i2ctools; see another section on this page describing how to do this).
The output will be something like this (there's no default ordering in the output):
pi@rb3bplus:~ $ i2cdetect -l
i2c-15 i2c i2c-1-mux (chan_id 4) I2C adapter
i2c-13 i2c i2c-1-mux (chan_id 2) I2C adapter
i2c-1 i2c bcm2835 (i2c@7e804000) I2C adapter
i2c-11 i2c i2c-1-mux (chan_id 0) I2C adapter
i2c-18 i2c i2c-1-mux (chan_id 7) I2C adapter
i2c-16 i2c i2c-1-mux (chan_id 5) I2C adapter
i2c-14 i2c i2c-1-mux (chan_id 3) I2C adapter
i2c-2 i2c bcm2835 (i2c@7e805000) I2C adapter
i2c-12 i2c i2c-1-mux (chan_id 1) I2C adapter
i2c-17 i2c i2c-1-mux (chan_id 6) I2C adapter
To have the output ordered, simply add | sort after the command i2cdetect -l like so:
pi@rb3bplus:~ $ i2cdetect -l | sort
i2c-11 i2c i2c-1-mux (chan_id 0) I2C adapter
i2c-12 i2c i2c-1-mux (chan_id 1) I2C adapter
i2c-13 i2c i2c-1-mux (chan_id 2) I2C adapter
i2c-14 i2c i2c-1-mux (chan_id 3) I2C adapter
i2c-15 i2c i2c-1-mux (chan_id 4) I2C adapter
i2c-16 i2c i2c-1-mux (chan_id 5) I2C adapter
i2c-17 i2c i2c-1-mux (chan_id 6) I2C adapter
i2c-18 i2c i2c-1-mux (chan_id 7) I2C adapter
i2c-1 i2c bcm2835 (i2c@7e804000) I2C adapter
i2c-2 i2c bcm2835 (i2c@7e805000) I2C adapter
As you can see above, i2c-1 remains the "master" I2C bus (bcm2835 I2C adapter) but you have an extra of 8 new I2C busses available. In this case, the busses start at 11 and end at 18.
I2C bus 2 (i2c-2)is never taken since that one is occupied for the second I2C bus on the Raspberry Pi for EEPROM purposes.
Some advantages of having multiple I2C busses:
Spread of the bus capacity: an I2C bus can have a max. of 400pF as bus capacity. Having more busses allows you to spread the capacity load
More of the same devices are possible. Suppose you have a temperature sensor device on I2C and it has only 2 address pins. This means you can have a maximum of 4 such sensors in your system.
But what if you want to have 8 or 10 of those devices? Then the I2C switch/mux comes to the rescue.
If you define an I2C device on the bus and you connect it to e.g. i2c-15 you have to define this bus in your call to setting up an I2C device.
If you use Pi4J for instance, it's something like this (a MCP23017 has been taken as an example):
MCP23017GpioProvider provider_0x20 = new MCP23017GpioProvider(I2CBus.BUS_15, 0x20);
Here, I2CBus.BUS_15 is "just" a number, but then further down the road, in the class I2CProviderImpl.java to be precise, that number is added to a string like so: /sys/bus/i2c/devices/i2c- + busNumber. So, in the end it gets /sys/bus/i2c/devices/i2c-15 which results in a new Linux sysFs File object.
If that sysFs file exists, then a Linux devFs is made like so: final File devfs = new File("/dev/i2c-" + busNumber);. Again the bus number is added to another device, located in /dev => /dev/i2c-15.
When you look to the type of device on the command line (ls -als /dev/i2c-15), you will see this is a character device, typically for such kind of files.
Through this character device, the I2C communication is done.
When the Raspberry Pi is not connected through SSH to a terminal it is still possible to stop the device in a smooth way, just like you would issue a sudo halt on the command line. This way, the SD card is more protected against corruption which can happen if the Raspberry Pi is shut down in an uncontrolled way.
To use this mechanism the following line has to be added to the file /boot/config.txt:
dtoverlay=gpio-shutdown,gpio_pin=5,active_low=1,gpio_pull=up
In this example, pin GPIO 5 (BCM numbering!) is used. That is pin 29 on the 40-pins header of the RPi.
See this web page for more info about the Raspberry Pi pin numbering. The default layout shows the BCM (BroadCom) numbering.
Since the setup of the pin is set to be active low, one side of the switch has to be connected to GND and the other side of the switch has to be connected to pin GPIO 5. An activated pull-up resistor on pin GPIO 5 makes sure the level of the pin is high (3V3) when the button is not pressed and 0V when the button is pressed. Hence, the pin is also set as active_low.
This is by far the easiest approach.
Another approach is to have a small daemon running in the background, checking the state of a certain GPIO pin (defined by you) and act accordingly.
Adafruit has made such application (in C) and can be found here: https://github.com/adafruit/Adafruit-GPIO-Halt. But to be honest, the effort to install this does not outweigh the easy approach of one simple line added to the /boot/config.txt file. However, as usual, the choice is yours!
The temperature of the Raspberry Pi core can be measured using the following command:
/opt/vc/bin/vcgencmd measure_temp
Instead of typing in such a long command each and every time, you can make an alias for it in a file called ~/.bash_aliases.
alias temp='/opt/vc/bin/vcgencmd measure_temp'
This file should then be called from your ~/.bashrc file like so:
[ -f ~/.bash_aliases ] && . ~/.bash_aliases
This command first checks if there's a file called .bash_aliases in the root directory (hence, the ~ sign) and if so, it will source this file using the dot-operator.
Note that . ~/.bash_aliases is the same as source ~/.bash_aliases (the dot is a shortcut for source)
Example:
pi@rpi2B-bureau:~ $ temp
temp=35.8'C
When you run the command sudo apt install default-jdk on the Raspberry Pi then Java 11 will be installed.
If you want to install Java 8, you have to specify it in the sudo installation command. You have to type sudo apt install openjdk-8-jdk instead.
After installation you can run java -version to see the version installed.
As of 2023/02/18 the following Java 8 version is installed with the above mentioned installation command:
pi@desktop:~ $ java -version
openjdk version "1.8.0_312"
OpenJDK Runtime Environment (build 1.8.0_312-8u312-b07-1+rpi1-b07)
OpenJDK Client VM (build 25.312-b07, mixed mode)
On the Windows PC, download Java17 LTS from the Azul website. See image below for the correct settings on the Azul website.
Make sure you select the ARM 32-bit HF (hard float) architecture and NOT the ARM 64-bit version!!!
The downloaded file will be zulu17.38.21-ca-jdk17.0.5-linux_aarch32hf.tar.gz.
Using WinSCP, copy the file on the Raspberry Pi in the directory /home/pi/mystuff/Java_17_LTS.
On the Raspberry Pi, unzip using gunzip zulu17.38.21-ca-jdk17.0.5-linux_aarch32hf.tar.gz
Untar using tar -xvf zulu17.38.21-ca-jdk17.0.5-linux_aarch32hf.tar
You have now a few options to start java from everywhere in the system:
The simplest is to add the path to the /bin directory (so /home/pi/mystuff/Java_17_LTS/.../bin) into the ~/.bash_paths file like so:
PATH= /home/pi/.......:$PATH
Once this is done, save the file and source again the ~/.bashrc file: . ~/.bashrc.
Now you should be able to access java/javac/... from everywhere.
You can also point to a Java version with the update-alternatives command. See here for a detailed explanation of the update-alternatives command.
sudo update-alternatives --config java
Check overview shown, active version is indicated with a *. If you want to change the preferred java version, type in the number.
Raspberry Pi has a unique way of dealing with their versions.
In the past, the revision code was simply a number between 0x0002 and 0x0015 but that's long gone.
The new revision code is still a hex number and can be found when showing the content of the file /proc/cpuinfo.
For a Raspberry Pi 2B, for example, that number can be 0xa01041 (there are other numbers assigned to other Raspberry Pi 2B versions, depending on, for instance, the location of manuacturing).
Therefor, a new structure is put in place and looks like so: NOQuuuWuFMMMCCCCPPPPTTTTTTTTRRRR.
The really interesting part is this, however: FMMMCCCCPPPPTTTTTTTTRRRR.
The details are given below (more information can be found here):
Revision number Raspberry Pi 2B, made in the UK by Sony.
0xA01041 = 10489921d = 101000000001000001000001b
N O Q uuu W u F MMM CCCC PPPP TTTTTTTT RRRR
1 010 0000 0001 00000100 0001
| \_/ \__/ \__/ \______/ \__/
| | | | | |
| | | | | +---> Revision: 0, 1, 2, ...
| | | | +----------> Type: 0 = A
| | | | 1 = B
| | | | 2 = A+
| | | | 3 = B+
| | | | 4 = 2B
| | | | 5 = Alpha (early prototype)
| | | | 6 = CM1
| | | | 8 = 3B
| | | | 9 = Zero
| | | | a = CM3
| | | | c = Zero W
| | | | d = 3B+
| | | | e = 3A+
| | | | f = Internal use only
| | | | 10 = CM3+
| | | | 11 = 4B
| | | | 12 = Zero 2 W
| | | | 13 = 400
| | | | 14 = CM4
| | | | 15 = CM4S
| | | +-----------------> Processor: 0 = BCM2835
| | | 1 = BCM2836
| | | 2 = BCM2837
| | | 3 = BCM2711
| | +----------------------> Manufacturer: 0 = Sony UK
| | 1 = Egoman
| | 2 = Embest
| | 3 = Sony Japan
| | 4 = Embest
| | 5 = Stadium
| +---------------------------> Memory size: 0 = 256MB
| 1 = 512MB
| 2 = 1GB
| 3 = 2GB
| 4 = 4GB
| 5 = 8GB
+------------------------------> New flag: 0 = old-style revision
1 = new-style revision
For an overview of the different revisions, see here.
All possible values you can write in /boot/config.txt are mentioned here.
All about the Raspberry Pi versions can be found here. For instance, if you want to see the schematics of the Raspberry Pi Zero W, then go to the beforementioned page, select Raspberry Pi Hardware and you'll end up on a page describing the hardware (including electrical and mechanical drawings) of all recent (and not so recent) Raspberry Pi's.
This is how I came to know if the Raspberry Pi Zero W also has the 1k8 resistors mounted to pull up the I2C bus. And indeed, it has...
Similar chapters are available about the config.txt file, datasheets, processors used by the Raspberry Pi family, configurations, Linux kernel... and so on.
getconf LONG_BIT:
- 32: 32 bit
- 64: 64 bit
file /lib/systemd/systemd:
Second parameter gives the bit version:
pi@pizero2:~/mystuff/java $ file /lib/systemd/systemd
/lib/systemd/systemd: ELF 32-bit LSB pie executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, BuildID[sha1]=3f96d054e53eada57de95fc8e01e9925396c2be6, for GNU/Linux 3.2.0, stripped