Witajcie.
Chciałem podzielić się drobnym cookbookiem na podpięcie expandera MCP23017 do RockPi S.
Expander MCP23017 posiada 16 konfigurowalnych portów I/O z możliwością ustawienia rezystorów podciągających - z mojej praktyki stabilnie chodzą pull-up.
Dla tego przykładu ustawimy 8 portów GPA0-GPA7 jako wyjścia oraz 8 portów GPB0-GPB7 jako wejścia.
Adres na szynie i2c (zworki) mojego MCP ustawiłem na 0x20 (wejścia A0, A1, A2 do masy).
Sprawdzam, czy widać moje MCP : sudo i2cdetect -y 1
Otrzymałem tabelkę - widzę urządzenie pod adresem 0x20.
Kilka informacji na początek :
- używamy narzędzi i2c-tools - jak nie masz - instaluj.
a/ polecenie do ustawiania bitów : i2cset [-y] i2cbus chip-address data-address value
b/ polecenie do odczytu bitów : i2cget [-y] i2cbus chip-address data-address
Opis bardziej szczegółowy :
Wstaw "-y" po i2cget i i2cset, brak tego spowoduje oczekiwanie na potwierdzenie wykonania polecenia przez usera - czyli tego chcemy uniknąć
i2cbus odczytujemy za pomocą : sudo i2cdetect -l lub /usr/sbin/i2cdetect -l
Na ekranie będziemy widzieli i2c-0 lub i2c-1
data-adres (mapa pamięci) i value (wartości) omówimy poniżej.
Mapa pamięci
a/ rejestr IODIRA - adres hex 0x00 - kierunek portów A0-A7 : 0 - wyjście, 1 - wejście
Przykład 1 : Port A 0-7 jako wyjścia - sudo i2set -y 1 0x20 0x00 0x00
Przykład 2 : Port A 0-6 jako wyjścia, A7 jako wejście - sudo i2cset -y 1 0x20 0x00 0x80
b/ rejestr IODIRB - adres hex 0x01 - kierunek portów B0-B7 : 0 - wyjście, 1 - wejście
Ustawienia jak powyżej, w naszym przykładzie : sudo i2cset -y 1 0x20 0x01 0xFF
c/ rejestr GPPUA - adres hex 0x0C - pull-up portu A : 0 - off, 1 -on
d/ rejestr GPPUB - adres hex 0x0D - pull-up portu B : 0 - off, 1 -on
Jako, że ustawiliśmy port B jako wejścia - ustawimy też pull-up.
Przykład nr 1 : pull-up na portach 0-7 (1111 1111 = 0xFF) : sudo i2cset -y 1 0x20 0x0d 0xFF
Przykład nr 2 : pull-up na porcie 0 i 1 (0000 0011 = 0x03) : sudo i2cset -y 1 0x20 0x0d 0x03
e/ rejestr GPIOA - adres hex 0x12 - odczyt stanu portu A - jeżeli A jest wejściem
f/ rejestr GPIOB - adres hex 0x13 - odczyt stanu portu B - jeżeli B jest wejściem
Przykład : sudo i2cget -y 1 0x20 0x13
Jeżeli ustawiliśmy pull-up i nie mamy podłączonego żadnego wejścia do masy to otrzymamy 0xFF.
Jeśli podłączymy GPB0 do masy to otrzymamy 0xFE czyli 1111 1110.
Dla GPB1 do masy otrzymamy 0xFD czyli 1111 1101.
g/ rejestr OLATA - adres hex 0x14 - jeżeli A jest wyjściem to zapis do portu wyjściowego (1 włącza stan wysoki, 0 niski)
Przykład1 : włączamy stan wysoki H na GPA0 : sudo i2cset -y 1 0x20 0x14 0x01
Przykład2 : włączamy stan niski L na GPA0 : sudo i2cset -y 1 0x20 0x14 0x00
UWAGA : taki zapis wyzeruje inne porty - jak chcesz pozostawić inne porty w stanie niezmiennym to musisz :
- dla włączenia dosumować dany pin do odczytanej wartości portu OLATA (suma logiczna OR)
- dla wyłączenia wykonać iloczyn logiczny (and) - patrz niżej w config
h/ rejestr OLATB - adres hex 0x15 - jeżeli B jest wyjściem to zapis do portu wyjściowego (1 włącza stan wysoki, 0 niski)
jak potrzebujesz więcej :
https://gist.github.com/ChickenProp/3183960
----------------------------------------------------------------------------------------------------------------------------------
Wstępna teoria za nami.
Teraz zajmijmy się wartościami początkowymi.
Najprościej początkową robotę załatwić w crontrab :
sudo crontab -e
Kod: Zaznacz cały
# port A jako wyjścia
@reboot /usr/sbin/i2cset -y 1 0x20 0x00 0x00
# port B jako wejścia
@reboot /usr/sbin/i2cset -y 1 0x20 0x01 0xFF
# port B pull up 0..7
@reboot /usr/sbin/i2cset -y 1 0x20 0x0d 0xFF
i w końcu plik konfiguracyjny :
Kod: Zaznacz cały
#
Example supla-device config file for Linux device
# https://github.com/SUPLA/supla-device
name: RockPiS
log_level: debug
state_files_path: "/home/xxxx/supla-stan"
security_level: 2 # disable certyficate verification
supla:
server: svrx.supla.org
mail: xxxx@xxxx.xxxx.pl
channels:
# CmdRelay with state kept in memory and stored in storage
- type: CmdRelay
name: GPA0
initial_state: restore
cmd_on: "/usr/sbin/i2cset -y 1 0x20 0x14 $(( $(/usr/sbin/i2cget -y 1 0x20 0x14) | 0x01 ))"
cmd_off: "/usr/sbin/i2cset -y 1 0x20 0x14 $(( $(/usr/sbin/i2cget -y 1 0x20 0x14) & 0xfe ))"
- type: CmdRelay
name: GPA1
initial_state: restore
cmd_on: "/usr/sbin/i2cset -y 1 0x20 0x14 $(( $(/usr/sbin/i2cget -y 1 0x20 0x14) | 0x02 ))"
cmd_off: "/usr/sbin/i2cset -y 1 0x20 0x14 $(( $(/usr/sbin/i2cget -y 1 0x20 0x14) & 0xfd ))"
- type: CmdRelay
name: GPA2
initial_state: restore
cmd_on: "/usr/sbin/i2cset -y 1 0x20 0x14 $(( $(/usr/sbin/i2cget -y 1 0x20 0x14) | 0x04 ))"
cmd_off: "/usr/sbin/i2cset -y 1 0x20 0x14 $(( $(/usr/sbin/i2cget -y 1 0x20 0x14) & 0xfb ))"
- type: CmdRelay
name: GPA3
initial_state: restore
cmd_on: "/usr/sbin/i2cset -y 1 0x20 0x14 $(( $(/usr/sbin/i2cget -y 1 0x20 0x14) | 0x08 ))"
cmd_off: "/usr/sbin/i2cset -y 1 0x20 0x14 $(( $(/usr/sbin/i2cget -y 1 0x20 0x14) & 0xf7 ))"
- type: CmdRelay
name: GPA4
initial_state: restore
cmd_on: "/usr/sbin/i2cset -y 1 0x20 0x14 $(( $(/usr/sbin/i2cget -y 1 0x20 0x14) | 0x10 ))"
cmd_off: "/usr/sbin/i2cset -y 1 0x20 0x14 $(( $(/usr/sbin/i2cget -y 1 0x20 0x14) & 0xef ))"
- type: CmdRelay
name: GPA5
initial_state: restore
cmd_on: "/usr/sbin/i2cset -y 1 0x20 0x14 $(( $(/usr/sbin/i2cget -y 1 0x20 0x14) | 0x20 ))"
cmd_off: "/usr/sbin/i2cset -y 1 0x20 0x14 $(( $(/usr/sbin/i2cget -y 1 0x20 0x14) & 0xdf ))"
- type: CmdRelay
name: GPA6
initial_state: restore
cmd_on: "/usr/sbin/i2cset -y 1 0x20 0x14 $(( $(/usr/sbin/i2cget -y 1 0x20 0x14) | 0x40 ))"
cmd_off: "/usr/sbin/i2cset -y 1 0x20 0x14 $(( $(/usr/sbin/i2cget -y 1 0x20 0x14) & 0xbf ))"
- type: CmdRelay
name: GPA7
initial_state: restore
cmd_on: "/usr/sbin/i2cset -y 1 0x20 0x14 $(( $(/usr/sbin/i2cget -y 1 0x20 0x14) | 0x80 ))"
cmd_off: "/usr/sbin/i2cset -y 1 0x20 0x14 $(( $(/usr/sbin/i2cget -y 1 0x20 0x14) & 0x7f ))"
- type: BinaryParsed
name: GPB0
source:
type: Cmd
command: "if [ $(($(/usr/sbin/i2cget -y 1 0x20 0x13) & 0x01 )) = 1 ]; then /home/xxxx/supla-stan/gpa0_off>/dev/null 2>&1; echo 0; else /home/xxxx/supla-stan/gpa0_on>/dev/null 2>&1; echo 1; fi"
parser:
type: Simple
refresh_time_ms: 1000
state: 0
- type: BinaryParsed
name: GPB1
source:
type: Cmd
command: "if [ $(($(/usr/sbin/i2cget -y 1 0x20 0x13) & 0x02 )) = 2 ]; then echo 0; else echo 1; fi"
parser:
type: Simple
refresh_time_ms: 1000
state: 0
- type: BinaryParsed
name: GPB2
source:
type: Cmd
command: "if [ $(($(/usr/sbin/i2cget -y 1 0x20 0x13) & 0x04 )) = 4 ]; then echo 0; else echo 1; fi"
parser:
type: Simple
refresh_time_ms: 1000
state: 0
- type: BinaryParsed
name: GPB3
source:
type: Cmd
command: "if [ $(($(/usr/sbin/i2cget -y 1 0x20 0x13) & 0x08 )) = 8 ]; then echo 0; else echo 1; fi"
parser:
type: Simple
refresh_time_ms: 1000
state: 0
- type: BinaryParsed
name: GPB4
source:
type: Cmd
command: "if [ $(($(/usr/sbin/i2cget -y 1 0x20 0x13) & 0x10 )) = 16 ]; then echo 0; else echo 1; fi"
parser:
type: Simple
refresh_time_ms: 1000
state: 0
- type: BinaryParsed
name: GPB5
source:
type: Cmd
command: "if [ $(($(/usr/sbin/i2cget -y 1 0x20 0x13) & 0x20 )) = 32 ]; then echo 0; else echo 1; fi"
parser:
type: Simple
refresh_time_ms: 1000
state: 0
- type: BinaryParsed
name: GPB6
source:
type: Cmd
command: "if [ $(($(/usr/sbin/i2cget -y 1 0x20 0x13) & 0x40 )) = 64 ]; then echo 0; else echo 1; fi"
parser:
type: Simple
refresh_time_ms: 1000
state: 0
- type: BinaryParsed
name: GPB7
source:
type: Cmd
command: "if [ $(($(/usr/sbin/i2cget -y 1 0x20 0x13) & 0x80 )) = 128 ]; then echo 0; else echo 1; fi"
parser:
type: Simple
refresh_time_ms: 1000
state: 0
W katalogu supla-stan mam 2 pliki : gpa0_on i gpa0_off. W nich mam linki bezpośrednie - w tym przypadku stan niski na gpa0 włącza przekaźnik - można to użyć np. w czujniku zalania, itp.
Jeszcze raz wielkie dzięki dla Klew-a za super robotę z supla-device.
Pozdrawiam.