This C-language tutorial is for the 8-core Propeller microcontroller. It features the Propeller Activity Board (original or WX version) or Propeller FLiP. Other Propeller boards will work in most cases; check each activity's circuit for notes.
Build simple circuits on a breadboard, and write Propeller C programs to interact with them. Blink lights, beep a speaker, monitor a dial, measure or set a voltage, and sense light.
You do not have to do all of these lessons in order — just choose what you need. Some "Your Turn" suggested activities will challenge you to combine various circuits, though.
You will be ready to make your own projects that combine these simple electronic components. How about making an LED blink faster by turning a dial, or using pushbuttons to make the piezo speaker beep different tunes?
Once you have learned Simple Circuits, don't forget to move on to Simple Devices [5] to put those new skills to the test!
The Propeller microcontroller has 32 input/output pins, or I/O pins, that are designed to interact with other circuits. The circuits in this example are built into the Propeller Activity Board's printed circuit board, but later examples' circuits are constructed using the white breadboard prototyping area. This tutorial can be done using a Propeller FLiP module as well.
We'll experiment with the "O" (output) feature of an I/O pin by programming the Propeller to use an I/O pin to turn a light on and off.
Our light circuit is already built into the Propeller Activity Board (original or WX version), Propeller FLiP, and the Propeller Board of Education.
Note: if you are using a different Propeller board, build the equivalent circuit using the schematic.
Now, let’s try running an example program that blinks the LED light connected to P26.
The function call high(26) sets the Propeller chip's P26 I/O pin to output-high, which connects the pin to its 3.3 V supply. The pin applies 3.3 V of electrical pressure to the LED circuit, causing electric current to pass through it and the light to turn on. After that, pause(100) makes the program do nothing for 100 ms, which keeps the light on for 1/10 of a second.
Next, low(26) sets P26 to output-low, which connects the pin to its 0 V ground supply voltage instead. This takes away the electrical pressure, so the current stops flowing through the circuit and the light turns off. Another pause(100) makes the light stay off for 1/10 of a second.
Those four commands are in a code block in a while(1) loop, which repeats endlessly, so the light keeps blinking.
/* Blink Light.c Blink light circuit connected to P26. */ #include "simpletools.h" // Include simpletools int main() // main function { while(1) // Endless loop { high(26); // Set P26 I/O pin high pause(100); // Wait 1/10 second low(26); // Set P26 I/O pin low pause(100); // Wait another 1/10 second } }
The simpletools library has lots of useful functions for controlling and monitoring circuits; high, low, and pause are just three examples. Click the SimpleIDE Help menu and choose Simple Library Reference to see a link to the simpletools library's functions.
You can make the light blink faster by reducing the pause function’s parameter. For example, to blink the light twice as fast, just reduce the pauses to half as long.
Try controlling the P27 light along with the P26 light.
Many items you use every day have pushbuttons. Cell phones, microwave ovens, TV remotes, and computer keyboards might all have pushbuttons.
Here we introduce a common pushbutton circuit and a program for monitoring it with your microcontroller. It also shows how to use a pushbutton's state to control LED light circuits. Keep in mind that lights are just one example of a device you can turn on and off with a microcontroller. Your invention might instead use pushbuttons to control circuits for motors, heating elements, or other devices.
This circuit uses the same P26 and P27 LEDs on the Propeller Activity Board or FLiP from Blink a Light [8], along with two pushbutton circuits you will build onto your breadboard.
(2) pushbuttons (#400-00002)
(2) 100 ohm resistors (brown-black-brown) or (2) 220 ohm resistors (red-red-brown)
(2) 10 k-ohm resistors (brown-black-orange)
If you don't have 100 ohm resistors, switch them out for 220 ohm resistors (red-red-brown) when setting up your circuit. The Activity Board diagram shows 100 ohm resistors, the FLiP breadboard shows 220 ohm resistors.
Note: Use the schematics with any Propeller board that has a prototyping area. This activity will not work with the resistive touch-buttons on the Propeller QuickStart.
This example will display the state of the button connected to P3 in the SimpleIDE Terminal. It displays 1 if the button is pressed, or 0 if it is not pressed.
The pushbutton circuit: When the pushbutton is not pressed, the circuit applies GND (0 V) to the I/O pin. If the pushbutton is pressed, the circuit applies 3.3 V to the I/O pin, and a small amount of current passes from the 3.3 V connection, through the 10 kΩ resistor to ground. Setting P3 and P4 to input lets the I/O pins monitor the voltages on the pushbutton circuits while remaining invisible to them.
The code: The simpletools library’s input function returns 1 if the button is pressed, or 0 if it is not pressed. int button = input(3) copies the result to a variable named button. Then, pause(100) delays for 1/10 of a second before repeating the while(1) loop.
/* Button Display.c Displays the state of the P3 button in the SimpleIDE Terminal. 1 -> button pressed, 0 -> button not pressed. */ #include "simpletools.h" // Include simpletools int main() // main function { while(1) // Endless loop { int button = input(3); // P3 input -> button variable print("button = %d\n", button); // Display button state pause(100); // Wait 0.1 second before repeat } }
Remember if...else if... statements from Make Several Decisions [10]? You can add one of those statements to your program to make the light blink if the button is pressed, or stay off and just wait for 1/10 of a second before repeating if the button is not pressed.
Can you modify your program to make the LED connected to P27 blink when the button connected to P4 is pressed?
Many devices beep to get your attention. Microwave ovens let you know your food is ready, alarm system keypads respond when you press a number key, and smoke alarms warn you something is burning. These devices often use piezospeakers because they are inexpensive, yet make clear, audible tones. If you make a project that needs to beep to get someone’s attention, consider using a piezospeaker.
Ever notice how a guitar string has to vibrate to make sound? The same applies to the element in a piezospeaker (short for piezoelectric speaker). The piezoelectric element in the speaker bends when voltage is applied to it. If you turn the voltage on and off rapidly, it will vibrate rapidly and make a sound.
It's easy to program the Propeller to make an I/O pin turn on/off rapidly. Let's connect a piezospeaker's positive (+) terminal to P4, and its unmarked negative terminal to GND.
(1) Piezo speaker (#900-00001)
Note: if you are using a different Propeller board, build the circuit using the schematic on the right of the top image.
The test code will make the piezospeaker beep for one second with fairly high-pitched tone.
The freqout function has parameters of pin, msTime, and frequency. The function call freqout(4, 1000, 3000) sends an alternating high/low signal to pin 4, for 1000 ms (or 1 second), at a frequency of 3000 Hz (3000 times per second). Since the speaker is connected to P4, this rapid 3.3 V to 0 V high/low sequence makes the piezoelectic element in it vibrate 3000 times per second. The result is a high-pitched tone.
/* Piezo Beep.c Beep a piezo speaker connected to P4. */ #include "simpletools.h" // Include simpletools int main() // main function { freqout(4, 1000, 3000); // pin, duration, frequency }
If you want to make your code do something while it's broadcasting the tone, use the squre_wave function instead. It's the "set it and forget it" version of freqout. Check the simpletools library documentation for more info. You can find it at: ...\Documents\SimpleIDE\Learn\Simple Libraries\Utility\libsimpletools\Documentation simpletools Library.html
When you press a key on a piano, it makes a small hammer strike a tightly pulled wire, causing the wire to vibrate at a certain frequency. Here are the frequencies of some higher keys to the right side of the piano keyboard:
You can use an array to store note values, and then play them with a for loop. (See Array Variables [11] for a refresher.)
You can also use #define to give your frequencies note names, and then you can use those note names in your array in place of the numbers. It’ll make your digital composing a lot easier.
Voltage is like a measure of electrical pressure, and measuring voltage answers questions like: “How much life is left in this battery?” and “How much does this sensor detect?”
A normal, alkaline AA battery might measure 1.6 or even 1.65 V across its terminals when it is new. After it’s been used for a while, measure it again and it may only have 1.45 V. By the time it gets down to 1.3 or 1.2 V, it is wearing out and may not be able to power whatever device it is in.
Many analog sensors output a voltage that varies in proportion to the sensor's input. Joysticks are a common example, where voltage varies depending on the position of the stick. Let’s try measuring the actual sensor inside a joystick; it’s called a potentiometer. Let’s also test the voltages on your board’s GND, 3.3 and 5 V supplies.
This activity is not compatible with the Propeller FLiP.
The Propeller Activity Board has four analog to digital (A/D) channels for measuring voltage. We’ll use A/D2 for probing the supply voltages. In the picture below, A/D2 is connected to GND, but we’ll also use it to probe 3.3 V and 5 V. A/D3 is connected to a potentiometer sensor’s output. As you turn the knob on top of the potentiometer, its voltage will tell you what position you have turned it to.
(1) 10 k-ohm single-turn potentiometer (#152-01031)
If the potentiometer keeps popping out of the breadboard, use a pair of pliers to gently straighten the potentiometer's legs.
Note: This lesson is designed for the Propeller Activity Board (original or WX version). It is not compatible with the Propeller Board of Education, which uses a different A/D converter, or the Propeller FLiP, which does not have an onboard A/D converter.
The test code will display the voltages at A/D2, which should be zero volts, and A/D3, which will vary as you turn the potentiometer’s knob. Here’s an example with the A/D2 correctly measuring GND as 0.00 V, and measuring the dial at about 1.62 V. That is about half way through the dial's range of motion, and about half of the total 0.0 to 3.3 V voltage range.
The A/D converter compares the voltage levels it measures to GND, so that’s its 0 V. That’s why A/D2 displays 0 V, because it’s connected to GND. You can also use A/D2 your board’s 3.3 V and 5 V supplies.
The code includes the adcDCpropab library, which is designed for measuring voltages using the A/D converter on the Propeller Activity Board (original or WX version). This library's function adc_init gets called first, to tell it which Propeller I/O pins are connected to the A/D converter's /CS, SCL, DO and DI pins. You will find these numbers next to the A/D converter chip, which is right below the GND sockets on your board.
After that, float v2, v3 declares two floating point variables for storing measurements. Inside the while(1) loop, v2 = adc_volts(2) stores the voltage at A/D2 into the v2 variable, and v3 = adc_volts(3) does the same for A/D3. A couple of print calls display the two voltage values, followed by a 1/10 second pause before the loop repeats.
/* Measure Volts.c Make voltmeter-style measurements with the Propeller Activity Board. */ #include "simpletools.h" // Include simpletools #include "adcDCpropab.h" // Include adcDCpropab int main() // main function { adc_init(21, 20, 19, 18); // CS=21, SCL=20, DO=19, DI=18 float v2, v3; // Voltage variables while(1) // Loop repeats indefinitely { v2 = adc_volts(2); // Check A/D 2 v3 = adc_volts(3); // Check A/D 3 putChar(HOME); // Cursor -> top-left "home" print("A/D2 = %f V%c\n", v2, CLREOL); // Display volts print("A/D3 = %f V%c\n", v3, CLREOL); // Display volts pause(100); // Wait 1/10 s } }
The adcDCpropab library’s adc_in function returns the actual numbers the A/D converter sends the Propeller chip. As mentioned earlier, these numbers vary from 0 to 4095, and represent voltage measurements as a number of 4096ths of 5 V.
Temperature probes are another common analog sensor with a variable-voltage output. Imagine that you have a terrarium with this kind of temperature sensor. The terrarium is too warm for its occupants if the sensor's output exceeds 1.0 V, or too cold when it goes below 0.5 V.
This lesson uses D/A conversion to make the LED lights on the Propeller Activity Board (original or WX version) brighter or dimmer.
In the lesson Blink a Light [12], the Propeller is programmed to output 3.3 V on an I/O pin to turn a light on, and to output 0 V to turn a light off. The Propeller can also be programmed to switch an I/O pin between 0 and 3.3 V very rapidly, in a pattern that delivers an average output voltage anywhere between 0 V and 3.3 V. These duty-modulation patterns, called duty-modulation signals, change the average "on" time for the LEDs which our eyes will interpret as different levels of brightness.
This activity is not compatible with the Propeller FLiP.
Although you can do this kind of duty-modulation D/A conversion for LEDs on any Propeller I/O pin, P26 and P27 have LEDs built into the Propeller Activity Board (original or WX version), so let’s use those.
On the Propeller Activity Board (original or WX version), P26 and P27 are also connected to filter and amplifier circuitry that converts the duty-modulated D/A signals into steady voltages. Those voltages are then available at the D/A sockets, D/A0 and D/A1. These sockets are useful for other circuits that might need need a specific steady voltage but draw a varying amount of current. We can use the board's A/D converter to measure the voltages we set on the D/A sockets.
Note: This lesson is designed for the Propeller Activity Board (original or WX version). On the Propeller Board of Education, you can use this D/A technique to control the brightness of LEDs. However, the Propeller Board of Education uses a different A/D converter chip, so trying to use the A/D sockets to measure the voltage at the D/A sockets will not work.
This example program will make P26 send a 2.5 V signal to D/A0, and P27 send a 1 V signal to D/A1. As a result, the P26 LED should be considerably brighter than P27.
The dac_ctr(26, 0, 194) call has three parameters: pin, channel, and dacVal. Pin is the Propeller I/O pin that you want to send the D/A signal, and this example uses 26.
The channel parameter allows you to select one of two counter modules (0 or 1) in a Propeller core (also called a cog) to generate the duty-modulation signal. This example uses channel 0.
The dacVal parameter allows you to set the voltage as the number of 256ths of 3.3 V. This example uses 194, so we'll expect D/A1 to send 194/256ths of 3.3 V. That's 2.5 V because 194/256 * 3.3 V ≈ 2.5 V.
Next, the dac_ctr(27, 1, 78) call sends a D/A signal with P27, channel 1, and D/A1 gets 78/256ths of 3.3 V ≈ 1 V.
Since we added wires to connect the D/A voltage outputs to the A/D voltage inputs, we need code to read and display the those voltages. A call to adc_volts(0) returns the measured D/A0 output, and adc_volts(1) returns D/A1’s output. Instead of storing those measurements in variables, the calls to adc_volts are nested right in the print statements, which can use their return values directly. So, print("A/D0 = %f\n", adc_volts(0)) sends the result of the adc_volts(0) call straight to the SimpleIDE Terminal. Likewise with print("A/D1 = %f\n", adc_volts(1)).
/* Set and Measure Volts.c Set D/A0 to 2.5 V and D/A1 to 1 V, and measure with A/D0 and A/D1. */ #include "simpletools.h" // Include simpletools #include "adcDCpropab.h" // Include adcDCpropab int main() // main function { adc_init(21, 20, 19, 18); // CS=21, SCL=20, DO=19, DI=18 dac_ctr(26, 0, 194); // D/A ch 0 -> 2.5 V to D/A 0 dac_ctr(27, 1, 78); // D/A ch 1 -> 1 V to D/A 1 print("A/D0 = %f\n", adc_volts(0)); // Display A/D0 volts print("A/D1 = %f\n", adc_volts(1)); // Display A/D1 volts }
The channel 0 and channel 1 parameters don't have anything to do with D/A0 and D/A1. D/A0 makes a steady voltage from P26 signals and D/A1 makes a steady voltage from P27 signals, no matter which channel you use.
The great thing about channels is that you can use them to move a D/A signal off one pin and onto another. For example, adding dac_ctr(9, 0, 194) after the rest of the statements would turn the P26 light off, and then turn a P9 light on (if you had an LED connected to P9, of course).
Let’s try making the voltages hold at D/A0 = 2.5 V and D/A1 = 1 V for 2 seconds, then change to D/A0 = 1 V and D/A1 = 2.5 V.
You can use variables and loops to gradually change the voltages, for a fade-out effect.
Light sensing has many uses. Think of a street light turning on at dusk, or a camera knowing when to use auto-flash. Phototransistors are a common type of light sensor used in these kinds of applications. Let’s try one with the Propeller for measuring light levels.
You might see a resistor and an A/D converter used with these analog light sensors elsewhere. However, the circuit here offers the ability to sense a much wider range of light levels, without needing A/D conversion. It’s called a charge transfer or QT circuit. It is a simple option for a variety of analog sensors.
Think of the 0.01 µF capacitor in the circuit as a very small battery, and the phototransistor as a light-controlled current valve. The Propeller will charge the capacitor-battery by sending an output-high signal to I/O P5. Then, the Propeller will change P5 to input and just watch what happens in the QT circuit. The phototransistor, our light controlled current valve, will control how quickly the capacitor loses its charge. More light = quicker capacitor discharge, less light = slower discharge. The Propeller’s job will be to measure the discharge time, and report that as a light measurement.
(1) Phototransistor (#350-00029)
(1) 0.01 µF capacitor (labeled 103, #200-01031)
(1) 0.1 µF capacitor (labeled 104, #200-01040)
(1) 220 ohm resistor (red-red-brown, #150-02210)
Note: Use the schematics with any Propeller board that has a prototyping area.
The Sense Light application will display a number that corresponds with the light level the QT circuit detects.
First, high(5) makes P5 send a 3.3 V high signal. Just as this type of signal can make an I/O pin deliver current to turn on the light, it can also deliver current to charge the capacitor. The pause(1) call gives the I/O pin time to charge the capacitor.
After that, int t = rc_time(5, 1) sets the variable t equal to the value returned by the rc_time function. This function from the simpletools library is designed to set an I/O pin to input, and then measure how long it takes for the voltage on that I/O pin to decay past the 1.65 V logic threshold.
The logic threshold is the dividing line between 1 and 0 for a Propeller input. Remember when you pressed a pushbutton and got a 1, or released it and got a 0? When the button was pressed, its I/O pin saw 3.3 V, well above 1.65 V, so the Propeller reported 1. Likewise, when the button was released, the I/O pin saw 0 V, well below 1.65 V, so the Propeller reported 0. Here, as soon as the voltage the circuit applies to the I/O pin decays to 1.65, the rc_time function stops tracking time and returns its time measurement. That time measurement gets stored in the t variable, and then displayed by print.
/* Sense Light.side Display light sensor levels. */ #include "simpletools.h" // Include simpletools int main() // main function { while(1) // Endless loop { high(5); // Set P5 high pause(1); // Wait for circuit to charge int t = rc_time(5, 1); // Measure decay time on P5 print("t = %d\n", t); // Display decay time pause(100); // Wait 1/10th of a second } }
Phototransistor — The C, B, and E labels in the phototransistor schematic stand for collector, base, and emitter. These are the terminals of a transistor called a bipolar junction transistor, or BJT. The amount of current entering the base terminal controls how much current passes from C to E. Tens to hundreds of times the current entering B is what the transistor conducts from C to E. By removing the wire and placing the transistor in a clear case, the base terminal acts like a small solar collector, supplying current to the B terminal. More light means more current into B, and therefore lots more current conducted from C to E.
Capacitor — A capacitor is constructed of two metal plates that placed very close together. When voltage is applied, it charges as electrons leave one of the plates and accumulate on the other. The amount of charge a capacitor can store is measured in terms of farads (abbreviated F). Capacitors in electronic designs tend to measure in fractions of a farad. Here are some of the fraction abbreviations you might see:
The 103 on the 0.01 µF capacitors case is the number of picofarads. It’s 10 + 3 zeros or 10,000, which is 1×104. A trillionth, or pico is 1×10-12. Multiply the two together, and you get 1×10-8, which is also 0.01×10-6 , or 0.01 µF.
If you use a capacitor that’s 10 times as large, your decay measurements will take ten times as long. So, the value rc_time returns will be 10 times larger.
You have now experimented with blinking lights and light brightness, and you may also have tried speaker tones. Pick one of those and make it respond to light. Maybe with less light shining on the phototransistor, an LED will get brighter, or maybe blink faster. Or you could make a speaker tone go lower as more light shines on the phototransistor.
Hint: You may have to divide or multiply t by some value to make it useful for your output device.
A 7-segment display is a great way to display numbers using your Propeller. You can find these in many products that need to display numbers in a simple way, like clocks, kitchen appliances, or digital scales. This display uses seven LEDs arranged in a special pattern that makes it possible to show any number from 0 to 9. This tutorial will show you exactly how to control the display, and use it to count.
Each individual LED in the 7-segment display needs a resistor between it and the Propeller’s I/O pin. When each I/O pin is set to high (outputs 3.3 V), the LED it is connected to lights up. Any resistor value between 100 Ω and 1 kΩ will work for the LED resistor and the lower the resistance, the brighter the segment. It’s best to use resistors of the same value so all the segments light up evenly.
(8) 1 kΩ Resistors (brown-black-red). Or, you can substitute 220 Ω resistors (red-red-brown) if necessary.
(1) 7-Segment Green LED (Part #350-00027)
Note: The FLiP wiring diagram uses pins 6-13, not pins 8-15. You will need to adjust your pin assignments in the code if using the FLiP.
The test code will count from 0 to 9 on the display, with half a second between each digit.
If you haven't already installed the latest USB driver, SimpleIDE, or Learn folder, go to Propeller C - Set up SimpleIDE [6] and Propeller C - Start Simple [7].
First, the code sets all the pins between 8 and 15 to outputs with set_directions(15, 8, 0b11111111). Next, the code outputs a 0 with the command set_outputs(15, 8, 0b11100111). If you look through the rest of the code, you can see that each digit has its own binary representation. The number 1, for example, is represented as 0b10000100. If you investigate more closely, you’ll notice the binary digits correspond to I/O pins, in reverse order, from 15 to 8. So the binary representation for the number 1 sets pins 15 and 10 to high. If you look at the schematic, you’ll notice that pin 15 is connected to segment B and pin 10 is connected to segment C. Referring to the diagram below, you’ll see that together, segments B and C make up the number 1.
/* Seven Segment.c Display digits on a 7-segment (common cathode) LED display. */ #include "simpletools.h" // Include simpletools int main() // main function { set_directions(15, 8, 0b11111111); // P15...P8 -> output set_outputs(15, 8, 0b11100111); // 0 -> 7-segment display pause(500); set_outputs(15, 8, 0b10000100); // 1 pause(500); set_outputs(15, 8, 0b11010011); // 2 pause(500); set_outputs(15, 8, 0b11010110); // 3 pause(500); set_outputs(15, 8, 0b10110100); // 4 pause(500); set_outputs(15, 8, 0b01110110); // 5 pause(500); set_outputs(15, 8, 0b01110111); // 6 pause(500); set_outputs(15, 8, 0b11000100); // 7 pause(500); set_outputs(15, 8, 0b11110111); // 8 pause(500); set_outputs(15, 8, 0b11110110); // 9 pause(500); }
7-segment LEDs can also be used to display letters. You may already have seen examples of this on CD/DVD players, calculators, or microwaves. Although every letter of the English alphabet can be represented (in capital and/or lowercase form) using a single device, some letters are a bit more difficult to display in an easily recognizable way.
The capital letter “A”, for example, is easy to display using 0b11110101 as one of your outputs’ binary representations in SimpleIDE (try it!). Alternatively, letters like “w” or “k” require a bit more imagination to represent using only a single 7-segment LED; often it takes LEDs with more segments or two, side-by-side devices to accurately display them.
Want to learn more? Visit the Wikipedia article about 7-segment display character representations at http://en.wikipedia.org/wiki/Seven-segment_display_character_representations [13].
Instead of referencing each number individually, a better method to display numbers on a 7-segment display is to store each binary value in an array and then reference them later in the code. Here, we use a for loop to do just that.
Since the Propeller Activity Board (original or WX version) has a built-in analog to digital converter, you can make a voltmeter using your 7-segment display. Try combining what you learned in Measure Volts [14] with the information in this tutorial to make your display show voltages.
Note that the FLiP does not have this feature built-in, and to complete this activity you would need to add an A/D converter to your breadboard circuit.
Tip: If you have two 7-segment displays, you can use the decimal point on the first display. This involves changing the 5th bit of every value for the first display: i.e. 0b11100111 becomes 0b11101111.
Links
[1] https://learn.parallax.com/propeller-c-set-simpleide
[2] https://learn.parallax.com/propeller-c-set-simpleide/update-your-learn-folder
[3] https://learn.parallax.com/propeller-c-start-simple
[4] https://learn.parallax.com/reference/breadboard-basics
[5] http://learn.parallax.com/propeller-c-simple-devices
[6] http://learn.parallax.com/propeller-c-set-simpleide
[7] http://learn.parallax.com/propeller-c-start-simple
[8] http://learn.parallax.com/propeller-c-simple-circuits/blink-light
[9] http://learn.parallax.com/reference/breadboard-basics
[10] https://learn.parallax.com/propeller-c-start-simple/make-several-decisions
[11] https://learn.parallax.com/node/620
[12] https://learn.parallax.com/propeller-c-simple-circuits/blink-light
[13] http://en.wikipedia.org/wiki/Seven-segment_display_character_representations
[14] https://learn.parallax.com/propeller-c-simple-circuits/measure-volts