Embedded stream January 3rd-10th 2021 Platinum sponsors: Gold sponsors: Silver sponsors

Page created by Vernon Kelly
 
CONTINUE READING
Embedded stream January 3rd-10th 2021 Platinum sponsors: Gold sponsors: Silver sponsors
Embedded stream
                      January 3rd-10th 2021
Platinum sponsors:

Gold sponsors:

Silver sponsors:
Embedded stream January 3rd-10th 2021 Platinum sponsors: Gold sponsors: Silver sponsors
TABLE OF CONTENTS

  Chapter 1 – Intro to embedded . . . . . . . . . . . . . . . . .      . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .    1
       The Project . . . . . . . . . . . . . . . . . . . . . . . .     . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .    1
       Too Much Information!!! . . . . . . . . . . . . . . . . .       . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .    1
  Chapter 2 – micro:bit basics . . . . . . . . . . . . . . . . . .     . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .    3
       Getting Started . . . . . . . . . . . . . . . . . . . . . .     . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .    3
       Using the micro:bit . . . . . . . . . . . . . . . . . . . .     . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .    4
               Our first program (variables, the micro:bit display     and sleep)    .   .   .   .   .   .   .   .   .   .   .   .   .   .    4
               Working with the display . . . . . . . . . . . . .      . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .    5
               Working with Text . . . . . . . . . . . . . . . .       . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .    6
               More scrolling . . . . . . . . . . . . . . . . . . .    . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .    7
               The REPL . . . . . . . . . . . . . . . . . . . . .      . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .    8
               Printing to the console . . . . . . . . . . . . . .     . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .    8
               Using loops . . . . . . . . . . . . . . . . . . . .     . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .    8
               Buttons and if statements . . . . . . . . . . . .       . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .    9
               Was it pressed? . . . . . . . . . . . . . . . . . .     . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   10
               Lists . . . . . . . . . . . . . . . . . . . . . . . .   . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   10
               The for loop . . . . . . . . . . . . . . . . . . . .    . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   11
               The range function - counting in a loop . . . . .       . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   11
               Functions . . . . . . . . . . . . . . . . . . . . .     . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   12
       Debugging Your Code . . . . . . . . . . . . . . . . . .         . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   13
       Where to go from here . . . . . . . . . . . . . . . . . .       . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   14
  Chapter 3 – Electronics . . . . . . . . . . . . . . . . . . . . .    . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   15
       Voltages and Currents . . . . . . . . . . . . . . . . . .       . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   15
       Relating voltage and current: resistance . . . . . . . . .      . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   15
       Series and Parallel . . . . . . . . . . . . . . . . . . . .     . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   16
       Analog and Digital . . . . . . . . . . . . . . . . . . . .      . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   17
               Aside: Ground . . . . . . . . . . . . . . . . . . .     . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   17
       Voltage Dividers . . . . . . . . . . . . . . . . . . . . .      . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   17
               Calibrating Sensors . . . . . . . . . . . . . . . .     . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   18
       Pull-up and down resistors . . . . . . . . . . . . . . . .      . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   19
               Does it matter if I use pull-up or down? . . . . .      . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   20
       Level shifting . . . . . . . . . . . . . . . . . . . . . . .    . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   20
               Why do we even need this? . . . . . . . . . . . .       . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   20
       Light Emitting Diodes (LEDs) . . . . . . . . . . . . . .        . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   21
               Theory . . . . . . . . . . . . . . . . . . . . . . .    . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   21
               Powering an LED . . . . . . . . . . . . . . . . .       . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   21
               More notes on current limiting resistors . . . . .      . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   22
  Chapter 4 – Program State, Classes . . . . . . . . . . . . . .       . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   23
       Program States . . . . . . . . . . . . . . . . . . . . . .      . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   23
               High Scores . . . . . . . . . . . . . . . . . . . .     . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   23
               Detecting Sequences . . . . . . . . . . . . . . .       . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   24
               Program modes . . . . . . . . . . . . . . . . . .       . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   24
       Classes . . . . . . . . . . . . . . . . . . . . . . . . . .     . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   26
               Example Class . . . . . . . . . . . . . . . . . . .     . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   27
  Chapter 5 – Grove . . . . . . . . . . . . . . . . . . . . . . . .    . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   28
               Grove and micro:bit . . . . . . . . . . . . . . . .     . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   28
               Summary Table . . . . . . . . . . . . . . . . . .       . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   28
               Grove Components . . . . . . . . . . . . . . . .        . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   29
               Other non-Grove Components: . . . . . . . . . .         . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   34
       Pulse Width Modulation . . . . . . . . . . . . . . . . .        . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   36
               Built-in PWM Support . . . . . . . . . . . . . .        . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   38
       Servo Motors . . . . . . . . . . . . . . . . . . . . . . .      . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   38
               Regular Motors . . . . . . . . . . . . . . . . . .      . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   38

NCSS Embedded Stream                                                                                                                          i
Embedded stream January 3rd-10th 2021 Platinum sponsors: Gold sponsors: Silver sponsors
Continuous Rotation Servo Motors . . . .        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   39
               Standard Servos (angle) . . . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   39
               Controlling a servo motor . . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   40
               Extra: Stepper motors . . . . . . . . . .       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   40
  Chapter 6 – Radio, Files, Plotting . . . . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   42
       Radio . . . . . . . . . . . . . . . . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   42
               Groups and addresses . . . . . . . . . . .      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   42
       Files . . . . . . . . . . . . . . . . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   43
       Plotting with Mu . . . . . . . . . . . . . . . . .      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   43
  Chapter 7 – Robotics with the micro:bit . . . . . . . .      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   44
       Getting Started with bit:bots . . . . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   44
               Programming . . . . . . . . . . . . . . .       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   45
       Neopixels & programmable LEDs . . . . . . . .           .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   47
               Programmable LEDs . . . . . . . . . . .         .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   47
               Programming . . . . . . . . . . . . . . .       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   48
               Colour mixing . . . . . . . . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   48
               Extra: Other types of programmable LED          .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   49
       Line following . . . . . . . . . . . . . . . . . . .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   49
               Theory of Control . . . . . . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   49
               Control Algorithms . . . . . . . . . . . .      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   51
       Ultrasonic distance sensing . . . . . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   53
  Chapter 8 – Filtering . . . . . . . . . . . . . . . . . .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   55
       Windowed Averaging . . . . . . . . . . . . . . .        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   55
       Exponential Averaging . . . . . . . . . . . . . .       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   56
       The downside of filtering . . . . . . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   57
  Chapter 9 – Integrated circuits . . . . . . . . . . . . .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   58
               Pin numbers . . . . . . . . . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   58
               Datasheets . . . . . . . . . . . . . . . . .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   59
       Digital signalling . . . . . . . . . . . . . . . . .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   59
               UART . . . . . . . . . . . . . . . . . . .      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   59
               SPI . . . . . . . . . . . . . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   60
               I²C . . . . . . . . . . . . . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   61
               Drivers . . . . . . . . . . . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   62
  Chapter 10 – Pyboard, Quokka . . . . . . . . . . . . .       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   64
               Uploading code to the pyboard . . . . . .       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   64
               Programming on the pyboard . . . . . . .        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   65
               Programming the Quokka . . . . . . . . .        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   66
               More info . . . . . . . . . . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   69
  Chapter 11 – Learn more . . . . . . . . . . . . . . . .      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   70
               Electronics . . . . . . . . . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   70
               Mathematics . . . . . . . . . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   70
               Other . . . . . . . . . . . . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   71
  Lab Exercises . . . . . . . . . . . . . . . . . . . . . .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   72
       About the labs . . . . . . . . . . . . . . . . . .      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   72
               Installing Mu . . . . . . . . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   72
       Lab 1 – Monday morning . . . . . . . . . . . . .        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   73
       Lab 2 – Monday afternoon . . . . . . . . . . . .        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   74
       Lab 3 – Tuesday morning . . . . . . . . . . . . .       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   75
       Lab 4 – Tuesday afternoon . . . . . . . . . . . .       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   76
       Lab 5 – Wednesday morning . . . . . . . . . . .         .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   78
       Lab 6 – Wednesday afternoon . . . . . . . . . .         .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   80
       Lab 7 – Thursday morning . . . . . . . . . . . .        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   81
       Lab 8 – Thursday afternoon . . . . . . . . . . .        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   83

NCSS Embedded Stream                                                                                                                                            ii
Embedded stream January 3rd-10th 2021 Platinum sponsors: Gold sponsors: Silver sponsors
CHAPTER                                                                       NCSS Embedded Stream

Chapter 1 – Intro to embedded
Electronic devices are everywhere in modern life. From light bulbs to toasters to computers and cell-
phones, we rely on the principles of electronics to survive in modern society. As technology develops,
perhaps the more surprising development is that even seemingly simple items are no longer just basic
electronic devices, but rather are becoming embedded devices that incorporate small microcontrollers to
make them operate in increasingly smart ways. A simple light bulb is no longer just a wire that glows,
it’s a complicated circuit that includes a computer to monitor and control the brightness and power
consumption of the light. Toasters and kettles contain little microcontrollers to allow fine adjustment of
temperature and cooking time. Even the charger for your phone or laptop contains a little computer to
ensure safe charging of your device and to improve the efficiency with which it can operate. And this is
WAY before we even start to consider the proliferation of internet enabled devices that are permeating
our households.
So what is an embedded device? It’s a small, programmable computer, tightly integrated with a set of
sensors and mechanical parts to enable it to perform a specific task. As microcontrollers have become
smaller, cheaper and more efficient, we’ve been able to put them into an ever increasing number of places,
and to do ever more complicated tasks with them.
And this is exactly what the focus of this course is going to be! Learning how to design simple electronic
devices to perform some specific task of choice. Since we are talking about embedded design, the course
focusses not just on software development, but includes a certain amount of electronics as well. We
don’t want to get stuck in the land of pure software work. An embedded engineer is often plugging and
unplugging, working with motors, sensors, lights and speakers to make devices that interact with the
real world. Of course, this also brings along with it a measure of pain…. Over the course of the coming
days you will deal not only with buggy code, but faulty wiring and the crazy interaction between the
messy real world and the devices you are making.
But ultimately, that’s why we love embedded development so much. As painful as it is to deal with the
real world, making devices that we can touch, see and hear, whether it’s for a specific purpose, art, or
fun, brings along with it a huge amount of satisfaction. We’re super excited to get started!
The Project
By the end of the camp, you and a group of 3/4 other team members will have developed:
  • an interactive art piece or game that uses a small microcontroller, a host of sensors and various
    lights and outputs
  • a 3-5 minute video that introduces your project and your team, and goes through the process of
    developing your final project.
In order to successfully accomplish these tasks you will learn not only about programming and electronics,
but about how to work together as a group to juggle completing the various tasks before the deadline on
Saturday night. Just like a real project there are a lot of things to figure out, tight deadlines to meet,
compromises you’ll have to make, and limited resources to manage (you can’t hire more people            ).
You’ll learn about the techniques that real tech companies use to manage teams and, by the end, have
taken a project from idea to realization. One of the most important lessons to learn over the course of
the camp is that engineering real products is not a solo effort, but will require you to work with others
to optimally utilize the talents and skills of everyone in your group, and that effective team management
plays as much of a role in making something as being a boss coder.
As the course progresses, you will get more information about exactly what sort of project you and your
team will be working on.
Too Much Information!!!
Given the amount of material that we need to cover in a very limited amount of time, the academic
portion of the camp is going to be quite jam packed. There will be two 30-minute-to-1-hour lectures per
day, as well as two 3-hour lab sessions to put theory into practice. Since there is so much to cover, the
lectures will move through the content quite quickly. This year, we are also going to have opportunities
for some in-lab lectures that will go through some of the key concepts in a bit more detail.
In addition to this, this booklet serves as both a reference for the material covered during the lectures,
and a source of additional information. If you want to double check something that was previously
covered, it should be available in this book.

Owen Brasier/Sebastian Pauka/Alex McCulloch                                                             1
Embedded stream January 3rd-10th 2021 Platinum sponsors: Gold sponsors: Silver sponsors
CHAPTER                                                                       NCSS Embedded Stream

Don’t be concerned if you don’t understand everything in the lectures or labs first time around. Every-
thing progresses at an incredibly fast pace. If you do get stuck, ask one of the lecturers (Owen, Seb or
Alex), your group leader (Steven, Teigan or Emma), or one of the many tutors for help.
The only silly question, is the one that doesn’t get asked!
Chances are, if you have a question, you’re not the only one in the room who has the same issue. The
tutors are very happy to help, and the lecturers are more than happy to go through things in more detail,
but we can only go through things if you ask us questions! Not only are we here to help you understand
concepts, but we are also more than happy to help you find tricky bugs in your program, or figure out
wiring issues in your bots. Feel free to talk to us about what being at university is like, how we like
Computer Science as a subject, and how we ended up in computing. We’ll be here all week!
Finally, don’t forget to experiment. One of the best things about embedded is that you can wire things
up and see how they react in the real world. Although parts of the course are online, the joy of embedded
is in seeing lights flash, motors spin and speakers beep. Feel free to grab anything from the drawers over
the course of the week and play around with them. If you want help getting something to work ask.

Owen Brasier/Sebastian Pauka/Alex McCulloch                                                             2
Embedded stream January 3rd-10th 2021 Platinum sponsors: Gold sponsors: Silver sponsors
CHAPTER                                                                       NCSS Embedded Stream

Chapter 2 – micro:bit basics
The BBC micro:bit is a small, handheld, embedded microcontroller, which we will be using for the
duration of the camp. Apart from being very friendly, it has a huge number of peripherals that we can
use: a compass, an accelerometer, a thermometer, a radio for chatting between 2 micro:bits, two buttons
and a 5x5 display. More importantly, it can run Python! The aim of the next few days will be to get up
to speed on the various features of the micro:bit.

                              (a)                                       (b)

                                         Figure 1: A micro:bit

To get started we’re going to be working through the micro:bit Crash Course, (https://groklearning.
com/course/ncss-2021-embedded/), on the Grok Learning platform. For those of you who have done
the NCSS Challenge, this will be a very familiar interface, with the key difference that our code will now
be running on an emulated micro:bit in the browser.
The crash course will go through everything you need to play around with the micro:bit, as well as getting
you up to speed on Python. In addition to the course, we give a brief description of the peripherals of
the micro:bit below, and go through some key Python concepts, which you can use as a reference if you
ever get stuck.
Getting Started
If you’re using the micro:bit emulator on Grok, you don’t need anything more to get started.
If you’re playing around with a real micro:bit, you’ll need a couple of other things to get going. When
you plug the micro:bit in to your computer, it will show up as a drive connected to your computer. The
micro:bit expects you to copy a .hex file which contains the compiled program that you want to run.
There’s a couple of ways to get this file. If you are using the Grok interface to write your programs,
you can hit the “Download” button in the top right corner of the editor to download the hex file that
corresponds to your written program. Then, copy and paste that file onto the micro:bit drive that
appears.

Owen Brasier/Sebastian Pauka/Alex McCulloch                                                             3
Embedded stream January 3rd-10th 2021 Platinum sponsors: Gold sponsors: Silver sponsors
CHAPTER                                                                       NCSS Embedded Stream

                                Figure 2: The Grok Learning Interface

Alternatively, you can use the Mu editor - a simple editor for Python that interfaces directly with the
micro:bit, and is able to upload code directly to the micro:bit. During the micro:bit labs, this will be
the main editor we use. The editor can be downloaded from https://codewith.mu/en/. By pressing
the Flash button in the editor, we can upload the code to the micro:bit. Once the upload is completed,
the micro:bit will automatically reset and start running your new program.

                           Figure 3: The micro:bit buttons in the Mu editor

Note: If this set of buttons doesn’t appear in your copy of Mu, you may not be running in the “micro:bit”
mode. You can change the target in Mu by pressing the Mode button in the top left corner of the editor.
Using the micro:bit
Plug your micro:bit into the computer with a USB cable, open up Mu and let’s start coding!

Our first program (variables, the micro:bit display and sleep)
Let’s start by showing an image on the display.
from microbit import *

# Show an image on the 5 x 5 display
display.show(Image.HAPPY)
What’s happening here? The first line is to import the microbit module, which gives us access to the
functions and constants we’re going to use.
The third line is a comment line. In Python, all comments start with a # character and allow us to add
some descriptive text to our code.
display.show is a function that displays an image, while Image.HAPPY is the image we want to display.
It looks like a happy face :)
There are a long list of in-built images in the microbit documentation: https://microbit-micropython.
readthedocs.io/en/latest/tutorials/images.html.
To show multiple images, we need to sleep in between instructions. Without it, the micro:bit runs so
fast that the images will flash faster than our eyes can see.
The parameter of sleep is in milliseconds, so sleep(1000) means sleep for 1 second. So someone’s life
story told in 3 seconds might look like this:

Owen Brasier/Sebastian Pauka/Alex McCulloch                                                            4
Embedded stream January 3rd-10th 2021 Platinum sponsors: Gold sponsors: Silver sponsors
CHAPTER                                                                     NCSS Embedded Stream

from microbit import *

# Show an image on the 5 x 5 display
display.show(Image.HAPPY)
# Wait for a number of milliseconds
sleep(1000)
display.show(Image.SAD)
sleep(1000)
display.show(Image.SKULL)
sleep(1000)
display.clear()
In the above code, we are sleeping for 1 second after each image. If we wanted to change this time, we
would have to change our code in 3 different places. Rather than write our code like this, we can store
the amount of time we want to sleep in a variable, and reuse that value multiple times in our code:
from microbit import *

# Set the wait time
wait_time = 2000

# Show an image on the 5 x 5 display
display.show(Image.HAPPY)
# Wait for a number of milliseconds
sleep(wait_time)
display.show(Image.SAD)
sleep(wait_time)
display.show(Image.SKULL)
sleep(wait_time)
display.clear()
Now, we can change all of the the delay after each of the images while only changing a single number in
our code!
At various points in the program we can change or manipulate the values we store in variables. For
example, here is a program that doubles the wait time after we show the SKULL image. On line 13 of
our program we multiply the value stored in the variable wait_time and store it back into that same
variable.
from microbit import *

# Set the wait time
wait_time = 2000

# Show an image on the 5 x 5 display
display.show(Image.HAPPY)
# Wait for a number of milliseconds
sleep(wait_time)
display.show(Image.SAD)
sleep(wait_time)
display.show(Image.SKULL)
wait_time = wait_time * 2
sleep(wait_time)
display.clear()

Working with the display
The display module does more than just setting pre-built images. It’s also possible to individually
control each LED, including making them brighter and darker. We can programmatically do this with
the display.set_pixel function.

Owen Brasier/Sebastian Pauka/Alex McCulloch                                                          5
Embedded stream January 3rd-10th 2021 Platinum sponsors: Gold sponsors: Silver sponsors
CHAPTER                                                                      NCSS Embedded Stream

The display works on a grid with (0, 0) at the top left of the display:

                                      Figure 4: A happy micro:bit

For example, to control a single pixel we can write:
from microbit import *

display.clear()
#set_pixel(x,y,brightness)        3rd light across and 4th down because we count from 0
display.set_pixel(2, 3, 9)
The above code will do two things. First it clears the display, getting rid of any previously displayed
image. Then, since each pixel has a brightness from 0 to 9, the code above sets the pixel at coordinate
(2, 3) to full brightness.
As another example the code below will turn off the previous pixel, and light up the middle pixel, at
coordinate (2, 2), at half brightness instead:
from microbit import *

display.set_pixel(2, 3, 0)
display.set_pixel(2, 2, 5)

Working with Text
We can also use the display.show function to print out some text:
from microbit import *

# Show text on the 5 x 5 display one letter at a time
display.show('Hi NCSS')
That code flashes letters, and I find it ends up being a bit hard to read. Much better to scroll text
instead:
from microbit import *

# Scroll text on the 5 x 5 display
display.scroll('Hello there, this text is scrooooooolling')
Much like with numbers above, we can also store strings (that is text data) in variables as well.
from microbit import *

text_data = 'Hello there, this text is scrooooooolling'
# Scroll text on the 5 x 5 display
display.scroll(text_data)

Owen Brasier/Sebastian Pauka/Alex McCulloch                                                          6
Embedded stream January 3rd-10th 2021 Platinum sponsors: Gold sponsors: Silver sponsors
CHAPTER                                                                       NCSS Embedded Stream

Whenever we want to store text data, we need to wrap it in either ', or " characters. This tells Python
that the data that follows should be stored as text and not interpreted as code. We can also add different
strings together in order to make longer strings. For example, to print our name we might write code
that looks like:
name = "Sebastian"
display.scroll("Hi " + name + ". Welcome to NCSS!")
This code will scroll Hi Sebastian. Welcome to NCSS! across the screen.
One final caveat to keep in mind, text and numbers behave differently. By wrapping strings in ' or "
characters, we’re telling Python that values stored there should be treated as text.
For example, in the below code:
text_data_1 = "1"
text_data_2 = "2"
final_value = text_data_1 + text_data_2
the value stored in final_value will be "12", and not 3, since we’ve told Python that both of those
values are strings.
We can convert from strings into numbers by running the int function on the text. If our code was
instead:
final_value = int(text_data_1) + int(text_data_2)
the values stored in text_data_1 and text_data_2 are converted to numbers before being added, so
final value after running this code will be 3.
We can also do the opposite conversion, taking a number variable and turning it into text. For example:
number_data_1 = 1
number_data_2 = 2

final_value = str(number_data_1) + str(number_data_2)
In this case, final value will be "12" as before.

More scrolling
To scroll integers, we need to convert them to a string using the str function before scrolling:
from microbit import *

num = 50
# Scrolling text with joining
display.scroll('The answer is: ' + str(num))
We might want to repeatedly scroll text:
from microbit import *

# Scrolling text with repetition
display.scroll('LOLOLOLOLOLOLO', loop=True)
That text will keep repeating, to speed it up we can use the delay key word argument (called a kwarg).
from microbit import *

# Scrolling text with repetition and change of speed
display.scroll('LOLOLOLOLOLOLO', delay=50, loop=True)
The delay specifies the delay in milliseconds between each frame.
Find more info on scrolling text in the docs: https://microbit-micropython.readthedocs.io/en/latest/dis-
play.html?#microbit.display.scroll. Lots of those options are available in display.show too!

Owen Brasier/Sebastian Pauka/Alex McCulloch                                                             7
CHAPTER                                                                        NCSS Embedded Stream

The REPL
In addition to uploading scripts to the micro:bit and running them, we can also interactively run single
lines of Python code on the micro:bit. The easiest way to access the REPL on the micro:bit is using the
Mu editor, where we can press the REPL button in the menu bar. This will stop the currently running
program and bring up a prompt, into which you can type Python expressions.
Note: REPL stands for “Read, Evaluate, Print, Loop”
For example, try bringing up the REPL and type the following lines:
>>> display.show(Image.HAPPY)
Opening the REPL causes whatever code is uploading to stop, however we can also restart our running
code, either by pressing the “reset” button on the micro:bit, or pressing  in the REPL window.
Note, you won’t be able to upload code to the micro:bit while the REPL window is open. If you want to
upload a new program, you will have to close the REPL window first.

Printing to the console
It’s annoying to try and look at a scrolling error message on the LED display. Instead of printing to the
display, we can output straight to the REPL window. Upload the following code to your micro:bit.
# Output text to the console
print('Hello, World!')
That will print messages to the serial console so you can get an actual output, to do some debugging.
In Grok, look at the “Output” tab to view the serial output in the simulator. In Mu to see what the
output looks like, you can open the REPL window, and either hit the “reset” button on your micro:bit or
press  in the REPL window to start your program going again. Your message will show up in
the window:

                                    Figure 5: Printing to the REPL

If we want to print a number inside of a string, just like with the display, we need to convert that number
into a string:
answer = 42
print('The answer to life the universe and everything is ' + str(answer))

Using loops
In embedded systems, we generally want them to run for as long as power is being supplied to the.. So
we really want them to do things forever. The while loop is a language feature we can use to do this. It
comes in the form while :, when the condition evaluates to True then the loop repeats.

Owen Brasier/Sebastian Pauka/Alex McCulloch                                                              8
CHAPTER                                                                       NCSS Embedded Stream

At the beginning of each loop, the condition is checked to see if the loop continues. Let’s take a look a
program that does this:
from microbit import *

# Run this animation forever
while True:
    display.show(Image.HEART)
    sleep(500)
    display.show(Image.HEART_SMALL)
    sleep(500)
The code that we want to run is indented to indicate that it is all part of the while loop. Un-indented
code will not be run as part of the loop. For example, in the following code:
while True:
    print("Hello, World!")
    sleep(500)
print("Goodnight, Moon.")
The phrase “Hello, World!” will be printed indefinitely, while “Goodnight, Moon.” will never be reached.
In addition, in both the above loops, since True is always True (duh…), the above code will repeat
forever. It is an infinite loop.
We can also write a loop that will terminate once a certain action has taken place. For example, in the
following code:
i = 0
while i < 5:
    print("The number was: " + str(i))
    i += 1
print("Done")
the condition i < 5 is true until i == 5, so this code will print:
The number   was:   0
The number   was:   1
The number   was:   2
The number   was:   3
The number   was:   4
Done

Buttons and if statements
The microbit module gives us button_a and button_b objects to use the buttons.
To simply see if the button is pressed down right now, use the is_pressed() function, as the name
would imply.
from microbit import *

# Show a heart while the button is pressed
while True:
    display.clear()
    if button_a.is_pressed():
        display.show(Image.HEART)
    sleep(1000)
Notice the use of the if statement. Like the while loop, the if statement will check whether the condition
is True, and run the indented code if it is. In the above code, the function display.show(Image.HEART)
is run if button_a.is_pressed() is True. Since sleep(1000) isn’t indented relative to the if statement,
it will always be run.
We can connect an if statement with an else statement, which will run if the condition is False:

Owen Brasier/Sebastian Pauka/Alex McCulloch                                                             9
CHAPTER                                                                       NCSS Embedded Stream

from microbit import *

while True:
    if button_a.is_pressed():
        display.show(Image.HEART)
    else:
        display.show(Image.GHOST)
The elif statement lets us add even more options!
from microbit import *

while True:
    if button_a.is_pressed():
        display.show('A')
    elif button_b.is_pressed():
        display.show('B')
    else:
        display.clear()
What would happen here is both button_a and button_b are pressed?

Was it pressed?
While the is_pressed() function will tell us whether a button is currently being pressed, often what we
want to do is check whether a button was pressed at some point in the past. For this purpose we have
the was_pressed() function
The was_pressed() checks: between this time and the last time we checked, was the button pressed?
One thing to remember: the was_pressed() function will return True ONCE for a button press. If we
run it again without releasing the button, it will subsequently return False.
For example, we can write a simple stopwatch with a reset button like so:
count = 0
while True:
    # Show the current count, and increment it
    display.show(count)
    count += 1
    # If button a was pressed at some point, reset the count
    if button_a.was_pressed():
        count = 0
    # Wait 1 second before continuing
    sleep(1000)
If we were to replace was_pressed with is_pressed, we wouldn’t be able to detect any button presses
that occurred during the sleep. In other words, we would have a pretty rubbish reset button….

Lists
So far, we’ve stored strings and numbers in variables. In Python we can also store lists of values. To
create a list, just as we wrap strings in quotes ("), we wrap lists in square brackets ([). Let’s create a
list of the first 10 prime numbers:
primes = [2,3,5,7,11,13,17,19,23,29]
We can access values inside a list by indicating its position inside square brackets. Note that in Python,
and indeed in almost all programming languages, the positions of values starts from 0. To add the first
two prime numbers together we can write:
first_two_primes = primes[0] + primes[1]
display.scroll(str(first_two_primes))

Owen Brasier/Sebastian Pauka/Alex McCulloch                                                            10
CHAPTER                                                                        NCSS Embedded Stream

We can also add and remove items from a list. To add a few more primes into our list we can use the
append function:
primes.append(31)
primes.append(37)
To remove primes from the list, we can use the remove function if we know which value we want to
remove, or the pop function if we know its position.
primes.pop(0) # Remove the first prime number
primes.remove(11) # Remove prime number 11
After these two lines, our list will contain: [3,5,7,13,17,19,23,29,31,37]. If we’re ever in any doubt,
we can print the list to the console, which will give you the contents of the list:
print(primes)
We can also always get the length of a list using the len function, which will return the number of items
in a given list as a number:
list_length = len(primes)
print("The number of primes I know is: " + str(list_length))
There are more things that we can do with lists that are documented in the Python language. When
you have a chance you can find this documentation at: https://docs.python.org/3.4/tutorial/
datastructures.html. Note that this also includes some additional data structures that you might find
helpful later on.

The for loop
Aside from while loops, Python also allows us to loop over lists of things. For those of you that have
done some programming before, this is a for-each type loop. Note that this is different from the for
loops you may have seen in other languages, such as C.
The syntax for a for loop is:
for  in :
    # do something with each value
This loop will loop over each value in the given list, and put the value into the variable given.
For example, if we are working with the list of primes we made before, we can do something like:
for prime in primes:
    print("One of the primes I know is: " + str(prime))
This will print out each of the primes that is in the list.

The range function - counting in a loop
One of the really common patterns that we run into when we’re coding is we want to loop up to a certain
number of times. In the above code, we used a while loop to accomplish this.
i = 0
while i < 5:
    print("The number was: " + str(i))
    i += 1
print("Done")
Now that we know about the for loop, we can simplify this code quite a bit by using a list and a for
loop:
for i in [0,1,2,3,4]:
    print("The number was: " + str(i))
print("Done")
This will print out exactly the same count as before, but we can do even better using the range function,
which creates a list of numbers for us, rather than requiring us to do it manually:

Owen Brasier/Sebastian Pauka/Alex McCulloch                                                           11
CHAPTER                                                                       NCSS Embedded Stream

for i in range(5):
    print("The number was: " + str(i))
print("Done")
We can use these loops like this to replace most code that requires a range of values to be used. For
example, if we wanted to turn on the fourth row of the micro:bit display we can write:
from microbit import *

for x in range(5):
    display.set_pixel(x, 4, 9)
The equivalent code is:
from microbit import *

display.set_pixel(0,      4,   9)
display.set_pixel(1,      4,   9)
display.set_pixel(2,      4,   9)
display.set_pixel(3,      4,   9)
display.set_pixel(4,      4,   9)
but that’s pretty boring to write (and more error-prone). So use a for loop instead.
Note: The range function can actually do a whole lot more than count from 0 to n, you can set
start, and step values too. If you’re curious, the full documentation is available here: https://-
docs.python.org/3.4/library/stdtypes.html#range

Functions
So far we’ve been using lots of functions in Python like sleep or print. These functions are defined by
someone else, and we can just call that function to use it.
But you can also write your own functions just like these ones!
Say we just wanted to show the HAPPY image, sleep for 1 second, the clear the display.
from microbit import *
def happy():
    display.show(Image.HAPPY)
    sleep(1000)
    display.clear()

happy() # Call the function
The def keyword defines the function happy, and calling the function by using the name and parentheses
(in this case happy()), runs the lines of code inside the function.
It’s possible to send information into a function, via a parameter or argument (sometimes we abbreviate
this and call it an arg). Let’s look at an example:
from microbit import *
def happy(ms):
    display.show(Image.HAPPY)
    sleep(ms)
    display.clear()

happy(300) # Call the function, sleep for 300 ms
happy(500) # Call it again, sleep for 500 ms this time
Here we defined that there is a parameter to the function happy called ms, and each time we call this
function, we use the value of that is passed for ms. The argument ms behaves like a variable, but
importantly it only exists within the function itself. In the above example, the first time we call happy,
ms is set to 300, the second time we call happy, ms is set to 500.

Owen Brasier/Sebastian Pauka/Alex McCulloch                                                            12
CHAPTER                                                                        NCSS Embedded Stream

We can also get information back from functions by using the return statement. For example, we can
write a function that converts from celcius to farenheit.
from microbit import *

# Conversion functions for C->F and F->C
def celcius_to_fahrenheit(c):
    farenheit = c * 9 / 5 + 32
    return farenheit

# Shows the current temperature in C and F
def show_temperature():
    c = temperature()
    f = celcius_to_fahrenheit(c)
    print("micro:bit temperature in celcius: " + str(c) + "C")
    print("micro:bit temperature in farenheit: " + str(f) + "F")

# Update the temperature once per second
while True:
    show_temperature()
    sleep(1000)
Debugging Your Code
Apart from being a great way to quickly test out the functionality of the micro:bit, the REPL also allows
you to find errors in your code. For example, let’s upload this buggy code to our micro:bit.
from microbit import *

for i in range(10):
    display.show(i)
    sleep(1000)
display.show(done)
This above code has an error in it, we’ve forgotten to put quotes around the string done. As a result it
will crash once it finishes counting to 10. The micro:bit will scroll the error message across the display,
however this is usually slow and difficult to read.
We can get the same information by opening the REPL and restarting our program, either by pressing
the “reset” button on the micro:bit, or by pressing  in the REPL window. Once we run into the
error, the full error message will be output to the console.

                              Figure 6: A Python traceback in the REPL

Owen Brasier/Sebastian Pauka/Alex McCulloch                                                             13
CHAPTER                                                                     NCSS Embedded Stream

Where to go from here
Although we’ve covered a heap of content here, there are far more features available in both Python and
micro:bit than we can cover here. If you would like more information, you can:
  • The micro:bit documentation for features of the micro:bit https://microbit-micropython.readthe-
    docs.io/en/latest/index.html
  • The MicroPython documentation http://docs.micropython.org/en/latest/
  • The Python documentation https://docs.python.org/3.4/reference/index.html
     Note that although MicroPython is based on Python 3.4, there are a number of differences. The
     Python documentation is excellent at describing the built-in functions, and most of what you will
     find there is valid for MicroPython as well, there are some differences, that you can read about
     here: http://docs.micropython.org/en/latest/genrst/index.html

Owen Brasier/Sebastian Pauka/Alex McCulloch                                                         14
CHAPTER                                                                         NCSS Embedded Stream

Chapter 3 – Electronics
Since we’re learning all about embedded development, we need to spend some time learning about
electronics. Electronics is a huge field, and encompasses a large number of topics, so it’s impossible for
us to cover every topic exhaustively. Rather than trying to exhaustively cover the field of electronics,
we’ll try to introduce enough topics that you can put together simple circuits, hook components together
and start to understand what is going on with the embedded devices you see around you.
Since there is such a large number of topics to cover, don’t worry if this doesn’t all make sense on your
first read-through. Most of the content you will have a chance to learn along the way. But since we can’t
cover everything in the limited time we have, this section is meant to be a reference to come back to as
the program progresses.
Voltages and Currents
To build any electronic device, we need to have a way of sending energy and signals between controllers,
sensors and outputs. The way we send those signals is by sending electrons from one place to another.
The movement of electrons through a circuit is called current. The units of current is amps (A) and a
larger value means a greater number of electrons are flowing.
The way to create a current is to apply a voltage. A difference in voltage between two points in a circuit
will cause current to flow. Specifically, when we’re talking about electronics (as opposed to chemistry),
electrons flow along paths of positive voltage (i.e. from higher to lower voltage). The units of voltage are
volts (V).
We can draw an analogy between voltages and currents, and water pressures and flows. A voltage is
like a water pressure. If there is a pressure difference between two points, water will flow (like current)
between those two points to try and equalize those pressures.
There are two things we want to keep track of in our electronic circuits: voltage and current. Two
handy things to keep in mind are:
  • Voltage is across things
  • Current flows through things
Relating voltage and current: resistance
Now that we’ve established that an electron flow is current and that electrons flow from regions of high
voltage to low voltage, the next question you might ask is: how much current (how many electrons) will
flow when I connect two regions together.
A higher voltage difference should cause a higher current to flow (or reversing that statement, a higher
current means a higher voltage difference). What if they were just related by a simple constant? The
relation might look like:

                                                V =I ×R
                                                   V
                                                I=
                                                   R                                                    (1)
                                                   V
                                                R=
                                                    I

And in fact, this is Ohm’s famous law: The voltage across a device will be the current through the
device times the resistance of the device. Or equivalently, the current through the device is equal to the
voltage divided by the resistance. We’ve had to introduce a new constant: resistance, to describe how
current flows through various objects. Like its name suggests, resistance resists current flow. The unit
of resistance is an Ohm (Ω).
What do we expect the resistance of various objects to be? Well again, there are a couple of things we
might guess:
  • A thinner wire should carry less current than a thicker wire. So the thinner wire should have a
    higher resistance, just like a thick pipe can carry more water than a thin pipe.
  • A longer wire should carry a smaller current than a shorter wire. So the long wire should have a
    higher resistance, just like it’s easier to push water through a short hose than a long hose.

Owen Brasier/Sebastian Pauka/Alex McCulloch                                                              15
CHAPTER                                                                         NCSS Embedded Stream

Once again, the voltage is the resistance times the current. Remember this equation! Seriously. It’s
the foundation of everything.
Series and Parallel
The next question we might ask is what do resistors do when we start connecting them together. There
are two ways that we can connect them together:
  • Back to back, such that current passes through each of the resistors in series:

                                        Figure 7: Series Resistors

  • In parallel, such that the current can choose between multiple paths:

                                       Figure 8: Parallel Resistors

Before we start dropping equations, let’s again try and figure out what they should do intuitively.
  • If we put two resistors back to back, in series, they will both oppose the flow of electrons, so the
    current should drop. The resistance of the circuit should go up.
  • If we put two resistors in parallel, then the current can choose between two paths, so the total
    amount of current that can flow should go up. The resistance of the circuit should go down.
The simplest way we might think about implementing the series case is to have all the resistances add
together, and this is indeed what happens. The total series resistance is given by:

                                        Vtot = V1 + V2 + · · · + VN                                     (2)

In parallel the situation is slightly more difficult as we have to take into account the multiple paths that
current can flow. The equation becomes:

                                                               1
                                        Vtot =   1        1               1                             (3)
                                                 V1   +   V2   + ··· +   VN

Although this looks like a complicated equation, you can still draw some intuitive conclusions. If we have
two parallel resistors with equal resistance, then since we’ve doubled the number of paths that electrons
can take through equal resistances, the total resistance halves:

                                                               V
                                                  Vtot =                                                (4)
                                                               2

Try to plug two resistors into the above formula and see if you can get the same result…

Owen Brasier/Sebastian Pauka/Alex McCulloch                                                              16
CHAPTER                                                                         NCSS Embedded Stream

Analog and Digital
Now that we’ve defined and explained the key terms that we need to understand simple electronics, let’s
investigate what the signalling for sensors and microcontrollers actually looks like. We can break the
world of sensors down into two types: analog and digital sensors.
You may already be familiar with the concept of digital logic, this is what microcontrollers and computers
use internally. Digital circuits are either on or off. We don’t have ranges, it’s a binary world. On
or off. 0s or 1s. High or low. That’s it. On the micro:bit, we read digital values from pins using the
read_digital() function. For example, to read the digital value on pin0, we run pin0.read_digital().
Analog deals with continuous values, or ranges of values. So when we want to measure ranges of, for
example brightnesses, sound levels etc. we are often talking about analog sensors. On the micro:bit, we
read analog values using the read_analog() function. For example, to read the analog value on pin0,
we run pin0.read_analog().
So if we’re talking about things like “pressing a button” or “turning on a light”, we’re talking about
digital values. If we’re measuring a range, like “how bright it is”, we’re talking about analog values.
When we’re dealing with communication between sensors and microcontrollers we will almost always
be signalling with voltages. Both digital and analog signals need to map onto the voltages that our
microcontroller uses. When using digital circuits we usually define 0/low as ground: 0V, and 1/high as
the supply voltage. For a micro:bit that’s 3.3V. All digital signals that our micro:bit can read or produce
swing between these two ranges. For analog circuits, we still can usually only read voltages between
these two ranges (0V - 3.3V), but any value in that range is valid. 0V will represent the minimum value,
for example absolute silence for a sound sensor, and 3.3V will represent the maximum value, for example
the loudest sound that the sensor can sense.

Aside: Ground
One potentially confusing point about voltages is that voltages are relative. You can sort of think about
voltages as heights. We can talk about a height difference between two points on a mountain, but if
we want to talk about a universal height, we need to define where zero sits. For heights, we choose sea
level as our reference point, and call heights referenced to this point altitude. In electronics, things are
usually a little bit harder; there isn’t a universal point we can reference everything to. It’s up to us to
pick this point. Once we have, this point is called ground and by definition we say it is always at zero.
Since ground is just a point we choose, we have to make sure that whenever we are working with grounds
we are consistent with our choice. Once ground is connected to microcontrollers and sensors, those
sensors will assume that the ground they see is the same ground that every other connected component
sees. So it’s important to connect all the different grounds together, otherwise our signalling won’t
work. With disconnected grounds, the definition of logic high that one chip has might be different to the
definition of logic high that the other chip has.
Voltage Dividers
A voltage divider is one of the most common circuits that exist! It looks like this:

                                       Figure 9: A voltage divider

Given a voltage input, it produces a fraction of the input as the output.

Owen Brasier/Sebastian Pauka/Alex McCulloch                                                              17
CHAPTER                                                                        NCSS Embedded Stream

The equation for the output is:

                                                          R2
                                           Vout = Vin                                                  (5)
                                                        R1 + R2

The voltage divider produces a smaller voltage using the ratio of resistors, which we can calculate from
the equation above. For example we can make a simple volume control by changing the ratios of R1, R2
such that the output voltage being fed to our headphones is reduced.
At NCSS, the main way we’ll be using voltage dividers is to read in analog sensors, like a joystick, flex
sensor, or any sensor that changes its own resistance.
It’s hard for us to read resistance directly, but the micro:bit is really good at measuring voltages. So by
adding another resistor that is known and applying an input voltage that is known, by measuring the
output voltage, we can calculate the resistance of the sensor with our voltage divider!
What value resistor should we pick for any given sensor? The aim of the voltage divider circuit should
be to maximize the change in voltage when our sensor measures some change. If we look at how the
output voltage of a voltage divider varies as a function of the sensor resistance, what we find is that we
get the most sensitivity to changes in resistance when the value of the resistor in the voltage divider
is set to:

                                                                                                       (6)
                                                  p
                                         Ropt =       Rmin × Rmax

In practice this means we should measure the resistance of the sensor at the two extremes of what we
want to measure (for example in a bright room, and a dark room if we were using a resistive light sensor),
and choose a resistor value that we have that occurs between these two extremes, as close as possible to
the optimum.

                       Figure 10: Optimizing the sensitivity of a voltage divider

Calibrating Sensors
How do we know what the resistance means in the real world?
That depends on the sensor. Usually, looking up the datasheet will tell us what it means. But if it’s
something like a light sensor, we can calibrate the sensor ourselves by measuring the voltage at lots of
light, and measuring it again at no light, and getting a threshold of what we want to call enough light
to trigger an action (like turn on a light, because it’s dark).
Let’s see how you might do that in practice! First, the code to calibrate the sensor (which is R2 in our
voltage divider circuit). pin0 is Vout in the circuit diagram, and Vin is the micro:bit power at 3.3V.
from microbit import *
while True:

Owen Brasier/Sebastian Pauka/Alex McCulloch                                                             18
CHAPTER                                                                           NCSS Embedded Stream

     sensor = pin0.read_analog()
     print(sensor)
     sleep(50)
then once we have a threshold value, we write a simple if statement to trigger the action!
from microbit import *

threshold = 600        # Measured during calibration

while True:
    sensor = pin0.read_analog()
    if sensor > threshold:
        pin1.write_digital(1) # turn on a light
    else:
        pin1.write_digital(0) # turn it off
Pull-up and down resistors
A pull-up or pull-down resistor is a resistor that “pulls” a point that is floating to a positive voltage (pull
up), or to ground (pull down). This is used in digital circuits because everything has to be either on or
off.
Say we wanted to connect a button to a controller (we do want to do that, a lot), how do we wire it up?
For starters, it’s possible to wire it directly to the positive rail like this:

                          Figure 11: A floating switch. This probably won’t work!

But how do we know what the voltage is at the pin when the switch is open (not pressed)?
We don’t! The pin is floating, which means we can’t tell what the voltage at the pin will be. When
something is supposed to be either “on” or “off”, floating is the opposite of what we want, because we
have no idea what it is.
So what we do is use a resistor to pull the voltage to a known state when it isn’t connected to anything.

                                 Figure 12: A pull-down resistor on a switch

When the switch is open, the resistor pulls the voltage at the pin to 0V, and when it is closed, this
connects the pin directly to high (3.3V), so we never have an undefined voltage. This is called a pull-
down resistor since it pulls the voltage down to 0V

Owen Brasier/Sebastian Pauka/Alex McCulloch                                                                 19
CHAPTER                                                                           NCSS Embedded Stream

We can also invert the behavior of the switch by changing around the order of the switch and the resistor.

                                Figure 13: A pull-up resistor on a switch

In this case the opposite is true, when the switch is open the voltage at the pin is 3.3V, and when the
switch is closed, the voltage is 0V. For this reason it is called a pull-up resistor.

Does it matter if I use pull-up or down?
No, it’s just a matter of preference. It’s much more important to know what each of them means (and
write your code accordingly), and that you need to use one of them when you’re connecting a button (or
basically anything) to a digital input.
Level shifting
Digital circuits have a signal level that they use as their “on” voltage level.
On the micro:bit, a pin1.write_digital(1) will set the voltage on pin1 to 3.3V, that’s what “on”
means.
But some other circuits might use a signal of 5V to decide if something is “on”. For example, the neopixel
LEDs want 5V power and 5V digital signals, which the micro:bit simply can’t provide.
So what we do in this case, is use a level-shifter to transform the waveform.
Rather than building a circuit to do this ourselves (which you could do using a few transistors), we use
an integrated circuit (or chip) designed for this purpose. One example is the 74AHCT125, which converts
a 3.3V input signal to a 5V output signal (as shown in the diagram below).

                            Figure 14: Level shifting a signal from 3.3V to 5V

Level shifting can be generalised in that it is shifting from any voltage level to any other voltage level.
It is quite common the shift the other way (5V→3.3V where you might use 74LVC245 chip to do this).

Why do we even need this?
Some devices are only designed to work at a certain voltage. A 1 might be defined as a voltage above
a threshold, and if the logic level coming in is below that value, our device may not detect a 1 that we
send.
If a logic level is too high, it might be a value greater than a device will accept, so you could damage
the components. It’s important to send a value to a device that it expects, so it’s important to know the
voltage of your microcontroller (on the micro:bit it is 3.3V), and the voltage the device operates at.

Owen Brasier/Sebastian Pauka/Alex McCulloch                                                             20
CHAPTER                                                                        NCSS Embedded Stream

For example, neopixels (WS2812B is the name of the chip), are designed to run at 5V, the reason is
because extra voltage is required to produce the full range of colours from the LED, if you supply less,
some colours will not be as bright, so the white looks more like an off-brown.
Light Emitting Diodes (LEDs)
Almost every electronic device has an LED in it. Whether it’s just the power light, or some sort of status
indicator, or perhaps the device needs to produce a lot of light, they are everywhere.
Although there are many types of lights that can be used in circuits, we almost exclusively use LEDs
because of their excellent power efficiency, small size, and ease of use.

Theory
LEDs are a type of diode, which is a semiconductor device that contains a special junction that only
allows current to pass in one direction. The semiconductor junction in an LED is specially built such
that when current is flowing, the band gap of the semiconductor results in electron transitions that emit
photons of specific wavelengths. This is how LEDs have different colours, red LEDs produce photons
that have a wavelength of approximately 650nm, green are 520nm, etc. By combining different colours
(usually the primary colours, red, green, and blue) we can produce a whole rainbow of different colours.
There also exist LEDs that produce light outside the visible range, for example, ultraviolet (~300nm)
and infrared (~900nm). Infrared LEDs are used in television remote controls or night vision applications,
and ultraviolet has a wide range of uses from skin therapy to sterilization and even in the production of
white light using phosphors. This is how LED light bulbs you use in your house work, they are often
UV LEDs which cause a phosphor to glow.

Powering an LED
Diodes are “non-linear” or “non-ohmic” devices, which means that Ohm’s law doesn’t apply to them.
When they are conducting, they have very little resistance, and in the other direction they have a very
high resistance.
Something with a very low resistance effectively looks like a short circuit, which means that a lot of
current will flow and potentially damage the LED or the thing that is powering it (e.g. the micro:bit
pin). So what we need is a way to ensure that only a specific current flows, which is why every time we
use an LED, we also need a current-limiting resistor.

                           Figure 15: A current limiting resistor on an LED

*Note that in the symbol for an LED, the bar points towards the cathode (which should be connected
to the lower voltage, i.e. ground).
Typically we choose a desired brightness for our LED, and look up the LED’s data sheet to find out what
current it needs. Then we choose a resistor using Ohm’s Law (V=IR) to make that work. Remember
that devices in series will all have the same current flowing through them, so the current flowing through
the LED will be the same as what flows through the resistor.
Here’s the formula to figure out what resistor to use for a desired current:

Owen Brasier/Sebastian Pauka/Alex McCulloch                                                            21
CHAPTER                                                                        NCSS Embedded Stream

                                           Vres = Vpin − Vled
                                                  Vres
                                             R=
                                                   I                                                   (7)
                                                  Vpin − Vled
                                             R=
                                                       I

The Vled is the forward voltage drop across the LED. This is a property of the LED and it will be in the
data sheet. Typically it’s around 2 volts for a red LED.
So if we have an LED that is rated for 20mA at full brightness and has a forward drop of 2 volts, then
we get:

                                  Vres     =     3.3 − 2     =     1.3V                                (8)
                                                  1.3V
                                  R        =                 =     65Ω                                 (9)
                                                 0.02A

If we wanted it to be less bright, then for 10mA, the same calculations would yield 130 Ohms.
Resistors only come in specific values, so just round up to the nearest one (e.g. 68 Ohms or 150 Ohms).
But unless you’re adjusting for a very specific brightness, what matters more is that you have the resistor
at all. So most of the time people just use whatever resistor they have spare above about 300 Ohms (330
Ohms and 470 Ohms are extremely commonly used resistors).
Summary: If you want to use an LED, you must use a current limiting resistor. In almost
all cases, a 330 ohm resistor will do the trick.

More notes on current limiting resistors
  • Each LED requires its own resistor. Can you see why?
  • The resistor can be on either side of the LED, it doesn’t matter.
  • Sometimes you might choose to “invert” the LED by connecting it to VCC instead, then when you
    turn off the pin, the LED will turn on.
  • The micro:bit also has current limiting resistors for its built-in LED grid. They’re really tiny! Can
    you find them and measure their resistance?
  • Blue LEDs typically have a higher forward voltage drop, so will usually require a lower-value
    resistor for the same brightness. This is because the wavelength of blue light is much shorter than
    that of red light, so the photons that make up blue light are more energetic. The voltage drop
    across an LED is directly proportional to the energy of emitted photons.

Owen Brasier/Sebastian Pauka/Alex McCulloch                                                             22
You can also read