module main author unknown version 1 0 description '' variables T H script 139 78 { whenStarted forever { T = (temperature_DHT11 2) H = (humidity_DHT11 2) sayIt ('[data:join]' 'T=' T 'H=' H) waitMillis 1000 } } module 'LCD Display' Output author MicroBlocks version 1 6 description 'Library for 16x2 LCD text displays with 1602 controller I2C "backpack" like the ones from DFRobot, SunFounder, and others. These displays have two lines of sixteen characters. Most of these displays require 5 volts to provide sufficient LCD contrast, so you will need an external power source for 3.3v boards like the micro:bit. ' variables _LCD1602_ADDR _LCD1602_LINE1 _LCD1602_LINE2 _LCD1602_LOCK_MSECS _LCD1602_CUSTOM_CHARS spec ' ' 'LCD1602_write' 'write _ on LCD line _' 'str num num num' 'Hello, World!' 1 1 16 spec ' ' 'LCD1602_write_field' 'write field _ on LCD line _ from _ to _' 'str num num num' 'Moon!' 1 8 12 spec ' ' 'LCD1602_clear' 'clear LCD' spec 'r' 'LCD1602_isConnected' 'is LCD connected?' advanced spec ' ' 'LCD1602 draw char' 'draw char _ on LCD line _ column _' 'str num num' '00000 01010 01010 00000 00100 00000 10001 01110' 1 10 space spec 'r' '_LCD1602 init' '_LCD1602 init' spec ' ' '_LCD1602 send' '_LCD1602 send byte _ mode _' 'num num' 10 1 spec ' ' '_LCD1602 toggle enable' '_LCD1602 toggle enable _' 'num' 10 to 'LCD1602 draw char' char line col { if (not ('_LCD1602 init')) {return} if (_LCD1602_CUSTOM_CHARS == 0) {_LCD1602_CUSTOM_CHARS = (newList 8)} comment 'Create the character bytes' local 'character bytes' ('[data:makeList]') for 'each line' ('[data:split]' char ('[data:unicodeString]' 10)) { local 'byte' 0 for position 5 { byte = (byte + ((at position (v 'each line')) << (position - 1))) } '[data:addLast]' byte (v 'character bytes') } comment 'Find out whether the character has already been created' local 'index' 0 local 'last empty' 0 for i 8 { if ((at i _LCD1602_CUSTOM_CHARS) == 0) { 'last empty' = i } else { local 'found' (booleanConstant true) for position 8 { found = (and found ((at position (at i _LCD1602_CUSTOM_CHARS)) == (at position (v 'character bytes')))) } if found { index = i exitLoop } } } comment 'Character not found. Let''s create it and add it to the LCD CGRAM. If there''s an empty spot, we''ll put it there. Otherwise, we''ll reuse the first spot.' if (index == 0) { index = (maximum (v 'last empty') 1) atPut index _LCD1602_CUSTOM_CHARS (v 'character bytes') '_LCD1602 send' ((hexToInt '40') | ((index - 1) << 3)) 0 for i 8 { '_LCD1602 send' (at i (v 'character bytes')) 1 } } if (line == 1) { atPut col _LCD1602_LINE1 (index - 1) } else { atPut col _LCD1602_LINE2 (index - 1) } waitUntil (((millisOp) - _LCD1602_LOCK_MSECS) > 500) _LCD1602_LOCK_MSECS = (millisOp) LCD1602_write_buffer line _LCD1602_LOCK_MSECS = 0 } to LCD1602_clear { if (not ('_LCD1602 init')) {return} waitUntil (((millisOp) - _LCD1602_LOCK_MSECS) > 500) _LCD1602_LOCK_MSECS = (millisOp) _LCD1602_LINE1 = ('[data:newByteArray]' 16 32) _LCD1602_LINE2 = ('[data:newByteArray]' 16 32) '_LCD1602 send' 1 0 _LCD1602_LOCK_MSECS = 0 } to LCD1602_isConnected { return ('_LCD1602 init') } to LCD1602_write string line { LCD1602_write_field string line 1 16 } to LCD1602_write_buffer line { local 'bytes' 0 if (line == 1) { '_LCD1602 send' (hexToInt '80') 0 bytes = _LCD1602_LINE1 } else { '_LCD1602 send' (hexToInt 'C0') 0 bytes = _LCD1602_LINE2 } for b bytes { '_LCD1602 send' b 1 } } to LCD1602_write_field string line start end { if (not ('_LCD1602 init')) {return} string = ('[data:join]' '' string) if (or (start < 1) (start > 16)) { return } if (or (end < start) (end > 16)) { return } if (line == 1) { bytes = _LCD1602_LINE1 } else { bytes = _LCD1602_LINE2 } waitUntil (((millisOp) - _LCD1602_LOCK_MSECS) > 500) _LCD1602_LOCK_MSECS = (millisOp) local 'count' ((end - start) + 1) for i count { local 'char' 32 if (i <= (size string)) { char = ('[data:unicodeAt]' i string) if (char > 127) { char = 32 } } atPut ((start - 1) + i) bytes char } LCD1602_write_buffer line _LCD1602_LOCK_MSECS = 0 } to '_LCD1602 init' { comment 'Return true if already initialized' if (_LCD1602_ADDR != 0) { return true } comment 'Use slow I2C speed' '[sensors:i2cSetClockSpeed]' 100000 comment 'Try two common I2C addresses and use the one that gets a response' _LCD1602_ADDR = (hexToInt '27') if ((i2cGet _LCD1602_ADDR 0) < 0) { _LCD1602_ADDR = (hexToInt '3F') } if ((i2cGet _LCD1602_ADDR 0) < 0) { _LCD1602_ADDR = 0 comment 'LCD panel not found' return false } _LCD1602_LINE1 = ('[data:newByteArray]' 16 32) _LCD1602_LINE2 = ('[data:newByteArray]' 16 32) comment 'Initialize display' '_LCD1602 send' (hexToInt '33') 0 '_LCD1602 send' (hexToInt '32') 0 '_LCD1602 send' (hexToInt '06') 0 '_LCD1602 send' (hexToInt '0C') 0 '_LCD1602 send' (hexToInt '28') 0 '_LCD1602 send' (hexToInt '01') 0 '[sensors:i2cSetClockSpeed]' 400000 waitMillis 250 return true } to '_LCD1602 send' bits mode { comment 'Use slow I2C speed' '[sensors:i2cSetClockSpeed]' 100000 local '_LCD1602 BACKLIGHT' (hexToInt '8') local 'high bits' ((mode | (bits & (hexToInt 'F0'))) | (v '_LCD1602 BACKLIGHT')) local 'low bits' ((mode | ((bits << 4) & (hexToInt 'F0'))) | (v '_LCD1602 BACKLIGHT')) '[sensors:i2cWrite]' _LCD1602_ADDR (v 'high bits') '_LCD1602 toggle enable' (v 'high bits') '[sensors:i2cWrite]' _LCD1602_ADDR (v 'low bits') '_LCD1602 toggle enable' (v 'low bits') comment 'Revert to fast I2C speed' '[sensors:i2cSetClockSpeed]' 400000 waitMillis 1 } to '_LCD1602 toggle enable' bits { local '_LCD1602 ENABLE' 4 waitMicros 5 '[sensors:i2cWrite]' _LCD1602_ADDR (bits | (v '_LCD1602 ENABLE')) waitMicros 5 '[sensors:i2cWrite]' _LCD1602_ADDR (bits & ('~' (v '_LCD1602 ENABLE'))) waitMicros 5 } module NeoPixel Output author MicroBlocks version 1 14 description 'Control NeoPixel (WS2812) RGB LED strips and rings. ' variables _np_pixels _np_pin _np_haswhite spec ' ' 'neoPixelAttach' 'attach _ LED NeoPixel strip to pin _ : has white _' 'num auto bool' 10 '' false spec ' ' 'setNeoPixelColors10' 'set NeoPixels _ _ _ _ _ _ _ _ _ _' 'color color color color color color color color color color' spec ' ' 'setNeoPixelColors25' 'set NeoPixels #BR# _ _ _ _ _ #BR# _ _ _ _ _ #BR# _ _ _ _ _ #BR# _ _ _ _ _ #BR# _ _ _ _ _' 'color color color color color color color color color color color color color color color color color color color color color color color color color' spec ' ' 'clearNeoPixels' 'clear NeoPixels' spec ' ' 'neoPixelSetAllToColor' 'set all NeoPixels color _' 'color' spec ' ' 'setNeoPixelColor' 'set NeoPixel _ color _' 'num color' 1 space spec 'r' 'neoPixel_colorSwatch' '_' 'color' spec 'r' 'colorFromRGB' 'color r _ g _ b _ (0-255)' 'num num num' 0 100 100 spec 'r' 'randomColor' 'random color' space spec ' ' 'rotateNeoPixelsBy' 'rotate NeoPixels by _' 'auto' 1 space spec ' ' 'NeoPixel_brighten' 'brighten NeoPixel _ by _' 'num num' 1 10 spec ' ' 'NeoPixel_brighten_all' 'brighten all NeoPixels by _' 'num' 10 spec ' ' 'NeoPixel_shift_color' 'shift NeoPixel _ color by _' 'num num' 1 10 spec ' ' 'NeoPixel_shift_all_colors' 'shift all NeoPixel colors by _' 'num' 10 space spec ' ' '_NeoPixel_ensureInitialized' '_NeoPixel_ensureInitialized' spec ' ' '_NeoPixel_increaseRGB' '_NeoPixel_increaseRGB of _ by _' 'num num' 1 10 spec ' ' '_NeoPixel_rotate' '_NeoPixel_rotate_left _' 'bool' true spec ' ' '_NeoPixel_update' '_NeoPixel_update' spec ' ' '_NeoPixel_shift_hue' '_NeoPixel_shift_hue of _ by _' 'auto auto' '10' '10' to NeoPixel_brighten i delta { '_NeoPixel_increaseRGB' i delta '_NeoPixel_update' } to NeoPixel_brighten_all delta { for i (size _np_pixels) { '_NeoPixel_increaseRGB' i delta } '_NeoPixel_update' } to NeoPixel_shift_all_colors delta { for i (size _np_pixels) { '_NeoPixel_shift_hue' i delta } '_NeoPixel_update' } to NeoPixel_shift_color i delta { '_NeoPixel_shift_hue' i delta '_NeoPixel_update' } to '_NeoPixel_ensureInitialized' { if (_np_pixels == 0) {if (or ((boardType) == 'M5Atom-Matrix') (or ((boardType) == 'Mbits') ((boardType) == 'micro:STEAMakers'))) { neoPixelAttach 25 '' false } ((boardType) == 'D1-Mini') { comment 'D1 mini kit' neoPixelAttach 7 15 false } ((boardType) == 'FOXBIT') { neoPixelAttach 35 '' false } ((boardType) == 'CodingBox') { neoPixelAttach 35 '' false } else { neoPixelAttach 10 '' false }} } to '_NeoPixel_increaseRGB' i delta { if (or (i < 1) (i > (size _np_pixels))) {return} local 'rgb' (at i _np_pixels) if (rgb != 0) { local 'h' ('[misc:hue]' rgb) local 's' ('[misc:saturation]' rgb) local 'v' (('[misc:brightness]' rgb) + delta) v = (maximum 20 (minimum v 100)) atPut i _np_pixels ('[misc:hsvColor]' h s v) } } to '_NeoPixel_rotate' left { '_NeoPixel_ensureInitialized' local 'length' (size _np_pixels) if left { local 'first' (at 1 _np_pixels) for i (length - 1) { atPut i _np_pixels (at (i + 1) _np_pixels) } atPut length _np_pixels first } else { local 'last' (at length _np_pixels) for i (length - 1) { atPut ((length - i) + 1) _np_pixels (at (length - i) _np_pixels) } atPut 1 _np_pixels last } } to '_NeoPixel_shift_hue' i delta { if (or (i < 1) (i > (size _np_pixels))) {return} local 'rgb' (at i _np_pixels) if (rgb != 0) { local 'h' ((('[misc:hue]' rgb) + delta) % 360) local 's' ('[misc:saturation]' rgb) local 'v' ('[misc:brightness]' rgb) atPut i _np_pixels ('[misc:hsvColor]' h s v) } } to '_NeoPixel_update' { comment 'NeoPixel pin and hasWhite may have been changed by another library.' '[display:neoPixelSetPin]' _np_pin _np_hasWhite '[display:neoPixelSend]' _np_pixels waitMicros 300 } to clearNeoPixels { '_NeoPixel_ensureInitialized' atPut 'all' _np_pixels 0 '_NeoPixel_update' } to colorFromRGB r g b { r = (maximum 0 (minimum r 255)) g = (maximum 0 (minimum g 255)) b = (maximum 0 (minimum b 255)) return (((r << 16) | (g << 8)) | b) } to neoPixelAttach number pinNumber optionalHasWhite { _np_pin = pinNumber _np_hasWhite = false if ((pushArgCount) > 2) { _np_hasWhite = optionalHasWhite } if (or (_np_pixels == 0) (number != (size _np_pixels))) { _np_pixels = (newList number) } atPut 'all' _np_pixels 0 '[display:neoPixelSetPin]' _np_pin _np_hasWhite } to neoPixelSetAllToColor color { '_NeoPixel_ensureInitialized' atPut 'all' _np_pixels color '_NeoPixel_update' } to neoPixel_colorSwatch color { return color } to randomColor { local 'n1' (random 100 200) local 'n2' (random 0 100) if (1 == (random 1 3)) { return ((n1 << 16) | (n2 << 8)) } (1 == (random 1 2)) { return ((n2 << 16) | n1) } else { return ((n1 << 8) | n2) } } to rotateNeoPixelsBy n { '_NeoPixel_ensureInitialized' local 'rotateLeft' (n < 0) if (or ((boardType) == 'CircuitPlayground') ((boardType) == 'CircuitPlayground Bluefruit')) { rotateLeft = (n > 0) } repeat (absoluteValue n) { '_NeoPixel_rotate' rotateLeft } '_NeoPixel_update' } to setNeoPixelColor i color { '_NeoPixel_ensureInitialized' if (and (1 <= i) (i <= (size _np_pixels))) { atPut i _np_pixels color '_NeoPixel_update' } } to setNeoPixelColors10 c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 { '_NeoPixel_ensureInitialized' if ((size _np_pixels) >= 1) { atPut 1 _np_pixels c1 } if ((size _np_pixels) >= 2) { atPut 2 _np_pixels c2 } if ((size _np_pixels) >= 3) { atPut 3 _np_pixels c3 } if ((size _np_pixels) >= 4) { atPut 4 _np_pixels c4 } if ((size _np_pixels) >= 5) { atPut 5 _np_pixels c5 } if ((size _np_pixels) >= 6) { atPut 6 _np_pixels c6 } if ((size _np_pixels) >= 7) { atPut 7 _np_pixels c7 } if ((size _np_pixels) >= 8) { atPut 8 _np_pixels c8 } if ((size _np_pixels) >= 9) { atPut 9 _np_pixels c9 } if ((size _np_pixels) >= 10) { atPut 10 _np_pixels c10 } '_NeoPixel_update' } to setNeoPixelColors25 c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16 c17 c18 c19 c20 c21 c22 c23 c24 c25 { '_NeoPixel_ensureInitialized' if ((size _np_pixels) >= 1) { atPut 1 _np_pixels c1 } if ((size _np_pixels) >= 2) { atPut 2 _np_pixels c2 } if ((size _np_pixels) >= 3) { atPut 3 _np_pixels c3 } if ((size _np_pixels) >= 4) { atPut 4 _np_pixels c4 } if ((size _np_pixels) >= 5) { atPut 5 _np_pixels c5 } if ((size _np_pixels) >= 6) { atPut 6 _np_pixels c6 } if ((size _np_pixels) >= 7) { atPut 7 _np_pixels c7 } if ((size _np_pixels) >= 8) { atPut 8 _np_pixels c8 } if ((size _np_pixels) >= 9) { atPut 9 _np_pixels c9 } if ((size _np_pixels) >= 10) { atPut 10 _np_pixels c10 } if ((size _np_pixels) >= 11) { atPut 11 _np_pixels c11 } if ((size _np_pixels) >= 12) { atPut 12 _np_pixels c12 } if ((size _np_pixels) >= 13) { atPut 13 _np_pixels c13 } if ((size _np_pixels) >= 14) { atPut 14 _np_pixels c14 } if ((size _np_pixels) >= 15) { atPut 15 _np_pixels c15 } if ((size _np_pixels) >= 16) { atPut 16 _np_pixels c16 } if ((size _np_pixels) >= 17) { atPut 17 _np_pixels c17 } if ((size _np_pixels) >= 18) { atPut 18 _np_pixels c18 } if ((size _np_pixels) >= 19) { atPut 19 _np_pixels c19 } if ((size _np_pixels) >= 20) { atPut 20 _np_pixels c20 } if ((size _np_pixels) >= 21) { atPut 21 _np_pixels c21 } if ((size _np_pixels) >= 22) { atPut 22 _np_pixels c22 } if ((size _np_pixels) >= 23) { atPut 23 _np_pixels c23 } if ((size _np_pixels) >= 24) { atPut 24 _np_pixels c24 } if ((size _np_pixels) >= 25) { atPut 25 _np_pixels c25 } '_NeoPixel_update' } module 'RFID (RC522)' Input author MicroBlocks version 1 6 description 'Support for RC522 RFID card with I2C and SPI interfaces. Based on José Garcia RC522 MicroBlocks library which itself was based on: https://github.com/m5stack/UIFlow-Code/blob/master/units/_rfid.py and Arduino SPI Library: https://github.com/miguelbalboa/rfid/ Tested with: https://www.microcenter.com/product/639731/inland-ks0067-rc522-rfid-module-for-arduino https://techatronic.com/rfid-rc522-module-rfid-sensor-working-description/ https://shop.m5stack.com/products/rfid-unit-2-ws1850s https://shop.m5stack.com/products/rfid-sensor-unit ' variables _rc522_mode _rc522_i2cAddr _rc522_initialized _rc522_nssPin spec ' ' 'rc522_initialize_I2C' 'RC522 initialize I2C addr _' 'num' 40 spec ' ' 'rc522_initialize_SPI' 'RC522 initialize SPI ssPin _' 'num' 17 spec 'r' 'rc522_connected' 'RC522 is connected' space spec 'r' 'rc522_card_present' 'RC522 is card present' spec 'r' 'rc522_read_uid' 'RC522 card UID' space spec 'r' 'rc522_equal_ids' 'RC522 _ = _' 'auto auto' 'uid1' 'uid2' space spec ' ' '_rc522_antenna_on' '_rc522_antenna_on' spec 'r' '_rc522_request' '_rc522_request' spec 'r' '_rc522_send_to_card' '_rc522_send_to_card _ _' 'auto auto' 0 'list' spec ' ' '_rc522_bitset' '_rc522_bitset reg _ mask _' 'num num' 0 128 spec ' ' '_rc522_bitclear' '_rc522_bitclear reg _ mask _' 'num num' 0 128 spec 'r' '_rc522_read_reg' '_rc522_read_reg _' 'num' 55 spec ' ' '_rc522_write_reg' '_rc522_write_reg _ value _' 'num num' 1 15 to '_rc522_antenna_on' { local 'value' ('_rc522_read_reg' (hexToInt '14')) if (and (value >= 0) ((value & 3) != 3)) { '_rc522_write_reg' (hexToInt '14') (value | 3) } } to '_rc522_bitclear' reg mask { '_rc522_write_reg' reg (('_rc522_read_reg' reg) & ('~' mask)) } to '_rc522_bitset' reg mask { '_rc522_write_reg' reg (('_rc522_read_reg' reg) | mask) } to '_rc522_read_reg' reg { local 'result' 0 if ('SPI' == _rc522_mode) { digitalWriteOp _rc522_nssPin false spiSend (128 | (reg << 1)) result = (spiRecv) digitalWriteOp _rc522_nssPin true } ('I2C' == _rc522_mode) { result = (i2cGet _rc522_i2cAddr reg) } return result } to '_rc522_request' { '_rc522_write_reg' (hexToInt '0D') 7 return ('_rc522_send_to_card' (hexToInt '0C') ('[data:makeList]' (hexToInt '26'))) } to '_rc522_send_to_card' cmd send { '_rc522_write_reg' 2 ((hexToInt '77') | (hexToInt '80')) '_rc522_bitclear' (hexToInt '04') (hexToInt '80') '_rc522_bitset' (hexToInt '0A') (hexToInt '80') for i (size send) { '_rc522_write_reg' 9 (at i send) } '_rc522_write_reg' 1 cmd '_rc522_bitset' (hexToInt '0D') (hexToInt '80') waitMillis 10 '_rc522_bitclear' (hexToInt '0D') (hexToInt '80') local 'response' (newList 1) atPut 1 response (('_rc522_read_reg' 6) & (hexToInt '1B')) if ((at 1 response) == 0) { local 'n' ('_rc522_read_reg' (hexToInt '0A')) for i n { '[data:addLast]' ('_rc522_read_reg' 9) response } } return response } to '_rc522_write_reg' reg value { if ('SPI' == _rc522_mode) { digitalWriteOp _rc522_nssPin false spiSend (reg << 1) spiSend value digitalWriteOp _rc522_nssPin true } ('I2C' == _rc522_mode) { i2cSet _rc522_i2cAddr reg value } } to rc522_card_present { local 'res' ('_rc522_request') if ((at 1 res) == 0) { if ((size res) == 3) { return (booleanConstant true) } else { waitMillis 5 res = ('_rc522_request') return ((size res) == 3) } } else { return (booleanConstant false) } } to rc522_connected { local 'version' ('_rc522_read_reg' (hexToInt '37')) if (('[data:find]' version ('[data:makeList]' 21 136 144 145 146 178)) > 0) { return true } (version > 0) { sayIt 'Unknown RC522 Version:' version waitMillis 1000 return true } else { return false } } to rc522_equal_ids id1 id2 { if (or (id1 == 0) (id2 == 0)) {return (booleanConstant false)} if ((size id1) != (size id2)) {return (booleanConstant false)} for i (size id1) { if ((at i id1) != (at i id2)) {return (booleanConstant false)} } return (booleanConstant true) } to rc522_initialize_I2C i2cAddr { _rc522_mode = 'I2C' _rc522_i2cAddr = i2cAddr if (_rc522_initialized == 0) { _rc522_initialized = (booleanConstant true) '_rc522_write_reg' 1 (hexToInt 'F') waitMillis 50 '_rc522_write_reg' (hexToInt '2A') (hexToInt '80') '_rc522_write_reg' (hexToInt '2B') (hexToInt 'A9') '_rc522_write_reg' (hexToInt '2C') (hexToInt '03') '_rc522_write_reg' (hexToInt '2D') (hexToInt 'E8') '_rc522_write_reg' (hexToInt '15') (hexToInt '40') '_rc522_write_reg' (hexToInt '11') (hexToInt '3D') '_rc522_antenna_on' } } to rc522_initialize_SPI ssPin { _rc522_mode = 'SPI' _rc522_nssPin = ssPin if (_rc522_initialized == 0) { _rc522_initialized = (booleanConstant true) '_rc522_write_reg' 1 (hexToInt 'F') waitMillis 1 '_rc522_write_reg' (hexToInt '2A') (hexToInt '80') '_rc522_write_reg' (hexToInt '2B') (hexToInt 'A9') '_rc522_write_reg' (hexToInt '2C') (hexToInt '03') '_rc522_write_reg' (hexToInt '2D') (hexToInt 'E8') '_rc522_write_reg' (hexToInt '15') (hexToInt '40') '_rc522_write_reg' (hexToInt '11') (hexToInt '3D') '_rc522_antenna_on' } } to rc522_read_uid { if (rc522_card_present) { '_rc522_write_reg' (hexToInt '0D') 0 local 'res' ('_rc522_send_to_card' (hexToInt '0C') ('[data:makeList]' (hexToInt '93') (hexToInt '20'))) '[data:delete]' 1 res '[data:delete]' 'last' res return res } else { return ('[data:makeList]') } } module Servo Output author MicroBlocks version 1 4 tags servo motor angle rotation position description 'Control both positional (angle) and rotational servo motors. ' variables _servoPin _servoPulseWidth spec ' ' 'setServoAngle' 'set servo _ to _ degrees (-90 to 90)' 'num num' 1 90 spec ' ' 'setServoSpeed' 'set servo _ to speed _ (-100 to 100)' 'num num' 1 100 spec ' ' 'stopServo' 'stop servo _' 'num' 1 spec 'r' '_servoIndex' '_servoIndex _' 'num' 1 spec ' ' '_servoPulse' '_servoPulse pin _ usecs _' 'num num' 1 1500 spec ' ' '_servoUpdateLoop' '_servoUpdateLoop' to '_servoIndex' which { if (_servoPin == 0) { _servoPin = ('[data:makeList]') _servoPulseWidth = ('[data:makeList]') sendBroadcast '_servoUpdateLoop' } local 'i' ('[data:find]' which _servoPin) if (i < 0) { comment 'Add new pin' '[data:addLast]' which _servoPin '[data:addLast]' 1500 _servoPulseWidth i = (size _servoPin) } return i } to '_servoPulse' pin usecs { if (usecs == 0) { comment 'Servo stopped; do nothing' return 0 } usecs = (maximum 500 (minimum usecs 2900)) comment 'Split wait into a long wait followed by a wait of <= 30 usecs for greater accuracy' local 'endTime' ((microsOp) + usecs) digitalWriteOp pin true waitMicros (usecs - 30) waitMicros (endTime - (microsOp)) digitalWriteOp pin false } to '_servoUpdateLoop' { forever { if (_servoPin != 0) { comment 'If the _servoPin list is not 0, update the servos' for i (size _servoPin) { local 'pin' (at i _servoPin) local 'usecs' (at i _servoPulseWidth) if (and (pin >= 0) (usecs != 0)) { '_servoPulse' pin usecs } } waitMillis 15 } } } to setServoAngle which degrees optionalReverse { local 'reversed' false if ((pushArgCount) > 2) { reversed = optionalReverse } if reversed { degrees = (0 - degrees) } local 'pulseWidth' (1500 - (10 * degrees)) if ('[io:hasServo]') { '[io:setServo]' which pulseWidth } else { atPut ('_servoIndex' which) _servoPulseWidth pulseWidth } } to setServoSpeed which speed optionalReverse { local 'reversed' false if ((pushArgCount) > 2) { reversed = optionalReverse } if reversed { speed = (0 - speed) } local 'pulseWidth' (1500 - (10 * speed)) if ((absoluteValue speed) < 2) { pulseWidth = 0 } if ('[io:hasServo]') { '[io:setServo]' which pulseWidth } else { atPut ('_servoIndex' which) _servoPulseWidth pulseWidth } } to stopServo which { if ('[io:hasServo]') { '[io:setServo]' which 0 } else { atPut ('_servoIndex' which) _servoPulseWidth 0 } } module 'Smart Home' author 'Josep Ferràndiz & José García' version 1 2 depends 'LCD Display' 'Temperature Humidity (DHT11, DHT22)' Tone Servo NeoPixel 'RFID (RC522)' choices smarthome_notes c 'c#' d 'd#' e f 'f#' g 'g#' a 'a#' b choices smarthome_window open close choices smarthome_onoff on off choices smarthome_power 'voltage (V)' 'current (mA)' 'power (mW)' choices smarthome_lr 'shbutton;left' 'shbutton;right' choices smarthome_fan clockwise 'counter-clockwise' stop description 'Library for Keyestudio IoT Smart Home Kit for ESP32 STEAMakers Pin Connection Values ---------------------------------- Fan: -IN io18, +IN io19 Led: io12 Steam sensor: io34 NeoPixel (4 leds): io4 PIR: io14 Gas sensor: io23 Left button: io16 Right button: io27 DHT11: io17 Buzzer: io25 Servo (window): io5 Servo (door): io13 RFID: I2C LCD: I2C ----------------------------------- https://shop.innovadidactic.com/ca/standard-placas-shields-y-kits/1626-keyestudio-kit-smart-home-para-arduino-con-placa-esp32-steamakers-8436574314069.html https://www.keyestudio.com/products/keyestudio-esp32-smart-home-kit-for-esp32-diy-starter-kit-edu ' variables _smarthomeInitialized spec ' ' 'smarthome_setFan' 'Home fan _' 'menu.smarthome_fan' 'clockwise' spec ' ' 'smarthome_displayText' 'Home display _ in line _' 'str num' 'ESP32 Smart Home' 1 spec ' ' 'smarthome_setWindow' 'Home _ the window' 'menu.smarthome_window' 'open' spec ' ' 'smarthome_setDoor' 'Home activate the door' spec ' ' 'smarthome_playNote' 'Home play _ octave _ for _ ms' 'menu.smarthome_notes num num' 'c' 0 100 spec ' ' 'smarthome_setLight' 'Home set light _' 'menu.smarthome_onoff' 'on' space spec 'r' 'smarthome_temperature' 'Home temperature ºC' spec 'r' 'smarthome_humidity' 'Home humidity' spec 'r' 'smarthome_steamLevel' 'Home steam level' space spec 'r' 'smarthome_readRFID' 'Home read RFID card : _' 'bool' true spec 'r' 'smarthome_motion' 'Home movement detected?' spec 'r' 'smarthome_button' 'Home _ button pressed?' 'menu.smarthome_lr' 'shbutton;left' spec 'r' 'smarthome_gasDetected' 'Home gas detected?' space spec ' ' 'smarthome_setNeoPixels' 'Home set NeoPixels _ _ _ _' 'color color color color' spec ' ' 'smarthome_clearNeoPixels' 'Home clear NeoPixels' space spec 'r' 'smarthome_electricConsumption' 'Home electric consumption _' 'menu.smarthome_power' 'voltage (V)' to '_initialize' { if (not _smarthomeInitialized) { local '_pinBuzzer' 25 'attach buzzer to pin' _pinBuzzer local '_pinNeopixel' 4 neoPixelAttach 4 _pinNeopixel local '_addrRFID' 40 rc522_initialize_I2C _addrRFID _smarthomeInitialized = (booleanConstant true) } } to 'read samples' sampleCount pin { local 'sum' 0 repeat sampleCount { sum += (analogReadOp pin) } return (sum / sampleCount) } to smarthome_button button { if (button == 'shbutton;left') { local 'pin' 16 } (button == 'shbutton;right') { local 'pin' 27 } else { return false } return (not (digitalReadOp pin)) } to smarthome_clearNeoPixels { '_initialize' clearNeoPixels } to smarthome_displayText text line { LCD1602_write text line waitMillis 1000 for i ((size text) - 15) { LCD1602_write ('[data:copyFromTo]' text i (16 + i)) line waitMillis 350 } } to smarthome_electricConsumption magnitude { local '_pinVo' 36 local '_pinV' 39 local 'Vo' ('read samples' 500 _pinVo) local 'V' ('read samples' 500 _pinV) local 'Vout' ((V * 323) / 500) local 'Vsen' (Vo - V) local 'Iout' (Vsen * 17) local 'value' 0 if (magnitude == 'voltage (V)') { value = ('[data:join]' (Vout / 100) ',' (Vout % 100)) } if (magnitude == 'current (mA)') { value = Iout } if (magnitude == 'power (mW)') { value = (((Vout * 10) * Iout) / 1000) } return value } to smarthome_gasDetected { local '_pinGas' 23 return (not (digitalReadOp _pinGas)) } to smarthome_humidity { local '_pinDHT11' 17 return (humidity_DHT11 _pinDHT11) } to smarthome_motion { local '_pinPIR' 14 return (digitalReadOp _pinPIR) } to smarthome_playNote note octave time { '_initialize' 'play tone' note octave time } to smarthome_readRFID beep { '_initialize' if (rc522_card_present) { if beep {'play tone' 'c' 0 60} return (rc522_read_uid) } } to smarthome_setDoor { local '_pinServoDoor' 13 setServoAngle _pinServoDoor -90 waitMillis 1000 setServoAngle _pinServoDoor 90 waitMillis 1000 stopServo pin } to smarthome_setFan state { local '_pinFanPos' 19 local '_pinFanNeg' 18 if (state == 'clockwise') { digitalWriteOp _pinFanNeg true digitalWriteOp _pinFanPos false } if (state == 'counter-clockwise') { digitalWriteOp _pinFanNeg false digitalWriteOp _pinFanPos true } if (state == 'stop') { digitalWriteOp _pinFanNeg false digitalWriteOp _pinFanPos false } } to smarthome_setLight state { local '_pinLED' 12 if (state == 'on') { digitalWriteOp _pinLED true } if (state == 'off') { digitalWriteOp _pinLED false } } to smarthome_setNeoPixels c1 c2 c3 c4 { '_initialize' setNeoPixelColors10 c1 c2 c3 c4 (colorSwatch 35 190 30 255) (colorSwatch 35 190 30 255) (colorSwatch 35 190 30 255) (colorSwatch 35 190 30 255) (colorSwatch 35 190 30 255) (colorSwatch 35 190 30 255) } to smarthome_setWindow position { local '_pinServoWindow' 5 if (position == 'open') { setServoAngle _pinServoWindow -90 } if (position == 'close') { setServoAngle _pinServoWindow 90 } waitMillis 2000 } to smarthome_steamLevel { local '_pinSteam' 34 return (analogReadOp _pinSteam) } to smarthome_temperature { local '_pinDHT11' 17 return (temperature_DHT11 _pinDHT11) } module 'Temperature Humidity (DHT11, DHT22)' Input author MicroBlocks version 1 3 tags sensor dht11 dht22 temperature humidity description 'Support for the DHT11 and DHT22 environmental sensors. These sensors provide temperature and humidity readings. ' variables _dht_temperature _dht_humidity _dhtData _dhtLastReadTime data spec 'r' 'temperature_DHT11' 'temperature (Celsius) DHT11 pin _' 'auto' 4 spec 'r' 'humidity_DHT11' 'humidity DHT11 pin _' 'auto' 4 spec 'r' 'temperature_DHT22' 'temperature (Celsius) DHT22 pin _' 'auto' 4 spec 'r' 'humidity_DHT22' 'humidity DHT22 pin _' 'auto' 4 spec ' ' '_dhtReadData' '_dhtReadData pin _' 'auto any' 4 spec 'r' '_dhtChecksumOkay' '_dhtChecksumOkay' 'any' spec ' ' '_dhtUpdate' '_dhtUpdate _ isDHT11 _' 'auto bool any' 4 true spec 'r' '_dhtReady' '_dhtReady' 'any' spec ' ' '_dhtCaptureData' '_dhtCaptureData _' 'num' 4 to '_dhtCaptureData' pin { '[sensors:captureStart]' pin waitMillis 10 local 'pulses' ('[sensors:captureEnd]') local 'pulseCount' (size pulses) if (pulseCount < 80) { return 0 } (pulseCount > 80) { pulses = ('[data:copyFromTo]' pulses (pulseCount - 79)) } data = pulses local 'byte' 0 for i 40 { if ((at ((2 * i) - 1) pulses) > 40) { comment 'Long pulse - appends a "1" bit' byte += 1 } if ((i % 8) == 0) { atPut (i / 8) _dhtData byte byte = 0 } else { byte = (byte << 1) } } } to '_dhtChecksumOkay' { if (not (isType _dhtData 'list')) {return (booleanConstant false)} local 'checksum' 0 for i 4 { checksum += (at i _dhtData) } checksum = (checksum & 255) return (checksum == (at 5 _dhtData)) } to '_dhtReadData' pin { comment 'Create DHT data array the first time' if (_dhtData == 0) { _dhtData = (newList 5) } comment 'fill with 1''s set checksum will be bad if read fails' atPut 'all' _dhtData 1 comment 'Pull pin low for >18msec to request data' digitalWriteOp pin false waitMillis 20 local 'useDHTPrimitive' (booleanConstant true) if useDHTPrimitive { '_dhtCaptureData' pin return 0 } comment 'Read DHT start pulses (H L H L)' waitUntil (digitalReadOp pin) waitUntil (not (digitalReadOp pin)) waitUntil (digitalReadOp pin) waitUntil (not (digitalReadOp pin)) local 'i' 1 local 'byte' 0 local 'bit' 1 comment 'Read 40 bits (5 bytes)' repeat 40 { waitUntil (digitalReadOp pin) local 'start' (microsOp) waitUntil (not (digitalReadOp pin)) if (((microsOp) - start) > 40) { comment 'Long pulse - append a "1" bit' byte += 1 } if (bit == 8) { atPut i _dhtData byte i += 1 byte = 0 bit = 1 } else { byte = (byte << 1) bit += 1 } waitUntil (not (digitalReadOp pin)) } } to '_dhtReady' { local 'elapsed' ((millisOp) - _dhtLastReadTime) return (or (elapsed < 0) (elapsed > 2000)) } to '_dhtUpdate' pin isDHT11 { if ('_dhtReady') { _dht_temperature = 0 _dht_humidity = 0 '_dhtReadData' pin _dhtLastReadTime = (millisOp) } if ('_dhtChecksumOkay') { if isDHT11 { _dht_temperature = (at 3 _dhtData) _dht_humidity = (at 1 _dhtData) } else { local 'n' (((at 1 _dhtData) * 256) + (at 2 _dhtData)) _dht_humidity = ((n + 5) / 10) n = ((((at 3 _dhtData) & 127) * 256) + (at 4 _dhtData)) if (((at 3 _dhtData) & 128) != 0) { n = (0 - n) } _dht_temperature = ((n + 5) / 10) } } } to humidity_DHT11 pin { '_dhtUpdate' pin true return _dht_humidity } to humidity_DHT22 pin { '_dhtUpdate' pin false return _dht_humidity } to temperature_DHT11 pin { '_dhtUpdate' pin true return _dht_temperature } to temperature_DHT22 pin { '_dhtUpdate' pin false return _dht_temperature } module Tone Output author MicroBlocks version 1 10 tags tone sound music audio note speaker choices tone_NoteName 'nt;c' 'nt;c#' 'nt;d' 'nt;d#' 'nt;e' 'nt;f' 'nt;f#' 'nt;g' 'nt;g#' 'nt;a' 'nt;a#' 'nt;b' description 'Audio tone generation. Make music with MicroBlocks! ' variables _tonePin _toneInitalized _toneLoopOverhead _toneNoteNames _toneArezzoNotes _toneFrequencies spec ' ' 'play tone' 'play note _ octave _ for _ ms' 'str.tone_NoteName num num' 'nt;c' 0 500 spec ' ' 'playMIDIKey' 'play midi key _ for _ ms' 'num num' 60 500 spec ' ' 'play frequency' 'play frequency _ for _ ms' 'num num' 261 500 space spec ' ' 'startTone' 'start tone _ Hz' 'num' 440 spec ' ' 'stopTone' 'stop tone' space spec ' ' 'attach buzzer to pin' 'attach buzzer to pin _' 'auto' '' space spec 'r' '_measureLoopOverhead' '_measureLoopOverhead' spec 'r' '_baseFreqForNote' '_baseFreqForNote _' 'auto' 'c' spec 'r' '_baseFreqForSemitone' '_baseFreqForSemitone _' 'num' 0 spec ' ' '_toneLoop' '_toneLoop _ for _ ms' 'num num' 440000 100 spec 'r' '_trimmedLowercase' '_trimmedLowercase _' 'str' 'A. b C...' spec ' ' '_tone init note names' '_tone init note names' to '_baseFreqForNote' note { comment 'Return the frequency for the given note in the middle-C octave scaled by 1000. For example, return 440000 (440Hz) for A. Note names may be upper or lower case. Note names may be followed by # for a sharp or b for a flat.' local 'normalized note' ('_trimmedLowercase' note) 'normalized note' = (ifExpression ((at 1 (v 'normalized note')) == 'n') (v 'normalized note') ('[data:join]' 'nt;' (v 'normalized note'))) '_tone init note names' if (('[data:find]' (v 'normalized note') _toneArezzoNotes) > 0) { return ('_baseFreqForSemitone' ('[data:find]' (v 'normalized note') _toneArezzoNotes)) } else { return ('_baseFreqForSemitone' ('[data:find]' (v 'normalized note') _toneNoteNames)) } } to '_baseFreqForSemitone' semitone { if (_toneFrequencies == 0) {_toneFrequencies = ('[data:makeList]' 261626 277183 293665 311127 329628 349228 369994 391995 415305 440000 466164 493883 246942 277183 277183 311127 311127 349228 329628 369994 369994 415305 415305 466164 466164 523252)} if (and (1 <= semitone) (semitone <= (size _toneFrequencies))) { return (at semitone _toneFrequencies) } else { comment 'Bad note name; return 10 Hz' return 10000 } } to '_measureLoopOverhead' { comment 'Measure the loop overhead on this device' local 'halfCycle' 100 local 'startT' (microsOp) repeat 100 { digitalWriteOp _tonePin false waitMicros halfCycle digitalWriteOp _tonePin false waitMicros halfCycle } local 'usecs' ((microsOp) - startT) return ((usecs - 20000) / 200) } to '_tone init note names' { if (_toneNoteNames == 0) { _toneNoteNames = ('[data:makeList]' 'nt;c' 'nt;c#' 'nt;d' 'nt;d#' 'nt;e' 'nt;f' 'nt;f#' 'nt;g' 'nt;g#' 'nt;a' 'nt;a#' 'nt;b' 'nt;c_' 'nt;db' 'nt;d_' 'nt;eb' 'nt;e_' 'nt;e#' 'nt;f_' 'nt;gb' 'nt;g_' 'nt;ab' 'nt;a_' 'nt;bb' 'nt;b_' 'nt;b#') _toneArezzoNotes = ('[data:makeList]' 'nt;do' 'nt;do#' 'nt;re' 'nt;re#' 'nt;mi' 'nt;fa' 'nt;fa#' 'nt;sol' 'nt;sol#' 'nt;la' 'nt;la#' 'nt;si' 'nt;do_' 'nt;dob' 'nt;re_' 'nt;reb' 'nt;mi_' 'nt;mi#' 'nt;fa_' 'nt;solb' 'nt;sol_' 'nt;lab' 'nt;la_' 'nt;sib' 'nt;si_' 'nt;si#') } } to '_toneLoop' scaledFreq ms { if (_toneInitalized == 0) {'attach buzzer to pin' ''} if ('[io:hasTone]') { '[io:playTone]' _tonePin (scaledFreq / 1000) waitMillis ms '[io:playTone]' _tonePin 0 } else { local 'halfCycle' ((500000000 / scaledFreq) - _toneLoopOverhead) local 'cycles' ((ms * 500) / halfCycle) repeat cycles { digitalWriteOp _tonePin true waitMicros halfCycle digitalWriteOp _tonePin false waitMicros halfCycle } } } to '_trimmedLowercase' s { comment 'Return a copy of the given string without whitespace or periods and all lowercase.' local 'result' (newList (size s)) '[data:delete]' 'all' result for i (size s) { local 'ch' ('[data:unicodeAt]' i s) if (and (ch > 32) (ch != 46)) { if (and (65 <= ch) (ch <= 90)) {ch = (ch + 32)} '[data:addLast]' ch result } } return ('[data:unicodeString]' result) } to 'attach buzzer to pin' pinNumber { if (pinNumber == '') { comment 'Pin number not specified; use default pin for this device' if ((boardType) == 'Citilab ED1') { _tonePin = 26 } ((boardType) == 'M5Stack-Core') { _tonePin = 25 } ((boardType) == 'M5StickC') { _tonePin = 26 } ((boardType) == 'Calliope') { digitalWriteOp 23 true digitalWriteOp 24 true _tonePin = 25 } ((boardType) == 'D1-Mini') { _tonePin = 12 } ((boardType) == 'CodingBox') { _tonePin = 32 } else { _tonePin = -1 } } else { _tonePin = pinNumber } _toneLoopOverhead = ('_measureLoopOverhead') _toneInitalized = (booleanConstant true) } to 'play frequency' freq ms { '_toneLoop' (freq * 1000) ms } to 'play tone' note octave ms { local 'freq' ('_baseFreqForNote' note) if (freq <= 10000) { waitMillis ms return 0 } if (octave < 0) { repeat (absoluteValue octave) { freq = (freq / 2) } } repeat octave { freq = (freq * 2) } '_toneLoop' freq ms } to playMIDIKey key ms { local 'freq' ('_baseFreqForSemitone' ((key % 12) + 1)) local 'octave' ((key / 12) - 5) if (octave < 0) { repeat (absoluteValue octave) { freq = (freq / 2) } } repeat octave { freq = (freq * 2) } '_toneLoop' freq ms } to startTone freq { if (_toneInitalized == 0) {'attach buzzer to pin' ''} if ('[io:hasTone]') {'[io:playTone]' _tonePin freq} } to stopTone { startTone 0 }