Add digital output block and GPIO handling
- Introduced a new Blockly block for setting digital output pins (`digitalOut`). - Implemented the corresponding handler in Python to manage digital output actions. - Updated dummy, GPIO, and real hardware interfaces to support digital output functionality. - Modified the workspace configuration to include the new digital output block in the Blockly environment. - Added potential enhancements to the README for future improvements.master
parent
c82e30b9b1
commit
dced16a00b
986
DOCUMENTATION.md
986
DOCUMENTATION.md
File diff suppressed because it is too large
Load Diff
|
|
@ -18,6 +18,8 @@ Feature Task : Penjabaran Pekerjaan yang ready untuk dikerjakan. Ta
|
||||||
|
|
||||||
# Potential Enhancements
|
# Potential Enhancements
|
||||||
this list is short by priority
|
this list is short by priority
|
||||||
|
- **Potensial inefective development**: in handlers/hardware use interface.py to all hardware (dummy, ros2, and hardware) class that posibly haavily change.
|
||||||
|
- ** UI bug **: stop button not actualy stop execution. tried with long delay with loop and press stop button, program still continue
|
||||||
- **Launch files**: `blockly_bringup` package with ROS2 launch files to start all nodes with one command
|
- **Launch files**: `blockly_bringup` package with ROS2 launch files to start all nodes with one command
|
||||||
- **Sensor integration**: Subscriber nodes for sensor data feeding back into Blockly visual feedback
|
- **Sensor integration**: Subscriber nodes for sensor data feeding back into Blockly visual feedback
|
||||||
- **RealHardware implementation**: Fill in ROS2 publishers/service clients for actual Pi hardware nodes (topics TBD)
|
- **RealHardware implementation**: Fill in ROS2 publishers/service clients for actual Pi hardware nodes (topics TBD)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
|
||||||
|
BlockRegistry.register({
|
||||||
|
name: 'digitalOut', // Must match Python handler name
|
||||||
|
category: 'Robot',
|
||||||
|
categoryColor: '#5b80a5',
|
||||||
|
color: '#4CAF50',
|
||||||
|
tooltip: 'set a digital output pin to HIGH (turn on LED)',
|
||||||
|
|
||||||
|
definition: {
|
||||||
|
init: function () {
|
||||||
|
this.appendValueInput('digitalOut')
|
||||||
|
.appendField(' gpio:')
|
||||||
|
// FieldNumber(default, min, max, step)
|
||||||
|
.appendField(new Blockly.FieldNumbint(er(1, 0, 27, 1), 'GPIO')
|
||||||
|
.setCheck('Boolean')
|
||||||
|
.appendField(' state:');
|
||||||
|
|
||||||
|
this.setPreviousStatement(true, null); // connect above
|
||||||
|
this.setNextStatement(true, null); // connect below
|
||||||
|
this.setColour('#4CAF50');
|
||||||
|
this.setTooltip('set a digital output pin to HIGH (turn on LED)');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
generator: function (block) {
|
||||||
|
const GPIO = block.getFieldValue('GPIO');
|
||||||
|
const STATE = Blockly.JavaScript.valueToCode(block, 'digitalOut', Blockly.JavaScript.ORDER_ATOMIC) || 'false';
|
||||||
|
return (
|
||||||
|
'highlightBlock(\'' + block.id + '\');\n' +
|
||||||
|
'await executeAction(\'digital_out\', { gpio: \'' + GPIO + '\', state: \'' + STATE + '\' });\n'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
@ -9,7 +9,6 @@
|
||||||
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
const BLOCK_FILES = [
|
const BLOCK_FILES = [
|
||||||
'led_on.js',
|
'digitalOut.js',
|
||||||
'led_off.js',
|
|
||||||
'delay.js',
|
'delay.js',
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -15,3 +15,11 @@ def handle_led_off(params: dict[str, str], hardware) -> tuple[bool, str]:
|
||||||
pin = int(params["pin"])
|
pin = int(params["pin"])
|
||||||
hardware.set_led(pin, False)
|
hardware.set_led(pin, False)
|
||||||
return (True, f"LED on pin {pin} turned OFF")
|
return (True, f"LED on pin {pin} turned OFF")
|
||||||
|
|
||||||
|
@handler("digital_out")
|
||||||
|
def handle_digital_out(params: dict[str, str], hardware) -> tuple[bool, str]:
|
||||||
|
gpio = int(params["gpio"])
|
||||||
|
state = bool(params["state"])
|
||||||
|
hardware.set_digital_out(gpio, state)
|
||||||
|
state_str = "HIGH" if state else "LOW"
|
||||||
|
return (True, f"GPIO pin {gpio} set to {state_str}")
|
||||||
|
|
@ -22,3 +22,6 @@ class DummyHardware(HardwareInterface):
|
||||||
def is_ready(self) -> bool:
|
def is_ready(self) -> bool:
|
||||||
self.call_log.append("is_ready()")
|
self.call_log.append("is_ready()")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def set_digital_out(self, gpio: int, state: bool) -> None:
|
||||||
|
self.call_log.append(f"set_digital_out(gpio={gpio}, state={state})")
|
||||||
|
|
|
||||||
|
|
@ -30,3 +30,9 @@ class GpioHardware(HardwareInterface):
|
||||||
|
|
||||||
def is_ready(self) -> bool:
|
def is_ready(self) -> bool:
|
||||||
return self._initialized
|
return self._initialized
|
||||||
|
|
||||||
|
def set_digital_out(self, gpio: int, state: bool) -> None:
|
||||||
|
if not self._initialized:
|
||||||
|
raise RuntimeError("GPIO not available on this platform")
|
||||||
|
self._gpio.setup(gpio, self._gpio.OUT)
|
||||||
|
self._gpio.output(gpio, self._gpio.HIGH if state else self._gpio.LOW)
|
||||||
|
|
|
||||||
|
|
@ -32,3 +32,14 @@ class HardwareInterface(ABC):
|
||||||
True if hardware is initialized and ready.
|
True if hardware is initialized and ready.
|
||||||
"""
|
"""
|
||||||
...
|
...
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def set_digital_out(self, gpio: int, state: bool) -> None:
|
||||||
|
"""
|
||||||
|
Set a GPIO pin to HIGH or LOW.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
gpio: GPIO pin number.
|
||||||
|
state: True for HIGH, False for LOW.
|
||||||
|
"""
|
||||||
|
...
|
||||||
|
|
|
||||||
|
|
@ -29,3 +29,7 @@ class RealHardware(HardwareInterface):
|
||||||
def is_ready(self) -> bool:
|
def is_ready(self) -> bool:
|
||||||
# TODO: check if Pi hardware nodes are reachable
|
# TODO: check if Pi hardware nodes are reachable
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def set_digital_out(self, gpio: int, state: bool) -> None:
|
||||||
|
# TODO: publish to Pi hardware node
|
||||||
|
self._logger.info(f"RealHardware.set_digital_out(gpio={gpio}, state={state}) — stub")
|
||||||
|
|
|
||||||
|
|
@ -3,17 +3,75 @@
|
||||||
"languageVersion": 0,
|
"languageVersion": 0,
|
||||||
"blocks": [
|
"blocks": [
|
||||||
{
|
{
|
||||||
"type": "controls_if",
|
"type": "controls_repeat_ext",
|
||||||
"id": "WLmpkq!^,rcoKGH+bQgN",
|
"id": "j+usYB.X4%o``Le;Q,LA",
|
||||||
"x": 210,
|
"x": 190,
|
||||||
"y": 70,
|
"y": 150,
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"DO0": {
|
"TIMES": {
|
||||||
"block": {
|
"shadow": {
|
||||||
"type": "led_on",
|
"type": "math_number",
|
||||||
"id": "._%j-2DZ*BZJlyW:1#`Q",
|
"id": "cI`]|Us0+)Ol~XY0L`wE",
|
||||||
"fields": {
|
"fields": {
|
||||||
"PIN": 1
|
"NUM": 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"DO": {
|
||||||
|
"block": {
|
||||||
|
"type": "digitalOut",
|
||||||
|
"id": "3}G7M%~([nNy9YHlug!|",
|
||||||
|
"fields": {
|
||||||
|
"GPIO": 17
|
||||||
|
},
|
||||||
|
"inputs": {
|
||||||
|
"digitalOut": {
|
||||||
|
"block": {
|
||||||
|
"type": "logic_boolean",
|
||||||
|
"id": "Sw__`~LvxpKyo}./q]1/",
|
||||||
|
"fields": {
|
||||||
|
"BOOL": "TRUE"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"next": {
|
||||||
|
"block": {
|
||||||
|
"type": "delay",
|
||||||
|
"id": "?o-l1IBd(^YR,u[;k$-|",
|
||||||
|
"fields": {
|
||||||
|
"DURATION_MS": 500
|
||||||
|
},
|
||||||
|
"next": {
|
||||||
|
"block": {
|
||||||
|
"type": "digitalOut",
|
||||||
|
"id": "t}@.X|Ac7F?J;C4v`5ic",
|
||||||
|
"fields": {
|
||||||
|
"GPIO": 17
|
||||||
|
},
|
||||||
|
"inputs": {
|
||||||
|
"digitalOut": {
|
||||||
|
"block": {
|
||||||
|
"type": "logic_boolean",
|
||||||
|
"id": "]I]_@v6=ErAYdiolo|+n",
|
||||||
|
"fields": {
|
||||||
|
"BOOL": "FALSE"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"next": {
|
||||||
|
"block": {
|
||||||
|
"type": "delay",
|
||||||
|
"id": "45BA([9g7/_tItSnUwB-",
|
||||||
|
"fields": {
|
||||||
|
"DURATION_MS": 500
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue