Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

The pico engine has one instance of modules. That is when the a pico uses a module provide by the engine, the pico does not have a instance unique to itself, all picos must share that module.  Normally this is something a pico developer does not need to worry about, but when modules are created to control restricted resources, a pico developer must think about read write access to resources. Singleton pattern is a solution for protecting restricted resources. The pattern is to create a single pico for a single resource. An example of this pattern can be found in the pico rover project.

Table of Contents

Pico Rover Singleton Pattern

The pico rover has a custom JavaScript module which is a singleton for GPIO pins that control wheels.  Each wheel has a pico which represents that wheel.

 Image Added

Wheels.krl

The following code came from wheels.krl. In the example below you can see that each wheel keeps track of the motor it controls by setting an entity variable called motorIndex.  Then in each method call, the wheel pico passes the motorIndex.  This provides write access to a single pico which represents a single GPIO pin or wheel motor.

Code Block
languagejs
titleWheels.krl
global{
	stop = defaction(){
		motorHat:dc_stop(ent:motorIndex);
	}  
}
rule setMotorIndex { 
	select when rover motorIndex
	always{ 
		ent:motorIndex := event:attr("motorIndex")
	}
}

WheelsController.krl

A controller pico then creates a higher level access point for each wheel pico.
The code below is taken from wheelsController.krl.  The controller has an eci to each wheel. To move the pico rover in any direction you must send wheel directions and speed to each spacific wheel pico. The controller creates defaction wrappers to send events to each wheel with correlated information. In this way each pico wheel is used as a type of semaphore to protect each GPIO pin. While the singleton pattern could be sercumvented in this example by placeing all logic in the controller, this would not scale if more picos that accessed the wheels where added. 

Code Block
languagejs
titleWheelsController.krl
config= { // hard coded eci to wheels, this would be MUCH better as subscriptions.
	"FR":"5tj6Xi4deyAsninzbj7sK",
    "FL":"GyTnMVWqrzVPXWUx2D2NB",
    "BR":"N7j7beQx6VYsR9H81NbGD",
    "BL":"XYv1HUQxcuwXmTHoNS72K"
};

to_motors = defaction(event,attr1,attr2,attr3,attr4){
	every{
    	event:send( 
        	{ "eci": config{"FR"},
              "domain": "rover", "type": event,
              "attrs": attr1
              });
        event:send( 
            { "eci": config{"FL"},
              "domain": "rover", "type": event,
              "attrs": attr2
              });
        event:send( 
            { "eci": config{"BR"},
              "domain": "rover", "type": event,
              "attrs": attr3
              });
        event:send( 
            { "eci": config{"BL"},
              "domain": "rover", "type": event,
              "attrs": attr4
              });
      }
}
run_motors = defaction(dir1,dir2,dir3,dir4){
	to_motors("run", {"direction": dir1},
                     {"direction": dir2},
                     {"direction": dir3},
                     {"direction": dir4} )
    }
fwd   = defaction(){ run_motors("fwd","back","back","fwd") }
back  = defaction(){ run_motors("back","fwd","fwd","back") }
right = defaction(){ run_motors("back","back","back","back") }
left  = defaction(){ run_motors("fwd","fwd","fwd","fwd") } 
stop  = defaction(){ to_motors("stop",{},{},{},{} ) }