node-red-contrib-seeed-recamera
Version:
Node-RED nodes for reCamera
195 lines (173 loc) • 7.31 kB
HTML
<script type="text/html" data-template-name="angle-to-can">
<div class="form-row">
<label for="node-input-name">
<i class="fa fa-tag"></i>
<span>Name</span>
</label>
<input type="text" id="node-input-name" />
</div>
<div class="form-row">
<label for="node-input-name">
<i class="fa fa-arrow-circle-right"></i>
<span>Input</span>
</label>
<input type="text" id="node-input-input" />
<input type="hidden" id="node-input-input-type" />
</div>
<div class="form-row">
<label style="width: 100%;">
<i class="fa fa-arrow-circle-left"></i>
<span>Output as <b>CAN command</b></span>
</label>
</div>
<div class="form-row" style="margin-left: 20px; margin-bottom: 0;">
<label style="width: 100%;"><b>Yaw Axis (Left and Right):</b></label>
</div>
<div class="form-row">
<div style="margin-left: 10px;">
<div>
<div style="display: flex; margin-bottom: 5px;">
<input style="width: auto; margin: 0 10px;" type="radio" name="node-input-output" value="0" />
<span>Absolute Position</span>
</div>
<div style="display: flex;">
<input style="width: auto; margin: 0 10px;" type="radio" name="node-input-output" value="1" />
<span>Relative Offset</span>
</div>
</div>
</div>
</div>
<div class="form-row" style="margin-left: 20px; margin-bottom: 0;">
<label style="width: 100%;"><b>Pitch Axis (Up and Down):</b></label>
</div>
<div class="form-row">
<div style="margin-left: 10px;">
<div>
<div style="display: flex; margin-bottom: 5px;">
<input style="width: auto; margin: 0 10px;" type="radio" name="node-input-output" value="2" />
<span>Absolute Position</span>
</div>
<div style="display: flex;">
<input style="width: auto; margin: 0 10px;" type="radio" name="node-input-output" value="3" />
<span>Relative Offset</span>
</div>
</div>
</div>
</div>
<div class="form-row">
<label for="node-input-unit">
<i class="fa fa-pencil"></i>
<span>Unit</span>
</label>
</div>
<div class="form-row">
<div style="margin-left: 10px;">
<div>
<div style="display: flex; margin-bottom: 5px;">
<input style="width: auto; margin: 0 10px;" type="radio" name="node-input-unit" id="node-input-unit-decimal" value="0" />
<span>Input in decimal (e.g 180.23 as 180.23 degrees)</span>
</div>
<div style="display: flex;">
<input style="width: auto; margin: 0 10px;" type="radio" name="node-input-unit" id="node-input-unit-integer" value="1" />
<span>Input in integer (e.g 18023 as 180.23 degrees)</span>
</div>
</div>
</div>
</div>
</script>
<script type="text/javascript">
RED.nodes.registerType("angle-to-can", {
category: "reCamera gimbal",
color: "#C6D09C",
defaults: {
name: { value: "" },
input: { value: "payload", required: true },
"input-type": { value: "msg" },
output: { required: true, value: "0" },
unit: { value: "0" }
},
inputs: 1,
outputs: 1,
icon: "font-awesome/fa-exchange",
paletteLabel: "angle to CAN",
label: function () {
return this.name || "angle to CAN";
},
oneditprepare: function () {
const node = this;
$("#node-input-input").typedInput({
type: "msg",
types: ["msg", "flow", "global"],
typeField: "#node-input-input-type",
});
$(`input[name="node-input-output"][value="${node.output}"]`).prop("checked", true);
$(`input[name="node-input-unit"][value="${node.unit || "0"}"]`).prop("checked", true);
},
oneditsave: function () {
this.output = $('input[name="node-input-output"]:checked').val();
this.input = $("#node-input-input").typedInput("value");
this.unit = $('input[name="node-input-unit"]:checked').val();
},
});
</script>
<script type="text/markdown" data-help-name="angle-to-can">
# Angle to CAN
This node converts and parses the angle value in degrees to hexadecimal raw data for motor control.
## Overview
The node takes a numeric angle value as input and generates a CAN message object that can be sent directly to a CAN bus interface or to a CAN Write node.
## Configuration
### Motor Type
Select which motor to control:
- **Yaw** (horizontal axis): Used for left/right movement
- **Pitch** (vertical axis): Used for up/down movement
### Control Mode
Choose the type of control:
- **Absolute Position**: Set the motor to a specific angle
- **Relative Offset**: Move the motor by a specific angle offset from current position
### Input source
Specify the source of the angle value:
- **msg.xxx**: Use the value in the message such as payload or topic
- **flow.xxx**: Use a value from flow context
- **global.xxx**: Use a value from global context
### Number Format
Choose how to interpret your input value:
- **Decimal degrees**: Input is in standard degrees (e.g., 90.5°)
- **Motor units**: Input is in motor internal units (hundredths of degrees, e.g., 9050 = 90.5°)
## Input
The input should be a numeric value representing the target angle (for absolute positioning) or angle offset (for relative movement).
Examples:
- `90.5` - Move to 90.5 degrees (when using decimal degrees)
- `9050` - Move to 90.5 degrees (when using motor units)
- `-10` - Move 10 degrees counterclockwise (when using relative offset)
## Output
The node outputs a CAN message object that can be sent directly to a CAN bus:
```json
{
"payload": {
"id": 0x141, // Motor ID in hex format (0x141 for Yaw, 0x142 for Pitch)
"data": [0xA4, 0x00, 0x5A, 0x00, 0x10, 0x27, 0x00, 0x00] // Command data as byte array
}
}
```
## Command Format
The output CAN message follows this format:
### Absolute Position Command:
- **Byte 0**: Command type (0xA4)
- **Byte 1**: Direction (0x00)
- **Byte 2-3**: Speed (2 bytes, little-endian)
- **Byte 4-7**: Angle (4 bytes, little-endian)
### Relative Offset Command:
- **Byte 0**: Command type (0xA8)
- **Byte 1**: Direction (0x00)
- **Byte 2-3**: Speed (2 bytes, little-endian)
- **Byte 4-7**: Offset (4 bytes, little-endian)
## Angle Limits
- **Yaw**: -180° to +180°
- **Pitch**: -90° to +90°
Values outside these ranges will be automatically limited to the allowed range.
## Notes
- The node converts input values to the proper internal format for the motor
- For absolute position, angles are automatically limited to the valid range for each motor
- The output format is compatible with the CAN Write node and direct SocketCAN interfaces
- Status updates show the target angle or offset value
</script>