Christian's Blog

Linux, programming, hacking, electronics, Python… These are the things I love.

Control your light at home with a Raspberry Pi and Olimex’s MOD-IO2

Since I’ve won the RPI-UEXT + MOD-IO2 I had to test it and this is the result.

Controlling your light is just an example, you can control nearly everything from everywhere in the world.

Install Arch Linux ARM on your RPi

  1. Download the latest Arch Linux ARM image from http://www.raspberrypi.org/downloads.
  2. Copy the image to your Raspberry Pi SD card:
[chris@thinkpad Downloads]$ unzip archlinux-hf-2012-09-18.zip
Archive:  archlinux-hf-2012-09-18.zip
  inflating: archlinux-hf-2012-09-18.img
[chris@thinkpad Downloads]$ dd if=archlinux-hf-2012-09-18.img of=/dev/mmcblk0
dd: opening `/dev/mmcblk0': Permission denied
[chris@thinkpad Downloads]$ sudo dd if=archlinux-hf-2012-09-18.img of=/dev/mmcblk0
3862528+0 records in
3862528+0 records out
1977614336 bytes (2.0 GB) copied, 713.874 s, 2.8 MB/s
[chris@thinkpad Downloads]$
  1. Use gparted to resize the the partitions on your SD card so that they use the entire space.
  2. Mount the SD card and enable the serial console on boot, the default command would be systemctl enable getty@ttyAMA0.service or systemctl enable serial-getty@ttyAMA0.service but at the moment it is easier to create the symlink manually:
[chris@thinkpad ~]$ sudo mkdir /mnt/rpi
[chris@thinkpad ~]$ sudo mount /dev/mmcblk0p2 /mnt/rpi
[chris@thinkpad ~]$ sudo ln -s /usr/lib/systemd/system/serial-getty@.service /mnt/rpi/etc/systemd/system/getty.target.wants/serial-getty@ttyAMA0.service
[chris@thinkpad ~]$ ls -l /mnt/rpi/etc/systemd/system/getty.target.wants/serial-getty@ttyAMA0.service
lrwxrwxrwx. 1 root root 45 Jan 14 19:36 /mnt/rpi/etc/systemd/system/getty.target.wants/serial-getty@ttyAMA0.service -> /usr/lib/systemd/system/serial-getty@.service
[chris@thinkpad ~]$

In order to see more kernel messages the loglevel variable in /boot/cmdline.txt needs to be changed from 2 to something greater than 2, with a max of 7 (https://www.kernel.org/doc/Documentation/kernel-parameters.txt).

When more than one console is listed in the kernel parameters, it is the the last one that gets assigned to /dev/console. So, to see the systemd startup messages on the serial port, ensure the console=ttyAMA0 entry comes after the console=tty1 entry in /boot/cmdline.txt.

[chris@thinkpad ~]$ sudo mount /dev/mmcblk0p1 /mnt/rpi/boot/
[chris@thinkpad ~]$ sudo vim /mnt/rpi/boot/cmdline.txt
[chris@thinkpad ~]$ cat /mnt/rpi/boot/cmdline.txt
sdhci-bcm2708.enable_llm=1 sdhci-bcm2708.sync_after_dma=0 smsc95xx.turbo_mode=N dwc_otg.lpm_enable=0 console=tty1 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 loglevel=5 root=/dev/mmcblk0p2 init=/bin/systemd rootfstype=ext4 rootwait
[chris@thinkpad ~]$

Umount the SD card:

[chris@thinkpad ~]$ sudo umount /mnt/rpi/boot
[chris@thinkpad ~]$ sudo umount /mnt/rpi
[chris@thinkpad ~]$
  1. Boot Arch Linux ARM and open a console, I’m using no display on my Raspberry Pi but a 3V3 FTDI USB serial cable, see http://elinux.org/RPi_Serial_Connection and http://www.element14.com/community/groups/raspberry-pi/blog/2012/07/18/look-ma-no-display-using-the-raspberry-pi-serial-console for more details.

    You will need to connect the pins Ground, GPIO 14 (TXD) and GPIO 15 (RXD).

    USB serial cable connected

    USB serial cable connected

  2. Open a serial console, configuration: /dev/ttyUSB0 : 115200,8,N,1, you may need to hit a few times enter until the login prompt is visible, then login as root with password root.

    Gtkterm RPi

    Gtkterm is a simple GTK+ terminal used to communicate with a serial port.

    You can also use screen sudo screen /dev/ttyUSB0 115200 or minicom to open the serial port.

  3. Get a network connection on your Pi via Ethernet, WiFi or 3G.

Get a network connection

Wired internet connection

  1. Connect your Pi with a Ethernet cable to your router or laptop
  2. Use dhcpcd to get a IP adress
[root@alarmpi ~]# dhcpcd eth0
dhcpcd[168]: version 5.6.2 starting
dhcpcd[168]: eth0: sending IPv6 Router Solicitation
dhcpcd[168]: eth0: broadcasting for a lease
dhcpcd[168]: eth0: offered 10.42.1.60 from 10.42.1.1
dhcpcd[168]: eth0: acknowledged 10.42.1.60 from 10.42.1.1
dhcpcd[168]: eth0: checking for 10.42.1.60
dhcpcd[168]: eth0: sending IPv6 Router Solicitation
dhcpcd[168]: eth0: leased 10.42.1.60 for 3600 seconds
dhcpcd[168]: forked to background, child pid 194
[root@alarmpi ~]# ping google.de
PING google.de (74.125.230.248) 56(84) bytes of data.
64 bytes from par08s10-in-f24.1e100.net (74.125.230.248): icmp_req=1 ttl=52 time=72.2 ms
64 bytes from par08s10-in-f24.1e100.net (74.125.230.248): icmp_req=2 ttl=52 time=54.2 ms
64 bytes from par08s10-in-f24.1e100.net (74.125.230.248): icmp_req=3 ttl=52 time=52.9 ms

--- google.de ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 52.923/59.794/72.210/8.800 ms
[root@alarmpi ~]#
  1. install wireless_tools if you want to use wifi
[root@alarmpi ~]# pacman -Sy
:: Synchronizing package databases...
core is up to date
extra                    436.3 KiB  6.65K/s 01:06 [######################] 100%
community                429.6 KiB  5.85K/s 01:13 [######################] 100%
alarm is up to date
aur is up to date
[root@alarmpi ~]# pacman -S wireless_tools
resolving dependencies...
looking for inter-conflicts...

Targets (1): wireless_tools-29-7

Total Download Size:    0.06 MiB
Total Installed Size:   0.29 MiB

Proceed with installation? [Y/n] y
:: Retrieving packages from core...
wireless_tools-29-7...    81.0 KiB  14.1K/s 00:06 [######################] 100%
(1/1) checking package integrity                   [######################] 100%
(1/1) loading package files                        [######################] 100%
(1/1) checking for file conflicts                  [######################] 100%
(1/1) checking available disk space                [######################] 100%
(1/1) installing wireless_tools                    [######################] 100%
[root@alarmpi ~]#
  1. Install some useful tools
[root@alarmpi ~]# pacman -S vim git python2 python2-pip base-devel

Setting up a WiFi connection

I’m using a LogiLink WL0084B (rt2800usb) adapter.

LogiLink WL0084B

LogiLink WL0084B (rt2800usb)

  1. Create a shared WiFi connection on your laptop:
../../../_images/olinuxino_conf_1.png ../../../_images/olinuxino_conf_2.png ../../../_images/olinuxino_conf_3.png
  1. Configure the WiFi connection on the RPi:

Debug output when connecting the wireless adapter:

[root@alarmpi ~]# tail /var/log/messages.log
Jan  1 01:06:40 alarmpi kernel: [  400.823812] usbcore: registered new interface driver rt2800usb
Jan  1 01:07:07 alarmpi kernel: [  427.862220] ADDRCONF(NETDEV_UP): wlan0: link is not ready
Jan  1 01:13:26 alarmpi kernel: [  806.084715] usb 1-1.3.4: USB disconnect, device number 5
Jan  1 01:13:32 alarmpi kernel: [  812.977580] usb 1-1.3.4: new high-speed USB device number 6 using dwc_otg
Jan  1 01:13:33 alarmpi kernel: [  813.095902] usb 1-1.3.4: New USB device found, idVendor=148f, idProduct=5370
Jan  1 01:13:33 alarmpi kernel: [  813.095934] usb 1-1.3.4: New USB device strings: Mfr=1, Product=2, SerialNumber=3
Jan  1 01:13:33 alarmpi kernel: [  813.095969] usb 1-1.3.4: Product: 802.11 n WLAN
Jan  1 01:13:33 alarmpi kernel: [  813.095987] usb 1-1.3.4: Manufacturer: Ralink
Jan  1 01:13:33 alarmpi kernel: [  813.096001] usb 1-1.3.4: SerialNumber: 1.0
Jan  1 01:13:33 alarmpi kernel: [  813.177609] usb 1-1.3.4: reset high-speed USB device number 6 using dwc_otg
[root@alarmpi ~]# lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 002: ID 0424:9512 Standard Microsystems Corp.
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp.
Bus 001 Device 004: ID 1a40:0101 Terminus Technology Inc. 4-Port HUB
Bus 001 Device 006: ID 148f:5370 Ralink Technology, Corp. RT5370 Wireless Adapter
[root@alarmpi ~]#

Set up the wifi connection:

[root@alarmpi ~]# ifconfig wlan0 down
[root@alarmpi ~]# iwconfig wlan0 mode ad-hoc
[root@alarmpi ~]# iwconfig wlan0 channel 4
[root@alarmpi ~]# iwconfig wlan0 essid tuxnet
[root@alarmpi ~]# iwconfig wlan0 key 73598253812539275395295235
[root@alarmpi ~]# ifconfig wlan0 up
[root@alarmpi ~]# dhcpcd wlan0
dhcpcd[230]: version 5.6.2 starting
dhcpcd[230]: wlan0: sending IPv6 Router Solicitation
dhcpcd[230]: wlan0: broadcasting for a lease
dhcpcd[230]: wlan0: offered 10.42.0.68 from 10.42.0.1
dhcpcd[230]: wlan0: acknowledged 10.42.0.68 from 10.42.0.1
dhcpcd[230]: wlan0: checking for 10.42.0.68
dhcpcd[230]: wlan0: sending IPv6 Router Solicitation
dhcpcd[230]: wlan0: sending IPv6 Router Solicitation
dhcpcd[230]: wlan0: leased 10.42.0.68 for 3600 seconds
dhcpcd[230]: forked to background, child pid 256
[root@alarmpi ~]# ping google.de
PING google.de (74.125.230.247) 56(84) bytes of data.
64 bytes from par08s10-in-f23.1e100.net (74.125.230.247): icmp_req=1 ttl=52 time=420 ms
64 bytes from par08s10-in-f23.1e100.net (74.125.230.247): icmp_req=2 ttl=52 time=340 ms

--- google.de ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 340.642/380.453/420.265/39.816 ms
[root@alarmpi ~]#

Another possibility to configure your wireless network is wifi-menu, it ships with netcfg pacman -S netcfg dialog wpa_supplicant, it scans for available networks, just select one and enter your password.

wifi-menu

wifi-menu

See also https://wiki.archlinux.org/index.php/Wireless_Setup.

Using a USB 3G modem

How to setup a USB 3G Modem under Arch Linux is explained in the ArchWiki: https://wiki.archlinux.org/index.php/USB_3G_Modem.

We use wvdial to connect via UMTS to the internet.

  1. Install usb_modeswitch and wvdial
[root@alarmpi ~]# pacman -S usb_modeswitch wvdial
  1. Configure wvdial

You need to create the configuration file /etc/wvdial.conf, just google for wvdial.conf and the name of your USB 3G modem and you will likely find a working configuration, mine looks like this:

[root@alarmpi ~]# vim /etc/wvdial.conf
[root@alarmpi ~]# cat /etc/wvdial.conf
[Dialer Defaults]
Phone = *99#
Username = "blau"
Password = "blau"
Stupid Mode = on
Dial Command = ATDT
Modem Type = USB Modem
Modem = /dev/ttyUSB2
Init1 = ATZ
[Dialer nopin]
Init2= AT+CPIN="1234"
Init3= AT+CLCK="SC",0,"1234"
[Dialer umts]
Carrier Check = on
Init2= AT+CGDCONT?
Init3= AT+CGDCONT=1,"IP","internet.eplus.de"
ISDN = off
[root@alarmpi ~]#
  1. Connect to the internet
[root@alarmpi ~]# wvdial umts &

Note

This isn’t working at the moment, there is no /dev/ttyUSBx device:

[root@alarmpi ~]# ls /dev/ttyU*
ls: cannot access /dev/ttyU*: No such file or directory
[root@alarmpi ~]#

But the same setup is working on a OLinuXino with Arch Linux ARM and a newer 3.7 kernel.

As an alternative you can use sakis3g:

[root@alarmpi ~]# wget -O sakis3g http://sourceforge.net/projects/janncc/files/raspberrypi/sakis3g/download
[root@alarmpi ~]# chmod +x sakis3g
[root@alarmpi ~]# ./sakis3g --interactive
Connect with 3G - sakis3g

Connect with 3G - sakis3g

Select APN - sakis3g

Select APN - sakis3g

And it works:

[root@alarmpi ~]# ping google.de
PING google.de (173.194.78.94) 56(84) bytes of data.
64 bytes from wg-in-f94.1e100.net (173.194.78.94): icmp_seq=1 ttl=48 time=398 ms
64 bytes from wg-in-f94.1e100.net (173.194.78.94): icmp_seq=2 ttl=48 time=806 ms
64 bytes from wg-in-f94.1e100.net (173.194.78.94): icmp_seq=3 ttl=48 time=76.2 ms

--- google.de ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1999ms
rtt min/avg/max/mdev = 76.236/426.980/806.298/298.730 ms
[root@alarmpi ~]# cat sakis3g
sakis3g          sakis3g.desktop  sakis3g.tar.gz
[root@alarmpi ~]# cat sakis3g.desktop
[Desktop Entry]
Version=1.0
Encoding=UTF-8
Type=Application
Terminal=false
Name=E-Plus Internet
Name[en_US]=E-Plus Internet
Exec=/root/sakis3g clicked
Comment=Manages 3G internet connection and 3G USB modems
Comment[en_US]=Manages 3G internet connection and 3G USB modems
Icon=/root/.local/share/icons/sakis3g.png
Icon[en_US]=/root/.local/share/icons/sakis3g.png
GenericName=
GenericName[en_US]=
[root@alarmpi ~]# /root/sakis3g clicked
Disconnected.
[root@alarmpi ~]# /root/sakis3g clicked
Please select APN by using APN variable, or by enabling interactive mode.
        $ /root/sakis3g --interactive "clicked"

Available options are:
internet.eplus.de       E-Plus (internet.eplus.de)
internet.eplus.de       MedionMobile (internet.eplus.de)
internet.eplus.de       blau.de (internet.eplus.de)
internet.vistream.net   Vistream reseller (internet.vistream.net)
CUSTOM_APN      Custom APN...

Example:
        $ /root/sakis3g APN="internet.eplus.de"

[root@alarmpi ~]# /root/sakis3g APN="internet.eplus.de"
Sakis 3G All-in-one script - Version 0.2.0e
(c) Sakis Dimopoulos 2009, 2010 under GNU GPL v2


Usage:
      sakis3g [actors] [switches] [variables]

Sakis3G is a shell script which is supposed to work out-of-the-box for establishing a 3G connection with any combination of modem or operator.

NOTE: This script requires root priviledges to properly work. If not executed from root, it will try to acquire them.

Common actors are:
connect       - Attempts to establish 3G connection.
disconnect    - Stops all active PPP connections.
toggle        - Attempts to establish 3G connection. If already connected, it disconnects instead.
reconnect     - Attempts to establish 3G connection. If already connected, it first disconnects and then attempts.
start         - Same as connect. Provided for use as init.d script.
stop          - Same as disconnect. Provided for use as init.d script.
reload        - Same as reconnect. Provided for use as init.d script.
force-reload  - Same as reload. Provided for use as init.d script.
restart       - Same as reload. Provided for use as init.d script.
desktop       - Creates desktop shortcut for this script.
status        - Prints connection status and exits. Exit code is 0 if connected, or 6 if not connected.
help          - Prints this screen and exits.
man           - Displays man page.

NOTE: For more information, you should consult man page or official Sakis3G wiki, available at:
  http://wiki.sakis3g.org/
[root@alarmpi ~]# /root/sakis3g connect APN="internet.eplus.de"
W14 connected to blau.de (26203).
[root@alarmpi ~]#

I’ve uploaded the sakis3g script here: http://sourceforge.net/projects/janncc/files/raspberrypi/sakis3g/download, since www.sakis3g.org is offline at the moment.

Update all packages

Use the pacman package manager to update all packages on the RPi:

[root@alarmpi ~]# pacman -Syu
:: Synchronizing package databases...
core is up to date
extra is up to date
community is up to date
alarm is up to date
aur is up to date
:: Starting full system upgrade...
:: Replace dbus-core with core/dbus? [Y/n] y
resolving dependencies...
looking for inter-conflicts...

Targets (70): bash-4.2.042-1  binutils-2.23.1-2  ca-certificates-20121105-1
              coreutils-8.20-1  cronie-1.4.9-2  cryptsetup-1.5.1-1
              curl-7.28.1-1  dbus-1.6.8-6  dbus-core-1.6.4-1 [removal]
              device-mapper-2.02.98-1  dhcpcd-5.6.4-1  e2fsprogs-1.42.6-1
              filesystem-2012.12-1  fuse-2.9.2-1  gawk-4.0.2-1
              gcc-libs-4.7.2-3  gettext-0.18.2-1  glib2-2.34.3-1  glibc-2.17-1
              gmp-5.1.0-1  gnupg-2.0.19-3  hwids-20121203-1  iproute2-3.6.0-2
              iptables-1.4.16.3-1  iputils-20121126-1  kmod-12-1  krb5-1.11-2
              ldns-1.6.16-1  libarchive-3.0.4-2  libldap-2.4.33-3
              libpipeline-1.2.2-1  libssh2-1.4.3-1  libtirpc-0.2.2-4
              libusbx-1.0.14-1  linux-api-headers-3.7.1-1
              linux-firmware-20121118-1  linux-headers-raspberrypi-3.6.11-3
              linux-raspberrypi-3.6.11-3  logrotate-3.8.2-2  lvm2-2.02.98-1
              man-db-2.6.3-1  man-pages-3.45-1  mdadm-3.2.6-1
              mkinitcpio-0.12.0-2  mkinitcpio-busybox-1.20.2-1
              nss-myhostname-0.3-3  ntfs-3g-2012.1.15-4  openntpd-3.9p1-21
              openssh-6.1p1-4  pacman-4.0.3-5  pacman-mirrorlist-20130102-1
              pam-1.1.6-1  pcre-8.32-1  perl-5.16.2-2  pinentry-0.8.2-1
              ppp-2.4.5-5  procps-ng-3.3.5-1  raspberrypi-firmware-20130110-1
              run-parts-4.3.4-1  sed-4.2.2-1  shadow-4.1.5.1-2
              syslog-ng-3.3.7-1  systemd-196-2  systemd-sysvcompat-196-2
              sysvinit-tools-2.88-9  tzdata-2012j-1  util-linux-2.22.2-1
              vi-1:050325-3  wget-1.14-2  wpa_supplicant-1.0-2

Total Download Size:    128.32 MiB
Total Installed Size:   413.61 MiB
Net Upgrade Size:       29.41 MiB

Proceed with installation? [Y/n] y
:: Retrieving packages from core...
 linux-api-headers-3...   591.7 KiB  7.26K/s 01:22 [######################] 100%
 tzdata-2012j-1-any       140.6 KiB  6.91K/s 00:20 [######################] 100%
 glibc-2.17-1-armv6h        7.4 MiB  6.48K/s 19:30 [######################] 100%
 ...
 (70/70) upgrading wpa_supplicant                  [######################] 100%
[root@alarmpi ~]#

SSH into your Pi

If your network connection is established, you should be able to SSH into your Raspberry Pi and the serial cable is not longer needed.

  1. Get the IP of you Pi:
[root@alarmpi ~]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.42.0.60  netmask 255.255.255.0  broadcast 10.42.0.255
        inet6 fe80::ba27:ebff:fe47:e6a4  prefixlen 64  scopeid 0x20<link>
        ether b8:27:eb:47:e6:a4  txqueuelen 1000  (Ethernet)
        RX packets 7  bytes 889 (889.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 27  bytes 4714 (4.6 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 16436
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 0  (Local Loopback)
        RX packets 40  bytes 2856 (2.7 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 40  bytes 2856 (2.7 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[root@alarmpi ~]#

My IP is 10.42.0.60 at the moment.

  1. SSH into your Pi from another PC in the same network:
[chris@thinkpad ~]$ ssh root@10.42.0.60
The authenticity of host '10.42.0.60 (10.42.0.60)' can't be established.
RSA key fingerprint is 3a:dd:ee:ff:11:44:01:cc:55:12:31:55:aa:ae:6f:99.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '10.42.0.60' (RSA) to the list of known hosts.
root@10.42.0.60's password:
Last login: Thu Jan  1 01:00:21 1970
[root@alarmpi ~]#
  1. Now you can disconnect your USB serial cable.

Test the hardware

Connect everything

First connect the RPi-UEXT to your Pi with a 26-PIN RIBBON CABLE like shown in the picture below:

RPi-UEXT connected

RPi-UEXT connected

Since Ground (GND), GPIO 14 (TXD) and GPIO 15 (RXD) are also available on the RPi-UEXT you should be able to access the serial console again if everything is connected correctly. For the other pins have a look at the schematic.

Now you can connect the MOD-IO2, it needs a separate power adapter, the red power LED should light up:

MOD-IO2 connected

MOD-IO2 connected

Everything connected

Everything connected

Now we can concentrate on the software.

Control the MOD-IO2 via i2c

Update

If you have a MOD-IO2 with firmware version 3 then have a look here too: https://www.olimex.com/forum/index.php?topic=2034.msg9155#msg9155

[root@alarmpi ~]# modprobe i2c-dev
[root@alarmpi ~]# ls /dev/i2c*
/dev/i2c-0  /dev/i2c-1
[root@alarmpi ~]# ls -l /dev/i2c*
crw------- 1 root root 89, 0 Jan  1 01:07 /dev/i2c-0
crw------- 1 root root 89, 1 Jan  1 01:07 /dev/i2c-1
[root@alarmpi ~]# chmod o+rw /dev/i2c*
[root@alarmpi ~]# ls -l /dev/i2c*
crw----rw- 1 root root 89, 0 Jan  1 01:07 /dev/i2c-0
crw----rw- 1 root root 89, 1 Jan  1 01:07 /dev/i2c-1
[root@alarmpi ~]# pacman -S i2c-tools
resolving dependencies...
looking for inter-conflicts...

Targets (1): i2c-tools-3.1.0-3

Total Download Size:    0.06 MiB
Total Installed Size:   0.27 MiB

Proceed with installation? [Y/n] y
:: Retrieving packages from community...
i2c-tools-3.1.0-3-armv6h   59.1 KiB   386K/s 00:00 [##################] 100%
(1/1) checking package integrity                   [##################] 100%
(1/1) loading package files                        [##################] 100%
(1/1) checking for file conflicts                  [##################] 100%
(1/1) checking available disk space                [##################] 100%
(1/1) installing i2c-tools                         [##################] 100%
Optional dependencies for i2c-tools
    read-edid: for decode-edid script
[root@alarmpi ~]# i2cdetect -l
i2c-0   i2c             bcm2708_i2c.0                           I2C adapter
i2c-1   i2c             bcm2708_i2c.1                           I2C adapter
[root@alarmpi ~]#

Edit /etc/rc.local and add the modprobe and chmod commands so that you don’t have to run them after every reboot.

[root@alarmpi ~]# vim /etc/rc.local
[root@alarmpi ~]# cat /etc/rc.local
#!/bin/sh
#
# This script will be executed at the end of the boot process.
# You can put your own initialization stuff in here if you don't
# want to do the full Sys V style init stuff.

modprobe i2c-dev
chmod o+rw /dev/i2c*

[root@alarmpi ~]# chmod +x /etc/rc.local
[root@alarmpi ~]# vim /etc/systemd/system/rc-local.service
[root@alarmpi ~]# cat /etc/systemd/system/rc-local.service
[Unit]
Description=/etc/rc.local Compatibility

[Service]
# is forking instead of oneshot needed here?
Type=oneshot
ExecStart=/etc/rc.local
TimeoutSec=0
#StandardInput=tty
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

[root@alarmpi ~]# systemctl enable rc-local.service
ln -s '/etc/systemd/system/rc-local.service' '/etc/systemd/system/multi-user.target.wants/rc-local.service'
[root@alarmpi ~]# systemctl start rc-local.service
[root@alarmpi ~]# systemctl status rc-local.service
rc-local.service - /etc/rc.local Compatibility
          Loaded: loaded (/etc/systemd/system/rc-local.service; enabled)
          Active: active (exited) since Thu, 1970-01-01 01:00:05 BST; 29s ago
        Process: 105 ExecStart=/etc/rc.local (code=exited, status=0/SUCCESS)
          CGroup: name=systemd:/system/rc-local.service

[root@alarmpi ~]#

The MOD-IO2 has the address 0x48:

[root@alarmpi ~]# i2cdetect 0
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-0.
I will probe address range 0x03-0x77.
Continue? [Y/n] y
    0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- 48 -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
[root@alarmpi ~]#

Note

Also try i2cdetect 1 if i2cdetect 0 detects nothing. If it detects your MOD-IO2 at address 21 then you have a MOD-IO2 with firmware version v3 and not v2, please have a look here: https://www.olimex.com/forum/index.php?topic=2034.msg9155#msg9155.

Download and compile i2c-tool.c, have a look at the SOFTWARE section under https://www.olimex.com/Products/Modules/IO/MOD-IO2/, there is also a README.

Or get it from GitHub: https://github.com/OLIMEX/OLINUXINO/blob/master/SOFTWARE/iMX233/I2C/MOD-IO2/i2c-tool.c

[root@alarmpi ~]# wget http://www.jann.cc/_downloads/i2c-tool.c
--1970-01-01 01:19:31--  http://www.jann.cc/_downloads/i2c-tool.c
Resolving www.jann.cc (www.jann.cc)... 107.22.36.32
Connecting to www.jann.cc (www.jann.cc)|107.22.36.32|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 11583 (11K) [text/plain]
Saving to: 'i2c-tool.c'

100%[=========================================>] 11,583      --.-K/s   in 0.1s

1970-01-01 01:19:33 (86.2 KB/s) - 'i2c-tool.c' saved [11583/11583]

[root@alarmpi ~]# gcc i2c-tool.c -o i2c-tool
-bash: gcc: command not found
[root@alarmpi ~]# pacman -S gcc
[root@alarmpi ~]# gcc i2c-tool.c -o i2c-tool
[root@alarmpi ~]# cp i2c-tool /usr/bin/
[root@alarmpi ~]#

Turn both relays on:

[root@alarmpi ~]# i2c-tool -w 0 0x48 4 0x02 0xA0 0x40 0x03
SLAVE ADDRESS: 0x48
NUMBER OF BYTES TO WRITE: 4
MEMORY ALLOCATED AT ADDRESS: 0x17A5008
/dev/i2c-0 OPENDED!
WRITE:SUCCESS
[root@alarmpi ~]#

Note

If you see something like Failed writing to the I2C-bus: Input/output error then try also i2c-tool -w 1 0x48 4 0x02 0xA0 0x40 0x03, the 1 is important, maybe /dev/i2c-0 and /dev/i2c-0 are exchanged on your Raspberry Pi.

Turn both relays off:

[root@alarmpi ~]# i2c-tool -w 0 0x48 4 0x02 0xA0 0x40 0x00
SLAVE ADDRESS: 0x48
NUMBER OF BYTES TO WRITE: 4
MEMORY ALLOCATED AT ADDRESS: 0x13D7008
/dev/i2c-0 OPENDED!
WRITE:SUCCESS
[root@alarmpi ~]# i2c-tool -w 0 0x48 4 0x02 0xA0 0x40 0x01 #REL 1 on
[root@alarmpi ~]# i2c-tool -w 0 0x48 4 0x02 0xA0 0x40 0x02 #REL 2 on
[root@alarmpi ~]# i2c-tool -w 0 0x48 4 0x02 0xA0 0x40 0x03 #REL 1&2 on
[root@alarmpi ~]# i2c-tool -w 0 0x48 4 0x02 0xA0 0x40 0x00 #REL 1&2 off

Now do it from Python, here is another example.

[root@alarmpi ~]# vim modio.py
[root@alarmpi ~]# cat modio.py
import subprocess
from time import sleep

def send_modio(data):
  try:
    subprocess.call(["i2c-tool", "-w", "0", "0x48", "4",
                    "0x02", "0xA0", "0x40", data])
  except OSError:
    print("ERR: i2c-tool not found")

while 1:
  send_modio("0x00")
  sleep(1)
  send_modio("0x01")
  sleep(1)
  send_modio("0x02")
  sleep(1)
  send_modio("0x03")
  sleep(1)
[root@alarmpi ~]# python2 modio.py
SLAVE ADDRESS: 0x48
NUMBER OF BYTES TO WRITE: 4
MEMORY ALLOCATED AT ADDRESS: 0x1705008
/dev/i2c-0 OPENDED!
WRITE:SUCCESS
SLAVE ADDRESS: 0x48
NUMBER OF BYTES TO WRITE: 4
MEMORY ALLOCATED AT ADDRESS: 0x1F91008
/dev/i2c-0 OPENDED!
WRITE:SUCCESS
SLAVE ADDRESS: 0x48
NUMBER OF BYTES TO WRITE: 4
MEMORY ALLOCATED AT ADDRESS: 0x7DB008
/dev/i2c-0 OPENDED!
WRITE:SUCCESS
Traceback (most recent call last):
  File "modio.py", line 17, in <module>
    sleep(1)
KeyboardInterrupt
[root@alarmpi ~]#

The webcam

If you have also connected a webcam to your pi then you will be able to monitor the light from inside the webapp.

To use the webcam you need to install fswebcam:

[root@alarmpi ~]# pacman -S fswebcam

If you are able to save a picture from your webcam with the following command, then it should also work later from within the webapp:

[root@alarmpi ~]# fswebcam -r 640x480 -d /dev/video0 test.jpeg
--- Opening /dev/video0...
Trying source module v4l2...
/dev/video0 opened.
No input was specified, using the first.
--- Capturing frame...
[  564.033417] gspca_main: ISOC data error: [23] len=0, status=-71
[  564.072763] gspca_main: ISOC data error: [1] len=0, status=-71
[  564.143835] gspca_main: ISOC data error: [18] len=0, status=-71
[  564.279866] gspca_main: ISOC data error: [25] len=0, status=-71
[  564.510386] gspca_main: ISOC data error: [10] len=0, status=-71
[  564.548702] gspca_main: ISOC data error: [20] len=0, status=-71
[  564.650375] gspca_main: ISOC data error: [6] len=0, status=-71
[  564.720894] gspca_main: ISOC data error: [8] len=0, status=-71
[  564.855913] gspca_main: ISOC data error: [10] len=0, status=-71
[  564.862004] gspca_main: ISOC data error: [17] len=0, status=-71
[  564.868055] gspca_main: ISOC data error: [25] len=0, status=-71
[  564.974977] gspca_main: ISOC data error: [12] len=0, status=-71
Captured frame in 0.00 seconds.
--- Processing captured image...
Unable to load font 'sans': fontconfig: Couldn't retrieve font file name.
Disabling the the banner.
Writing JPEG image to 'test.jpeg'.
[root@alarmpi ~]# du -h test.jpeg
120K    test.jpeg
[root@alarmpi ~]#

gspca_main: ISOC data error is a known kernel bug: #677533 - video: USB webcam fails since kernel 3.2 but on my pi I get a image nevertheless.

To get rid of the Unable to load font 'sans': fontconfig: Couldn't retrieve font file name error, install some fonts pacman -S ttf-liberation.

The webapp will also call fswebcam to grab the images from the camera, you can change the command in app/hardware.py:

@hardware.route('/webcam.jpeg')
def camimage():
  print('Acquiring image file....')
  # this may wear out your SD card because
  # each time the page gets reloaded
  # a new image will be stored on your SD card
  try:
    subprocess.call(['fswebcam', '-r', '640x480', '-d', '/dev/video0',
                    '--title=Raspberry Pi Webcam', '--subtitle=www.jann.cc',
                    os.path.join(hardware.root_path, '../data/webcam.jpg')])
  except OSError:
    print("ERR: fswebcam not found, please install fswebcam")
  return send_from_directory(os.path.join(hardware.root_path, '../data'),
                            'webcam.jpg', mimetype='image/jpeg')

It would be better to keep the image in memory and do not write it to the SD card but it seems nobody has written a good Python webcam module so far and OpenCV may be a bit overkill here, on the fswebcam website was also written “The resulting image is saved to a file or sent to stdio where it can be piped to something like ncftpput or scp” but I was not able to get fswebcam to write the image to stdout so that I can read the image into an Python byte array. I think the current implementation should be OK for now since this example application should be as simple as possible, if you find a better way just tell me.

Other ideas:

I’ve commented out the auto refresh in templates/webcam.j2, so you have to reload the page manually if you want to see the next webcam picture.

{% block head_extra %}
{# reload page every three seconds #}
{#<meta http-equiv="refresh" content="3; URL={{ url_for('hardware.webcam') }}">#}
{% endblock %}

Get a public IP address with PageKite

The main problem with mobile internet is that if you connect through a 3G USB dongle you don’t have a public IP address but one behind a NAT gateway that is not accessible from the internet.

So theoretically you can’t run a web server via UMTS but luckily there exists a little Open Source Python script called PageKite to overcome this problem.

Install PageKite on the Raspberry Pi

The QuickStart Guide: https://pagekite.net/support/quickstart/

Setup date and time so that ssl certificates can be validated:

[root@alarmpi ~]# date
Thu Jan  1 01:56:47 BST 1970
[root@alarmpi ~]# pacman -S ntp
resolving dependencies...
looking for inter-conflicts...
:: ntp and openntpd are in conflict. Remove openntpd? [y/N] n
error: unresolvable package conflicts detected
error: failed to prepare transaction (conflicting dependencies)
:: ntp and openntpd are in conflict
[root@alarmpi ~]# ntpd -qg
ntpd: invalid option -- 'q'
usage: ntpd [-dSs] [-f file]
[root@alarmpi ~]# ntpd -s
[root@alarmpi ~]# date
Sat Jan 12 20:53:42 GMT 2013
[root@alarmpi ~]#
[root@alarmpi ~]# wget http://pagekite.net/pk/pagekite.py
--2013-01-12 20:56:05--  http://pagekite.net/pk/pagekite.py
Resolving pagekite.net (pagekite.net)... 69.164.211.158
Connecting to pagekite.net (pagekite.net)|69.164.211.158|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 160192 (156K) [text/x-python]
Saving to: 'pagekite.py'

100%[======================================>] 160,192     6.67KB/s   in 15s

2013-01-12 20:56:23 (10.3 KB/s) - 'pagekite.py' saved [160192/160192]

[root@alarmpi ~]# python2 pagekite.py --signup
[root@alarmpi ~]#

Test if the Raspberry Pi is accessible via web

[root@alarmpi ~]# mkdir www
[root@alarmpi ~]# vim www/index.html
[root@alarmpi ~]# cat www/index.html
<h1>Hello World!</h1>
[root@alarmpi ~]# python2 pagekite.py www raspberrypi.pagekite.me
  >>> Hello! This is pagekite.py v0.5.4a.                         [CTRL+C = Stop]
    Connecting to front-end 178.79.140.143:443 ...
    - Protocols: http http2 http3 https websocket irc finger httpfinger raw
    - Ports: 79 80 443 843 2222 3000 4545 5222 5223 5269 5670 6667 8000 8080
    - Ports: 8081 9292
    - Raw ports: 22 virtual
!!! Quota: You have 0.02 MB, 1 days and 5 connections left.
~<> Flying builtin HTTPD as https://raspberrypi.pagekite.me/
    - https://raspberrypi.pagekite.me/
<< pagekite.py [flying]   Kites are flying and all is well.
[root@alarmpi ~]#
PageKite Hello World

PageKite Hello World

SSH into the Raspberry Pi from everywhere

Warning: Make sure to change the default root password.

[root@alarmpi ~]# passwd
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
[root@alarmpi ~]#

Start a simple www server for the www directory and also redirect port 22 for incoming ssh connections:

[root@alarmpi ~]# python2 pagekite.py www raspberrypi.pagekite.me AND 22 ssh:raspberrypi.pagekite.me
  >>> Hello! This is pagekite.py v0.5.4a.                         [CTRL+C = Stop]
    Connecting to front-end 178.79.140.143:443 ...
    - Protocols: http http2 http3 https websocket irc finger httpfinger raw
    - Ports: 79 80 443 843 2222 3000 4545 5222 5223 5269 5670 6667 8000 8080
    - Ports: 8081 9292
    - Raw ports: 22 virtual
    Quota: You have 2560.00 MB, 31 days and 5 connections left.
~<> Flying localhost:22 as ssh://raspberrypi.pagekite.me:22/ (HTTP proxied)
~<> Flying builtin HTTPD as https://raspberrypi.pagekite.me/
    - https://raspberrypi.pagekite.me/
<< pagekite.py [flying]   Kites are flying and all is well.
[root@alarmpi ~]#

Login from your PC:

[chris@thinkpad ~]$ cat /etc/redhat-release
Fedora release 17 (Beefy Miracle)
[chris@thinkpad ~]$ ssh root@raspberrypi.pagekite.me
ssh_exchange_identification: Connection closed by remote host
[chris@thinkpad ~]$

So we get the error ssh_exchange_identification: Connection closed by remote host, the solution as written here and there is to edit your ~/.ssh/config on your PC and add the following:

Host *.pagekite.me
  CheckHostIP no
  ProxyCommand /bin/nc -X connect -x %h:443 %h %p

And now I can ssh into my pi:

[chris@thinkpad ~]$ ssh root@raspberrypi.pagekite.me
The authenticity of host 'raspberrypi.pagekite.me (<no hostip for proxy command>)' can't be established.
RSA key fingerprint is 9c:2a:26:87:dc:67:cd:a4:88:74:f1:18:b6:cb:37:95.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'raspberrypi.pagekite.me' (RSA) to the list of known hosts.
root@raspberrypi.pagekite.me's password:
Last login: Sun Jan 13 21:30:14 2013 from localhost.localdomain
[root@alarmpi ~]# uname -a
Linux alarmpi 3.6.11-3-ARCH+ #1 PREEMPT Thu Jan 10 22:05:04 UTC 2013 armv6l GNU/Linux
[root@alarmpi ~]# uname -r
3.6.11-3-ARCH+
[root@alarmpi ~]# cat /etc/arch-release
[root@alarmpi ~]# cat /etc/issue
Arch Linux \r (\l)
[root@alarmpi ~]# exit
logout
Connection to raspberrypi.pagekite.me closed.
[chris@thinkpad ~]$

A simple Python webapp to control something via Olimex’s MOD-IO2

Used software

Install everything:

[root@alarmpi ~]# pacman -S python2-flask python2-yaml git fswebcam
[root@alarmpi ~]# git clone http://github.com/christianjann/raspberrypi-modio-web.git webio
Cloning into 'webio'...
remote: Counting objects: 54, done.
remote: Compressing objects: 100% (45/45), done.
remote: Total 54 (delta 5), reused 54 (delta 5)
Unpacking objects: 100% (54/54), done.
[root@alarmpi ~]#

Test it

Try some functions on the interactive python command prompt:

[root@alarmpi ~]# cd webio/
[root@alarmpi webio]# python2
Python 2.7.3 (default, Dec 25 2012, 21:52:48)
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from app.modio import Modio
>>> mymodio = Modio()
SLAVE ADDRESS: 0x48
NUMBER OF BYTES TO WRITE: 4
MEMORY ALLOCATED AT ADDRESS: 0x7A4008
/dev/i2c-0 OPENDED!
WRITE:SUCCESS
>>> mymodio.relay1_on()
SLAVE ADDRESS: 0x48
NUMBER OF BYTES TO WRITE: 4
MEMORY ALLOCATED AT ADDRESS: 0x1515008
/dev/i2c-0 OPENDED!
WRITE:SUCCESS
>>> mymodio.relay2_on()
SLAVE ADDRESS: 0x48
NUMBER OF BYTES TO WRITE: 4
MEMORY ALLOCATED AT ADDRESS: 0x16FE008
/dev/i2c-0 OPENDED!
WRITE:SUCCESS
>>> mymodio.relay2_off()
SLAVE ADDRESS: 0x48
NUMBER OF BYTES TO WRITE: 4
MEMORY ALLOCATED AT ADDRESS: 0x1858008
/dev/i2c-0 OPENDED!
WRITE:SUCCESS
>>> mymodio.relay1_off()
SLAVE ADDRESS: 0x48
NUMBER OF BYTES TO WRITE: 4
MEMORY ALLOCATED AT ADDRESS: 0x19AF008
/dev/i2c-0 OPENDED!
WRITE:SUCCESS
>>>
KeyboardInterrupt
>>>

Start the webapp

With the help of GNU Screen ([root@alarmpi ~]# man screen) you can open several terminals at once on the Raspberry Pi (or just open several SSH sessions):

[chris@thinkpad ~]$ screen /dev/ttyUSB0 115200
[root@alarmpi ~]# pacman -S screen
[root@alarmpi ~]# screen

Now you can use the following key combinations to create new virtual terminals and switch between them:

  • “Ctrl-a” “a” “c” for a new virtual terminal
  • “Ctrl-a” “a” “n” for the next window
  • “Ctrl-a” “a” “p” for the previous window
  • “Ctrl-a” “a” “k” Kill, destroy the current window.
  • “Ctrl-a” “d” to detach screen from the current terminal, screen -ls to list terminal sessions and screen -r to attach to one of them.

Virtual terminal 1: run.py

[root@alarmpi ~]# cd webio/
[root@alarmpi webio]# python2 run.py
* Reading settings
GPIO 23 already Exists, so skipping export gpio
GPIO 24 already Exists, so skipping export gpio
SLAVE ADDRESS: 0x48
NUMBER OF BYTES TO WRITE: 4
MEMORY ALLOCATED AT ADDRESS: 0x1C2008
/dev/i2c-0 OPENDED!
WRITE:SUCCESS
* Running on http://0.0.0.0:8080/
* Restarting with reloader
* Reading settings
GPIO 23 already Exists, so skipping export gpio
GPIO 24 already Exists, so skipping export gpio
SLAVE ADDRESS: 0x48
NUMBER OF BYTES TO WRITE: 4
MEMORY ALLOCATED AT ADDRESS: 0x1818008
/dev/i2c-0 OPENDED!
WRITE:SUCCESS
127.0.0.1 - - [21/Jan/2013 17:26:59] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [21/Jan/2013 17:27:00] "GET /static/bootstrap/css/bootstrap.min.css HTTP/1.1" 200 -
127.0.0.1 - - [21/Jan/2013 17:27:00] "GET /static/bootstrap/css/bootstrap-responsive.min.css HTTP/1.1" 200 -
127.0.0.1 - - [21/Jan/2013 17:27:00] "GET /static/css/webcontrol.css HTTP/1.1" 200 -
127.0.0.1 - - [21/Jan/2013 17:27:00] "GET /static/css/webcontrol-responsive.css HTTP/1.1" 200 -
127.0.0.1 - - [21/Jan/2013 17:27:00] "GET /static/css/bootstrap-docs.css HTTP/1.1" 200 -
127.0.0.1 - - [21/Jan/2013 17:27:01] "GET /static/img/hardware.jpeg HTTP/1.1" 200 -
127.0.0.1 - - [21/Jan/2013 17:27:21] "GET /static/img/grid-18px-masked.png HTTP/1.1" 200 -
127.0.0.1 - - [21/Jan/2013 17:27:22] "GET /static/img/black_20px.png HTTP/1.1" 200 -
127.0.0.1 - - [21/Jan/2013 17:27:22] "GET /static/img/favicon.ico HTTP/1.1" 200 -

Virtual terminal 2: pagekite

[root@alarmpi ~]# ntpd -s
[root@alarmpi ~]# date
Mon Jan 21 17:16:43 GMT 2013
[root@alarmpi ~]# python2 pagekite.py 8080 raspberrypi.pagekite.me:80
>>> Hello! This is pagekite.py v0.5.4a.                         [CTRL+C = Stop]
    Connecting to front-end 178.79.140.143:443 ...
    - Protocols: http http2 http3 https websocket irc finger httpfinger raw
    - Ports: 79 80 443 843 2222 3000 4545 5222 5223 5269 5670 6667 8000 8080
    - Ports: 8081 9292
    - Raw ports: 22 virtual
    Quota: You have 2559.57 MB, 23 days and 5 connections left.
~<> Flying localhost:8080 as https://raspberrypi.pagekite.me:80/
<< pagekite.py [flying]   Kites are flying and all is well.

Screenshots

Raspberry Pi MOD-IO Web - Start

Raspberry Pi MOD-IO Web - Start

Raspberry Pi MOD-IO Web - Control

Raspberry Pi MOD-IO Web - Control

Raspberry Pi MOD-IO Web - Webcam

Raspberry Pi MOD-IO Web - Webcam

../../../_images/modio_web_on_nexus_1.png ../../../_images/modio_web_on_nexus_2.png ../../../_images/modio_web_on_nexus_3.png ../../../_images/modio_web_on_nexus_4.png ../../../_images/modio_web_on_nexus_5.png ../../../_images/modio_web_on_nexus_6.png ../../../_images/modio_web_on_nexus_7.png ../../../_images/modio_web_on_nexus_8.png

Now it’s up to you, put everything in a script, add it to /etc/rc.local so that it runs automatically at boot, improve the app or write your own.