====== Raspberry Pi ======
===== Flash an SD card =====
To install the RaspiOS you will need to flash the operating system image to an SD card.
With dd:
Good in Linux and Mac shell. More info at https://www.devdungeon.com/content/how-format-sd-card-or-usb-flash-drive
```bash
sudo dd if=/path/to/iso of=/path/to/device bs=1m
```
With Balena Etcher:
GUI that is easy to use on Windows, Mac, and Linux:
https://www.balena.io/etcher/
===== Force HDMI =====
To disable HDMI detection and force HDMI (fixes black screen after reboot)
In `/boot/config.txt` add:
```
hdmi_force_hotplug=1
# and
config_hdmi_boost=4
```
===== Default username and password =====
```text
pi/raspberry
```
===== Change password =====
```bash
# Change your own password
passwd
# Change specific user's password
sudo -u pi passwd
```
===== Update and upgrade =====
```bash
sudo apt update
sudo apt full-upgarde
sudo apt dist-upgrade # Upgrade Raspbian distro
sudo rpi-update # Update Pi firmawre
```
===== Configure everything =====
E.g. network, display, login, modules, hostname, timezone
sudo raspi-config
===== Check Pi revision version =====
cat /sys/firmware/devicetree/base/model
===== Get Raspbian distro version =====
cat /etc/os-release
===== Check pin layout =====
pinout
===== Networking =====
==== Configure static IP address for eth0 ====
It should use DHCP by default, but if you want to specify an IP Address you can.
Edit ''/etc/dhcpcd.conf'' and uncomment the lines with the example static IP address.
Be sure to change the IP address, net mask, and gateway as necessary.
Then reboot with ''sudo reboot''.
# Look for eth0 static IP example in comments
sudo vim /etc/dhcpcd.conf # Update config
sudo reboot
==== Manually configure wpa_supplicant for WiFi ====
sudo ifconfig
sudo iwconfig
sudo ip addr
sudo iwlist wlan0 scan
wpa_supplicant
wpa_passphrase my-wifi-essid secret pasword >etc/wpa_supplicant/
sudo service networking restart
In the file ''/etc/wpa_supplicant/wpa_supplicant.conf'', you should see
something like this:
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=US
network={
ssid="my-wifi-essid"
psk="password-as-is"
}
==== Expose local port via remote server ====
You can take a service running locally, and use a remote VPS to be a proxy and allow connectivity from the internet.
https://www.devdungeon.com/content/expose-local-port-over-remote-vps-ssh-remote-port-forwarding
E.g. ''curl http://my-remote-host.com:9999'' returns response from ''locahost:8000''
# This will SSH to `my-remote-host.com` and while
# the session is open, the remote server will
# start listening on on port 9999 and any
# connection it recieves will get forward
# straight back to port 8000 on your local computer
ssh -R 9999:localhost:8000 my-remote-host.com
===== Create a system service user account =====
# To create a use that can't login. Good for running low privilege services
sudo useradd --system --no-create-home --shell=/sbin/nologin some_user
# https://www.devdungeon.com/content/how-create-secure-linux-system-user
===== Create a systemd service =====
https://www.devdungeon.com/content/creating-systemd-service-files
# /etc/systemd/system/my_service.service
[Unit]
Description=My Custom Service
After=network.target
[Service]
Type=simple
User=pi
WorkingDirectory=/home/pi
ExecStart=/home/pi/my_app --option=123
Restart=always
[Install]
WantedBy=multi-user.target
===== Setup cron =====
https://www.devdungeon.com/content/cron-job-examples-and-tip
# To edit `pi` user's cron jobs
crontab -e
# For root
sudo crontab -e
# For some other user
sudo -u some_user crontab -e
===== Take pictures and video =====
==== Pi Camera ====
Make sure Camera is enabled with `sudo raspi-config`.
To take picture:
raspistill
To take video:
https://www.raspberrypi.org/documentation/usage/camera/raspicam/raspivid.md
raspivid
raspivid -t 30000 -w 640 -h 480 -fps 25 -b 1200000 -p 0,0,640,480 -o pivideo.h264
See below for how to convert `.h264` to `.mp4`.
==== Webcam ====
List webcam devices:
lsusb
ls /dev/video*
For pictures:
sudo apt install fswebcam
# sudo gpasswd -a pi video # Not needed for pics?
fswebcam --help | less
fswebcam image.jpg
fswebcam -r 1920x1080 ~/fswebcamtest.jpg
For video recording:
sudo apt install libav-tools
avconv -f video4linux2 -r 25 -s 1920x1080 -i /dev/video0 output.avi
==== Make timelapse video from images ====
sudo apt install mencoder
ls *.jpg > image_list.txt
mencoder -nosound -ovc lavc -lavcopts vcodec=mpeg4:aspect=16/9:vbitrate=8000000 -vf scale=1280:960 -o timelapse.avi -mf type=jpeg:fps=30 mf://@image_list.txt
===== Convert h264 video files to mp4 =====
`raspivid` saves `.h264` videos by default. You can convert to mp4 with
sudo apt install -y gpac
# Convert .h264 to .mp4
MP4Box -add video.h264 video.mp4
## Example app: Pi-Cam-Server (Flask)
https://github.com/NanoDano/Pi-Cam-Server
## Example app: Pi-Timelaper (Django)
https://github.com/NanoDano/Pi-Timelapser
===== Remote desktop with VNC =====
Official docs at https://www.raspberrypi.org/documentation/remote-access/vnc/
Turn on VNC service first through `raspi-config`. It uses RealVNC. Go to the Interfacing Options and enable VNC.
# Go to 5) Interfacing Options and enable VNC
sudo raspi-config
If you want to connect to view, you'll need to use the RealVNC client which supports username and password auth.
To use a generic client like TigerVNC https://tigervnc.org instead of RealVNC, you'll need to change the authentication mechanism and essentially make it less secure. To do that, update the config file, update the VNC settings, and then restart the service.
sudo vim /root/.vnc/config.d/vncserver-x11
# Set `Authentication=VncAuth`
# Change VNC server to use one password instead of user auth
sudo vncpasswd -service
# Enter the password when it asks
systemctl restart vncserver-x11-serviced
Then connect as normal using a client like TigerVNC using the Pi's IP address or hostname and the password you set for the service.
FIX: When you connect and authenticate with VNC but then see `Cannot currently show the desktop`, it is because there is no graphical desktop running. You have
Option 1) set the Pi to boot into graphical mode. Use `raspi-config` and go to the Boot options and set it to boot to graphical desktop. You can also do it at the CLI with:
# Set default boot to graphical mode (`graphical`) and not CLI only (`multi-user`)
sudo systemctl set-default graphical
sudo reboot
Option 2) SSH into the Pi and run `vncserver` from the command line. This will create a virtual desktop that you can use. The virtual desktop numbers look like ports and start with the number 1. For example: `192.168.1.10:1`.
# Repeat this command to create multiple desktops
vncserver
# To kill a display, pass it the desktop numbers
vncserver -kill :1
TIP: You can change the desktop resolution and it will change the HDMI port an VNC at the same time.
==== Fix "failed to open vchiq instance" with raspi-still ====
This means your user can't open the video device and needs to be in group `video`.
===== I2C stuff =====
Turn on i2c using ''raspi-config'' under Interface options. Reboot after enabling. This will create a device like ''/dev/i2c-1''.
Install ''i2c-utils'' to get tools like ''/usr/sbin/i2cdetect''.
sudo apt install i2c-tools
dpkg -L i2c-tools
sudo i2cdetect 1 # they're in sbin, so need sudo
sudo i2cdump --help
==== I2C C library ====
/* test_i2c.cpp
* Compile with:
* g++ test_i2c.cpp -lwiringPi
*/
#include
#include
#include
int main() {
/* Provide the i2c address from `sudo i2cdetect` */
int file_handle = wiringPiI2CSetup(0x60);
int result = wiringPiI2CWrite(file_handle, 0x40, 0xDEAD );
if (result == -1) {
std::cout << "Error #" << errno << std::endl;
} else {
std::cout << "Result: " << result << std::endl;
}
return 0;
}
==== I2C Python Library ====
Install the [[https://packages.debian.org/buster/python3-smbus|Python3 smbus]] library using ''apt''.
sudo apt-get install python3-smbus
# Reference adapted from: https://pypi.org/project/smbus2/
from smbus import SMBus
DEVICE_ADDRESS = 80
bus1 = SMBus(1)
data = bus1.read_byte_data(DEVICE_ADDRESS, 0) # From offset 0
print(data)
bus1.close()
with SMBus(1) as bus1:
# Write a byte to device address, offset 0
data = 45
bus1.write_byte_data(DEVICE_ADDRESS, 0, data)