164 lines
5.1 KiB
JavaScript
164 lines
5.1 KiB
JavaScript
// ESP32-S3 Robot addon
|
|
//
|
|
// Blocks: move(left, right) — set both motors -255..255
|
|
// distance left — sonar distance in cm (value)
|
|
// distance right — sonar distance in cm (value)
|
|
//
|
|
// ─── CONFIGURE YOUR ROBOT ───────────────────────────────────
|
|
// Edit the pin numbers below to match your wiring, then re-install
|
|
// the addon (Addons → Remove "esp32s3-robot-addon" → Install same file again).
|
|
|
|
var LEFT_MOTOR_PIN1 = 3;
|
|
var LEFT_MOTOR_PIN2 = 4;
|
|
var RIGHT_MOTOR_PIN1 = 5;
|
|
var RIGHT_MOTOR_PIN2 = 6;
|
|
var LEFT_SONAR_TRIG = 9;
|
|
var LEFT_SONAR_ECHO = 8;
|
|
var RIGHT_SONAR_TRIG = 11;
|
|
var RIGHT_SONAR_ECHO = 10;
|
|
|
|
// ─── Block definitions ───────────────────────────────────────
|
|
|
|
api.Blockly.Blocks['robot_move'] = {
|
|
init() {
|
|
this.appendValueInput('LEFT')
|
|
.setCheck('Number')
|
|
.appendField('move left');
|
|
this.appendValueInput('RIGHT')
|
|
.setCheck('Number')
|
|
.appendField('right');
|
|
this.setInputsInline(true);
|
|
this.setPreviousStatement(true, null);
|
|
this.setNextStatement(true, null);
|
|
this.setColour(45);
|
|
this.setTooltip('Set left and right motor speed (-255 to 255). DRV8833 on pins 3,4 and 5,6.');
|
|
},
|
|
};
|
|
|
|
api.Blockly.Blocks['robot_distance_left'] = {
|
|
init() {
|
|
this.appendDummyInput()
|
|
.appendField('distance left (cm)');
|
|
this.setOutput(true, 'Number');
|
|
this.setColour(65);
|
|
this.setTooltip('Left sonar distance in cm (trig=9, echo=8)');
|
|
},
|
|
};
|
|
|
|
api.Blockly.Blocks['robot_distance_right'] = {
|
|
init() {
|
|
this.appendDummyInput()
|
|
.appendField('distance right (cm)');
|
|
this.setOutput(true, 'Number');
|
|
this.setColour(65);
|
|
this.setTooltip('Right sonar distance in cm (trig=11, echo=10)');
|
|
},
|
|
};
|
|
|
|
// --- Code generators ---
|
|
|
|
var gen = api.pythonGenerator;
|
|
|
|
// Generated Python pin constants (from config at top of this file).
|
|
var ROBOT_PINS = [
|
|
'# Robot pin configuration',
|
|
'LEFT_MOTOR_PIN1 = ' + LEFT_MOTOR_PIN1,
|
|
'LEFT_MOTOR_PIN2 = ' + LEFT_MOTOR_PIN2,
|
|
'RIGHT_MOTOR_PIN1 = ' + RIGHT_MOTOR_PIN1,
|
|
'RIGHT_MOTOR_PIN2 = ' + RIGHT_MOTOR_PIN2,
|
|
'LEFT_SONAR_TRIG = ' + LEFT_SONAR_TRIG,
|
|
'LEFT_SONAR_ECHO = ' + LEFT_SONAR_ECHO,
|
|
'RIGHT_SONAR_TRIG = ' + RIGHT_SONAR_TRIG,
|
|
'RIGHT_SONAR_ECHO = ' + RIGHT_SONAR_ECHO,
|
|
].join('\n');
|
|
|
|
var ROBOT_MOTOR_DEF = [
|
|
'from machine import Pin, PWM',
|
|
'_robot_left1 = PWM(Pin(LEFT_MOTOR_PIN1), freq=20000, duty=0)',
|
|
'_robot_left2 = PWM(Pin(LEFT_MOTOR_PIN2), freq=20000, duty=0)',
|
|
'_robot_right1 = PWM(Pin(RIGHT_MOTOR_PIN1), freq=20000, duty=0)',
|
|
'_robot_right2 = PWM(Pin(RIGHT_MOTOR_PIN2), freq=20000, duty=0)',
|
|
'def _robot_set_motor(pwm1, pwm2, speed):',
|
|
' speed = max(-255, min(255, int(speed)))',
|
|
' duty = abs(speed) * 4',
|
|
' if speed > 0:',
|
|
' pwm1.duty(duty)',
|
|
' pwm2.duty(0)',
|
|
' elif speed < 0:',
|
|
' pwm1.duty(0)',
|
|
' pwm2.duty(duty)',
|
|
' else:',
|
|
' pwm1.duty(0)',
|
|
' pwm2.duty(0)',
|
|
].join('\n');
|
|
|
|
var ROBOT_SONAR_DEF = [
|
|
'def _robot_sonar_cm(trig, echo):',
|
|
' from machine import Pin, time_pulse_us',
|
|
' import time',
|
|
' t = Pin(trig, Pin.OUT)',
|
|
' e = Pin(echo, Pin.IN)',
|
|
' t.off()',
|
|
' time.sleep_us(2)',
|
|
' t.on()',
|
|
' time.sleep_us(10)',
|
|
' t.off()',
|
|
' d = time_pulse_us(e, 1, 30000)',
|
|
' return round(d / 58.0, 1) if d >= 0 else -1',
|
|
].join('\n');
|
|
|
|
function addRobotDefs() {
|
|
gen.definitions_['robot_pins'] = ROBOT_PINS;
|
|
gen.definitions_['robot_motors'] = ROBOT_MOTOR_DEF;
|
|
gen.definitions_['robot_sonar'] = ROBOT_SONAR_DEF;
|
|
}
|
|
|
|
gen.forBlock['robot_move'] = function (block) {
|
|
if (api.getDeviceId() !== 'esp32s3') {
|
|
return '# Robot move block is for ESP32-S3 robot (DRV8833 on 3,4,5,6)\n';
|
|
}
|
|
addRobotDefs();
|
|
var left = gen.valueToCode(block, 'LEFT', gen.ORDER_NONE) || '0';
|
|
var right = gen.valueToCode(block, 'RIGHT', gen.ORDER_NONE) || '0';
|
|
return '_robot_set_motor(_robot_left1, _robot_left2, ' + left + ')\n' +
|
|
'_robot_set_motor(_robot_right1, _robot_right2, ' + right + ')\n';
|
|
};
|
|
|
|
gen.forBlock['robot_distance_left'] = function (block) {
|
|
if (api.getDeviceId() !== 'esp32s3') {
|
|
return ['-1', gen.ORDER_ATOMIC];
|
|
}
|
|
addRobotDefs();
|
|
return ['_robot_sonar_cm(LEFT_SONAR_TRIG, LEFT_SONAR_ECHO)', gen.ORDER_FUNCTION_CALL];
|
|
};
|
|
|
|
gen.forBlock['robot_distance_right'] = function (block) {
|
|
if (api.getDeviceId() !== 'esp32s3') {
|
|
return ['-1', gen.ORDER_ATOMIC];
|
|
}
|
|
addRobotDefs();
|
|
return ['_robot_sonar_cm(RIGHT_SONAR_TRIG, RIGHT_SONAR_ECHO)', gen.ORDER_FUNCTION_CALL];
|
|
};
|
|
|
|
// --- Register toolbox category ---
|
|
|
|
api.registerCategories([
|
|
{
|
|
kind: 'category',
|
|
name: 'ESP32-S3 Robot',
|
|
colour: '45',
|
|
contents: [
|
|
{
|
|
kind: 'block',
|
|
type: 'robot_move',
|
|
inputs: {
|
|
LEFT: { shadow: { type: 'math_number', fields: { NUM: 0 } } },
|
|
RIGHT: { shadow: { type: 'math_number', fields: { NUM: 0 } } },
|
|
},
|
|
},
|
|
{ kind: 'block', type: 'robot_distance_left' },
|
|
{ kind: 'block', type: 'robot_distance_right' },
|
|
],
|
|
},
|
|
]);
|