Controlling GPIO on a cluster machine


#1

Hi,

I have several development boards set up in a Beowulf cluster [with passwordless ssh] along with my desktop machine (a Dell Optiplex 755). I have 4 nodes: NODE-DELL755 [which is the master], NODE-RPI2 [a Raspberry Pi 2], NODE-BBB [a Beaglebone Black], and NODE-UDOOX86 [a Udoo x86]. I am able to control the GPIO on the Raspberry Pi with the following code:

rpi = addprocs([“julia-user@NODE-RPI2”],dir="/home/julia-user/julia-0.6.0/bin/")

include(“GPIO_Module.jl”)

import GPIO
using GPIO

17 is the GPIO for an LED and 27 is the GPIO for a PIR sensor

remotecall(blink_led_sensor2, rpi[1], “17”, “27”)

So, if the PIR sensor sees movement - it blinks and LED 5 times and breaks out of the loop. See my question at the bottom.

The GPIO_Module looks like:

@everywhere module GPIO

export export_pin, unexport_pin, setdirection_pin, setvalue_pin, getvalue_pin, blink_led, blink_led_sensor, blink_led_sensor2

function export_pin(pin::String)
export_str = "/sys/class/gpio/export"
f = open(export_str,“w”)
write(f, pin)
close(f)
end

function unexport_pin(pin::String)
unexport_str = "/sys/class/gpio/unexport"
f = open(unexport_str, “w”)
write(f, pin)
close(f)
end

function setdirection_pin(pin::String, dir::String)
setdir_str = “/sys/class/gpio/gpio” * pin * "/direction"
f = open(setdir_str, “w”)
write(f, dir)
close(f)
end

function getvalue_pin(pin::String)
setval_str = “/sys/class/gpio/gpio” * pin * "/value"
f = open(setval_str, “r”)
val::String = readline(f)
close(f)
return val
end

function setvalue_pin(pin::String, val::String)
setval_str = “/sys/class/gpio/gpio” * pin * "/value"
f = open(setval_str, “w”)
write(f, val)
close(f)
end

function blink_led(node::Int, pin::String, howMany::Int)
remotecall_fetch(export_pin, node, pin)
remotecall_fetch(setdirection_pin, node, pin, “out”)
for n = 1:howMany
remotecall_fetch(setvalue_pin, node, pin, “1”)
sleep(1)
remotecall_fetch(setvalue_pin, node, pin, “0”)
sleep(1)
end
remotecall_fetch(unexport_pin, node, pin)
end

function blink_led_sensor(node::Int, pinLED::String, pinSensor::String)
remotecall_fetch(export_pin, node, pinLED)
sleep(1)
remotecall_fetch(setdirection_pin, node, pinLED, “out”)

remotecall_fetch(export_pin, node, pinSensor)
sleep(1)
remotecall_fetch(setdirection_pin, node, pinSensor, "in")

while (true)
    ret = remotecall_fetch(getvalue_pin, node, pinSensor)  
    sleep(1)
    if ret == "1"
        for n = 1:5
            remotecall_fetch(setvalue_pin, node, pinLED, "1")
            sleep(1)
            remotecall_fetch(setvalue_pin, node, pinLED, "0")
            sleep(1)
        end
        break
    end
end
remotecall_fetch(unexport_pin, node, pinLED)
sleep(1)
remotecall_fetch(unexport_pin, node, pinSensor)

end

function blink_led_sensor2(pinLED::String, pinSensor::String)
export_pin(pinLED)
sleep(1)
setdirection_pin(pinLED, “out”)

export_pin(pinSensor)
sleep(1)
setdirection_pin(pinSensor, "in")

while (true)
    ret::String = getvalue_pin(pinSensor)  
    sleep(1)
    if ret == "1"
        for n = 1:5
            setvalue_pin(pinLED, "1")
            sleep(1)
            setvalue_pin(pinLED, "0")
            sleep(1)
        end
        break
    end
end
unexport_pin(pinLED)
sleep(1)
unexport_pin(node, pinSensor)

end

end

My question is: Is there a way to make the remote call communicate back to the “master” Julia environment? What I would like to do is if the PIR sensor “sees” movement to set a variable that the “master” would be able to interrogate and say “hey - something moved in front of the PIR sensor.” And, the routine checking the sensor would never break. It would just run - like a thread.

Is this possible?

Frank


#2

Set up a ZMQ based channel between the nodes? https://github.com/JuliaInterop/ZMQ.jl


#3

I’ve done that with sockets in Java and C++, but I was wondering if there was a way using Julia’s remote procs or tasks or something like that. Thanks.