Wednesday, August 21, 2013

DS1621 with Raspberry Pi/ArchLinuxARM

Here is  how to get DS1621 I2C Temperature sensor working with Raspberry Pi running ArchLinuxARM

Make sure you have a working setup of RPi and Arch Linux, if not refer here:
HelloWorld in Lua on Raspberry Pi running Mihini on ArchLinux with Koneki as IDE

After you have the setup ready, attach the DS1621 sensor to your RPi as shown in the schematic below.
I have Model B Revision 1.0 Raspberry Pi (cat /proc/cpuinfo shows Revision : 0002)

DS1621 connected to Raspberry Pi (.fzz file here)

The following commands issues to RPi over a terminal (SSH or Serial using PuTTY):

  1. Install i2c-tools:
    pacman -Sy i2c-tools
  2. Install lm-sensors:
    pacman -Sy lm_sensors
  3. Open kernel module load config file for editing:
    nano /etc/modules-load.d/raspberrypi.conf
  4. Add the following line at the end of the file and save it.
    i2c-dev

    This will load the i2c-dev kernel module at boot up.
    This module will allow you to access the I2C bus via /dev/i2c-0
  5. Reboot Raspberry Pi
  6. When the Raspberry Pi comes back on, issue the following command:
    i2cdetect -y 0

    You will see the following output:
  7. [root@alarmpi ~]# i2cdetect -y 0
         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: -- -- -- -- -- -- -- --
    
    Observe that DS1621's address shows up - it means it was detected successfully.

  8. Now we need to tell Linux to instantiate the device, issue the command:
    echo ds1621 0x48 >/sys/class/i2c-adapter/i2c-0/new_device

    If you check the kernel messages using the dmesg command, you will see the following new entry:
    i2c-0: new_device: Instantiated device ds1621 at 0x48
  9. To read the temperature issue the command:
    sensors

    and you will get an output similar to:

    [root@alarmpi ~]# sensors
    ds1621-i2c-0-48
    Adapter: bcm2708_i2c.0
    temp1:        +23.5 C  (low  = +10.0 C, high = +15.0 C)  ALARM (HIGH) 
    
    

Using Lua:
And in case you have Eclipse M2M tools installed on your PC and RPi, here is a lua script which will instantiate a DS1621 and display the temperature once every second:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
-- Instantiate a DS1621 device on I2C bus 0 
-- And display its reading once every second
package.path = '/opt/mihini/lua/?.lua;/opt/mihini/lua/?/init.lua;' .. package.path
package.cpath = '/opt/mihini/lua/?.so;' .. package.cpath

local sched = require "sched"
local os = require "os"
local socket = require "socket"
---------------------------------------------------------------
local function main() -- Idle task
 while true do
  local temp_file=io.open("/sys/devices/platform/bcm2708_i2c.0/i2c-0/0-0048/temp1_input","r")
  if temp_file~=nil then
   local temperature = temp_file:read()
   temperature = tonumber(temperature)
   temperature = temperature/1000
   print(string.format("Time %15s | Temperature = %f",os.date("%X"), temperature))
   temp_file:close()
  end
  sched.wait(1)
 end
end

---------------------------------------------------------------
-- -- Schedule the idle thread
local configfile = io.open("/sys/class/i2c-adapter/i2c-0/new_device","a")
if not configfile then
 return nil
end
configfile:write("ds1621 0x48")
configfile:close()
sched.run(main)

-- -- Start Scheduler
sched.loop()

Output will look like:

Time        16:22:21 | Temperature = 28.500000
Time        16:22:22 | Temperature = 28.500000
Time        16:22:23 | Temperature = 28.500000
Time        16:22:24 | Temperature = 28.500000



NOTES:

  1. To check the current speed of the IC bus in hertz, you can issue the command:
    cat /sys/module/i2c_bcm2708/parameters/baudrate
  2. Change the bus speed to, for example 500 Hz, issue the following three commands in succession:
    echo bcm2708_i2c.0 > /sys/bus/platform/drivers/bcm2708_i2c/unbind
    echo 500 > /sys/module/i2c_bcm2708/parameters/baudrate
    echo bcm2708_i2c.0 > /sys/bus/platform/drivers/bcm2708_i2c/bind
References:

Friday, August 9, 2013

Reading switches via GPIOs on Raspberry Pi in Lua (ArchLinux+Mihini)

My previous posts on using Eclipse M2M with Raspberry Pi:
  1. HelloWorld in Lua on Raspberry Pi running Mihini on ArchLinux with Koneki as IDE (link)
  2. LED Blinky in Lua on Raspberry Pi running Mihini on ArchLinux (link)
  3. Autostart Lua script on RasPi+Archlinux+Mihini at power up (link)
After having accomplished the above, I moved on to reading switches and controlling LEDs
My schematic looks like below:

This is how I connected 4 switches and 4 LEDs to the
GPIO pins of my Raspberry Pi. Black wire is Gnd.
I wanted to toggle an LED for each press of the corresponding switch. I paired up each switch to an LED:

Switch at GPIO 4 would control the LED at GPIO 22
Switch at GPIO 17 would control the LED at GPIO 23
Switch at GPIO 18 would control the LED at GPIO 24
Switch at GPIO 21 would control the LED at GPIO 25

I registered a hook function which would be called whenever the state changed of any of the four GPIOs to which the switches were connected. From within the hook functions, LED corresponding to that switch is toggled. A message is printed from inside the hook function with timestamp retrieved using the gettime() function of the 'socket' module. gettime() provides higher resolution (returns time in milliseconds) than the time() function of the 'os' module (returns time in seconds). We create an idle task using main() with an infinite loop in it. This keeps the script running albeit doing nothing while the hook listens for switch presses.

sw2leds.lua:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
-- Switches to LEDs

package.path = '/opt/mihini/lua/?.lua;/opt/mihini/lua/?/init.lua;' .. package.path
package.cpath = '/opt/mihini/lua/?.so;' .. package.cpath

local sched = require "sched"
local gpio = require "gpio"
local socket = require "socket"
---------------------------------------------------------------
local function toggle_led(n)
 local stat = gpio.read(n)
 if stat == 1 then
  gpio.write(n,0)
 elseif stat == 0 then
  gpio.write(n,1)
 end
end

local function main()
 while true do
 sched.wait(1)
 end
end

local function myhook(id, value)
 print(string.format("Time %15s | GPIO %2d changed | New value %s",socket.gettime(), id, value))
 if     id == 4 then toggle_led(22)
 elseif id == 17 then toggle_led(23)
 elseif id == 18 then toggle_led(24)
 elseif id == 21 then toggle_led(25)
 end
end
---------------------------------------------------------------
gpio.configure(22, {direction="out", edge="both", activelow="0"})
gpio.configure(23, {direction="out", edge="both", activelow="0"})
gpio.configure(24, {direction="out", edge="both", activelow="0"})
gpio.configure(25, {direction="out", edge="both", activelow="0"})
gpio.configure(4, {direction="in", edge="falling", activelow="1"})
gpio.configure(17, {direction="in", edge="falling", activelow="1"})
gpio.configure(18, {direction="in", edge="falling", activelow="1"})
gpio.configure(21, {direction="in", edge="falling", activelow="1"})

gpio.register(4, myhook)
gpio.register(17, myhook)
gpio.register(18, myhook)
gpio.register(21, myhook)


sched.run(main)
sched.loop()

As you will note, this script doesn't debounce the switches and on each press, you end up with flickering LEDs which end up in a random state post bouncing. You also get a lot of messages printed for each press:

Time 1376043551.5499 | GPIO  4 changed | New value 0
Time 1376043551.5523 | GPIO 17 changed | New value 0
Time  1376043551.554 | GPIO 18 changed | New value 0
Time  1376043551.556 | GPIO 21 changed | New value 0
Time 1376043552.9756 | GPIO  4 changed | New value 0
Time 1376043552.9786 | GPIO  4 changed | New value 1
Time 1376043552.9816 | GPIO  4 changed | New value 1
Time 1376043552.9844 | GPIO  4 changed | New value 1
Time 1376043552.9874 | GPIO  4 changed | New value 1
Time 1376043552.9901 | GPIO  4 changed | New value 1
Time  1376043552.993 | GPIO  4 changed | New value 1
Time 1376043552.9956 | GPIO  4 changed | New value 1
Time 1376043552.9989 | GPIO  4 changed | New value 1
Time 1376043553.0015 | GPIO  4 changed | New value 1
Time 1376043553.0044 | GPIO  4 changed | New value 1
Time  1376043553.007 | GPIO  4 changed | New value 1
Time 1376043553.0098 | GPIO  4 changed | New value 1
Time 1376043553.0124 | GPIO  4 changed | New value 1
Time  1376043553.161 | GPIO  4 changed | New value 0
Time 1376043554.0234 | GPIO  4 changed | New value 0
Time 1376043554.0333 | GPIO  4 changed | New value 1
Time 1376043554.0359 | GPIO  4 changed | New value 1
Time 1376043554.0387 | GPIO  4 changed | New value 1
Time 1376043554.1286 | GPIO  4 changed | New value 1
Time 1376043554.1311 | GPIO  4 changed | New value 1
Time 1376043570.8616 | GPIO 17 changed | New value 1
Time 1376043570.8643 | GPIO 17 changed | New value 1
Time 1376043570.8674 | GPIO 17 changed | New value 1
Time 1376043570.8704 | GPIO 17 changed | New value 1
Time 1376043570.8732 | GPIO 17 changed | New value 1
Time 1376043570.9058 | GPIO 17 changed | New value 0
Time 1376043571.5563 | GPIO 17 changed | New value 0
Time 1376043571.5589 | GPIO 17 changed | New value 1
Time  1376043571.681 | GPIO 17 changed | New value 0
Time 1376043571.7638 | GPIO 17 changed | New value 0

And so, I added some debouncing to each of the switches. We do this by ignoring the latter of two consecutive calls to the hook function for a particular switch if the time difference between them is less than quarter of a second. All message prints have been removed from this code.

sw2leds_debounce.lua:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
-- Switches to LEDs (with debouncing)

package.path = '/opt/mihini/lua/?.lua;/opt/mihini/lua/?/init.lua;' .. package.path
package.cpath = '/opt/mihini/lua/?.so;' .. package.cpath

local sched = require "sched"
local gpio = require "gpio"
local socket = require "socket"
---------------------------------------------------------------
local function toggle_led(n) -- Function to toggle the led
  local stat = gpio.read(n)
  if stat == 1 then
    gpio.write(n,0)
  elseif stat == 0 then
    gpio.write(n,1)
  end
end

do -- Hook function to debounce the switches
  -- First up are the variables to store the time when the switch was last pressed
  local gpio4time = socket.gettime()
  local gpio17time = socket.gettime()
  local gpio18time = socket.gettime()
  local gpio21time = socket.gettime()
  -- Second we have the variable to hold the debounce time in seconds
  -- If two consecutive pulses arrive within this interval, second pulse is ignored 
  local bounce_interval_secs = 0.25 
  -- Finally we have the function 
  function hook_switch_debounce(id, value) 
    if id == 4 then
      if socket.gettime() - gpio4time > bounce_interval_secs then
        toggle_led(22)
      end
      gpio4time = socket.gettime()
    elseif id == 17 then
      if socket.gettime() - gpio17time > bounce_interval_secs then
        toggle_led(23)
      end
      gpio17time = socket.gettime()
    elseif id == 18 then
      if socket.gettime() - gpio18time > bounce_interval_secs then
        toggle_led(24)
      end
      gpio18time = socket.gettime()
    elseif id == 21 then
      if socket.gettime() - gpio21time > bounce_interval_secs then
        toggle_led(25)
      end
      gpio21time = socket.gettime()
    end
  end
end

local function main() -- Idle task
  while true do
    sched.wait(1)
  end
end

---------------------------------------------------------------

-- Main Logic Begins
-- -- Configure the GPIOS for the 4 LEDs 
gpio.configure(22, {direction="out", edge="both", activelow="0"})
gpio.configure(23, {direction="out", edge="both", activelow="0"})
gpio.configure(24, {direction="out", edge="both", activelow="0"})
gpio.configure(25, {direction="out", edge="both", activelow="0"})

-- -- Configure the GPIOS for the 4 Switches
gpio.configure(4, {direction="in", edge="falling", activelow="1"})
gpio.configure(17, {direction="in", edge="falling", activelow="1"})
gpio.configure(18, {direction="in", edge="falling", activelow="1"})
gpio.configure(21, {direction="in", edge="falling", activelow="1"})

-- -- Register the hooks for the 4 Switches
gpio.register(4, hook_switch_debounce)
gpio.register(17, hook_switch_debounce)
gpio.register(18, hook_switch_debounce)
gpio.register(21, hook_switch_debounce)

-- -- Schedule the idle thread
sched.run(main)

-- -- Start Scheduler
sched.loop()

Tuesday, August 6, 2013

Autostart Lua script on RasPi+Archlinux+Mihini at power up

After having setup Mihini on my Raspberry Pi/ArchLinux and having blinked a few LEDs via GPIOs, I wanted to try out configuring Mihini to start a Lua script at power up.

Benjamin CabĂ© (blog | twitter) and the mihini contributors (twitter) pointed me in the right direction: Creating Launcher & Installing App | Appmon Daemon

First up, here is a code to blink four LEDs. How is it better than the previous code that blinked four LEDs together? Well, this one used the sched module to blink the four different LEDs at different rates using 4 tasks in parallel. 4 instances of tasks are created from the same function blink() using the sched.run. For each instance, we pass different parameters to blink a different LED at a different rate. We use sched.wait() within a task to relinquish control to another task waiting in queue - this is how collaborative multitasking is implemented here using the sched module.

blinky.lua:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
-- All four LEDs blinking at different rates (cooperative multitasking)

package.path = '/opt/mihini/lua/?.lua;/opt/mihini/lua/?/init.lua;' .. package.path
package.cpath = '/opt/mihini/lua/?.so;' .. package.cpath

local sched = require "sched"
local gpio = require"gpio"

local clock = os.clock

local function sleep(n)  -- seconds
  local t0 = clock()
  while clock() - t0 <= n do end
end

local function toggle_pin(n)
  local stat = gpio.read(n)
  if stat == 1 then
    gpio.write(n,0)
  elseif stat == 0 then
    gpio.write(n,1)
  end
end

local function blink(pin,timeout_secs)
  gpio.configure(pin, {direction="out", edge="both", activelow="0"})
  gpio.write(pin, 1)
  while true do
    toggle_pin(pin)
    sched.wait(timeout_secs)
  end
end

sched.run(blink,22,0.25)
sched.run(blink,23,0.5)
sched.run(blink,24,1)
sched.run(blink,25,2)
sched.loop()

Next step was to configure my Raspberry Pi to start executing this script every time at boot up. Here is how I got that done:
  1. Open a new ssh terminal to access Raspberry Pi's console. You can do this from within Eclipse itself - switch to "Remote System Explorer" perspective, make sure your Raspberry Pi's IP address is listed in the Remote Systems pane. Then ensure that a connection to Raspberry Pi is established (Right click on IP address and click connect). Further on, right click on "Ssh Terminals" listed under your RPi's IP address and select "Launch Terminal"
  2. In the terminal, issue the command "netstat -lptu". Ensure that app_daemon is listening on 4242 as shown below, if it is not, then you may have to redo the steps listed under "Finalizing mihini installation" here
    using netstat to check if app_demon is running on port 4242
  3. Now use the Sftp Files feature of Remote System Explorer within Eclipse LDT to create a new folder in your home directory. Since I have logged in as root, my home folder is /root.
    Name this folder "blinky"
    Creating a new folder called "blinky" in /root
  4. Within the blinky folder, create two blank files named "blinky.lua" and "run".
  5. You can double click on these files while in Remote Systems Explorer view and a new pane will open up allowing you to edit them.
  6. In "blinky.lua", paste the LED blinking code presented above and save it.
  7. In "run" paste the following two lines and save:
    #!/bin/sh
    lua blinky.lua

    Editing "blinky.lua" and "run" present in /root/blinky on the Raspberry Pi remotely
    from within Eclipse LDT
  8. We are running Eclipse on Windows, where as Raspberry Pi is running Linux, hence there is a need to convert the line endings from windows format to unix format especially for the run script. To do this, issue the command:
    pacman -Syu dos2unix
    via the SSH Terminal to RPi to install the dos2unix utility. Further, issue the command :
    dos2unix ~/blinky/run
    to convert the run scripts to unix format. On successful execution, you will see the message:
    dos2unix: converting file /root/blinky/run to Unix format ...
  9. Now we need to communicate with the mihini runtime and install the blinky app in the app container. Mihini telnet server on port 2000. To connect to it issue the following commend to RPi (via SSH Terminal):
    telnet localhost 2000
    You will be greeted with the following message:
    Trying 127.0.0.1...
    Connected to localhost.
    Escape character is '^]'.
    Lua interactive shell
    >
  10. Now you can issue commands to the runtime. The first thing we need to do is to enable the app container, issue the following command to the runtime:
    agent.config.appcon.activate = true
  11. Press "Ctrl+D" to exit the runtime and restart your RPi by issuing the command "reboot". Allow a few seconds for RPi to bootup, and then reconnect to it using the Remote Systems Explorer and open a SSH Terminal. Also re-enter the Mihni runtime by issuing the command "telnet localhost 2000"
  12. Issue the following two commands to install your blinky app:
    > appcon = require 'agent.appcon'
    > = appcon.install('blinky', '/root/blinky', true)

    If successful, Mihini will respond with an "=ok". Observe that the third argument passed to install() is true which means that the app will autostart at boot up.
  13. You will see the LEDs blinking now. Even if you restart your Raspberry Pi, the LED, the blinky app will start running immediately after the system has booted. 
  14. If you want to check the list of installed apps you can do so by issuing the command ":appcon.list()" to the Mihini runtime.
    > appcon = require 'agent.appcon'
    > :appcon.list()
    = { blinky = {
          autostart = true,
          runnable = true } }
  15. To uninstall the app, you can use the uninstall() function like so:
    > appcon = require 'agent.appcon'
    > :appcon.uninstall('blinky')
    = "ok"
    = nil
  16. Note: Every time you reboot and reconnect to SSH Terminal on RPi, you will have to issue the command telnet localhost 2000 to connect to the Mihini runtime. To communicate with the app container, make sure to issue appcon = require 'agent.appcon'as the first command when you enter the mihini interactive shell. Use Ctrl+D to exit the shell whenever needed.
video

NOTE: During my trials, I observed that the LEDs started blinking around 20 seconds after the application of power to RPi. This is when the Raspberry Pi was plugged into my WiFi Router via Ethernet. So 20 seconds was the time for Linux to boot up and for app_daemon to start executing the blinky.lua script.
When I powered the Raspberry Pi without any network connection, the interval from power up till the time the LEDs started blinking was 40 seconds. I guess the DHCP fails and retries must have caused the additional delays.

NOTE2: Mihini's appmon_daemon sends log messages to syslog. If you want to capture and view these messages, make sure to install syslog-ng (pacman -Syu syslog-ng). Also enable syslog-ng service (systemctl enable syslog-ng). To view only those messages which are logged by appmon_daemon, use the command cat /var/log/everything.log | grep appmon

Friday, August 2, 2013

LED Blinky in Lua on Raspberry Pi running Mihini on ArchLinux

After setting up Eclipse M2M toolchain for Raspberry Pi, I wanted to try out a simple lua script to blink LEDs using GPIOs. Here is the schematic and lua script for the same. I used the 3.3V available on RPi for powering the LEDs. 1 kiloohm resistors were used to limit the current passing through the LED. The cathodes of the LED were connected to drain the current into the GPIO pins. I used 4 LEDs connected to 4 different GPIOS (GPIO 22, GPIO 23, GPIO 24, GPIO 25).

Schematic

Photo of the setup, I used a LED/Switches widget


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package.path = '/opt/mihini/lua/?.lua;/opt/mihini/lua/?/init.lua;' .. package.path
package.cpath = '/opt/mihini/lua/?.so;' .. package.cpath

local gpio = require"gpio"

local clock = os.clock

local function sleep(n)  -- seconds
 local t0 = clock()
 while clock() - t0 <= n do end
end

local function toggle_pin(n)
 local stat = gpio.read(n)
 if stat == 1 then
  gpio.write(n,0)
 elseif stat == 0 then
  gpio.write(n,1)
 end
end

local function main()
 gpio.configure(22, {direction="out", edge="both", activelow="0"})
 gpio.configure(23, {direction="out", edge="both", activelow="0"})
 gpio.configure(24, {direction="out", edge="both", activelow="0"})
 gpio.configure(25, {direction="out", edge="both", activelow="0"})
 gpio.write(22, 1)
 gpio.write(23, 1)
 gpio.write(24, 1)
 gpio.write(25, 1)

 while true do
  sleep(1)
  toggle_pin(22)
  toggle_pin(23)
  toggle_pin(24)
  toggle_pin(25)
 end
end

main()
Lua script code to blink 4 LEDs

References:
  1. Raspberry Pi pinout
  2. Reference for the gpio module supplied with mihini
  3. Mihini Specifications