About this project
The Micro Python project can be found at micropython.org
The Micro Python project has been Kick-started! Thanks to all backers! You can find the project, including the software and hardware, at micropython.org.
We have passed the initial funding goal of £15,000!
We have passed the first stretch goal of £40,000! This means that Wi-Fi will be supported via a CC3000 module. Micro Python will include a library which allows you to connect to the internet via wi-fi. For this to work, you will need to add a CC3000 wi-fi module. This module connects via SPI pins to the Micro Python board.
We have passed the second stretch goal of £50,000! This means that Ethernet will be supported via a WIZ820io module. Similar to the CC3000 module, you connect the WIZ820io module via SPI to the Micro Python board, and access it through a library.
We have passed the third stretch goal of £60,000! This means that there will be support for the NRF24L01+ low-power wireless module. Again, this will be library support.
What is Micro Python?
Micro Python is a lean and fast implementation of the Python programming language (python.org) that is optimised to run on a microcontroller. The Micro Python board is a small electronic circuit board that runs the Micro Python language. The aim of this Kickstarter campaign is to make Micro Python open source software so you can use it in your own projects, and also to fund a small manufacturing run of Micro Python boards so that you can own one for yourself!
Python is a scripting language that is very easy to learn, yet highly expressive and very powerful, and has a huge existing community. Running on a small microcontroller, Micro Python allows you to effortlessly blink LEDs, read voltages, make motors and servos move, play sounds, write data to SD cards, communicate wirelessly, and be the brains of your robot, among countless other things. It is the perfect choice to control your next project!
When building an electronics project, like an intruder detector or a smart robot, a microcontroller is used as the "brain", and does all the decision making and control. There are two kinds of things that a microcontroller typically needs to do. It must do low-level control of lights, LCD displays, motors, etc, as well as high-level tasks such as reading and writing data and images, communicating wirelessly, and being an artificial intelligence. Micro Python allows you to do both low-level and high-level control, by augmenting the Python language with inline assembler and native types, as described below.
How do I use it?
The Micro Python board comes preinstalled with Micro Python and is suitable for everyone, whether a beginner or an expert robot builder. It requires no set-up, no compiling and no soldering, and if you don't know Python it is very easy to learn the language.
You plug the board into your PC (Windows, Mac and Linux all work) using a USB cable. It then acts just like a USB flash drive.
To control servo motors, it is a simple as writing the following code:
Put this code in a text file and copy it to the Micro Python USB flash drive, press the reset button on the board and it will run! You can also open a terminal emulator (freely available for Windows, Mac and Linux) to connect to the board over USB and type these commands directly to the board (which gives you a Python command line), and it will run them as soon as you press the enter key.
To flash an LED once a second, you could use the following code:
To read the accelerometer and print out the x-axis value:
You have the full Python programming language at your disposal, and can write functions and classes, make lists and dictionaries, do string processing, read and write files (to the SD card or built-in flash storage), and have more sophisticated features such as generators, closures, list comprehension and exception handling. The possibilities for programming are endless!
The board has many input/output pins which can be connected to other circuits, and you can solder on wires to make it part of your own project. The board can run without a PC, as long as it is connected to a battery or other power supply between 3.6V and 10V.
Some of the rewards on offer include a kit of parts with the Micro Python board. These kits allow you to get started programming and building things straight away. There will be a set of online instructions explaining exactly how to get it all working, and detailing some example projects. Even with just the Micro Python board on its own you can still do some pretty nifty things, such as logging accelerometer data, making a Python USB mouse, and using the USB serial Python command line. These projects will also be explained online for you to follow.
You may be wondering how the Micro Python board compares with other, similar boards. Compared with an Arduino, the Micro Python board is more powerful, easier to program, and you don't need a compiler on your PC. Compared with a Raspberry Pi, the Micro Python board is cheaper, smaller, simpler (you can make one yourself, or even modify the design to fit your needs) and it uses less power. Most other boards are programmed in C, which is a low-level language and can be difficult to program correctly. On the other hand, Python is a very high-level language, which means that Python has simpler, smaller code to do the same thing as C.
What reward should I choose?
It's totally up to you! But here are some pointers to get you thinking. If you would like to support the development of Micro Python and see it become free open source software, then choose the "Supporter" reward. This, and all other reward levels, will get you access to the source code and board design files a few months before they become open to the public. All reward levels allow you to have your name in the source code as a supporter, if you like.
If you want a single board on its own, go for the "Single board" reward. To have some fun making servo motors move, the "Robotics kit" is for you. If you are new to microcontrollers and electronic circuit building, and want to learn how to build and program some nifty circuits, then the "Starter kit" has everything you need (except a USB cable, which you probably alread have).
For the more adventurous, there is the "Wireless kit" which is the "Starter kit" plus a Bluetooth module, speaker, amplifier, microphone and light sensor. The "Batteries included kit" is the "Starter kit" plus a Bluetooth module, an additional Micro Python board, an additional servo, a rechargeable LiPo battery with charger, and a mini-joystick.
For the people who don't need any introduction to microcontrollers and programming, there is the "Hacker's kit" and "Jumbo hacker's kit" which have 2 or 4 Micro Python boards, pure and simple. If you want it early, there is a limited reward to get a handmade board, as well as access to all the source as soon as the campaign ends. There are also limited rewards where you can choose to have a specific Python library implemented in Micro Python, or choose to have Micro Python ported to a different board. Get in touch for details if you are interested in this.
A note on shipping. Shipping is free within the UK. For outside the UK, the shipping price is for non-tracked shipping. If you want tracking, please increase the shipping price to £10.
Tell me more about Micro Python...
Certainly! Micro Python is a complete rewrite, from scratch, of the Python scripting language. It is written in clean, ANSI C and includes a complete parser, compiler, virtual machine, runtime system, garbage collector and support libraries to run on a microcontroller. The compiler can compile to byte code or native machine code, selectable per function using a function decorator. It also supports inline assembler. All compilation happens on the chip, so there is no need for any software on your PC.
Micro Python currently supports 32-bit ARM processors with the Thumb v2 instruction set, such as the Cortex-M range used in low-cost microcontrollers. It has been tested on an STM32F405 chip.
Micro Python has the following features:
- Full implementation of the Python 3 grammar (but not yet all of Python's standard libraries).
- Implements a lexer, parser, compiler, virtual machine and runtime.
- Can execute files, and also has a command line interface (a read-evaluate-print-loop, or REPL).
- Python code is compiled to a compressed byte code that runs on the built-in virtual machine.
- Memory usage is minimised by storing objects in efficient ways. Integers that fit in 31-bits do not allocate an object on the heap, and so require memory only on the stack.
- Using Python decorators, functions can be optionally compiled to native machine code, which takes more memory but runs around 2 times faster than byte code. Such functions still implement the complete Python language.
- A function can also be optionally compiled to use native machine integers as numbers, instead of Python objects. Such code runs at close to the speed of an equivalent C function, and can still be called from Python, and can still call Python. These functions can be used to perform time-critical procedures, such as interrupts.
- An implementation of inline assembler allows complete access to the underlying machine. Inline assembler functions can be called from Python as though they were a normal function.
- Memory is managed using a simple and fast mark-sweep garbage collector. It takes less than 4ms to perform a full collection. A lot of functions can be written to use no heap memory at all and therefore require no garbage collection.
Tell me about the Micro Python board...
The Micro Python board is an electronics development board that runs Micro Python, and is based on the STM32F405 microcontroller. This microcontroller is one of the more powerful ones available, and was chosen so that Micro Python could run at its full potential. The microcontroller is clocked at 168MHz and has 1MiB flash and 192KiB RAM, which is plenty for writing complex Python scripts. The board measures 33x40 mm and is pictured below.
The board has a built-in USB interface that presents itself as a serial device (CDC VCP) as well as a removable storage device (MSC). When connected to a PC, you can open a serial communications program and interact with the board through a Python command line. You can also print messages and read input, since the serial device acts like stdin and stdout. The board also acts as a storage device (a USB flash drive) and you can easily copy your Python scripts to the board's local filesystem or SD card, and they are then executed independent of the PC.
Powered by a battery, the board can compile and execute Python scripts without any PC connection. There is a Micro SD slot for storing large amounts of data, 2 LEDs, a switch, a real-time clock, an accelerometer, and 30 general purpose I/O pins. The I/O pins include: 5 USARTs, 2SPIs, 2 I2C busses, 14 ADC pins, 2 DAC pins, and 4 servo ports with power.
There is a special pin, BOOT0, which is used to reprogram the microcontroller. By connecting the BOOT0 pin to the 3.3V pin next to it, and resetting the board with the reset button, you enter the "device firmware upgrade" mode. This is a standard USB mode and allows you to easily put an updated version of Micro Python onto the microcontroller (using freely available software for Windows, Mac and Linux). It also allows you to download your own version of Micro Python if you want to modify it, or even download your own C program.
The Micro Python board is suitable for everyone, regardless of knowledge in hardware or software. With a few lines of Python code in a text file, anyone can start flashing LEDs and responding to accelerometer input, all without soldering, or connecting components, or installing software on your PC.
I wanted to share with you my passion for robotics and programming, and, have a chance to give something back to the open source community that I rely on everyday.
I need your support to make Micro Python open source software, and to help fund the production of the Micro Python boards. Making electronic circuits in bulk allows the cost to be kept low. Components are much cheaper when bought in bulk quantities.
With your support I can have the Micro Python boards professionally assembled at a very reasonable cost. This directly benefits you, as the reward of a Micro Python board means you can have a fantastic and powerful development board at a very low price.
If the Kickstarter campaign is successful, Micro Python and the Micro Python board will be made available under Open Source Software, and Open Source Hardware licenses. Backers will get early and complete access to the source code of Micro Python, and a few months later it will be released to the general public. You can implement new features in Micro Python or port it to your own board, or to a different microcontroller.
The Micro Python software will be released under the MIT license.
What about those technical details?
Okay! Here they are, the technical details for the Micro Python implementation and the Micro Python board. There are many extra details that are not listed here. Please ask if you would like further information, as I would be more than happy to share it with you.
The Micro Python implementation is a complete rewrite of Python specifically designed to be run on a microcontroller with minimal flash storage and minimal RAM. When design decisions were made, the first priority was to minimise RAM usage, then minimise code size, and, finally, to execute quickly. Some of the important features of the implementation are listed below.
- Follows the Python 3.3 grammar and language semantics. This means that Micro Python produces equivalent byte code (up to optimisations) to the official CPython version 3.3.
- Size of space-optimised binary compiled to Thumb v2 machine code: around 60KiB. This includes the parser, compiler, runtime and garbage collector, but excludes all other code, including file system support and libraries related to the specific microcontroller. This size will increase if more Python libraries are added.
- Size of all code, including FAT support, SD card, USB serial, USB mass storage, USB HID, Bluetooth, LCD, servo, timer: about 110KiB.
- Minimum RAM required to compile and execute "print('hello world')": around 4KiB.
- Memory is managed using a fast, non-precise, mark-sweep garbage collector. This eliminates reference counting overhead in flash code size and object RAM size. A fast CPU and small amount of RAM means that a complete garbage collection takes under 4ms. The garbage collector RAM overhead is 2 bits per 32 bytes = 1KiB for 128KiB usable RAM.
- Size of int object: 4 bytes, stored on the stack or directly in a tuple/list/dictionary.
- Size of other objects: 32 bytes, plus extra for, eg, elements of a list.
- Limit on number of objects: none, so long as there is enough RAM.
- The grammar is encoded in a compact table using EBNF which is interpreted on-the-fly when parsing.
- RAM is minimised during compilation by performing 3 separate passes over the same data structure.
- There are 4 types of code emitters, selectable per function by function decorators: (compressed) byte code, native code, native code with native types, and inline assembler. Byte code runs on a virtual machine, similar to CPython. Native code has each byte code unrolled to its equivalent machine code, and supports the full Python language. It takes about 2-3 times more RAM, but runs about 2-3 times faster than byte code. The third type, native code with native types, has byte code unrolled to machine code and further assumes that integers are smaller than 31 bits, so that it can use a single machine instruction for integer and pointer operations. You can think of it as "Python syntax, C semantics". For tight loops that perform arithmetic and bit manipulation (common on a microcontroller), it can perform close to the speed of the equivalent C program. The fourth code emitter is inline assembler. It uses the Python grammar, but is interpreted as a list of machine code instructions. Inline assembler can be called from normal Python code with integer and pointer arguments.
- Python exceptions are handled using a variant of setjmp/longjmp. This reduces the amount of flash and RAM needed to implement exceptions.
- A function (byte code, native or inline assembler) can be called on an interrupt long as it does not allocate heap memory (since it can be called while a garbage collection is taking place). In practice this is not a big restriction, as you can do a lot of things using only memory on the stack. For example, you can make loops with while/for, do integer arithmetic and bitwise operations (but no bignums), call other functions and access and overwrite elements of collections like bytearrays (but not create new ones).
The Micro Python language can also run on a PC (it was developed under Linux on a 64-bit machine) and can be used as a lean version of Python where low memory usage is important. The PC version of Micro Python (compiling to byte code) actually runs faster than CPython for the various benchmarks I have tested, and the native compilation option makes Micro Python run significantly faster than CPython.
You can think of Micro Python as a "mini Python operating system", and the boot-up process proceeds as follows:
- Power on, or hard reset. If the DFU (device firmware upgrade) header is enabled (across BOOT0 and 3.3V pin) then the device enters DFU mode, allowing you to upgrade the Micro Python binary, or download your own C/C++ program.
- Otherwise, it goes into boot mode and the boot-LED turns on.
- Checks for a local filesystem on the flash. If none exists, or it is corrupt, a fresh one is created.
- Checks for /boot.py. If it doesn't exist, a fresh one is created.
- Runs /boot.py to configure USB and other low-level parameters that can't be changed without a reset.
- Sets up USB interfaces, depending on the configuration in boot.py. The default is a CDC VCP (virtual communications port, to redirect stdio) and an MSD (mass storage device for the flash and SD card). The MSD allows Linux/Mac/Windows to access the flash and SD card filesystem just like a USB flash drive. This way you can easily copy Python scripts to the board, and copy data files back.
- Boot-up finishes successfully and the boot-LED turns off.
- The main Python script is run if it exists. Default is /src/main.py. This is your main Python program and it can do whatever you like!
- If the main script doesn't exist, or exits, REPL (read-evaluate-print-loop) mode is entered. This gives you a standard Python interpreter prompt over the USB serial device. Exiting from this will soft-reset the board.
Technical details of the board and microcontroller:
- STM32F405RG microcontroller.
- 168 MHz Cortex-M4 CPU with 32-bit hardware floating point.
- 1 MiB flash storage, 192 KiB RAM.
- Micro-B USB connector, with software support for USB serial, USB mass storage, and USB HID (mouse, keyboard).
- Micro SD slot.
- MMA7660 3-axis accelerometer, up to 64 6-bit samples per second per axis.
- 4 LEDs, 1 reset switch, 1 user switch.
- 3.3V LDO regulator at 300mA, power from USB or external voltage source between 3.6V and 10V.
- Real-time clock with date and time.
- 30 general purpose I/O lines, 28 are 5V tolerant (unless in ADC mode).
- Communication: 2x SPI, 2x CAN, 2x I2C, 5x USART.
- 14x 12-bit ADC pins (analog signal in).
- 2x DAC pins (analog signal out).
- Board dimensions: 33mm by 40mm.
- Board weight: 6 grams.
- Board I/O connectors: 46 holes, standard 0.1 inch separation.
A pinout of the board is shown below. A pink triangle denotes that the pin is connected to a timer and can be used, for example, as a PWM output for a servo.
The production plan
The software is written and working. It still lacks some more advanced features, but these will be implemented over the duration of the Kickstarter campaign, and the code will be ready to install on the production boards.
Two iterations of the Micro Python board have been produced. The PCBs for these were professionally made by EuroCircuits, and components hand soldered by myself. These prototypes are fully functional and execute Micro Python with all the features described above. The final version of the board will have only minor differences to the second prototype, pictured above.
After the Kickstarter campaign has ended and the funds are received, the first thing to do will be to order the critical components: the STM32F405 microcontroller and the MMA accelerometer. I will then source the rest of the components. Knowing the parts, I will then make final adjustments to the PCB design and send it off for manufacture.
Once all parts and the PCBs are received I can then move to the assembly stage. I have a quote from the UK company Newbury Electronics to assemble the production run of the boards, and to keep costs down, I must place a large order, which is part of the reason for the Kickstarter campaign. The assembly time will be around 25 days.
During assembly I will be organising the rewards, putting together the different kits, and working out the shipping details. I will also continue to develop the Micro Python software and start work on implementing requested libraries and other microcontroller support.
The aim is to have the boards and kits shipped by the end of March, 2014.
The video was filmed and sequenced by Viktoriya Skoryk, http://vskography.com.
Risks and challenges
There is less risk with the software (the Micro Python implementation) than with the hardware (the Micro Python board). The software is mostly finished, except for implementing some more advanced features of the language and writing some additional Python libraries. I do not see any significant problems with finishing the software, as most of the difficult parts (compiler, memory manager, exception handler) are complete.
If software development is delayed and features are not implemented by the time the boards ship, the boards can always be reprogrammed by the user with an update available over the web.
The hardware side of things can have the following two problems: delays, and component sourcing. Delays can be in the PCB production and the assembly, but just take extra time and are not a show-stopper. Component sourcing is the biggest risk. Almost all the components can be interchanged with alternate manufacturers, most without even changing the PCB layout. The only one that cannot be interchanged is the STM32F405RG microcontroller chip itself. These chips are in "active marketing status" with STMicroelectronics, so should be available one way or the other for the coming years.Learn about accountability on Kickstarter
PyMite (also known as p14p, python-on-a-chip) is a great piece of software, and, while, it looks on the surface to be very similar to Micro Python (after all, it runs Python on a micro!), underneath the two are very different things. The following comparison of the two is rather technical, but hopefully makes clear my reason for writing Micro Python from scratch, rather than using, or building on, PyMite.
If there was to be any chance of running Python on a microcontroller for serious applications, one must be able to at least do basic operations, such as integer addition and calling methods, without allocating heap memory. Allocating heap memory is usually a large performance penalty, and consumes RAM, a scare resource on a microcontroller. But, most importantly, when using a garbage collector (which both PyMite and Micro Python use) allocating heap memory has the chance (and eventually it must occur) of inducing a garbage collection cycle.
If you are in the middle of doing some time critical processing (which is common on a microcontroller), you cannot afford to wait for a garbage collection. Also, if your code is running on an interrupt (that is, it has interrupted some other Python code halfway through some calculation) then it cannot allocate heap memory because it must not induce a garbage collection. It cannot, because the original code that it interrupted might have been in the middle of a garbage collection, and it is very difficult to make garbage collection re-entrant. Furthermore, an interrupt is supposed to run very quickly, and this will not be the case if a garbage collection needs to run which processing the interrupt.
In short, we don't want to garbage collect, and hence don't want to allocate from the heap, in a time critical function.
In PyMite (and CPython if I'm not mistaken), most integer operations, even a simple addition, require heap allocation. This is because everything in Python is an object, and objects (generally) need to be allocated on the heap. If you add two numbers (two objects), you first check they are integer objects, then extract their integer values, add them, and then put the result into a newly created object, which must be allocated on the heap. The same thing for subtraction, multiplication, division and bitwise operations, which are all very common in microcontroller code, especially low-level time-critical code.
Also, the read-only nature of Python integers means you can't mutate the object to reuse its heap memory.
Okay, that's one example of allocating heap memory that is unacceptable on a microcontroller. The other example that is important is the act of calling a method. In Python (CPython and PyMite), when you want to call a method foo.bar(), you first extract the attribute bar from foo. Since (in this case) foo is an instance of some class, you must pack together the result into a bound-method object. This is an object that has 2 elements: foo, the subject of the method call, and foo.bar, the actual function to call. Note that this object must be allocated on the heap. You then push this bound-method object onto the top of the stack. The next byte code will pop this off the top, and do a function-application on the bound-method object. The function-application will open up the bound-method object, take out the foo subject, and pass it as the first argument to the foo.bar function. This completes the execution of a method call.
So, we needed to allocate heap memory just to do a method call! Since method calls are everywhere in Python, this is going to lead to poor performance on a microcontroller, and will prevent you from calling methods in time critical places.
Micro Python solves these 2 problems, and does not need to allocate heap memory for integer operations and method calls (in contrast to PyMite).
In Micro Python, integers are still objects, but they are not stored on the heap. Rather we use a trick that I took from Smalltalk (probably some other languages use this trick too). If an integer is small enough to fit in 31 bits (which most are) then it is stored in the actual pointer itself. To distinguish a real object pointer from an integer, we use the least significant bit (LSB). If the LSB is set, then we have an integer object, whose value is stored in the top-most 31 bits. If the LSB is clear, then we have a real object, and the top-most 31 bits point to the memory location on the heap of that object.
With this scheme, integer operations such as addition and bitmanipulation require no heap allocation, and can be executed very quickly.
To solve the problem of method calls, we use the trick from PyPy (thanks PyPy!). That is, an attribute lookup followed directly by a function call is compiled to a new byte code called CALL_METHOD. This uses the stack to store the two values: the instance foo and the function foo.bar. So there is no heap allocation to call a simple method.
Thus, a lot of code in Micro Python can run in time critical places and on an interrupt without allocating heap memory. This is not true for PyMite.
Micro Python also includes a complete compiler (which is why we can do the CALL_METHOD trick), whereas PyMite does not. Micro Python can compile to native machine code.
Micro Python is called "Micro" Python because it is specifically designed from the ground up to run efficiently on a microcontroller. This means designing from the start the entire architecture of the program so it is suited to all these tricks and optimisations, two of which I have just described. This is why I wrote Micro Python from scratch.
Tinypy's aim is to be a small implementation of Python, but it's not targeted at microcontrollers. Tinypy is Python version 2. Integers are represented internally as a C double (a good design decision for simplicity, but not a good one for a microcontroller) so it would need heap allocation for arithmetic, and be quite slow performing the operation (especially if the microcontroller doesn't have hardware floating point). An instance of the tinypy VM needs around 30KiB of RAM. Tinypy does include a parser and byte-code compiler, but they are written in Python themselves, so would take quite a bit of RAM and be orders of magnitude slower than a native parser/compiler (Micro Python's lexer/parser/compiler/emitter is native, written in C).
PyMCU is a "Python controlled microcontroller", not Python on a microcontroller. It runs Python on your PC, and communicates to a slave device (the microcontroller) over USB. Python running on your PC sends commands to the PyMCU board to tell it to, for example, turn on an LED.
PyPy is an amazing piece of work and executes Python at a blinding speed. But the image size (the executable) is gigantic (44MiB for me). If you ever managed to strip it down to fit on a microcontroller, you'd be left with something that in no way resembled the original PyPy.
Let me say that I do not want in any way to demote any of these projects, nor disregard the hard work that has been put into them. I just want to help you understand the different ways that Python has been implemented in the past, and why I decided to write Micro Python rather than adapt an existing piece of code.
No. The Micro Python board has a small file system on the microcontroller itself. Out of the 1MiB flash memory on the STM32F405 chip, around 512KiB will be available to store Python scripts and data files. You only need to add an SD card if you want to store larger data files, or more easily transfer files to/from your PC.
Yes, there is some information in "Update #4" and "Update #5" which is available for everyone to read.
Yes, see "Update #7", accessible at the top of this page.
Micro Python has exactly the same grammar (syntax) as Python version 3. This means that the way you write Python code is exactly the same in Micro Python (for loops, function definitions, classes, list comprehension, etc). Scripts that compile in normal Python will compile in Micro Python, and vice versa.
Micro Python does not at the moment implement all of Python's standard libraries. Some Python standard libraries are written in C and need to be re-written to work with Micro Python. I am currently working on this. Ultimately, not all Python libraries will be fully supported because they are not feasible to run on a microcontroller, either because the functionality is not available on the microcontroller, or because they take too much memory.
Yes, see "Update #3" and "Update #10", accessible at the top of this page.
The pin holes have standard 0.1 inch spacing (2.54mm), so you can easily use some header pins to connect it to bread board, vero board or any other prototyping PCB, or even your own "mother board".
Update #14 (accessible at the top of this page) shows how you can screw the board down without using the header pins.
See Update #15, accessible at the top of this page.
Support this project
- (30 days)