{"id":19601603,"url":"https://github.com/alankrantas/microbit-micropython-cookbook","last_synced_at":"2025-04-27T17:32:01.156Z","repository":{"id":38824041,"uuid":"241393271","full_name":"alankrantas/microbit-micropython-cookbook","owner":"alankrantas","description":"Tricks and experiments using MicroPython on BBC micro:bit","archived":false,"fork":false,"pushed_at":"2024-08-18T02:34:44.000Z","size":2072,"stargazers_count":14,"open_issues_count":0,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-08-18T03:31:39.471Z","etag":null,"topics":["education","microbit","micropython","stem"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alankrantas.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-02-18T15:14:07.000Z","updated_at":"2024-08-18T02:34:47.000Z","dependencies_parsed_at":"2023-01-22T02:32:40.980Z","dependency_job_id":"7b8a0161-b929-4088-9db1-99dc2760d10b","html_url":"https://github.com/alankrantas/microbit-micropython-cookbook","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alankrantas%2Fmicrobit-micropython-cookbook","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alankrantas%2Fmicrobit-micropython-cookbook/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alankrantas%2Fmicrobit-micropython-cookbook/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alankrantas%2Fmicrobit-micropython-cookbook/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alankrantas","download_url":"https://codeload.github.com/alankrantas/microbit-micropython-cookbook/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224076396,"owners_count":17251745,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["education","microbit","micropython","stem"],"created_at":"2024-11-11T09:19:04.488Z","updated_at":"2024-11-11T09:19:05.298Z","avatar_url":"https://github.com/alankrantas.png","language":"Python","readme":"# micro:bit V2 MicroPython Cookbook\n\n![1](https://user-images.githubusercontent.com/44191076/79871966-c0ae8b00-8417-11ea-8255-cbc681d12b8d.jpg)\n\nThis is the collection of notes, tricks and experiments on BBC micro:bit V2 and MicroPython. Many examples work on micro:bit V1 but I no longer test on them.\n\n- [Official micro:bit Python editor](https://python.microbit.org/v/3)\n- [BBC micro:bit V2 MicroPython documentation](https://microbit-micropython.readthedocs.io/en/v2-docs/index.html)\n\nAlso there are a few projects:\n\n* Simon Says game ([link](https://github.com/alankrantas/microbit-micropython-cookbook/tree/master/simon_game))\n* Shake It game ([link](https://github.com/alankrantas/microbit-micropython-cookbook/tree/master/shake_it))\n* Simple micro:bit RC Car ([link](https://github.com/alankrantas/microbit-micropython-cookbook/tree/master/rc_car))\n\n---\n\n## About micro:bit's MicroPython\n\nmicro:bit's MicroPython is developed by [Damien George](https://github.com/dpgeorge), after the initial effort to [bring Python onto micro:bit](https://ntoll.org/article/story-micropython-on-microbit/) failed. Damien George developed the original [MicroPython](https://micropython.org/) in 2013, which also has a derived version: Adafruit's [CircuitPython](https://circuitpython.org/).\n\nAll MicroPython variants are based on standard Python or CPython `3.4`, while the other MicroPython versions incorporated a few features from newer Python. Unlike the [\"fake\" Python in the MakeCode editor](https://makecode.com/python), these are actual Python interpreters with full language syntax support, all basic built-ins along with a few special modules for the microcontrollers. On the other hand, most of the built-in modules are not available due to the hardware limitation. Not that we'll need them a lot for STEM education anyway.\n\nAs Python is a dynamic interpreted language, it is slower than compiled languages like C++ and requires more memory, although on micro:bit V2s (with 128 KB RAM instead of 16 KB of V1s) this is no longer a big issue. With 512 KB flash onboard, you can actually write and store some text data as well!\n\nThe firmware - the MicroPython interpreter - will be flashed onto the micro:bit when you upload the code for the first time. Actually, the firmware and the script will be [bundled together as a single .hex file](https://tech.microbit.org/software/hex-format/) to be uploaded into the [DAPLink interface](https://tech.microbit.org/software/daplink-interface/), which creates a fake \"USB drive\" on your computer. If the firmware is present, only the user script needs to be updated.\n\n## Ask Help From REPL\n\nREPL (Read-Evaluate-Print-Loop) or \"serial\" in the official editor is a very useful tool, although it is in fact the command line interface of the MicroPython interpreter, for witch you can test an expression (like `1 + 1`) or a statement (like `print(1 + 1)`). And here's some basic things you can do with it.\n\nIn the official Python editor, first connect your micro:bit, then open \"serial\". If there are code running onboard and the interpreter does not respond, press `Ctrl` + `C` to force the code to stop. (You can also press `Ctrl` + `D` to have the board restart and run the code again.)\n\nGet basic help information from REPL:\n\n```\n\u003e help()\n```\n\nList all built-in MicroPython modules:\n\n```\n\u003e help('modules')\n```\n\nTo see what's inside a module or submodule/function/attribute (has to be imported first):\n\n```\n\u003e import microbit\n\u003e help(microbit)\n\u003e help(microbit.pin0)\n\u003e dir(microbit)\n\u003e dir(microbit.pin0)\n```\n\n## Easter Eggs\n\nTry to type these in the REPL:\n\n```\n\u003e import this\n\u003e import antigravity\n\u003e import love\n```\n\n\u003cdetails\u003e\n    \u003csummary\u003eReference\u003c/summary\u003e\n\n- `import this` prints out \"The Zen of MicroPython\", which is a short version of [The Zen of Python](https://peps.python.org/pep-0020/) in CPython.\n- `import antigravity` prints out a text version of [this comic about Python 2](https://xkcd.com/353/); in CPython it will directly open the URL of that comic.\n    \n\u003c/details\u003e\n\n## Import * is a Bad Idea\n\nIn a lot of examples you may see\n\n```python\nfrom microbit import *\n```\n\nWhich means to import everything under \"microbit\" so you can use them without using ```microbit.something```.\n\nImport normally does not \"read\" a module or function into memory; what it really does is to add variables pointing to all the stuff under module \"microbit\". (The exceptions are some C++ based Python packages which have to be loaded upon being imported, which are common among data science packages, but there is no way to install these on the micro:bits anyway.)\n\nBut using * to import everything is still a bad practice. If you do this in standard Python, you might accidentally import things with conflicted names. Instead, you *should always* explicitly import what you need:\n\n```python\nfrom microbit import pin0, display, sleep\n```\n\n## How Much Memory Left?\n\n```python\nfrom micropython import mem_info\n\nprint(mem_info(1))\n```\n\nYou can also use garbage collection to free some memory if possible (it's not magic after all):\n\n```python\nimport gc\n\ngc.enable()  # enable automatic memory recycle\ngc.collect()  # force memory recycle\n```\n\n## Write and Read Text Files\n\nData can be preserved as files onboard until a new script is flashed onto it, although there is no way to download files\n\nWrite several lines into a file (will be created if not exist):\n\n```python\ndata = [\n    'line 1',\n    'line 2',\n    'line 3'\n]\n\nwith open(r'file.txt', 'w') as file:\n    file.write('\\n'.join(data))\n```\n\nRead content of a file:\n\n```python\ncontent = ''\nwith open(r'file.txt') as file:\n    content = file.read()\nprint(content)\n```\n\nList files using REPL:\n\n```\n\u003e\u003e\u003e import os\n\u003e\u003e\u003e os.listdir()\n```\n\nDelete file using REPL:\n\n```\n\u003e\u003e\u003e os.remove('file.txt')\n```\n\n### Classic Blinky (LED screen)\n\n```python\nfrom microbit import display, Image, sleep\n\nwhile True:\n    display.show(Image.HEART)\n    sleep(1000)\n    display.clear()\n    sleep(1000)\n```\n\n## Classic Blinky (LED on pin 0)\n\nThis version controls an external LED connected between pin 0 and GND and uses ```time.sleep()``` module instead of ```microbit.sleep()```.\n\nMost LEDs are anode so connect the longer leg to [micro:bit's pin 0](https://makecode.microbit.org/device/pins) and the shorter leg to GND pin, either using crocodile clip wires or a edge connector, two jumper wires and a breadboard.\n\n```python\nfrom microbit import pin0\nimport time\n\nwhile True:\n    pin0.write_digital(1)\n    time.sleep(0.5)\n    pin0.write_digital(0)\n    time.sleep(0.5)\n```\n\nNote: for both micro:bit V1/V2 you don't really need a resistor to protect the LED. The voltage and current from any pins (except the 3V pin) are low enough to cause real harms.\n\n## Blinky LEDs Without Using Sleep\n\nUsing the ```time``` module to make two LEDs on the LED screen blink asynchronously at different intervals in the same loop.\n\n```python\nfrom microbit import display\nimport time\n\ndelay1, delay2 = 500, 400\nsince1, since2 = time.ticks_ms(), time.ticks_ms()\n\n\nwhile True:\n    \n    now = time.ticks_ms()\n    \n    if time.ticks_diff(now, since1) \u003e= delay1:  # toogle LED (0, 0)\n        display.set_pixel(0, 0, 9 if display.get_pixel(0, 0) == 0 else 0)\n        since1 = time.ticks_ms()\n    \n    if time.ticks_diff(now, since2) \u003e= delay2:  # toogle LED (4, 4)\n        display.set_pixel(4, 4, 9 if display.get_pixel(4, 4) == 0 else 0)\n        since2 = time.ticks_ms()\n```\n\n## A More Convenient Pin Class?\n\nDefine a Pin class to wrap existing pin methods.\n\n```python\nfrom microbit import pin1, pin2, sleep\n\nclass Pin:\n    \n    __slots__ = ['pin']  # not to use dictionary to store attributes in the class to save memory\n    \n    def __init__(self, pin):\n        self.pin = pin\n    \n    def setPin(self, value):\n        self.pin.write_digital(value)\n    \n    def setPWM(self, value):\n        self.pin.write_analog(value)\n    \n    def getPin(self):\n        self.pin.set_pull(self.pin.NO_PULL)\n        return self.pin.read_digital()\n        \n    def getADC(self):\n        try:\n            return self.pin.read_analog()\n        except:\n            return 0\n    \n    def isPressed(self):\n        self.pin.set_pull(self.pin.PULL_UP)\n        return not self.pin.read_digital()\n        \n    def isTouched(self):  # for pin_logo\n        try:\n            self.pin.set_pull(self.pin.NO_PULL)\n            return self.pin.is_touched()\n        except:\n            return False\n\n\nled = Pin(pin1)  # external led at pin 1\nbutton = Pin(pin2)  # external button at pin 2\n\nwhile True:\n    # light up LED when button is pressed\n    led.setPin(button.isPressed())\n    sleep(50)\n```\n\nSee the following link for available pin functions:\n\n* [micro:bit pins](https://makecode.microbit.org/device/pins)\n* [Edge Connector Pins](https://tech.microbit.org/hardware/edgeconnector/#edge-connector-pins)\n* [pin functions in MicroPython](https://microbit-micropython.readthedocs.io/en/v2-docs/pin.html#pin-functions)\n\nThe class would set internal pull-up for reading button status with ```isPressed()```. The buttons can be connected to one pin and GND without physical resistors. The onboard A/B buttons already have built-in resistors.\n\nFor controlling external LEDs, it is recommended to add a resistor (at least 220Ω for micro:bit V1 and 100Ω for V2) between the micro:bit pin and the LED anode leg.\n\n## Simpler Alternate Pin Class\n\nUse **namedtuple** (a tuple that elements have attribute names) as a simple Pin class. We point the pin methods to these attributes.\n\n```python\nfrom microbit import pin1, pin2, sleep\nfrom ucollections import namedtuple\n\nPin = namedtuple('Pin', ['setPin', 'setPWM', 'getPin', 'getADC', 'isTouched'])\n\ndef newPin(pin, pull_up=False):\n    pin.set_pull(pin.PULL_UP if pull_up else pin.NO_PULL)\n    return Pin(pin.write_digital, pin.write_analog, pin.read_digital, pin.read_analog, pin.is_touched)\n\n\nled = newPin(pin1)\nbutton = newPin(pin2, pull_up=True)\n\nwhile True:\n    led.setPin(not button.getPin())\n    sleep(50)\n```\n\n## Value Mapping\n\nTranslate a value in a range to its corresponding value in anoher range, similar to **map()** in Arduino or micro:bit MakeCode. Borrowed from [here](https://stackoverflow.com/questions/1969240/mapping-a-range-of-values-to-another).\n\n```python\nfrom microbit import display, sleep\n\ndef translate(value, leftMin, leftMax, rightMin, rightMax):\n    leftSpan = leftMax - leftMin\n    rightSpan = rightMax - rightMin\n    valueScaled = float(value - leftMin) / float(leftSpan)\n    return rightMin + (valueScaled * rightSpan)\n\n\nwhile True:\n    lightLevel = display.read_light_level()\n    print(translate(lightLevel, 0, 255, 0, 1023))  # map value range 0-255 to 0-1023\n    sleep(100)\n```\n\n## Roll a Dice\n\nDefine dice images in a dictionary, and retrieve one using a random number when the shake gesture detected.\n\n```python\nfrom microbit import display, Image, accelerometer, sleep\nfrom random import randint\n\ndice = {  # dictionary of 5x5 dice images\n    1: '00000:00000:00900:00000:00000',\n    2: '90000:00000:00000:00000:00009',\n    3: '90000:00000:00900:00000:00009',\n    4: '90009:00000:00000:00000:90009',\n    5: '90009:00000:00900:00000:90009',\n    6: '90009:00000:90009:00000:90009',\n    }\n\nwhile True:\n    if accelerometer.was_gesture('shake'):  # if user has shaked micro:bit\n        display.show(Image(dice[randint(1, 6)]))  # get a image in random\n```\n\n## Fill LED Display\n\nLight up every LEDs in a specific brightness level (default max):\n\n```python\nfrom microbit import display, Image, sleep\n\ndef fillScreen(b=9):  # fill screen function, b = brightness (0-9)\n    display.show(Image(':'.join([str(b) * 5] * 5)))\n\n\nwhile True:\n    # blink screen twice\n    for _ in range(2):\n        fillScreen()  # default = max brightness\n        sleep(250)\n        display.clear()\n        sleep(250)\n    \n    sleep(500)\n    \n    # fade in\n    for i in range(10):\n        fillScreen(i)\n        sleep(75)\n    \n    # fade out\n    for i in reversed(range(10)):\n        fillScreen(i)\n        sleep(75)\n        \n    sleep(500)\n```\n\n## LED Bar Graph\n\nA 25-level LED progress bar, similar to the one you can use in the MakeCode JavaScript editor.\n\n```python\nfrom microbit import display, Image, sleep\n\ndef plotBarGraph(value, max_value, b=9):\n    order = (23, 21, 20, 22, 24,\n             18, 16, 15, 17, 19,\n             13, 11, 10, 12, 14,\n             8, 6, 5, 7, 9,\n             3, 1, 0, 2, 4,)\n    counter = 0\n    display.clear()\n    for y in range(5):\n        for x in range(5):\n            if value / max_value \u003e order[counter] / 25:\n                display.set_pixel(x, y, b)\n            counter += 1\n\nwhile True:\n    plotBarGraph(display.read_light_level(), 255)\n    sleep(50)\n```\n\nThe LED screen may flicker since ```read_light_level()``` uses LEDs themselves as light sensors (see [this video](https://www.youtube.com/watch?v=TKhCr-dQMBY) for explanation).\n\n## Tiny Two-Digit Display\n\nDisplay two 2x5 digits (range 0~99) on the 5x5 matrix. This is very similar to a MakeCode extension.\n\n```python\nfrom microbit import display, Image, sleep, temperature\n\ndigits = {\n    '0': ('99', '99', '99', '99', '99'),\n    '1': ('09', '09', '09', '09', '09'),\n    '2': ('99', '09', '99', '90', '99'),\n    '3': ('99', '09', '99', '09', '99'),\n    '4': ('90', '90', '99', '09', '09'),\n    '5': ('99', '90', '99', '09', '99'),\n    '6': ('90', '90', '99', '99', '99'),\n    '7': ('99', '09', '09', '09', '09'),\n    '8': ('99', '99', '00', '99', '99'),\n    '9': ('99', '99', '99', '09', '09'),\n    ' ': ('00', '00', '00', '00', '00'),\n}\n\ndef showDigits(value, b=9, fill_zero=False):\n    value = min(max(value, 0), 99)\n    d = ('{:02d}' if fill_zero else '{:2d}').format(value)\n    return Image(':'.join(\n        ['{}0{}'.format(digits[d[0]][i], digits[d[1]][i]).replace('9', str(b)) \n         for i in range(5)]))\n\n\nwhile True:\n    display.show(showDigits(temperature(), fill_zero=True))\n    sleep(1000)\n```\n\nIn ```showDigits()```, parameter b is brightness (0~9) and fill_zero=True means numbers smaller than 10 will be displayed as 01, 02, 03...\n\n## Get Pitch and Roll Degrees\n\nThis is another functionality exists in MakeCode but not in MicroPython. Be noted that the results would be outputed in the REPL console and it's +-180 decrees instead of 360 degrees.\n\n```python\nfrom microbit import accelerometer, sleep\nfrom math import pi, atan2, sqrt\n\ndef rotationPitch():\n    return atan2(\n            accelerometer.get_y(), \n            sqrt(accelerometer.get_x() ** 2 + accelerometer.get_z() ** 2)\n            ) * (180 / pi)\n\ndef rotationRoll():\n    return atan2(\n            accelerometer.get_x(), \n            sqrt(accelerometer.get_y() ** 2 + accelerometer.get_z() ** 2)\n            ) * (180 / pi)\n\n\nwhile True:\n    print('Pitch:', rotationPitch(), ' / roll:', rotationRoll())\n    sleep(100)\n```\n\n## Servo Control\n\nBe noted that a SG90 hobby servo comsumes a few hundred mA and the 3.3V pin from micro:bit V1 (90 mA) is barely enough. Use an external 5V power instead, or use micro:bit V2 (200 mA at 3.3V pin).\n\n```python\nfrom microbit import pin0, sleep\n\nclass Servo:  # define a servo class\n    def __init__(self, pin, degree=90):\n        self.pin = pin\n        self.degree = degree\n        self.write(degree)\n    \n    def write(self, degree):\n        self.pin.set_analog_period(20)\n        self.pin.write_analog(round((degree * 92 / 180 + 30), 0))\n\n\nservo = Servo(pin0)  # servo object\n\nwhile True:\n    servo.write(0)\n    sleep(1000)\n    servo.write(180)\n    sleep(1000)\n```\n\nDo not use servos and buzzers at the same time. They require different PWM frequencies and most microcontrollers can only use one frequency accross all pins at a time.\n\nmicro:bit V2 can output 190 mA from its 3V pin, which is enough for most hobby servos.\n\n## NeoPixel Rainbow/Rotation Effect\n\nThis code is based on Adafruit's example with adjustable brightness level. Change the NeoPixel (WS281x) data pin from pin0 to other pins if needed. (You can power the LED strips with 3.3V pin, although V1 can output less power than V2. One NeoPixel LED at full power may comsume as much as 50 mA. Running in low light level is recommended.)\n\n```python\nfrom microbit import pin0, sleep  # connect to pin 0\nfrom neopixel import NeoPixel\nfrom micropython import const\n\nled_num      = const(12)  # number of NeoPixels\nled_maxlevel = const(64)  # light level (0-255)\nled_delay    = const(5)   # NeoPixels cycle delay\n\nnp = NeoPixel(pin0, led_num)\n\ndef wheel(pos):\n    r, g, b = 0, 0, 0\n    if pos \u003c 0 or pos \u003e 255:\n        r, g, b = 0, 0, 0\n    elif pos \u003c 85:\n        r, g, b = 255 - pos * 3, pos * 3, 0\n    elif pos \u003c 170:\n        pos -= 85\n        r, g, b = 0, 255 - pos * 3, pos * 3\n    else:\n        pos -= 170\n        r, g, b = pos * 3, 0, 255 - pos * 3\n    r = round(r * led_maxlevel / 255)\n    g = round(g * led_maxlevel / 255)\n    b = round(b * led_maxlevel / 255)\n    return (r, g, b)\n\ndef rainbow_cycle(pos):\n    for i in range(led_num):\n        rc_index = (i * 256 // led_num) + pos\n        np[i] = wheel(rc_index \u0026 255)\n    np.show()\n    \n\npos = 0\nwhile True:\n    rainbow_cycle(pos)\n    pos = (pos + 1) % 255\n    sleep(led_delay)\n```\n\n### Calcualte Fibonacci Sequence\n\n[Fibonacci sequence](https://en.wikipedia.org/wiki/Fibonacci_number)\n\n```python\nfrom microbit import display\n\ndef Fibonacci(n):  # calculate nth number\n    a = 0\n    b = 1\n    for i in range(n - 2):\n        a, b = b, a + b\n    return b\n\nf = Fibonacci(42)\nprint(f)\ndisplay.scroll(f)\n```\n\nBelow is the recursive version, which is a lot slower and you may get ```RuntimeError: maximum recursion depth exceeded``` for a bigger number, especially in micro:bit V1.\n\n```python\nfrom microbit import display\n\ndef Fibonacci(n):\n    if n \u003c 2:\n        return n\n    return Fibonacci(n - 1) + Fibonacci(n - 2)\n\n\nf = Fibonacci(24)\nprint(f)\ndisplay.scroll(f)\n```\n\n### Calcuate a List of Prime Numbers\n\nPrime numbers (except 2, 3) are either 6n - 1 or 6n + 1. So we check if a number of 6n - 1/6n + 1 can be divided with any existing primes in the list. If not, it is a prime number and can be added to the list.\n\n```python\nfrom microbit import display\n\ndef find_primes(n):  # calculate primes up to n\n    primes = [2, 3]\n    for p in range(6, n + 1, 6):\n        for p_test in range(p - 1, p + 2, 2):\n            for prime in primes:\n                if p_test % prime == 0:\n                    break\n            else:  # only execute when for is not exited by break\n                primes.append(p_test)\n    return primes\n\nprimes = find_primes(50)\nprint(primes)\nfor prime in primes:\n    display.scroll(prime)\n```\n\n## Morse Code Machine\n\nThis allows you to enter your message into micro:bit and convert it to Morse code with the LED screen and buzzer. Go to the REPL mode and you'll see the prompt.\n\n```python\nfrom microbit import display, Image, set_volume, sleep\nfrom micropython import const\nimport music\n\nset_volume(255)  # speaker volume (0-255)\nmorse_delay = const(75)  # morse code delay speed\n\n# morse code table\nmorse_code = {\n    'A': '.-',\n    'B': '-...',\n    'C': '-.-.',\n    'D': '-..',\n    'E': '.',\n    'F': '..-.',\n    'G': '--.',\n    'H': '....',\n    'I': '..',\n    'J': '.---',\n    'K': '-.-',\n    'L': '.-..',\n    'M': '--',\n    'N': '-.',\n    'O': '---',\n    'P': '.--.',\n    'Q': '--.-',\n    'R': '.-.',\n    'S': '...',\n    'T': '-',\n    'U': '..-',\n    'V': '...-',\n    'W': '.--',\n    'X': '-..-',\n    'Y': '-.--',\n    'Z': '--..',\n    '1': '.----',\n    '2': '..---',\n    '3': '...--',\n    '4': '....-',\n    '5': '.....',\n    '6': '-....',\n    '7': '--...',\n    '8': '---..',\n    '9': '----.',\n    '0': '-----',\n}\n    \nwhile True:\n    \n    print('Enter your message: (Press enter to exit)')\n    msg_str = input('\u003e ').upper()\n    if not msg_str:\n        break\n    \n    morse_str = ''.join([morse_code[s] for s in msg_str\n                         if s in morse_code])\n    print('Message converted:\\n', morse_str)\n    \n    for code in morse_str:\n        music.pitch(392)\n        display.show(Image.TARGET)\n        sleep(morse_delay * (3 if code == '-' else 1))\n        music.stop()\n        display.clear()\n        sleep(morse_delay)\n    \n    print('')\n```\n\n## Text-based Group Chat\n\nLoad the code to at multiple micro:bits, each connected to a computer and enter the REPL mode. They will display any messages (250 characters max each) sent by other micro:bits on the same channel.\n\nIn order to send message, press A and enter text after the prompt. (Some incoming messages may be lost when you are typing. So you can also treat this as actual radio and use [procedure words](https://en.wikipedia.org/wiki/Procedure_word).)\n\n```python\nRADIO_CHANNEL = 42\n\nfrom microbit import display, Image, button_a, sleep\nimport radio\n\nradio.config(group=RADIO_CHANNEL, length=250, power=7)\nradio.on()\n\nprint('Receiving messages...')\nprint('Press A to send your message (max 250 characters each)')\ndisplay.show(Image.RABBIT)\n\nwhile True:\n    \n    if button_a.is_pressed():\n        text = input('Enter your message: ')\n        if len(text) \u003e 0 and len(text.strip()) \u003e 0:\n            to_be_send = text.strip()[:250]\n            radio.send(to_be_send)\n            print('YOU:', to_be_send)\n        else:\n            sleep(100)\n    \n    incoming = radio.receive()\n    if incoming != None:\n        print('MESSAGE:', incoming)\n        \n    sleep(50)\n```\n\n## Radio Proximity Sensor\n\nLoad the code to two micro:bits. They will detect each other's radio signal strength and show it as LED bar graph. Can be used as an indoor treasure hunt game.\n\n(This also works for micro:bit V1, however V1 is slower so there will be signal gap received by V2. So in order to mix V1 and V2, You'll have to either speed up V1 or slow down V2 loop delay.)\n\nDue to some reason, the signal strength or RSSI changes very little regardless of transmite power. So I roughly remapped the value to 0-60 so that you can see the changes more clearly.\n\nIf there's no signal received the strength data would be set as zero.\n\n```python\nRADIO_CHANNEL = 42\n\nfrom microbit import display, sleep\nimport radio\n\ndef plotBarGraph(value, max_value, b=9):\n    order = (23, 21, 20, 22, 24,\n             18, 16, 15, 17, 19,\n             13, 11, 10, 12, 14,\n             8, 6, 5, 7, 9,\n             3, 1, 0, 2, 4,)\n    counter = 0\n    display.clear()\n    for y in range(5):\n        for x in range(5):\n            if value / max_value \u003e order[counter] / 25:\n                display.set_pixel(x, y, b)\n            counter += 1\n\n\nradio.config(group=RADIO_CHANNEL, power=7)\nradio.on()\n\nwhile True:\n    \n    radio.send('0')\n    strength = 0.0\n    data = radio.receive_full()\n    \n    if data:\n        strength = data[1] + 255 - 155\n    \n    print('Signal strength:', strength)\n    plotBarGraph(strength, 60)\n    sleep(50)\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falankrantas%2Fmicrobit-micropython-cookbook","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falankrantas%2Fmicrobit-micropython-cookbook","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falankrantas%2Fmicrobit-micropython-cookbook/lists"}