esp32blockly/src/blocks/esp32_blocks.js

523 lines
16 KiB
JavaScript
Raw Normal View History

import * as Blockly from 'blockly';
// ─── Pin I/O ──────────────────────────────────────────────
Blockly.Blocks['pin_set_mode'] = {
init() {
this.appendDummyInput()
.appendField('set pin')
.appendField(new Blockly.FieldNumber(2, 0, 48, 1), 'PIN')
.appendField('as')
.appendField(new Blockly.FieldDropdown([
['OUTPUT', 'OUT'],
['INPUT', 'IN'],
['INPUT_PULLUP', 'PULL_UP'],
]), 'MODE');
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(230);
this.setTooltip('Configure a GPIO pin mode');
},
};
Blockly.Blocks['pin_digital_write'] = {
init() {
this.appendDummyInput()
.appendField('digital write pin')
.appendField(new Blockly.FieldNumber(2, 0, 48, 1), 'PIN')
.appendField('to')
.appendField(new Blockly.FieldDropdown([
['HIGH', '1'],
['LOW', '0'],
]), 'VALUE');
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(230);
this.setTooltip('Write HIGH or LOW to a digital pin');
},
};
Blockly.Blocks['pin_digital_read'] = {
init() {
this.appendDummyInput()
.appendField('digital read pin')
.appendField(new Blockly.FieldNumber(2, 0, 48, 1), 'PIN');
this.setOutput(true, 'Number');
this.setColour(230);
this.setTooltip('Read digital value from a pin (0 or 1)');
},
};
// ─── PWM ──────────────────────────────────────────────────
Blockly.Blocks['pwm_init'] = {
init() {
this.appendDummyInput()
.appendField('init PWM on pin')
.appendField(new Blockly.FieldNumber(2, 0, 48, 1), 'PIN')
.appendField('freq')
.appendField(new Blockly.FieldNumber(1000, 1, 40000000, 1), 'FREQ')
.appendField('Hz');
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(160);
this.setTooltip('Initialize PWM on a pin with a frequency');
},
};
Blockly.Blocks['pwm_set_duty'] = {
init() {
this.appendValueInput('DUTY')
.setCheck('Number')
.appendField('set PWM duty on pin')
.appendField(new Blockly.FieldNumber(2, 0, 48, 1), 'PIN')
.appendField('to');
this.appendDummyInput()
.appendField('(0-1023)');
this.setInputsInline(true);
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(160);
this.setTooltip('Set PWM duty cycle (0-1023)');
},
};
Blockly.Blocks['pwm_set_freq'] = {
init() {
this.appendValueInput('FREQ')
.setCheck('Number')
.appendField('set PWM freq on pin')
.appendField(new Blockly.FieldNumber(2, 0, 48, 1), 'PIN')
.appendField('to');
this.appendDummyInput()
.appendField('Hz');
this.setInputsInline(true);
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(160);
this.setTooltip('Set PWM frequency in Hz');
},
};
// ─── ADC ──────────────────────────────────────────────────
Blockly.Blocks['adc_read'] = {
init() {
this.appendDummyInput()
.appendField('read ADC on pin')
.appendField(new Blockly.FieldNumber(1, 0, 20, 1), 'PIN');
this.setOutput(true, 'Number');
this.setColour(30);
this.setTooltip('Read analog value from ADC pin (0-4095)');
},
};
// ─── Time ─────────────────────────────────────────────────
Blockly.Blocks['sleep_seconds'] = {
init() {
this.appendValueInput('SECONDS')
.setCheck('Number')
.appendField('sleep');
this.appendDummyInput()
.appendField('seconds');
this.setInputsInline(true);
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(120);
this.setTooltip('Pause execution for N seconds');
},
};
Blockly.Blocks['sleep_ms'] = {
init() {
this.appendValueInput('MS')
.setCheck('Number')
.appendField('sleep');
this.appendDummyInput()
.appendField('milliseconds');
this.setInputsInline(true);
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(120);
this.setTooltip('Pause execution for N milliseconds');
},
};
Blockly.Blocks['ticks_ms'] = {
init() {
this.appendDummyInput()
.appendField('ticks (ms)');
this.setOutput(true, 'Number');
this.setColour(120);
this.setTooltip('Get millisecond tick counter');
},
};
// ─── Random ───────────────────────────────────────────────
Blockly.Blocks['random_int'] = {
init() {
this.appendValueInput('FROM')
.setCheck('Number')
.appendField('random integer from');
this.appendValueInput('TO')
.setCheck('Number')
.appendField('to');
this.setOutput(true, 'Number');
this.setInputsInline(true);
this.setColour(200);
this.setTooltip('Random integer N where from ≤ N ≤ to (inclusive)');
},
};
Blockly.Blocks['random_float'] = {
init() {
this.appendDummyInput()
.appendField('random float (0.0 to 1.0)');
this.setOutput(true, 'Number');
this.setColour(200);
this.setTooltip('Random float in range [0.0, 1.0)');
},
};
Blockly.Blocks['random_uniform'] = {
init() {
this.appendValueInput('LOW')
.setCheck('Number')
.appendField('random float from');
this.appendValueInput('HIGH')
.setCheck('Number')
.appendField('to');
this.setOutput(true, 'Number');
this.setInputsInline(true);
this.setColour(200);
this.setTooltip('Random float in range [low, high]');
},
};
Blockly.Blocks['random_seed'] = {
init() {
this.appendValueInput('SEED')
.setCheck('Number')
.appendField('random seed');
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(200);
this.setTooltip('Set random seed for reproducible sequences (optional)');
},
};
// ─── WiFi ─────────────────────────────────────────────────
Blockly.Blocks['wifi_connect'] = {
init() {
this.appendDummyInput()
.appendField('connect WiFi SSID')
.appendField(new Blockly.FieldTextInput('MyNetwork'), 'SSID')
.appendField('password')
.appendField(new Blockly.FieldTextInput('password'), 'PASSWORD');
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(290);
this.setTooltip('Connect to a WiFi network');
},
};
Blockly.Blocks['wifi_get_ip'] = {
init() {
this.appendDummyInput()
.appendField('WiFi IP address');
this.setOutput(true, 'String');
this.setColour(290);
this.setTooltip('Get the current IP address');
},
};
// ─── NeoPixel ─────────────────────────────────────────────
Blockly.Blocks['neopixel_init'] = {
init() {
this.appendDummyInput()
.appendField('init NeoPixel on pin')
.appendField(new Blockly.FieldNumber(48, 0, 48, 1), 'PIN')
.appendField('with')
.appendField(new Blockly.FieldNumber(1, 1, 1024, 1), 'NUM')
.appendField('LEDs');
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(10);
this.setTooltip('Initialize a NeoPixel strip');
},
};
Blockly.Blocks['colour_rgb'] = {
init() {
this.appendValueInput('R').setCheck('Number').appendField('colour R');
this.appendValueInput('G').setCheck('Number').appendField('G');
this.appendValueInput('B').setCheck('Number').appendField('B');
this.setOutput(true, 'Colour');
this.setInputsInline(true);
this.setColour(10);
this.setTooltip('RGB colour as array [R, G, B] (values 0255)');
},
};
Blockly.Blocks['tuple_create_3'] = {
init() {
this.appendValueInput('A').appendField('tuple');
this.appendValueInput('B').appendField(',');
this.appendValueInput('C').appendField(',');
this.setOutput(true, 'Colour');
this.setInputsInline(true);
this.setColour(10);
this.setTooltip('Create a 3-element tuple (e.g. for NeoPixel colour). Use numbers or variables.');
},
};
Blockly.Blocks['neopixel_set_color'] = {
init() {
this.appendValueInput('INDEX')
.setCheck('Number')
.appendField('set NeoPixel #');
this.appendValueInput('COLOR')
.setCheck(null)
.appendField('colour');
this.setInputsInline(true);
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(10);
this.setTooltip('Set NeoPixel to a colour. Use the colour/tuple block or a variable (e.g. from a function parameter).');
},
};
Blockly.Blocks['neopixel_show'] = {
init() {
this.appendDummyInput()
.appendField('NeoPixel show');
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(10);
this.setTooltip('Push color data to NeoPixel strip');
},
};
// ─── I2C ──────────────────────────────────────────────────
Blockly.Blocks['i2c_init'] = {
init() {
this.appendDummyInput()
.appendField('init I2C SDA pin')
.appendField(new Blockly.FieldNumber(8, 0, 48, 1), 'SDA')
.appendField('SCL pin')
.appendField(new Blockly.FieldNumber(9, 0, 48, 1), 'SCL')
.appendField('freq')
.appendField(new Blockly.FieldNumber(400000, 1, 1000000, 1), 'FREQ');
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(200);
this.setTooltip('Initialize I2C bus');
},
};
Blockly.Blocks['i2c_scan'] = {
init() {
this.appendDummyInput()
.appendField('I2C scan devices');
this.setOutput(true, 'Array');
this.setColour(200);
this.setTooltip('Scan for I2C devices, returns list of addresses');
},
};
Blockly.Blocks['i2c_writeto'] = {
init() {
this.appendValueInput('DATA')
.setCheck(null)
.appendField('I2C write to address')
.appendField(new Blockly.FieldNumber(0, 0, 127, 1), 'ADDR')
.appendField('data');
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(200);
this.setTooltip('Write data bytes to an I2C device');
},
};
Blockly.Blocks['i2c_readfrom'] = {
init() {
this.appendDummyInput()
.appendField('I2C read from address')
.appendField(new Blockly.FieldNumber(0, 0, 127, 1), 'ADDR')
.appendField('bytes')
.appendField(new Blockly.FieldNumber(1, 1, 256, 1), 'NBYTES');
this.setOutput(true, null);
this.setColour(200);
this.setTooltip('Read N bytes from an I2C device');
},
};
// ─── Print ────────────────────────────────────────────────
Blockly.Blocks['print_text'] = {
init() {
this.appendValueInput('TEXT')
.setCheck(null)
.appendField('print');
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(60);
this.setTooltip('Print to serial output');
},
};
2026-02-20 07:27:56 +00:00
// ─── Sound ───────────────────────────────────────────────
Blockly.Blocks['sound_play_tone_speaker'] = {
init() {
this.appendDummyInput().appendField('play tone on speaker');
this.appendValueInput('FREQ')
.setCheck('Number')
.appendField('freq');
this.appendDummyInput().appendField('Hz');
this.appendValueInput('DURATION')
.setCheck('Number')
.appendField('for');
this.appendDummyInput()
.appendField('ms')
.appendField(new Blockly.FieldDropdown([
['wait', 'TRUE'],
['continue', 'FALSE'],
]), 'WAIT');
this.setInputsInline(true);
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(300);
this.setTooltip('Play a tone on the built-in speaker (micro:bit v2). "continue" runs code while tone plays.');
},
};
Blockly.Blocks['sound_stop_speaker'] = {
init() {
this.appendDummyInput().appendField('stop speaker');
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(300);
this.setTooltip('Stop sound on the built-in speaker (micro:bit v2)');
},
};
Blockly.Blocks['sound_play_tone'] = {
init() {
this.appendDummyInput()
.appendField('play tone on pin')
.appendField(new Blockly.FieldNumber(0, 0, 48, 1), 'PIN');
this.appendValueInput('FREQ')
.setCheck('Number')
.appendField('freq');
this.appendDummyInput().appendField('Hz');
this.appendValueInput('DURATION')
.setCheck('Number')
.appendField('for');
this.appendDummyInput()
.appendField('ms')
.appendField(new Blockly.FieldDropdown([
['wait', 'TRUE'],
['continue', 'FALSE'],
]), 'WAIT');
this.setInputsInline(true);
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(300);
this.setTooltip('Play a tone via PWM on a specific pin. "continue" runs code while tone plays.');
},
};
Blockly.Blocks['sound_stop'] = {
init() {
this.appendDummyInput()
.appendField('stop sound on pin')
.appendField(new Blockly.FieldNumber(0, 0, 48, 1), 'PIN');
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(300);
this.setTooltip('Stop sound on a specific pin');
},
};
// ─── micro:bit Display ────────────────────────────────────
// Helper to add one row of 5 checkboxes (Pxy = pixel at row x, col y)
function addMicrobitDisplayRow(block, row) {
const input = block.appendDummyInput(`ROW${row}`);
for (let col = 0; col < 5; col++) {
const name = `P${row}${col}`;
input.appendField(new Blockly.FieldCheckbox(false), name);
}
}
Blockly.Blocks['microbit_display_all'] = {
init() {
this.appendDummyInput()
.appendField('micro:bit display 5×5');
for (let row = 0; row < 5; row++) {
addMicrobitDisplayRow(this, row);
}
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(10);
this.setTooltip('Click LEDs to set the 5×5 display (micro:bit only). On = 9, off = 0.');
},
};
// ─── SuperBit (Yahboom SuperBit V2, micro:bit only) ───────
Blockly.Blocks['superbit_motor_run'] = {
init() {
this.appendDummyInput()
.appendField('SuperBit motor')
.appendField(new Blockly.FieldDropdown([
['M1', 'M1'],
['M2', 'M2'],
['M3', 'M3'],
['M4', 'M4'],
]), 'MOTOR');
this.appendValueInput('SPEED')
.setCheck('Number')
.appendField('speed (-255 to 255)');
this.setInputsInline(true);
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(45);
this.setTooltip('Run a SuperBit V2 motor (PCA9685 over I2C). Negative = reverse.');
},
};
Blockly.Blocks['superbit_motor_stop_all'] = {
init() {
this.appendDummyInput()
.appendField('SuperBit motor stop all');
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(45);
this.setTooltip('Stop all four SuperBit V2 motors.');
},
};
// ─── Sensors (HC-SR04 style sonar, all devices) ───────────
Blockly.Blocks['sonar_distance'] = {
init() {
this.appendValueInput('TRIG')
.setCheck('Number')
.appendField('sonar distance trigger');
this.appendValueInput('ECHO')
.setCheck('Number')
.appendField('echo');
this.setInputsInline(true);
this.setOutput(true, 'Number');
this.setColour(65);
this.setTooltip('HC-SR04 style ultrasonic distance in cm. Trigger and echo pin numbers.');
},
};