Easiest way to make two gadgets talk to each other is via Serial Communications. Serial communications is everywhere in our daily lives: USB, Bluetooth, TV-Remote, WIFI-Routers, etc are all devices that make use of serial communications. And it is no surprise that we can learn how to make use of this technology with the help of MicroBlocks Serial Library.
In this tutorial, we will learn how to transmit characters using a micro:bit v2 device and the Serial Library. Additionally, we will show how this task can be coded without using the library. And in the process, we will explore how characters are encoded, sent and received, bit by bit, using the serial communications techniques.
NOTE: If you are interested in trying this tutorial on other hardware platforms, please refer to the Pin Information article on our WIKI for correct assignment of the available pins on various platforms.Parts
To complete this tutorial we will need:
- a micro:bit ver2 device (or equivalent)
- alligator clips or a jumper cable
- {optional) an Edge Breakout board (three samples shown below)
While it is possible to make do with just a micro:bit and an alligator cable, this setup will be a bit unstable and hard to manage. The more secure and easier method would be to use one of many Edge Breakout boards to make the connections. This will help you achieve a more stable connectivity and performance.Here are both ways to setup the connections.
For this exercise, we have provided a single script that demonstrates two techniques:
- how to send / receive letters using the MicroBlocks Serial Library
- and how to achieve the same by writing our own code to do it
In the script pictures below, the blocks under:
- when started blocks help to setup the project operational details and provide optional graphing of the bits sent.
- when button A pressed blocks send and receive a letter using the Serial Library.
- when button B pressed blocks send and receive a letter using our own coded serial communication functionality.
NOTE: In the when started block set, there are blocks pertinent to both the Button-A and Button-B versions of the code. For simplicity sake, When describing blocks of each version, the blocks not pertaining to the particular version have been left out. Similarly, there are various information display blocks in both versions that have not been addressed due to the simplicity of their functions (eg: wait and say blocks).Process
For those interested only in the high-level functionality of sending and receiving letters across two ports of the micro:bit, what follows is a brief description of the Serial techniques. For those interested in more in depth treatment of the Serial Communications and UART operations, we'd like to redirect you to the Manually coding the Serial Transmission details section of Two Ways To Do The Same Thing further below.
Serial Communications BasicsBefore we dive into the details of the blocks, let's review the very basic principles of the character transmissions using a serial interface.
Characters are transmitted and received in binary format, one bit at a time. The least significant bit (LSB) is transmitted first, followed by all other in sequence.
Binary Encoding of LettersTo get the binary format of any letter, we need to go through a process of converting ASCII values of characters into their binary equivalents. To better explain what we are talking about, here is a sample table, showing letters of the alphabet and their ASCII and binary values.
Letter ASCII Binary Letter ASCII Binary
Code Code
A 065 01000001 a 097 01100001
B 066 01000010 b 098 01100010
C 067 01000011 c 099 01100011
D 068 01000100 d 100 01100100
E 069 01000101 e 101 01100101
F 070 01000110 f 102 01100110
G 071 01000111 g 103 01100111
H 072 01001000 h 104 01101000
I 073 01001001 i 105 01101001
J 074 01001010 j 106 01101010
K 075 01001011 k 107 01101011
L 076 01001100 l 108 01101100
M 077 01001101 m 109 01101101
N 078 01001110 n 110 01101110
O 079 01001111 o 111 01101111
P 080 01010000 p 112 01110000
Q 081 01010001 q 113 01110001
R 082 01010010 r 114 01110010
S 083 01010011 s 115 01110011
T 084 01010100 t 116 01110100
U 085 01010101 u 117 01110101
V 086 01010110 v 118 01110110
W 087 01010111 w 119 01110111
X 088 01011000 x 120 01111000
Y 089 01011001 y 121 01111001
Z 090 01011010 z 122 01111010
As can be seen, each letter has a corresponding binary value associated with it. This binary value, which consists of 1's and 0's, is what gets transmitted over the cable. 1 and 0 nature of this data is very suitable for transmission purposes. As we all know, computers like 1's and 0's and know how to deal with them. In serial communications, these 1's and 0's are represented as the presence of changing voltages on the pins of the micro:bit:
- a 1 bit is represented by a high voltage
- a 0 bit is represented by a low voltage
For example, if we take the letter M with its ASCII value of 77 and binary encoding of 01001101, the computer would transmit this binary value as a sequence of digital signals that look like this:
There are a few more technical details that go into making a successful serial transmission. But for our purposes, understanding the encoding and its digital representation is enough to go through this tutorial.
Binary Encoding ProcessNow, how do we get from a letter to its binary encoded format?
Simple! We write a custom block and do the conversion. It is simply a decimal to binary conversion routine. We input a decimal ASCII value of a letter into our custom block, and it returns a list that consists of the 1's and 0's representing the corresponding binary value. Since MicroBlocks digital signal blocks work with True / False values instead of the 1's and 0's, our custom block also returns the binary list encoded in true/false format. To elaborate on the previous example, the letter M would be encoded as: FTFFTTFT where F:false (0) and T:true (1).
The code for our custom block is very simple and is presented below:
As we mentioned in the beginning, we will present two different ways to accomplish the transmission of our letters:
- Using the Serial Library
- Manually coding the Serial Transmission details
This is the easy way! All the hard work is done by MicroBlocks and all we need to do is pick a few blocks from the Library and go about our business. We are spared from all the technical details of the serial transmission thanks to the Serial library.
This version of the task is coded in our project under the Button-A activity.
Button-A activity consists of two separate tasks run in parallel:
- one task for the sending activity
- one task for the receiving activity
When you press Button-A, these two parallel tasks will start running. While the sending side will be telling the library block to send out the character selected, the receiving side will be telling the library block to receive and store the character.
Once you complete the connections as described in the section Making the connections, you can try it out by doing the following:
- Press the RESET button on the micro:bit to initialize everything
- Then press Button-A
Pressing RESET should do the following:
When Started Blocks
- Variable BAUD will be set to the transmission speed
- Initialize transmit and receive pins to be used
- A randomly selected character (A-Z) will be placed into the char variable
- A checkmark will be displayed on the micro:bit LED display to indicate setup part is completed
Pressing Button-A should do the following:
Sending Activity:
- Graph display control will be initialized
- The selected character will be displayed on the micro:bit LED display
- Serial Library block serial open will open the connection at stated speed and serial write will send the character out.
Receiving Activity:
- micro:bit will display a smiley to indicate receiving has started
- Variable pinValue will be assigned the character that is received from Pin-0
- Character received will be displayed on the micro:bit LED display
- Graph activity will be stopped
- ASCII value of the received character will be converted to binary format using the custom blocks dec2TF and TF2INT
- The script will display the details of the received character and its encoded information.
This is the way that you will get the most out of this tutorial! All the hard work has to be done by us. Also, in this section, we will provide much more detailed information about the blocks used and their functionalities.
This version of the task is coded in our project under the Button-B activity.
Button-B activity consists of two separate tasks run in parallel:
- one task for the sending activity
- one task for the receiving activity
When you press Button-B, these two parallel tasks will start running. While the sending side will be busy transmitting the bits of the character being sent, the receiving side will be processing each bit received and storing them until a full transmission is complete.
While all this sounds almost like the Button-A description, there is a huge difference. In this version, the computer will be performing the character transmission according to the way we are going to instruct it. There will be no Library blocks to help us out.
Once you complete the connections as described in the section Making the connections, you can try it out by doing the following:
- Press the RESET button on the micro:bit to initialize everything
- Then press Button-B
Pressing RESET should do the following:
When Started Blocks
- Variable BAUD will be set to the transmission speed. What does the BAUD value represent? It simply states the number of bits we want to transmit in one second. We have a possibility of various values here: from 20 to 2400. There are higher values possible, but due to the performance details and coding complications, our code will run reliably only within these limits.
- Variable DELAY will be calculated. Here is a bit of explanation why we need this variable. When we transmit the bits of the character one after another, there needs to be a way for the receiving side to figure out when to know a bit has ended and when a new one starts. Since we only use a single cable for the transmission, there are no other signals involved, that we can rely on. So, it is up to us to create a way to send and receive the bits, without mixing up the signals. Here is a simple way this can be accomplished: We figure out a starting signal (the start-bit) and then wait a specific amount of time before sending out each bit. We also wait exactly the same amount after each bit. This amount of time is what we refer to as the DELAY, and it just got calculated in this step. To be able to use the microseconds as the unit of our delay period, we have divided 1, 000, 000 into the BAUD rate. This tells us that we need to wait DELAY microseconds between the tranmission of the bits.
- Initialize the Graph Information pin. This pin is used to graph the bit patterns received. It can be any pin available in the system. For specific Pin Information please refer to the WIKI article for correct assignment of the available pins on various platforms.
- Initialize transmit and receive pins to be usedSerial communcations can occur between any two sets of pins of a micro computer. In our case, these are the Pin-0 for receiving and Pin-1 for transmitting. While the Library version of our code has to obey the Library conventions and use pins 0 and 1 for the Serial blocks, we do not have to go by that rule. We are coding our own method and we can use any two pins we want. We just need to be careful of not conflicting with any other micro:bit functionalities when selecting our pins. So, for the initial tests, use the pins 0 and 1. And then you can experiment with others.
- A randomly selected character (A-Z) will be placed into the char variable. The table with the letters A-Z and a-z in section Binary Encoding of Letters, gave us a listing of the encodings for each letter. Here we use a random function to pick a number between 65 and 90. These numbers represent the ASCII values of the upper-case letters. This way, we will select a different letter each time we run our code.
- Variable bitsList is calculated by converting the ASCII value of the character selected into the binary equivalent. There are no number system conversion functions in MicroBlocks, except the one from HEX to Decimal. The actual conversion from the ASCII value to the binary has to be done by a custom block we have written. Here is the code for it:
It is a simple version of the many algorithms that can be found on the Internet. You can look it up and study it, if interested in the details.Also, the section Binary Encoding Process provides further details on this custom block.
- A checkmark will be displayed on the micro:bit LED display to indicate setup part is completed
- Pin-1 (transmit pin) is set to a true (high) state.Explanation for this will be in the Button-B section below.
- The graphing of the bits is started.
We mentioned in the opening section that the code we have could also graph the bits sent and received. This block set checks the status of the boolean variable stopGraph, and keeps graphing the results of reading the digital GRpin (Pin-2 here; but can be any assigned pin). GRpin is constantly updated by a parallel running block set, that starts when the program is started.
This simple loop keeps copying the status of the Pin-0, the receive pin; to GRpin. This way, when we continuously graph the value of GRpin, we are actually graphing the bit values received.
This completes the explanations of the when started portion of the code. Now we can proceed to the description of the activities when the Button-B is pressed.
Pressing Button-B should do the following:
Let's review at a high level all that we have to accomplish in this section:
- As far as the sending activity goes, we need to signal the receiving side that we are starting with the transmission of the bits. And then we need to send all eight bits of the character with proper delays. At the end, we will signal that we are done.
- As for the receiving activities, here is what has to happen. We wait for the start of the transmission signal. When we detect it, we start reading the bits from Pin-0 until all eight are received. After the full character is received, we display the information and stop.
Let's look at the blocks in detail.
Sending Activity:
- The selected character will be displayed on the micro:bit LED display
After a one second wait, we will display the character ">" to signal that we are starting the bit transmissions.
- Pin-1 (transmit pin) is set to a true (high) state.This gets us ready to signal the other side that a character transmission is about to begin. We set the Pin-1 signal to true. Then we wait DELAY microseconds, and then in the next step, we set it to false.
- Here is the start signal: Pin-1 is set to false.
Then we wait DELAY microseconds.
- We start sending all eight bits of the character in a loop, waiting DELAY microseconds after each bit.
Under when started block set, we had stored the bit representation of our character in the variable bitsList. Here, we iterate through that list and send the bits out by changing the status of the Pin-1 to the value of the bit (true/false).
- Send out the stop signal: Pin-1 is set to true
Once we are done with all of the eight bits, we signal the other side that we are done. We do this by setting Pin-1 to a true state, and waiting DELAY microseconds.
This completes the sending activities side of the process for Button-B.
Now, let's examine the parallel events happening on the receiving side.
Receiving Activity:
- We start by preparing the variable bits as an empty list, that will be used to store the incoming bits.
- Then we start monitoring Pin-0 (receive pin) for the start signal: Pin-0 goes false.
When we detect the start signal, we wait for the DELAY microseconds, and then get ready to receive the bits.
- Receive all eight bits in a loop and store them in the bits list.
We store the incoming bit values (true/false) by adding the Pin-0 value to the bits list.
- When all the bits are received, we wait about a second and set the boolean variable stopGraph to true. This makes the graph window display a small mount of graph activity after the last bit and then stop graphing.
The graph picture will look something like this, depending on the bit values of the character received. Below is a graph for letter M.
- Received bits are converted from bits list true/false format to the decimal ASCII value. This is done by a custom code block we have written: TF2dec. Here is the code for it:
This block set calculates the decimal value of the bits received. Since the bits are received as true/false values, another small custom block set, TF2INT is used to convert them from true/false to 1's and 0's. Here is the code for that:
As can be seen, it performs a simple conversion of true/false values to 1's and 0's.These bit values are converted to the decimal positional values by using a ** bitwise left shift operator**. We shift each bit position as many times as the bit position value and derive a decimal value for that bit. Then we add it to a variable called output and total it. Refer to bitwise left shift for details of this block.The decimal value calculated is used to lookup the character symbol, and store it in the pinValue variable.
- Next we display the character we have received on the micro:bit LED display, so we can confirm the transmission was correct.
- We then convert the true/false values stored in the bits list into 1's and 0's, so that we can display the bit encoding for the character received. Refer to TFT2INT custom block described above.
- Finally, the character info and its bit pattern is displayed on the MicroBlocks scripting area. We have also shown the graph of the bits received.
NOTE: Since the bits are sent and received in the order of LSB to MSB, the received character's binary encoding is displayed in REVERSE order. To match the values listed in the table in the beginning section, read the 1's and 0's displayed in right to left order.Discussion
This tutorial was based on a single character transmission, in order to simplify the coding necessary, and focus on the basics. Here are some other changes that would be interesting to implement, proving that concepts described have been comprehended.
The Library use version of the code, Button-A activities, are capable of sending and receiving at very high speeds: 20 baud to 115200 baud. Try to modify the code to achieve these higher speeds.
Current exercise sends out the uppercase letters A-Z. Try modifying the code to send out the lower case letters, as well as the numbers 0-9.
Another good expansion idea would be to modify either the Library based code or the custom coded version to send and receive more than one character; as well as longer length strings.
Multi-Platform SupportA unique capability of MicroBlocks environment is that same code base can be used with many of the 32-bit micro processor boards. So this tutorial can be tried on any of the following (some might require a pin breakout board), as well as the Raspberry Pi platforms.
Refer to Board Guide for more information.
Comments
Please log in or sign up to comment.