Making Of#
Switch Sockets via wired network Challenge accepted
Analyze and Create#
Elicitate Requirements#
Customer is a friend - no money involved
Customer is a tech-savvy person in mechanical and electronic matters
User is a tech-savvy person as well, especially in software.
Identify Design Constraints#
No Wireless data transfer at all (no WiFi, no Bluetooth, …)
Connect the system to the environment via wired network
Straight-forward to the point of usage by a tech-savvy user
Create the System-Design#
I choose the command line tool pinctrl shipped with RPI-OS to be used to control the Relais via the GPIO pins of the RPI. No additional software is needed to be installed on the RPI or developed.
Realize#
Flash OS Image#
Get the Raspberry Pi OS Imager for Windows via scoop.sh. Use Powershell:
PS C:\> scoop install raspberry-pi-imager
--snip--
PS C:\>
Troubleshooting: In case scoop isn’t already installed then install it as follows and repeat the above command:
PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
PS C:\> Invoke-RestMethod -Uri https://get.scoop.sh | Invoke-Expression
--snip--
PS C:\>
Use Raspberry Pi OS Imager to burn the image onto the SD-card:
Set GPIO settings after (re-)boot#
This is optional.
As default the GPIOs are OFF
after reboot. Let’s change it as described in the RPI documentation:
Directly after flashing open on config.txt
and append the following to the end of the file:
## GPIO settings
# Set pin 26 (BCM) to output and ON after (re-)boot
gpio=26=op,dh
# Set pin 19 (BCM) to output and ON after (re-)boot
gpio=19=op,dh
## EOF
Connect the System to the Environment#
Install Software#
Being logged on as user some_user
on host some_host
execute the following commands in a bash
or git-bash
:
1wget https://some_user.github.io/blog/2024-09-WeSwitch/_attachments/switch.py
2ssh-copy-id weswitch@weswitch
3scp switch.py weswitch@weswitch:~/
4ssh weswitch@weswitch "chmod +x switch.py"
5ssh weswitch@weswitch "sudo mv switch.py /usr/local/bin/switch"
6rm switch.py
Use System#
Being logged on as «user» some_user
on «host» some_host
execute the following commands in a bash
or git-bash
:
1some_electrical_device=26
2ssh weswitch@weswitch "switch $some_electrical_device"
3ssh weswitch@weswitch "switch $some_electrical_device:1"
4ssh weswitch@weswitch "switch $some_electrical_device:0"
Have a coffee with me#
Let’s enjoy our new tool and drink a ☕ together … 😁.
Discarded#
The procedure / walk#
We need an ssh client. If you’re under Linux, you have one. If you’re under Windows, you can use Putty or, what I recommend, just use the git-bash
, its environment has ssh included.
If you don’t have git with git-bash, then just install it via scoop
:
PS C:\> scoop install git
PS C:\>
Let’s enable password-less login via ssh:
1some_user@some_host:~$ ssh-copy-id weswitch@weswitch
2/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/c/Users/some_user/.ssh/id_rsa.pub"
3/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
4/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
5weswitch@weswitch's password:
6
7Number of key(s) added: 1
8
9Now try logging into the machine, with: "ssh 'weswitch@weswitch'"
10and check to make sure that only the key(s) you wanted were added.
11
12some_user@some_host:~$
Now let’s log onto system via ssh
:
1some_user@some_host:~$ ssh weswitch@weswitch
2Linux weswitch 6.6.31+rpt-rpi-v8 #1 SMP PREEMPT Debian 1:6.6.31-1+rpt1 (2024-05-29) aarch64
3
4The programs included with the Debian GNU/Linux system are free software;
5the exact distribution terms for each program are described in the
6individual files in /usr/share/doc/*/copyright.
7
8Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
9permitted by applicable law.
10Last login: Sat Aug 31 08:31:12 2024
11weswitch@weswitch:~ $
+-----+------------+----RPI---+------------+-----+
| BCM | Function | Physical | Function | BCM |
+-----+------------+----++----+------------+-----+
| | 3.3V | 1 || 2 | 5v | |
| 2 | I2C1 SDA | 3 || 4 | 5v | |
| 3 | I2C1 SCL | 5 || 6 | GND | |
| 4 | GPCLK0 | 7 || 8 | UART TX | 14 |
| | GND | 9 || 10 | UART RX | 15 |
| 17 | | 11 || 12 | PCM CLK | 18 |
| 27 | | 13 || 14 | GND | |
| 22 | | 15 || 16 | | 23 |
| | 3.3V | 17 || 18 | | 24 |
| 10 | SPI0 MOSI | 19 || 20 | GND | |
| 9 | SPI0 MISO | 21 || 22 | | 25 |
| 11 | SPI0 SCLK | 23 || 24 | SPI0 CE0 | 8 |
| | GND | 25 || 26 | SPI0 CE1 | 7 |
| 0 | EEPROM SDA | 27 || 28 | EEPROM SCL | 1 |
| 5 | | 29 || 30 | GND | |
| 6 | | 31 || 32 | | 12 |
| 13 | PWM1 | 33 || 34 | GND | |
| 19 | PCM FS | 35 || 36 | | 16 |
| 26 | | 37 || 38 | PCM DIN | 20 |
| | GND | 39 || 40 | PCM DOUT | 21 |
+-----+------------+----++----+------------+-----+
1weswitch@weswitch:~ $ python --version
2Python 3.11.2
3weswitch@weswitch:~ $ python -m pip install gpiozero
4error: externally-managed-environment
5
6× This environment is externally managed
7╰─> To install Python packages system-wide, try apt install
8 python3-xyz, where xyz is the package you are trying to
9 install.
10
11 If you wish to install a non-Debian-packaged Python package,
12 create a virtual environment using python3 -m venv path/to/venv.
13 Then use path/to/venv/bin/python and path/to/venv/bin/pip. Make
14 sure you have python3-full installed.
15
16 For more information visit http://rptl.io/venv
17
18note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages.
19hint: See PEP 668 for the detailed specification.
20weswitch@weswitch:~ $ sudo apt-get install python3-gpiozero
21Reading package lists... Done
22Building dependency tree... Done
23Reading state information... Done
24python3-gpiozero is already the newest version (2.0-1).
250 upgraded, 0 newly installed, 0 to remove and 92 not upgraded.
26weswitch@weswitch:~ $
The AI-driven development loop:
1weswitch@weswitch:~ $ touch switch.py && chmod +x switch.py
2
3weswitch@weswitch:~ $ # [A] Talk to the AI to get the code
4weswitch@weswitch:~ $ # Copy the code into the clipboard and transfer it to the RPI
5weswitch@weswitch:~ $ #
6weswitch@weswitch:~ $ cat > switch.py
7# Paste it from the clipboard with Mouse-Right-Click
8# Hit Ctrl-D (EOF) to save the file
9
10weswitch@weswitch:~ $ # Test the code
11weswitch@weswitch:~ $ ./switch.py
12weswitch@weswitch:~ $ # ...
13
14weswitch@weswitch:~ $ # Based on the results decide whether it needs rework or it's good to go ([A] or [B])
15weswitch@weswitch:~ $ # [B] Finish
Set up defined GPIO settings after (re-)boot.
As default the GPIOs are OFF after reboot. Let’s change it as described in the RPI documentation:
1weswitch@weswitch:~ $ sudo vi /boot/firmware/config.txt
2weswitch@weswitch:~ $ tail /boot/firmware/config.txt
3
4## GPIO settings
5# Set pin 26 (BCM) to output and ON after (re-)boot
6gpio=26=op,dh
7
8# Set pin 19 (BCM) to output and ON after (re-)boot
9gpio=19=op,dh
10
11## EOF
12
13weswitch@weswitch:~ $
Find through thread of issue gpiozero#707 more infos about state-of-the-art command line tool for gpio control under RPI: pinctrl
:
raspi-gpio <https://github.com/RPi-Distro/raspi-gpio/blob/master/README.md>
1weswitch@weswitch:~ $ raspi-gpio --help
2Unknown argument "--help" try "raspi-gpio help"
3weswitch@weswitch:~ $ raspi-gpio help
4
5WARNING! raspi-gpio set writes directly to the GPIO control registers
6ignoring whatever else may be using them (such as Linux drivers) -
7it is designed as a debug tool, only use it if you know what you
8are doing and at your own risk!
9
10The raspi-gpio tool is designed to help hack / debug BCM283x GPIO.
11Running raspi-gpio with the help argument prints this help.
12raspi-gpio can get and print the state of a GPIO (or all GPIOs)
13and can be used to set the function, pulls and value of a GPIO.
14raspi-gpio must be run as root.
15Use:
16raspi-gpio [<n>] get [GPIO]
17OR
18raspi-gpio [<n>] set <GPIO> [options]
19OR
20raspi-gpio [<n>] funcs [GPIO]
21OR
22raspi-gpio [<n>] raw
23
24<n> is an option GPIO chip index (default 0)
25GPIO is a comma-separated list of pin numbers or ranges (without spaces),
26e.g. 4 or 18-21 or 7,9-11
27Note that omitting [GPIO] from raspi-gpio get prints all GPIOs.
28raspi-gpio funcs will dump all the possible GPIO alt funcions in CSV format
29or if [GPIO] is specified the alternate funcs just for that specific GPIO.
30Valid [options] for raspi-gpio set are:
31ip set GPIO as input
32op set GPIO as output
33a0-a5 set GPIO to alternate function alt0-alt5
34pu set GPIO in-pad pull up
35pd set GPIO in-pad pull down
36pn set GPIO pull none (no pull)
37dh set GPIO to drive to high (1) level (only valid if set to be an output)
38dl set GPIO to drive low (0) level (only valid if set to be an output)
39Examples:
40raspi-gpio get Prints state of all GPIOs one per line
41raspi-gpio get 20 Prints state of GPIO20
42raspi-gpio get 20,21 Prints state of GPIO20 and GPIO21
43raspi-gpio set 20 a5 Set GPIO20 to ALT5 function (GPCLK0)
44raspi-gpio set 20 pu Enable GPIO20 ~50k in-pad pull up
45raspi-gpio set 20 pd Enable GPIO20 ~50k in-pad pull down
46raspi-gpio set 20 op Set GPIO20 to be an output
47raspi-gpio set 20 dl Set GPIO20 to output low/zero (must already be set as an output)
48raspi-gpio set 20 ip pd Set GPIO20 to input with pull down
49raspi-gpio set 35 a0 pu Set GPIO35 to ALT0 function (SPI_CE1_N) with pull up
50raspi-gpio set 20 op pn dh Set GPIO20 to ouput with no pull and driving high
51weswitch@weswitch:~ $ raspi-gpio gget 26
52Unknown argument "gget" try "raspi-gpio help"
53weswitch@weswitch:~ $ raspi-gpio get 26
54GPIO 26: level=0 func=INPUT
55[ raspi-gpio is deprecated - try `pinctrl` instead ]
56weswitch@weswitch:~ $ pinctrl --help
57Unknown option '--help' - try "pinctrl help"
58weswitch@weswitch:~ $ pinctrl help
59
60WARNING! pinctrl set writes directly to the GPIO control registers
61ignoring whatever else may be using them (such as Linux drivers) -
62it is designed as a debug tool, only use it if you know what you
63are doing and at your own risk!
64
65Running pinctrl with the help argument prints this help.
66pinctrl can get and print the state of a GPIO (or all GPIOs)
67and can be used to set the function, pulls and value of a GPIO.
68pinctrl must be run as root.
69Use:
70pinctrl [-p] [-v] get [GPIO]
71OR
72pinctrl [-p] [-v] [-e] set <GPIO> [options]
73OR
74pinctrl [-p] [-v] poll [GPIO]
75OR
76pinctrl [-p] [-v] funcs [GPIO]
77OR
78pinctrl -c <chip> [funcs] [GPIO]
79
80GPIO is a comma-separated list of GPIO names, numbers or ranges (without
81spaces), e.g. 4 or 18-21 or BT_ON,9-11
82
83Note that omitting [GPIO] from "pinctrl get" prints all GPIOs.
84If the -p option is given, GPIO numbers are replaced by pin numbers on the
8540-way header. If the -v option is given, the output is more verbose. Including
86the -e option in a "set" causes pinctrl to echo back the new pin states.
87pinctrl funcs will dump all the possible GPIO alt functions in CSV format
88or if [GPIO] is specified the alternate funcs just for that specific GPIO.
89The -c option allows the alt functions (and only the alt function) for a named
90chip to be displayed, even if that chip is not present in the current system.
91
92Valid [options] for pinctrl set are:
93ip set GPIO as input
94op set GPIO as output
95a1-a7 set GPIO to fsel in the range 1-7
96no set GPIO to no function (NONE)
97pu set GPIO in-pad pull up
98pd set GPIO pin-pad pull down
99pn set GPIO pull none (no pull)
100dh set GPIO to drive high (1) level (only valid if set to be an output)
101dl set GPIO to drive low (0) level (only valid if set to be an output)
102Examples:
103pinctrl get Prints state of all GPIOs one per line
104pinctrl get 10 Prints state of GPIO10
105pinctrl get 10,11 Prints state of GPIO10 and GPIO11
106pinctrl set 10 a2 Set GPIO10 to fsel 2 function (nand_wen_clk)
107pinctrl -e set 10 pu Enable GPIO10 ~50k in-pad pull up, echoing the result
108pinctrl set 10 pd Enable GPIO10 ~50k in-pad pull down
109pinctrl set 10 op Set GPIO10 to be an output
110pinctrl set 10 dl Set GPIO10 to output low/zero (must already be set as an output)
111pinctrl set 10 ip pd Set GPIO10 to input with pull down
112pinctrl set 35 a1 pu Set GPIO35 to fsel 1 (jtag_2_clk) with pull up
113pinctrl set 20 op pn dh Set GPIO20 to output with no pull and driving high
114pinctrl -c bcm2835 9-11 Display the alt functions for GPIOs 9-11 on bcm2835
115weswitch@weswitch:~ $ pinctrl get 10
11610: ip -- | lo // GPIO10 = input
117weswitch@weswitch:~ $ pinctrl get 26
11826: ip -- | lo // GPIO26 = input
119weswitch@weswitch:~ $ pinctrl set 26 op
120weswitch@weswitch:~ $ pinctrl set 26 dh
121weswitch@weswitch:~ $ pinctrl set 26 dl
122weswitch@weswitch:~ $ pinctrl set 26 dh
123weswitch@weswitch:~ $ pinctrl set 26 dl
124weswitch@weswitch:~ $
weswitch@weswitch:~ $ sudo tee -a /boot/firmware/config.txt > /dev/null
## GPIO settings
# Set pin 26 (BCM) to output and ON after (re-)boot
gpio=26=op,dh
# Set pin 19 (BCM) to output and ON after (re-)boot
gpio=19=op,dh
## EOF
weswitch@weswitch:~ $ tail /boot/firmware/config.txt
## GPIO settings
# Set pin 26 (BCM) to output and ON after (re-)boot
gpio=26=op,dh
# Set pin 19 (BCM) to output and ON after (re-)boot
gpio=19=op,dh
## EOF
weswitch@weswitch:~ $ sudo reboot
1weswitch@weswitch:~ $ sudo reboot
2
3Broadcast message from root@weswitch on pts/1 (Sun 2024-09-01 15:10:10 CEST):
4
5The system will reboot now!
6
7weswitch@weswitch:~ $ Connection to weswitch closed by remote host.
8Connection to weswitch closed.
9some_user@some_host:~$ ssh weswitch@weswitch "pinctrl set 26 dh"
10some_user@some_host:~$ ssh weswitch@weswitch "pinctrl set 26 dl"
11some_user@some_host:~$ ssh weswitch@weswitch "pinctrl set 26 dh"
12some_user@some_host:~$ ssh weswitch@weswitch "pinctrl help"
13
14WARNING! pinctrl set writes directly to the GPIO control registers
15ignoring whatever else may be using them (such as Linux drivers) -
16it is designed as a debug tool, only use it if you know what you
17are doing and at your own risk!
18
19Running pinctrl with the help argument prints this help.
20pinctrl can get and print the state of a GPIO (or all GPIOs)
21and can be used to set the function, pulls and value of a GPIO.
22pinctrl must be run as root.
23Use:
24pinctrl [-p] [-v] get [GPIO]
25OR
26pinctrl [-p] [-v] [-e] set <GPIO> [options]
27OR
28pinctrl [-p] [-v] poll [GPIO]
29OR
30pinctrl [-p] [-v] funcs [GPIO]
31OR
32pinctrl -c <chip> [funcs] [GPIO]
33
34GPIO is a comma-separated list of GPIO names, numbers or ranges (without
35spaces), e.g. 4 or 18-21 or BT_ON,9-11
36
37Note that omitting [GPIO] from "pinctrl get" prints all GPIOs.
38If the -p option is given, GPIO numbers are replaced by pin numbers on the
3940-way header. If the -v option is given, the output is more verbose. Including
40the -e option in a "set" causes pinctrl to echo back the new pin states.
41pinctrl funcs will dump all the possible GPIO alt functions in CSV format
42or if [GPIO] is specified the alternate funcs just for that specific GPIO.
43The -c option allows the alt functions (and only the alt function) for a named
44chip to be displayed, even if that chip is not present in the current system.
45
46Valid [options] for pinctrl set are:
47ip set GPIO as input
48op set GPIO as output
49a1-a7 set GPIO to fsel in the range 1-7
50no set GPIO to no function (NONE)
51pu set GPIO in-pad pull up
52pd set GPIO pin-pad pull down
53pn set GPIO pull none (no pull)
54dh set GPIO to drive high (1) level (only valid if set to be an output)
55dl set GPIO to drive low (0) level (only valid if set to be an output)
56Examples:
57pinctrl get Prints state of all GPIOs one per line
58pinctrl get 10 Prints state of GPIO10
59pinctrl get 10,11 Prints state of GPIO10 and GPIO11
60pinctrl set 10 a2 Set GPIO10 to fsel 2 function (nand_wen_clk)
61pinctrl -e set 10 pu Enable GPIO10 ~50k in-pad pull up, echoing the result
62pinctrl set 10 pd Enable GPIO10 ~50k in-pad pull down
63pinctrl set 10 op Set GPIO10 to be an output
64pinctrl set 10 dl Set GPIO10 to output low/zero (must already be set as an output)
65pinctrl set 10 ip pd Set GPIO10 to input with pull down
66pinctrl set 35 a1 pu Set GPIO35 to fsel 1 (jtag_2_clk) with pull up
67pinctrl set 20 op pn dh Set GPIO20 to output with no pull and driving high
68pinctrl -c bcm2835 9-11 Display the alt functions for GPIOs 9-11 on bcm2835
69some_user@some_host:~$ ssh weswitch@weswitch "pinctrl 26 dl"
70some_user@some_host:~$ ssh weswitch@weswitch "pinctrl 19 dl"
71some_user@some_host:~$ ssh weswitch@weswitch "sudo init 6"
72some_user@some_host:~$
1some_user@some_host:~$ ssh-copy-id weswitch@weswitch
2/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/c/Users/some_user/.ssh/id_rsa.pub"
3The authenticity of host 'weswitch (192.168.1.110)' can't be established.
4ED25519 key fingerprint is SHA256:TPMVfBCS/noxz4hr1w3rRYpVxk5YKuM418legTAkpjw.
5This key is not known by any other names.
6Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
7/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
8/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
9weswitch@weswitch's password:
10
11Number of key(s) added: 1
12
13Now try logging into the machine, with: "ssh 'weswitch@weswitch'"
14and check to make sure that only the key(s) you wanted were added.
15
16some_user@some_host:~$ ssh weswitch@weswitch "tail /boot/firmware/config.txt"
17[cm4]
18# Enable host mode on the 2711 built-in XHCI USB controller.
19# This line should be removed if the legacy DWC2 controller is required
20# (e.g. for USB device mode) or if USB support is not required.
21otg_mode=1
22
23[cm5]
24dtoverlay=dwc2,dr_mode=host
25
26[all]
27some_user@some_host:~$ ssh weswitch@weswitch "sudo tee -a /boot/firmware/config.txt > /dev/null"
28
29## GPIO settings
30# Set pin 26 (BCM) to output and ON after (re-)boot
31gpio=26=op,dh
32
33# Set pin 19 (BCM) to output and ON after (re-)boot
34gpio=19=op,dh
35
36## EOF
37weswitch@weswitch:~ $ tail /boot/firmware/config.txt
38
39
40## GPIO settings
41# Set pin 26 (BCM) to output and ON after (re-)boot
42gpio=26=op,dh
43
44# Set pin 19 (BCM) to output and ON after (re-)boot
45gpio=19=op,dh
46
47## EOF
48some_user@some_host:~$ ssh weswitch@weswitch "tail /boot/firmware/config.txt"
49
50
51## GPIO settings
52# Set pin 26 (BCM) to output and ON after (re-)boot
53gpio=26=op,dh
54
55# Set pin 19 (BCM) to output and ON after (re-)boot
56gpio=19=op,dh
57
58## EOF
59some_user@some_host:~$ ssh weswitch@weswitch "sudo reboot"
60some_user@some_host:~$
61
62
63some_user@some_host:~$ ssh weswitch@weswitch "pinctrl help"
64
65WARNING! pinctrl set writes directly to the GPIO control registers
66ignoring whatever else may be using them (such as Linux drivers) -
67it is designed as a debug tool, only use it if you know what you
68are doing and at your own risk!
69
70Running pinctrl with the help argument prints this help.
71pinctrl can get and print the state of a GPIO (or all GPIOs)
72and can be used to set the function, pulls and value of a GPIO.
73pinctrl must be run as root.
74Use:
75pinctrl [-p] [-v] get [GPIO]
76OR
77pinctrl [-p] [-v] [-e] set <GPIO> [options]
78OR
79pinctrl [-p] [-v] poll [GPIO]
80OR
81pinctrl [-p] [-v] funcs [GPIO]
82OR
83pinctrl -c <chip> [funcs] [GPIO]
84
85GPIO is a comma-separated list of GPIO names, numbers or ranges (without
86spaces), e.g. 4 or 18-21 or BT_ON,9-11
87
88Note that omitting [GPIO] from "pinctrl get" prints all GPIOs.
89If the -p option is given, GPIO numbers are replaced by pin numbers on the
9040-way header. If the -v option is given, the output is more verbose. Including
91the -e option in a "set" causes pinctrl to echo back the new pin states.
92pinctrl funcs will dump all the possible GPIO alt functions in CSV format
93or if [GPIO] is specified the alternate funcs just for that specific GPIO.
94The -c option allows the alt functions (and only the alt function) for a named
95chip to be displayed, even if that chip is not present in the current system.
96
97Valid [options] for pinctrl set are:
98ip set GPIO as input
99op set GPIO as output
100a1-a7 set GPIO to fsel in the range 1-7
101no set GPIO to no function (NONE)
102pu set GPIO in-pad pull up
103pd set GPIO pin-pad pull down
104pn set GPIO pull none (no pull)
105dh set GPIO to drive high (1) level (only valid if set to be an output)
106dl set GPIO to drive low (0) level (only valid if set to be an output)
107Examples:
108pinctrl get Prints state of all GPIOs one per line
109pinctrl get 10 Prints state of GPIO10
110pinctrl get 10,11 Prints state of GPIO10 and GPIO11
111pinctrl set 10 a2 Set GPIO10 to fsel 2 function (nand_wen_clk)
112pinctrl -e set 10 pu Enable GPIO10 ~50k in-pad pull up, echoing the result
113pinctrl set 10 pd Enable GPIO10 ~50k in-pad pull down
114pinctrl set 10 op Set GPIO10 to be an output
115pinctrl set 10 dl Set GPIO10 to output low/zero (must already be set as an output)
116pinctrl set 10 ip pd Set GPIO10 to input with pull down
117pinctrl set 35 a1 pu Set GPIO35 to fsel 1 (jtag_2_clk) with pull up
118pinctrl set 20 op pn dh Set GPIO20 to output with no pull and driving high
119pinctrl -c bcm2835 9-11 Display the alt functions for GPIOs 9-11 on bcm2835
120some_user@some_host:~$
121
122some_user@some_host:~$ ssh weswitch@weswitch "pinctrl get 26"
12326: op -- pd | hi // GPIO26 = output
124some_user@some_host:~$ ssh weswitch@weswitch "pinctrl get 19"
12519: op -- pd | hi // GPIO19 = output
126some_user@some_host:~$ ssh weswitch@weswitch "pinctrl set 26 dl"
127some_user@some_host:~$ ssh weswitch@weswitch "pinctrl get 26"
12826: op -- pd | lo // GPIO26 = output
129some_user@some_host:~$ ssh weswitch@weswitch "pinctrl set 19 dl"
130some_user@some_host:~$ ssh weswitch@weswitch "pinctrl get 19"
13119: op -- pd | lo // GPIO19 = output
132some_user@some_host:~$ ssh weswitch@weswitch "pinctrl set 26 dh ; pinctrl 19 dh"
133some_user@some_host:~$
134
135some_user@some_host:~$ ssh weswitch@weswitch "sudo shutdown now"
136System is going down. Unprivileged users are not permitted to log in anymore. For technical details, see pam_nologin(8).
137
138Connection closed by 192.168.1.110 port 22
139some_user@some_host:~$
1some_user@some_host:~$ ssh weswitch@weswitch "pinctrl 19 ; pinctrl 26"
219: op -- pd | hi // GPIO19 = output
326: op -- pd | hi // GPIO26 = output
4some_user@some_host:~$ ssh weswitch@weswitch "pinctrl 19 dl ; pinctrl 26 dl"
5some_user@some_host:~$ ssh weswitch@weswitch "pinctrl 19 ; pinctrl 26"
619: op -- pd | lo // GPIO19 = output
726: op -- pd | lo // GPIO26 = output
8some_user@some_host:~$ ssh weswitch@weswitch "pinctrl 19 dh ; pinctrl 26 dh"
9some_user@some_host:~$ ssh weswitch@weswitch "pinctrl 19 ; pinctrl 26"
1019: op -- pd | hi // GPIO19 = output
1126: op -- pd | hi // GPIO26 = output
12some_user@some_host:~$
1some_user@some_host:~$ ssh-copy-id weswitch@weswitch
2--snip--
3some_user@some_host:~$ ssh weswitch@weswitch "pinctrl 26"
426: op -- pd | hi // GPIO26 = output
5some_user@some_host:~$ ssh weswitch@weswitch "pinctrl 26 dl"
6some_user@some_host:~$ ssh weswitch@weswitch "pinctrl 26"
726: op -- pd | lo // GPIO26 = output
8some_user@some_host:~$ ssh weswitch@weswitch "pinctrl 26 dh"
Results#
As downloads#
Inlined here#
1#!/usr/bin/env python3
2
3# MIT License
4#
5# Copyright (c) 2024 Alexander Mann-Wahrenberg (basejumpa)
6#
7# Permission is hereby granted, free of charge, to any person obtaining a copy
8# of this software and associated documentation files (the "Software"), to deal
9# in the Software without restriction, including without limitation the rights
10# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11# copies of the Software, and to permit persons to whom the Software is
12# furnished to do so, subject to the following conditions:
13#
14# The above copyright notice and this permission notice shall be included in all
15# copies or substantial portions of the Software.
16#
17# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23# SOFTWARE.
24
25import argparse
26import sys
27import re
28from gpiozero import LED
29import gpiozero.pins.rpigpio
30
31
32def close(self):
33 pass
34
35def parse_state(state):
36 true_values = {"true", "1", "on", "t", "yes"}
37 false_values = {"false", "0", "off", "f", "no"}
38
39 state_lower = state.lower()
40 if state_lower in true_values:
41 return "True"
42 elif state_lower in false_values:
43 return "False"
44 else:
45 raise argparse.ArgumentTypeError(f"Invalid state value: '{state}'")
46
47def parse_pin_state(pin_state):
48 match = re.match(r"^(\d+)(:(1|0))?$", pin_state)
49 if match:
50 pin = int(match.group(1))
51 state = "True" if match.group(3) == "1" else "False" if match.group(3) == "0" else None
52 return pin, state
53 else:
54 raise argparse.ArgumentTypeError(f"Invalid pin:state format: '{pin_state}'")
55
56def main():
57
58 pinout = """
59 Raspberry Pi GPIO - BCM Pinout
60 +-----+------------+----RPI---+------------+-----+
61 | BCM | Function | Physical | Function | BCM |
62 +-----+------------+----++----+------------+-----+
63 | | 3.3V | 1 || 2 | 5v | |
64 | 2 | I2C1 SDA | 3 || 4 | 5v | |
65 | 3 | I2C1 SCL | 5 || 6 | GND | |
66 | 4 | GPCLK0 | 7 || 8 | UART TX | 14 |
67 | | GND | 9 || 10 | UART RX | 15 |
68 | 17 | | 11 || 12 | PCM CLK | 18 |
69 | 27 | | 13 || 14 | GND | |
70 | 22 | | 15 || 16 | | 23 |
71 | | 3.3V | 17 || 18 | | 24 |
72 | 10 | SPI0 MOSI | 19 || 20 | GND | |
73 | 9 | SPI0 MISO | 21 || 22 | | 25 |
74 | 11 | SPI0 SCLK | 23 || 24 | SPI0 CE0 | 8 |
75 | | GND | 25 || 26 | SPI0 CE1 | 7 |
76 | 0 | EEPROM SDA | 27 || 28 | EEPROM SCL | 1 |
77 | 5 | | 29 || 30 | GND | |
78 | 6 | | 31 || 32 | | 12 |
79 | 13 | PWM1 | 33 || 34 | GND | |
80 | 19 | PCM FS | 35 || 36 | | 16 |
81 | 26 | | 37 || 38 | PCM DIN | 20 |
82 | | GND | 39 || 40 | PCM DOUT | 21 |
83 +-----+------------+----++----+------------+-----+
84 """
85
86 examples = """
87 Examples:
88
89 1. Query the state of a pin:
90 ./switch.py --pin 19
91 ./switch.py 26
92 Output: "19:0" on stdout, "Pin 19 is currently OFF" on stderr
93
94 2. Turn on a pin using the --pin option:
95 ./switch.py True --pin 26
96 ./switch.py 1 --pin 26
97 ./switch.py on --pin 26
98
99 3. Turn off a pin using the --pin option:
100 ./switch.py False --pin 26
101 ./switch.py 0 --pin 26
102 ./switch.py off --pin 26
103
104 4. Turn on a pin using the pin:state format:
105 ./switch.py 26:1
106
107 5. Turn off a pin using the pin:state format:
108 ./switch.py 19:0
109 """
110
111 parser = argparse.ArgumentParser(
112 description=(
113 "Control a GPIO pin (use BCM numbering).\n\n"
114 + examples
115 + pinout
116 + "More detailed/interactive at: https://pinout.xyz/\n"
117 ),
118 formatter_class=argparse.RawTextHelpFormatter
119 )
120
121 parser.add_argument(
122 "command",
123 nargs="?",
124 help="Set the pin state in the format <pin>:<state> (e.g., 26:1 or 19:0) or use positional True/False with --pin. Providing only the pin number queries the pin state.",
125 )
126
127 parser.add_argument(
128 "--pin",
129 type=int,
130 help="BCM pin number to control (required if using positional True/False).",
131 )
132
133 args = parser.parse_args()
134
135 if not args.command and not args.pin:
136 parser.print_help()
137 sys.exit(1)
138
139 if args.command:
140 pin, state = parse_pin_state(args.command)
141 if state is None and args.pin is None:
142 # If only a pin is provided, query the pin state
143 state = None
144 elif state is None and args.pin is not None:
145 # Handle the True/False positional argument with --pin
146 state = parse_state(args.command)
147 pin = args.pin
148 else:
149 # If no command is provided, just query the pin state
150 pin = args.pin
151 state = None
152
153 # Override the close method to prevent the GPIO pin from being closed when application exits
154 gpiozero.pins.rpigpio.RPiGPIOPin.close = close
155
156 # Use the pin and state
157 pin_control = LED(pin, pin_factory=gpiozero.pins.rpigpio.RPiGPIOFactory())
158
159 # Determine the current state
160 current_state = "True" if pin_control.is_lit else "False"
161
162 if state is None:
163 # If no state is provided, just output the current state
164 machine_readable_state = "1" if current_state == "True" else "0"
165 human_readable_state = "ON" if current_state == "True" else "OFF"
166 print(f"{pin}:{machine_readable_state}", file=sys.stdout) # Machine-readable
167 print(f"Pin {pin} is currently {human_readable_state}", file=sys.stderr) # Human-readable
168 else:
169 # Determine if the state is changing
170 if state == current_state:
171 print(f"{pin}:{('1' if state == 'True' else '0')}", file=sys.stdout) # Machine-readable
172 print(f"Pin {pin} is already {('ON' if state == 'True' else 'OFF')}. No change made.", file=sys.stderr) # Human-readable
173 else:
174 # Set the pin state based on the provided argument
175 if state == "True":
176 pin_control.on()
177 print(f"{pin}:1", file=sys.stdout) # Machine-readable
178 print(f"Pin {pin} is now ON. State changed from OFF to ON.", file=sys.stderr) # Human-readable
179 else:
180 pin_control.off()
181 print(f"{pin}:0", file=sys.stdout) # Machine-readable
182 print(f"Pin {pin} is now OFF. State changed from ON to OFF.", file=sys.stderr) # Human-readable
183
184if __name__ == "__main__":
185 main()
186
# `switch` - GPIO Pin Control Tool
## Overview
`switch` is a tool implemented in Python designed to control a GPIO pin on a Raspberry Pi. The script allows you to turn a GPIO pin on or off (using True/False or similar commands), query its current state, and set the pin number.
This script is particularly useful for controlling LEDs or other simple devices connected to the GPIO pins.
## Installation
1. Ensure Python 3 and the `gpiozero` library are installed on your Raspberry Pi.
```bash
sudo apt-get update
sudo apt-get install python3 python3-gpiozero
```
2. Download or copy `switch.py` to your Raspberry Pi.
3. (Optional) Make the script executable:
```bash
chmod +x switch.py
```
4. (Optional) Move the script to a directory in your `PATH` (e.g., `/usr/local/bin`) for easy access:
```bash
sudo mv switch.py /usr/local/bin/switch
```
## Usage
### Basic Command Structure
```bash
switch [True|False] [--pin PIN]
switch <pin>:<state>
switch <pin>
```
- **True/False**: Set the pin to `True` (ON) or `False` (OFF).
- **<pin>:<state>**: Set the state of the specified pin directly, where `state` is `1` (ON) or `0` (OFF).
- **<pin>**: Query the state of the specified pin.
- **--pin PIN**: Specify the BCM pin number to control. Required when using the `True/False` format.
### Examples
1. **Query the state of a pin**:
```bash
./switch.py --pin 19
./switch.py 26
```
- Output: `19:0` on stdout, `Pin 19 is currently OFF` on stderr.
2. **Turn on a pin using the --pin option**:
```bash
./switch.py True --pin 26
./switch.py 1 --pin 26
./switch.py on --pin 26
```
3. **Turn off a pin using the --pin option**:
```bash
./switch.py False --pin 26
./switch.py 0 --pin 26
./switch.py off --pin 26
```
4. **Turn on a pin using the pin:state format**:
```bash
./switch.py 26:1
```
5. **Turn off a pin using the pin:state format**:
```bash
./switch.py 19:0
```
### Input Tolerance
The script accepts various forms of input for `True` and `False`:
- **True**: `True`, `true`, `1`, `on`, `On`, `ON`, `t`, `yes`
- **False**: `False`, `false`, `0`, `off`, `Off`, `OFF`, `f`, `no`
### Help Screen
For more information, run:
```bash
switch.py --help
```
This will display:
```
usage: switch.py [-h] [--pin PIN] [True | False]
Control a GPIO pin.
Pinout information can be found at: https://pinout.xyz/
Examples:
1. Query the state of a pin:
./switch.py --pin 19
./switch.py 26
Output: "19:0" on stdout, "Pin 19 is currently OFF" on stderr
2. Turn on a pin using the --pin option:
./switch.py True --pin 26
./switch.py 1 --pin 26
./switch.py on --pin 26
3. Turn off a pin using the --pin option:
./switch.py False --pin 26
./switch.py 0 --pin 26
./switch.py off --pin 26
4. Turn on a pin using the pin:state format:
./switch.py 26:1
5. Turn off a pin using the pin:state format:
./switch.py 19:0
positional arguments:
{True,False} Set the pin to True (ON) or False (OFF).
optional arguments:
-h, --help show this help message and exit
--pin PIN BCM pin number to control.
```
### Pinout Information
For detailed pinout information on your Raspberry Pi, visit [pinout.xyz](https://pinout.xyz/).
## Troubleshooting
If you don't see the expected behavior on the electrical side (e.g., the LED doesn't turn on/off):
- **Verify the Pin Numbering**: Ensure you are using the correct BCM pin number.
- **Check the Wiring**: Make sure the LED and resistor are correctly connected.
- **Check the LED Polarity**: The longer leg (anode) should be connected to the GPIO pin, and the shorter leg (cathode) should be connected to ground.
- **Test the Pin**: Use a simple script to manually test turning the pin on and off.
## License
```
MIT License
Copyright (c) 2024 Alexander Mann-Wahrenberg (basejumpa)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```
---
Happy remote switching :-)
Resources used#
gpiozero - A simple interface to GPIO devices with Raspberry Pi
Thread “Using gpiozero on RPI to control pins, but output pins are reset upon script exit, even though state is remembered between runs” at Stack Overflow.
gpiozero#707 - Issue “Allow users to disable implicit cleanup”
raspberrypi/utils - A collection of scripts and simple applications
Setting up Wi-Fi on the Raspberry Pi with nmtui