The Propeller microcontroller is a capable tool. It has 8 distinct processing cores (also called "cogs") that can each run their own small programs. Many of the sensors you will learn about in future BlocklyProp tutorials use one or two of these cores to read values from the sensor and to prepare them for you to use in your program. You can use these extra cores too, and this tutorial will show you how.
This set of lessons requires only your Propeller development board, its source of power, and its USB programming cable. It was written for the Propeller Activity Board WX in the BlocklyProp Starter Kit, but the Hackable Electronic Badges will also work fine.
Complete the two tutorials below first, so you have a solid foundation for understanding these BlocklyProp Functions and Multicore tutorials.
Upon completion of this tutorial, you will be ready to build more powerful and compact Blockly programs with your own custom-made functions, and run those functions in the multicore Propeller's processors. You will also understand how other BlocklyProp blocks make use of the Propeller's multiple cores, such as those for various sensors, which is helpful when building projects with lots of parts.
Functions are blocks of code that you put together to complete a specific job. Think of a function like a single block that you make, so you can use it over and over again. Just like other blocks, you can put it in your program anywhere that you need it, and as many times as you want.
With BlocklyProp, making a function is easy. Take a look at the example below:
To make a function, enclose a group of blocks with the define function block, and then give it a name. After that, in the FUNCTION menu you will see a new run function block with that name, to use in your program. In this example, when our BlocklyProp program gets to the run function “printAge” block, it jumps to the matching define function block and runs the code inside of it. Upon completion, it jumps back and the program continues on.
Functions are handy if you have to repeat the same code in a few different places in your program. Instead of using many blocks over and over, you can place those blocks in a function. Then just use one run function block wherever you need it in your program.
Blockly Variables are Global. Did you notice that the variable item countdown was defined right inside the run function "printAge" block? That did not prevent it from being used inside the oldAge function. In BlocklyProp, all variables are available for use by any other part of the program. This is not always the case in some programming languages, as you might learn if you study C.
In the last tutorial, a function you created only ran when it was called by the run function block. There are, however, situations where you need a function to run continuously on its own in the background while the rest of the program keeps going, Such a background function might keep watch on a button press or a sensor reading. The Propeller chip on the Activity Board (original or WX version) can do more than one thing at a time easily, because it is a multicore microcontroller. You will try that in the next lesson. But first, let's visualize this multicore thing before we work with it directly.
A microcontroller is an integrated circuit that includes a tiny processor "brain" to do the “thinking” and some memory for "taking notes" so it can keep track of what it is doing. Microcontrollers also have input/output pins, I/O pins for short, that can exchange electrical signals with other devices such as lights, switches, beepers, motors, and sensors.
A single-core microcontroller has just one processor inside. It is multitasking when it executes several tasks that must share its single processor. The processor must interrupt each task and switch briefly to another, to keep all of the processes going.
Imagine a chef in a kitchen alone, making bread, roast beef, and sauce. The chef must knead the bread dough for 15 minutes, interrupt that task every minute to stir the sauce, and remove the roast from the oven as soon as a thermometer reaches 120 °F. At any moment, the chef (processor) is executing only one task, while keeping all three processes (kneading, stirring, roasting) going at once.
Now imagine being that chef. The more tasks you must do at once, the more difficult it gets to keep track of them all, and keeping the timing right becomes more of a challenge.
A multicore microcontroller has two or more processors inside. It is multiprocessing when it executes several tasks at once, with each task using its own processor. This is also referred to as true multitasking.
Imagine a chef in a kitchen with three assistants, making bread, roast beef, and sauce. The chef puts one assistant at the stove to stir the sauce every minute. Another assistant is sent to keep watch on the thermometer, and remove the roast when it reaches 120 °F. Now the chef is free to knead bread dough for 15 minutes. The three cooks (processors) are keeping all three processes (kneading, stirring, roasting) executing at the same time, without any task-switching interruptions, and without missing the moment when the thermometer reaches 120 °F. There is even an extra assistant ready to help if something more is needed.
Multiple cores makes it easier to do many tasks at once, especially if precise timing is needed.
The Propeller microcontroller has 8 cores (sometimes called cogs) and so can do multiprocessing, also called true multitasking. The cores are all the same. It has 32 I/O pins, which are also all the same. Each core can work with every I/O pin. This means that all of the Propeller cores and I/O pins are equally good at any tasks they must perform. Each core has a bit of its own memory. Each core also takes turn accessing its Hub, where a larger Main Memory (a big "notepad") allows them to share information.
Got it? Now, let's try using the new processor block to run a function in its own Propeller core.
In the previous tutorial, a function you created only ran when the run function block called it. There are, however, situations where you need a function to run continuously on its own in the background while the rest of the program keeps going. Such a background function might keep watch on a button press or a sensor reading. The Propeller chip can do more than one thing at a time because it is a multicore microcontroller.
With BlocklyProp, the CONTROL > new processor block lets you run a function in its core, while the rest of the program keeps on executing at the same time.
The example below launches a new processor to keep track of how long the program has been running. Because a separate processor is used to keep track of the running time, the main program can stop and wait for the user to press a key before it displays how long the program has been running.
IMPORTANT! You may use only ONE run function block inside each new processor block!The new processor block starts the function named "timer" running in its own processor. It will continue to run its repeat forever loop while code execution in the main program continues.
As the function timer continues to run, the variable named "counter" increases by 1 every second. The rest of the program waits for you to press a key and when you do, it displays counter, which equals how many seconds the program has been running.
The next program you will create is a basic clock. It will use a new processor block to keep track of the time. The time will be displayed in the Terminal when you press any key.
The main program initializes the hours and minutes variables then launches the My Clock function into its own processor. After that, a repeat forever loop displays the time in the Terminal when a key is pressed. It is getting the time information from the My Clock function running it its own core, endlessly. That's why the values of minutes and hours are always up to date when you press a key in the Terminal again.
The My Clock functions adds 1 to the variable minutes every 60 seconds. When the variable minutes goes over 59, it adds 1 to the variable hours and sets the variable minutes back to 0.
Variables are still global! Even though the variable counter is set inside a function running in a new processor, it is still accessible from the main program. You can visualize that as though all the variables are written down on the big notepad in the middle of the Propeller that all of the cores can share.
Print from Main ONLY! The Terminal blocks cannot be used in a function that is launched with a new processor block. The same is true for the OLED display module blocks.
Give It Some Time! If you update the value of a variable item in a new processor, add a pause in your main program before trying to print the value of that variable to the Terminal. Otherwise, in rare cases the main program might print the old value before the new processor has a chance to spin up and update it.
There are 8 processors in the Propeller microcontroller. Your main program uses one of them, leaving you up to 7 additional processors that you can use for your own functions. However, there is a bit of a catch. The blocks for some of the sensors and devices use their own processors to operate, therefore leaving you with fewer than 7 extra processors.
There is a trick you can use to see if your new processor started, thanks to those global variables: Add a variable item to the top of your main program, update it at the beginning of your new processor's function, and then print the variable from the main program again. If the variable changed, you know the processor launched.
Links
[1] https://learn.parallax.com/tutorials/language/blocklyprop/getting-started-blocklyprop-solo
[2] https://learn.parallax.com/tutorials/language/blocklyprop/simple-blocklyprop-programs-propeller-boards