diff --git a/extensions/microPython/sensor/espUltrasonic/asset/ultrasonic.png b/extensions/microPython/sensor/espUltrasonic/asset/ultrasonic.png new file mode 100644 index 0000000..bad363e Binary files /dev/null and b/extensions/microPython/sensor/espUltrasonic/asset/ultrasonic.png differ diff --git a/extensions/microPython/sensor/espUltrasonic/blocks.js b/extensions/microPython/sensor/espUltrasonic/blocks.js new file mode 100644 index 0000000..f659aa6 --- /dev/null +++ b/extensions/microPython/sensor/espUltrasonic/blocks.js @@ -0,0 +1,47 @@ +/* eslint-disable func-style */ +/* eslint-disable max-len */ +/* eslint-disable require-jsdoc */ +function addBlocks (Blockly) { + const color = '#D39DDB'; + const secondaryColour = '#BA55D3'; + + const digitalPins = Blockly.Device.getPinOptions('microPython_pin_setDigitalOutput'); + + Blockly.Blocks.ultrasonic_readDistance = { + init: function () { + this.jsonInit({ + message0: Blockly.Msg.ULTRASONIC_READ_DISTANCE, + args0: [ + { + type: 'field_dropdown', + name: 'TRIG', + options: digitalPins + }, + { + type: 'field_dropdown', + name: 'ECHO', + options: digitalPins + }, + { + type: 'field_dropdown', + name: 'UNIT', + options: [ + ['cm', 'CM'], + ['mm', 'MM']] + } + ], + colour: color, + secondaryColour: secondaryColour, + extensions: ['output_number'] + }); + this.getField('TRIG').setValue(digitalPins[0][1]); + this.getField('ECHO').setValue(digitalPins[1][1]); + this.getField('UNIT').setValue('CM'); + } + }; + + + return Blockly; +} + +exports = addBlocks; diff --git a/extensions/microPython/sensor/espUltrasonic/generator.js b/extensions/microPython/sensor/espUltrasonic/generator.js new file mode 100644 index 0000000..a5272ec --- /dev/null +++ b/extensions/microPython/sensor/espUltrasonic/generator.js @@ -0,0 +1,23 @@ +/* eslint-disable func-style */ +/* eslint-disable require-jsdoc */ +function addGenerator (Blockly) { + Blockly.Python.ultrasonic_readDistance = function (block) { + const trig = block.getFieldValue('TRIG'); + const echo = block.getFieldValue('ECHO'); + const unit = block.getFieldValue('UNIT'); + + Blockly.Python.imports_.ultrasonic_readDistance = `from hcsr04_v0_2_1 import HCSR04`; + Blockly.Python.variables_[`ultrasonic_${trig}_${echo}`] = + `ultrasonic_${trig}_${echo} = HCSR04(trigger_pin = ${trig}, echo_pin = ${echo})`; + + if (unit === 'CM') { + return [`ultrasonic_${trig}_${echo}.distance_cm()`, Blockly.Python.ORDER_ATOMIC]; + } + return [`ultrasonic_${trig}_${echo}.distance_mm()`, Blockly.Python.ORDER_ATOMIC]; + }; + + + return Blockly; +} + +exports = addGenerator; diff --git a/extensions/microPython/sensor/espUltrasonic/index.js b/extensions/microPython/sensor/espUltrasonic/index.js new file mode 100644 index 0000000..8681d2b --- /dev/null +++ b/extensions/microPython/sensor/espUltrasonic/index.js @@ -0,0 +1,26 @@ +const ultrasonic = formatMessage => ({ + name: formatMessage({ + id: 'ultrasonic.name', + default: 'Ultrasonic' + }), + extensionId: 'espUltrasonic', + version: '1.0.0', + supportDevice: ['microPythonEsp32', 'microPythonEsp8266'], + author: 'ArthurZheng', + iconURL: `asset/ultrasonic.png`, + description: formatMessage({ + id: 'ultrasonic.description', + default: 'Standard ultrasonic distance measurement module.' + }), + featured: true, + blocks: 'blocks.js', + generator: 'generator.js', + toolbox: 'toolbox.js', + msg: 'msg.js', + library: 'lib', + official: true, + tags: ['sensor'], + helpLink: 'https://wiki.openblock.cc' +}); + +module.exports = ultrasonic; diff --git a/extensions/microPython/sensor/espUltrasonic/lib/hcsr04_v0_2_1.py b/extensions/microPython/sensor/espUltrasonic/lib/hcsr04_v0_2_1.py new file mode 100644 index 0000000..aa31e83 --- /dev/null +++ b/extensions/microPython/sensor/espUltrasonic/lib/hcsr04_v0_2_1.py @@ -0,0 +1,82 @@ +from machine import Pin, time_pulse_us +from utime import sleep_us + +__version__ = '0.2.1' +__author__ = 'Roberto Sánchez' +__license__ = "Apache License 2.0. https://www.apache.org/licenses/LICENSE-2.0" + +class HCSR04: + """ + Driver to use the untrasonic sensor HC-SR04. + The sensor range is between 2cm and 4m. + + The timeouts received listening to echo pin are converted to OSError('Out of range') + + """ + # echo_timeout_us is based in chip range limit (400cm) + def __init__(self, trigger_pin, echo_pin, echo_timeout_us=500*2*30): + """ + trigger_pin: Output pin to send pulses + echo_pin: Readonly pin to measure the distance. The pin should be protected with 1k resistor + echo_timeout_us: Timeout in microseconds to listen to echo pin. + By default is based in sensor limit range (4m) + """ + self.echo_timeout_us = echo_timeout_us + # Init trigger pin (out) + self.trigger = Pin(trigger_pin, mode=Pin.OUT, pull=None) + self.trigger.value(0) + + # Init echo pin (in) + self.echo = Pin(echo_pin, mode=Pin.IN, pull=None) + + def _send_pulse_and_wait(self): + """ + Send the pulse to trigger and listen on echo pin. + We use the method `machine.time_pulse_us()` to get the microseconds until the echo is received. + """ + self.trigger.value(0) # Stabilize the sensor + sleep_us(5) + self.trigger.value(1) + # Send a 10us pulse. + sleep_us(10) + self.trigger.value(0) + try: + pulse_time = time_pulse_us(self.echo, 1, self.echo_timeout_us) + # time_pulse_us returns -2 if there was timeout waiting for condition; and -1 if there was timeout during the main measurement. It DOES NOT raise an exception + # ...as of MicroPython 1.17: http://docs.micropython.org/en/v1.17/library/machine.html#machine.time_pulse_us + if pulse_time < 0: + MAX_RANGE_IN_CM = const(500) # it's really ~400 but I've read people say they see it working up to ~460 + pulse_time = int(MAX_RANGE_IN_CM * 29.1) # 1cm each 29.1us + return pulse_time + except OSError as ex: + if ex.args[0] == 110: # 110 = ETIMEDOUT + raise OSError('Out of range') + raise ex + + def distance_mm(self): + """ + Get the distance in milimeters without floating point operations. + """ + pulse_time = self._send_pulse_and_wait() + + # To calculate the distance we get the pulse_time and divide it by 2 + # (the pulse walk the distance twice) and by 29.1 becasue + # the sound speed on air (343.2 m/s), that It's equivalent to + # 0.34320 mm/us that is 1mm each 2.91us + # pulse_time // 2 // 2.91 -> pulse_time // 5.82 -> pulse_time * 100 // 582 + mm = pulse_time * 100 // 582 + return mm + + def distance_cm(self): + """ + Get the distance in centimeters with floating point operations. + It returns a float + """ + pulse_time = self._send_pulse_and_wait() + + # To calculate the distance we get the pulse_time and divide it by 2 + # (the pulse walk the distance twice) and by 29.1 becasue + # the sound speed on air (343.2 m/s), that It's equivalent to + # 0.034320 cm/us that is 1cm each 29.1us + cms = (pulse_time / 2) / 29.1 + return cms diff --git a/extensions/microPython/sensor/espUltrasonic/msg.js b/extensions/microPython/sensor/espUltrasonic/msg.js new file mode 100644 index 0000000..1e79efb --- /dev/null +++ b/extensions/microPython/sensor/espUltrasonic/msg.js @@ -0,0 +1,35 @@ +// This file was automatically generated. Do not modify. +/* eslint-disable func-style */ +/* eslint-disable require-jsdoc */ +/* eslint-disable quote-props */ +/* eslint-disable quotes */ +/* eslint-disable dot-notation */ + +function addMsg (Blockly) { + + Object.assign(Blockly.ScratchMsgs.locales["en"], + { + "ULTRASONIC_CATEGORY": "Ultrasonic", + "ULTRASONIC_READ_DISTANCE": "ultrasonic sensor pin TRIG %1 ECHO %2 read distance %3" + } + ); + + Object.assign(Blockly.ScratchMsgs.locales["zh-cn"], + { + "ULTRASONIC_CATEGORY": "超声波", + "ULTRASONIC_READ_DISTANCE": "超声波传感器引脚 TRIG %1 ECHO %2 读取距离 %3" + } + ); + + Object.assign(Blockly.ScratchMsgs.locales["zh-tw"], + { + "ULTRASONIC_CATEGORY": "超聲波", + "ULTRASONIC_READ_DISTANCE": "超聲波傳感器管腳 TRIG %1 ECHO %2 讀取距離 %3" + } + ); + + return Blockly; +} + +exports = addMsg; +// End of combined translations diff --git a/extensions/microPython/sensor/espUltrasonic/msg.json b/extensions/microPython/sensor/espUltrasonic/msg.json new file mode 100644 index 0000000..144dd4d --- /dev/null +++ b/extensions/microPython/sensor/espUltrasonic/msg.json @@ -0,0 +1,4 @@ +{ + "ULTRASONIC_CATEGORY": "Ultrasonic", + "ULTRASONIC_READ_DISTANCE": "ultrasonic sensor pin TRIG %1 ECHO %2 read distance %3" +} \ No newline at end of file diff --git a/extensions/microPython/sensor/espUltrasonic/toolbox.js b/extensions/microPython/sensor/espUltrasonic/toolbox.js new file mode 100644 index 0000000..d76f75d --- /dev/null +++ b/extensions/microPython/sensor/espUltrasonic/toolbox.js @@ -0,0 +1,11 @@ +/* eslint-disable func-style */ +/* eslint-disable max-len */ +/* eslint-disable require-jsdoc */ +function addToolbox () { + return ` + + + + `; +} +exports = addToolbox;