电机最大旋转角度限定100度
财位指令旋转电机以后返回原位
This commit is contained in:
@@ -47,7 +47,8 @@
|
|||||||
/* Liveness safety bound for the fixed two-cycle wealth spin intro (not the
|
/* Liveness safety bound for the fixed two-cycle wealth spin intro (not the
|
||||||
* animation length). On timeout the worker proceeds to reveal + rotate anyway. */
|
* animation length). On timeout the worker proceeds to reveal + rotate anyway. */
|
||||||
#define CONTROL_PLANE_SPIN_INTRO_TIMEOUT_MS 6000
|
#define CONTROL_PLANE_SPIN_INTRO_TIMEOUT_MS 6000
|
||||||
#define CONTROL_PLANE_COMMAND_ROTATION_DEG 45.0f
|
#define CONTROL_PLANE_COMMAND_ROTATION_DEG 100.0f
|
||||||
|
#define CONTROL_PLANE_COMMAND_RETURN_DELAY_MS 5000
|
||||||
|
|
||||||
#if (configSUPPORT_STATIC_ALLOCATION == 1) && \
|
#if (configSUPPORT_STATIC_ALLOCATION == 1) && \
|
||||||
((defined(CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM) && CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM) || \
|
((defined(CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM) && CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM) || \
|
||||||
@@ -716,8 +717,14 @@ static esp_err_t control_plane_apply_wealth_direction(size_t direction_index,
|
|||||||
|
|
||||||
(void)direction_index;
|
(void)direction_index;
|
||||||
|
|
||||||
float current_angle = domain_get_current_angle();
|
float start_angle = domain_get_current_angle();
|
||||||
return control_plane_rotate_to_angle(current_angle + CONTROL_PLANE_COMMAND_ROTATION_DEG);
|
esp_err_t rotate_err = control_plane_rotate_to_angle(start_angle + CONTROL_PLANE_COMMAND_ROTATION_DEG);
|
||||||
|
if (rotate_err != ESP_OK) {
|
||||||
|
return rotate_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(CONTROL_PLANE_COMMAND_RETURN_DELAY_MS));
|
||||||
|
return control_plane_rotate_to_angle(start_angle);
|
||||||
}
|
}
|
||||||
|
|
||||||
static esp_err_t control_plane_run_model_calibration_motion(void)
|
static esp_err_t control_plane_run_model_calibration_motion(void)
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
#define PLATFORM_STEPPER_DECEL_STEPS 48
|
#define PLATFORM_STEPPER_DECEL_STEPS 48
|
||||||
#define PLATFORM_STEPPER_STEPS_PER_REV 4128.0f
|
#define PLATFORM_STEPPER_STEPS_PER_REV 4128.0f
|
||||||
#define PLATFORM_STEPPER_POWER_OFF_WAIT_MS 1000
|
#define PLATFORM_STEPPER_POWER_OFF_WAIT_MS 1000
|
||||||
#define PLATFORM_STEPPER_MAX_ROTATION_DEG 330.0f
|
#define PLATFORM_STEPPER_MAX_ROTATION_DEG 100.0f
|
||||||
#define PLATFORM_GPIO_LOW_BANK_MAX_PIN 31
|
#define PLATFORM_GPIO_LOW_BANK_MAX_PIN 31
|
||||||
#define PLATFORM_GPIO_HIGH_BANK_OFFSET 32
|
#define PLATFORM_GPIO_HIGH_BANK_OFFSET 32
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,143 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Convert PNG images to the binary RGB565 RLE format used by lcd_direct."""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import struct
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
try:
|
||||||
|
from PIL import Image
|
||||||
|
except ImportError as exc:
|
||||||
|
raise SystemExit("Pillow is required. Install it with: python -m pip install Pillow") from exc
|
||||||
|
|
||||||
|
|
||||||
|
MAX_RUN_COUNT = 0xFFFF
|
||||||
|
|
||||||
|
|
||||||
|
def parse_rgb(value):
|
||||||
|
text = value.strip()
|
||||||
|
if text.startswith("#"):
|
||||||
|
text = text[1:]
|
||||||
|
if len(text) != 6:
|
||||||
|
raise argparse.ArgumentTypeError("expected RRGGBB or #RRGGBB")
|
||||||
|
try:
|
||||||
|
return tuple(int(text[index:index + 2], 16) for index in (0, 2, 4))
|
||||||
|
except ValueError as exc:
|
||||||
|
raise argparse.ArgumentTypeError("background must be hexadecimal RGB") from exc
|
||||||
|
|
||||||
|
|
||||||
|
def rgb888_to_rgb565(red, green, blue):
|
||||||
|
return ((red & 0xF8) << 8) | ((green & 0xFC) << 3) | (blue >> 3)
|
||||||
|
|
||||||
|
|
||||||
|
def image_to_runs(path, background):
|
||||||
|
with Image.open(path) as image:
|
||||||
|
rgba = image.convert("RGBA")
|
||||||
|
width, height = rgba.size
|
||||||
|
bg_red, bg_green, bg_blue = background
|
||||||
|
|
||||||
|
runs = []
|
||||||
|
current_color = None
|
||||||
|
current_count = 0
|
||||||
|
|
||||||
|
for red, green, blue, alpha in rgba.getdata():
|
||||||
|
if alpha < 255:
|
||||||
|
red = ((red * alpha) + (bg_red * (255 - alpha))) // 255
|
||||||
|
green = ((green * alpha) + (bg_green * (255 - alpha))) // 255
|
||||||
|
blue = ((blue * alpha) + (bg_blue * (255 - alpha))) // 255
|
||||||
|
|
||||||
|
color = rgb888_to_rgb565(red, green, blue)
|
||||||
|
if color == current_color and current_count < MAX_RUN_COUNT:
|
||||||
|
current_count += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
if current_color is not None:
|
||||||
|
runs.append((current_color, current_count))
|
||||||
|
current_color = color
|
||||||
|
current_count = 1
|
||||||
|
|
||||||
|
if current_color is not None:
|
||||||
|
runs.append((current_color, current_count))
|
||||||
|
|
||||||
|
return width, height, runs
|
||||||
|
|
||||||
|
|
||||||
|
def write_rle(path, runs):
|
||||||
|
path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
with path.open("wb") as output:
|
||||||
|
for color, count in runs:
|
||||||
|
output.write(struct.pack("<HH", color, count))
|
||||||
|
|
||||||
|
|
||||||
|
def iter_inputs(input_path, recursive):
|
||||||
|
if input_path.is_file():
|
||||||
|
if input_path.suffix.lower() != ".png":
|
||||||
|
raise SystemExit(f"input file is not a PNG: {input_path}")
|
||||||
|
yield input_path
|
||||||
|
return
|
||||||
|
|
||||||
|
pattern = "**/*.png" if recursive else "*.png"
|
||||||
|
yield from sorted(input_path.glob(pattern))
|
||||||
|
|
||||||
|
|
||||||
|
def output_path_for(input_file, input_root, output):
|
||||||
|
if output is None:
|
||||||
|
return input_file.with_suffix(".rle")
|
||||||
|
|
||||||
|
if input_root.is_file():
|
||||||
|
return output
|
||||||
|
|
||||||
|
relative = input_file.relative_to(input_root)
|
||||||
|
return (output / relative).with_suffix(".rle")
|
||||||
|
|
||||||
|
|
||||||
|
def convert_file(input_file, input_root, output, background):
|
||||||
|
out_path = output_path_for(input_file, input_root, output)
|
||||||
|
width, height, runs = image_to_runs(input_file, background)
|
||||||
|
write_rle(out_path, runs)
|
||||||
|
print(f"{input_file} -> {out_path} ({width}x{height}, {len(runs)} runs)")
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="Convert PNG files to lcd_direct RGB565 RLE binary assets.",
|
||||||
|
)
|
||||||
|
parser.add_argument("input", type=Path, help="PNG file or directory containing PNG files.")
|
||||||
|
parser.add_argument(
|
||||||
|
"-o",
|
||||||
|
"--output",
|
||||||
|
type=Path,
|
||||||
|
help="Output .rle file for one input file, or output directory for an input directory.",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-r",
|
||||||
|
"--recursive",
|
||||||
|
action="store_true",
|
||||||
|
help="Recursively convert PNG files when input is a directory.",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--background",
|
||||||
|
type=parse_rgb,
|
||||||
|
default=(0, 0, 0),
|
||||||
|
help="RGB background for transparent pixels, as RRGGBB or #RRGGBB. Default: 000000.",
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
input_path = args.input.resolve()
|
||||||
|
if not input_path.exists():
|
||||||
|
raise SystemExit(f"input path does not exist: {input_path}")
|
||||||
|
|
||||||
|
output = args.output.resolve() if args.output is not None else None
|
||||||
|
inputs = list(iter_inputs(input_path, args.recursive))
|
||||||
|
if not inputs:
|
||||||
|
raise SystemExit(f"no PNG files found in: {input_path}")
|
||||||
|
|
||||||
|
if input_path.is_file() and output is not None and output.suffix.lower() != ".rle":
|
||||||
|
raise SystemExit("single-file output must use a .rle suffix")
|
||||||
|
|
||||||
|
for input_file in inputs:
|
||||||
|
convert_file(input_file, input_path, output, args.background)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user