Maker.io main logo

CircuitPython Made Easy on Circuit Playground Express

2019-01-29 | By Adafruit Industries

License: See Original Project Circuit Playground

Courtesy of Adafruit

Guide by Kattni Rembor

Circuit Playground Express Library

The Circuit Playground Express, or CPX, has all kinds of sensors, buttons, switches and LEDs built into it. To top it off, it works with CircuitPython. Normally, using CircuitPython with a button or sensor requires setup in your code. Sometimes this means one line of code. Other times, it can mean several. Wouldn't it be nice to be able to skip all of that and get right to work? We've got you covered. Whether you're new to programming CircuitPython, or would like a simple way to include the Circuit Playground Express functionality in your code, the Circuit Playground Express Circuit Python library is exactly what you're looking for.

We've designed a CircuitPython library that makes it super easy to get started with Circuit Playground Express. All of the setup normally required for much of what is built into the CPX is done for you. All you need to do is import this library, and you can immediately begin to tell the board what to do. This guide will go through each feature available in the library and provide examples of how to use it.

There's a few things you should do before going through this guide to make sure you're all set to go. Let's take a look!

Figure-1

First Things First

Figure-2

Before We Get Started

If you're new to programming and CircuitPython, check out the Welcome to CircuitPython guide.

We recommend using Mu as your code editor, as it has the serial REPL built right in, and you can get immediate feedback from your code right inside the editor. For help getting Mu setup, read through Installing Mu Editor. A few of the features of this library work really well with the plotter function available in the Mu editor. Be sure to install the latest version to make sure you have access to this feature of Mu.

If you already have a favorite editor, feel free to use it for this guide. Many of the examples will utilise the serial REPL, so if you opt not to use Mu, and you've never connected to the serial console before, read through the Advanced Serial Console on Mac and Linux, or the Advanced Serial Console on Windows for help getting connected.

Installing and Updating CircuitPython

This process is covered in the Welcome to CircuitPython guide. Even if your board arrived with CircuitPython installed, it may not be the latest version. You always want to have the most up-to-date version of CircuitPython on your board - this ensures the latest features and best functionality. Please take the time to go through this page (if you haven't already) and make sure you've got CircuitPython installed and up to date.

Creating and Editing Code

This is covered in more detail in the Welcome to CircuitPython guide. However, since workflow is a key part of going through this guide, we're including a short explanation here.

Your Circuit Playground Express shows up on your computer as a USB drive called CIRCUITPY. You may already have some files on your CIRCUITPY drive. CircuitPython looks for specific files to run the code they contain, including code.py. We'll be putting each piece of code from this guide into code.py on your CIRCUITPY drive. This is easy to remember: code.py is where your code lives. As you progress through this guide, you have a couple of options to get the code from the guide onto your board.

  1. You can download the file, rename it to code.py and copy the file to your CIRCUITPY drive, replacing the current code.py if one already exists.
  2. You can copy and paste the contents of the code from the guide into your current code.py file on your CIRCUITPY drive using your editor. Be sure to replace all the code currently in your code.py. Do not add it to the end.

Both of these options work. It's entirely up to you which one to use. If you're unsure which to pick, give them both a try and see which workflow is best for you!

Using the Circuit Playground Express Library

To use the Circuit Playground Express library, simply include the following line at the beginning of code.py:

from adafruit_circuitplayground.express import cpx

That's it! After that, you can begin telling the board what to do.

Now, we'll take a look at all of the different things you can do with this library. Let's get started!

Figure-3

Red LED

Your Circuit Playground Express has a little red LED next to the USB port. It's labeled D13. The first thing we're going to do is turn on that red LED.

Figure-4

First, we need to add the following code to code.py. Remember, if you need help with this, check here.

Download: Project Zip or cpx_red_led.py | View on Github

Copy Code
from adafruit_circuitplayground.express import cpx

while True:
cpx.red_led = True

Red LED!

Figure-5

Now let's look at the code.

First we import the cpx library with from adafruit_circuitplayground.express import cpx.

Then we have a while statement. while True: essentially means, "Forever do:". while True: creates a loop. When there is a loop, the code will forever go through the code inside the loop. All code that is indented under while True: is "inside" the loop.

For the red LED, "on" and "off" are states referred to as True and False respectively. So, if you want to turn on the LED, you set it to True. If you want to turn it off, you set it to False. We want to turn on the LED. So let's set it to True by saying cpx.red_led = True.

And that's it! You should be rewarded by the little red LED next to your USB connector turning on! But why stop there? Let's try something a little more fun.

Blinky!

In any programming language, the first piece of code any programmer writes is a program called "Hello, world!" that prints exactly that. The idea behind it is it's an excellent introduction to the language and programming environment. In CircuitPython, our Hello, world! is called Blinky. Instead of simply writing code that prints out hello, we write code that blinks the LED! So, to welcome you to the world of programming, we're going to blink the little red LED. Let's take a look!

Add the following code to your code.py.

Download: Project Zip or cpx_red_led_blinky.py | View on Github

Copy Code
import time
from adafruit_circuitplayground.express import cpx

while True:
cpx.red_led = True
time.sleep(0.5)
cpx.red_led = False
time.sleep(0.5)

Figure-6

It blinks!

In this program, we need another library as well as cpx: time. So, we import time and cpx.

The first line inside our while True: loop is the same as the first line of our last program. We're turning on the red LED with cpx.red_led = True. Next, we have time.sleep(0.5). This tells the code to pause in the current state for 0.5 seconds. In other words, we're turning on the red LED and waiting with it on for 0.5 seconds. The next line, cpx.red_led = False, turns the LED off. And the last line, time.sleep(0.5), again tells the code to wait, this time with the LED off. Then it repeats forever - remember we're inside our while loop! And, when the LED turns on for 0.5 seconds and then off for 0.5 seconds, we have a blinking LED!

Try changing the numbers in the time.sleep(0.5) lines to change the speed of the blinking. You can slow down the blinking by replacing both 0.5's with a higher number, such as 1: time.sleep(1). You can speed it up by replacing both 0.5's with a lower number, such as 0.1: time.sleep(0.1). Or, try them different times to give it a funky rhythm!

Red LED On = Red LED Off

There's an even shorter way to do the same thing. Add the following code to your code.py.

Download: Project Zip or cpx_red_led_blnky_short.py | View on Github

Copy Code
import time
from adafruit_circuitplayground.express import cpx

while True:
cpx.red_led = not cpx.red_led
time.sleep(0.5)

This code simply tells the LED to cycle back and forth between on and off, or True and False, every 0.5 seconds. You can change the time.sleep(0.5) to a higher or lower number to slow down or speed up the blinking. That's it!

Slide Switch

The Circuit Playground Express has a slide switch on it, above the battery connector. The slide switch doesn't control the power of the board. It is a switch that returns True or False depending on whether it's left or right. So, you can use it as a toggle switch in your code! Let's take a look.

Figure-7

Add the following code to your code.py. Remember, if you need help with this, check here.

Download: Project Zip or cpx_slide_switch.py | View on Github

Copy Code
import time
from adafruit_circuitplayground.express import cpx

while True:
print("Slide switch:", cpx.switch)
time.sleep(0.1)

Open the serial console (REPL) to see the switch status printed out. Try moving the slide switch back and forth to see the status change!

Figure-8

Let's take a look at the code. First we import cpx.

Then, inside our while loop, we print the status of the switch to the serial console. This will print True if the switch is to the left, and False is the switch is to the right. To see the results, click the REPL button in Mu, or connect to the serial console if you're not using Mu.

Figure-9

If the switch is to the left, you'll see Slide switch: True printing the serial output (REPL). If the switch is to the right, you'll see Slide switch: False printing to the serial output.

Figure-11

Simple enough, right? Now, let's do something with it!

Blinky Switch

We just learned how to turn the little red LED on and off. Now let's incorporate an input to control it. Since the switch returns True or False, we can use it as an input.

Add the following code to your code.py.

Download: Project Zip or cpx_slide_switch_red_led.py | View on Github

Copy Code
from adafruit_circuitplayground.express import cpx

while True:
if cpx.switch:
cpx.red_led = True
else:
cpx.red_led = False

After importing cpx, our loop starts with an if statement. An if statement says, "if this event is happening, do the following." Our code says, if the switch is to the left, or True, turn on the red LED.

Note that we don't have to say if cpx.switch = True:. The True is implied in the if statement.

This is followed by an else statement. And else statement says, "Otherwise, do the following." An else typically follows an if. Together they say, "If this is happening, do this first thing, otherwise, do the second thing." Our code says, when the switch is to the right, or False, turn off the red LED.

Now, try moving the switch back and forth. Your red LED will turn on and off!

True is True

You may have noticed that when the switch is to the right, it's True, and when the LED is on, it is also True. We can use this to make our code even shorter. We started with the if/else block because it's easier to understand what's happening when it's written out. However, the following code does the same thing. Add the code to your code.py.

Download: Project Zip or cpx_slide_switch_red_led_short.py | View on Github

Copy Code
from adafruit_circuitplayground.express import cpx

while True:
cpx.red_led = cpx.switch

Whatever the switch is returning is what it will set the red LED to. So, if the switch is returning True, the LED is True. If the switch is False, the LED will be False. True is True, False is False. Move the switch back and forth and you'll still be turning the red LED on and off with this shorter code!

Tap

The Circuit Playground Express has an accelerometer built in which opens up all kinds of opportunities for inputs. One of those inputs is tap. You have the ability to tap your board to tell it to do something. There are two options: single tap and double tap. Single tap looks for one tap before reacting. Double tap looks for two taps before reacting. Let's take a look!

Figure-11

Add the following code to your code.py. Remember, if you need help with this, check here.

Download: Project Zip or cpx_tap.py | View on Github

Copy Code
from adafruit_circuitplayground.express import cpx

cpx.detect_taps = 2

while True:
if cpx.tapped:
print("Tapped!")

Open the serial console (REPL) to see when the board is double tapped. Try tapping the board twice to see it printed out!

Figure-12

First we import cpx.

Then we set cpx.detect_taps = 2. This tells the code to look for a double tap, or two taps, before responding.

Inside our loop, we have if cpx.tapped:. The code tells cpx.tapped that we're looking for 2 taps before responding. So, if the board is tapped twice, the response is to print Tapped! to the serial output. To see this, open the REPL, and tap your board twice. Tap twice. Tapped!

Try changing cpx.detect_taps to 1. Tap the board once to see the same response!

Now, let's do something with it! Add the following code to your code.py:

Download: Project Zip or cpx_tap_red_led.py | View on Github

Copy Code
import time
from adafruit_circuitplayground.express import cpx

cpx.detect_taps = 2

while True:
if cpx.tapped:
print("Tapped!")
cpx.red_led = True
time.sleep(0.1)
else:
cpx.red_led = False

Try tapping twice. Red LED!

Let's look at the code. First we import time and cpx.

We'll keep cpx.detect_taps = 2 to tell the code to look for two taps.

Inside our loop, we are checking to see if the board has been tapped twice. We still print to the serial output, so we can see if we've successfully tapped. But now, we've added turning on the red LED. Since the tap event is extremely quick, we've also included a time.sleep(0.1) so the red LED stays on long enough for us to see. Without it, it's a super quick flash. And we have our else to turn off the red LED when not tapping the board - otherwise it would turn on and never turn off.

Single Double

You can't detect a single tap and a double tap at the same time - it's a limitation of the hardware. You can include both single tap and double tap detection in one piece of code if you separate them with a delay of some sort. Let's take a look. Add the following code to your code.py.

Download: Project Zip or cpx_tap_single_double.py | View on Github

Copy Code
from adafruit_circuitplayground.express import cpx

# Set to check for single-taps.
cpx.detect_taps = 1
tap_count = 0

# We're looking for 2 single-taps before moving on.
while tap_count < 2:
if cpx.tapped:
print("Single-tap!")
tap_count += 1
print("Reached 2 single-taps!")

# Now switch to checking for double-taps.
tap_count = 0
cpx.detect_taps = 2

# We're looking for 2 double-taps before moving on.
while tap_count < 2:
if cpx.tapped:
print("Double-tap!")
tap_count += 1

print("Reached 2 double-taps!")
cpx.red_led = True
print("Done.")

This code looks for two single-taps and then two double-taps to complete the sequence. So, if you single-tap the board twice, and then double-tap the board twice, you'll work though this code and see the messages printed out as you go!

Figure-13

Let's take a look at the code. First we import cpx and then set it to look for single taps with cpx.detect_taps = 1.

Then we create the variable tap_count and assign it to 0 with tap_count = 0. We're going to use this to keep track of how many times we've tapped the board. This is how we know when to move on to the next part of the code.

Our loop is different from our previous loops. This loop begins with while tap_count < 2:. It says, "keep looping through the following indented code until tap_count is greater than 2." Since tap_count is currently 0, we'll begin the loop. The code inside the loop says, "If the board has been tapped, increase tap_count by 1." Each time you tap the board, it prints to the serial console, Single-tap! The first time you tap the board, tap_count = 1. The second time, tap_count = 2. 2 is not less than 2, so after the second tap, the code stops working through this loop and moves on to the next section. The last thing we do before moving on is print to the serial console, Reached 2 single-taps! so we know we've reached the end of this section.

Next, we set tap_count = 0 again since we're going to start looking for a new type of tap. Then we set the code to look for double taps with cpx.detect_taps = 2.

Our next loop is the same as the first. While tap_count is greater than 2, check to see if the board is double tapped, and if it is, print Double tapped! and increase tap_count by 1. Once it reaches 2, the code moves on. Then we print to the serial console, Reached 2 double-taps!.

The last thing we do is turn on the red LED so we know our code is finished, and print Done.

This type of code could be used to create a Circuit Playground Express controlled combination lock where the combination is a series of taps. Get creative with it and see what you can come up with!

Shake

The Circuit Playground Express accelerometer can detect other types of input actions besides taps. One of those inputs is shake. You have the ability to shake your board to tell it to do something. Let's give it a try!

Figure-14

Add the following code to your code.py. Remember, if you need help with this, check here.

Download: Project Zip or cpx_shake.py | View on Github

Copy Code
from adafruit_circuitplayground.express import cpx

while True:
if cpx.shake():
print("Shake detected!")

 

Open the serial console (REPL) and give the board a good shake. Shake detected!

Figure-15

Let's look at the code. First we import cpx.

Inside our loop, we check to see if the board has been shaken with if cpx.shake():. If the board is shaken, we print to the serial console, Shake detected!

Notice that there are parentheses after cpx.shake. These are necessary for shake detection to work properly. Without them, your code will run, but it won't work properly. Make sure you include them!

Shake It Up A Little

Let's use shaking the board to turn on the red LED. Add the following code to your code.py.

Download: Project Zip or cpx_shake_threshold_red_led.py | View on Github

Copy Code
from adafruit_circuitplayground.express import cpx

while True:
if cpx.shake(shake_threshold=20):
print("Shake detected!")
cpx.red_led = True
else:
cpx.red_led = False

 

Shake the board. Red LED!

Let's look at the code. First we import cpx.

Inside our loop, we check to see if the board has been shaken. However, we've added something to this line, shake_threshold=20. Sometimes you may find that the board doesn't respond to your shaking, or it responds too easily. You have the option to change the threshold to make it harder or easier to shake the board. The default threshold is 30. Decreasing the threshold makes it easier to have a shake detected. Increasing the threshold makes it harder to have a shake detected. The minimum value allowed is 10. 10 is the value when the board is not moving. So if you set the threshold to less than 10, the code will constantly return a shake detected even if the board is not moving. Set the threshold to any whole number above 10 to change the threshold to fit your needs.

In this case, we've included if cpx.shake(shake_threshold=20): which lowers the threshold, making it easier to shake the board. If a shake over the threshold of 20 is detected, we print Shake Detected! and we turn on the red LED. Otherwise, we turn off the red LED with our else block.

Try changing the threshold to 40 and see what happens. Be aware, if you set the threshold too high, the shake will never be detected. Play around with it to find out what works best for you!

Shake Other Projects

Here are some projects that use shake:

NeoPixels

The Circuit Playground Express has ten RGB NeoPixel LEDs built in. They're located in a ring around the board, just inside the outer ring of alligator-clip-friendly pads. RGB means red, green and blue, and that means you can create any color of the rainbow with these LEDs!

Figure-16

LED colors are set using a combination of red, green, and blue, in the form of an (R, G, B) tuple. A tuple is typically a group of numbers. Each member of the RGB tuple is set to a number between 0 and 255 that determines the amount of each color present. Red, green and blue in different combinations can create all the colors in the rainbow! So, for example, to set the LED to red, the tuple would be (255, 0, 0), which has the maximum level of red, and no green or blue. Green would be (0, 255, 0), etc. For the colors between, you set a combination, such as cyan which is (0, 255, 255), with equal amounts of green and blue.

We won't make you wait any longer. Let's get started!

Add the following code to your code.py. Remember if you need help with this, check here.

Download: Project Zip or cpx_neopixels_fill.py | View on Github

Copy Code
from adafruit_circuitplayground.express import cpx

while True:
cpx.pixels.fill((50, 0, 0))

Red lights!

Figure-17

First we import cpx.

Inside our loop, we have cpx.pixels.fill((50, 0, 0)) which turns on all the pixels red at approximately 20% brightness. Remember, the maximum level of red is 255. That's really bright! So we've set it to a lower level of red so that it's not so blinding by setting it to 50. The other two are 0, so there's no green or blue added into the mix yet. That's all there is to it!

Now, try changing the numbers to other values. For example, try cpx.pixels.fill((50, 50, 0)). See what happens!

One Pixel, Two Pixel, Red Pixel, Blue Pixel!

We turned on all the pixels to the same color. But what if you want to control each one individually? We can do that!

Add the following code to your code.py:

Download: Project Zip or cpx_neopixel_0.py | View on Github

Copy Code
from adafruit_circuitplayground.express import cpx

cpx.pixels.brightness = 0.3

while True:
cpx.pixels[0] = (255, 0, 0)

Now only the first pixel is red!

Figure-18

Let's look at the code.

First we import cpx.

Next, we have a new line: cpx.pixels.brightness = 0.3. Remember, we controlled brightness by using a lower number in the color tuple in the first piece of code. It's also possible to control brightness separately using cpx.pixels.brightness. The brightness is set by a number between 0 and 1 that represents a percentage. So, when we set it to 0.3, we are setting it to 30% brightness.

Inside our loop, we have cpx.pixels[0] = (255, 0, 0). Since we've set the brightness separately from the color, we are able to set the color to maximum red, or 255.

Notice we've set pixel number 0, but it's turned on the first pixel. This is because CircuitPython begins counting with 0. So the first of something numbered in CircuitPython will always be 0.

Figure-19

Let's try setting the second pixel to blue. Remember, the second pixel will be pixel number 1. Add the following to your code.py.

Download: Project Zip or cpx_neopixel_0_1.py | View on Github

Copy Code
from adafruit_circuitplayground.express import cpx

cpx.pixels.brightness = 0.3

while True:
cpx.pixels[0] = (255, 0, 0)
cpx.pixels[1] = (0, 0, 255)

Now your second pixel is blue.

Figure-20

That's all there is to it! You can keep adding more pixels up through 9 to set all of them different colors.

Give it a try!

Light

The Circuit Playground Express has a light sensor on the right side, next to the eye printed on the board. It senses the amount of ambient light and returns the light level based on that data. We've made it super easy to use. Let's take a look!

Figure-21

Add the following code to your code.py. Remember, if you need help with this, check here.

Download: Project Zip or cpx_light.py | View on Github

Copy Code
import time
from adafruit_circuitplayground.express import cpx

while True:
print("Light:", cpx.light)
time.sleep(1)

Open the serial console (REPL) and try shining a flashlight at your Circuit Playground Express. The printed values go up! If you place your hand over the CPX to block the light, the values go down.

Figure-22

Let's look at the code. First we import time and cpx.

Inside our loop, we print to the serial console, Light: followed by the light value, cpx.light. Then we have time.sleep(1) to slow down the speed at which it prints to the serial console. If it's too fast, it's really hard to read!

Plotting Light

Let's take a look at these values on the Mu plotter! Add the following code to your code.py:

Download: Project Zip or cpx_light_plotter.py | View on Github

Copy Code
import time
from adafruit_circuitplayground.express import cpx

while True:
print("Light:", cpx.light)
print((cpx.light,))
time.sleep(1)

The code is almost identical, but we've added one line, print((cpx.light,)).

Note that the Mu plotter looks for tuple values to plot. Tuples in Python come in parentheses () with comma separators. If you have two values, a tuple would look like (1.0, 3.14). Since we have only one value, we need to have it print out like (1.0,) - note the parentheses around the number, and the comma after the number. Thus the extra parentheses and comma in print((cpx.light,)).

As well, the Mu plotter requires that the tuple value be on a line all its own. That's why we can't simply add extra parenthesis and a comma to the print("Light:", cpx.light) line. The plotter doesn't know what to do with it if there's other information in there.

Click on the Plotter button on the top of Mu to see the plotter. Try shining a flashlight on your Circuit Playground Express and watch the plotter line go up! Remove or block the light with your hand to see it go down. Have fun with it!

Figure-23

NeoPixel Light Meter

You can also use the light values to create a fun light meter using the NeoPixels on your Circuit Playground Express! Add the following code to your code.py:

Download: Project Zip or cpx_light_neopixels.py | View on Github

Copy Code
import time
from adafruit_circuitplayground.express import cpx
import simpleio

cpx.pixels.auto_write = False
cpx.pixels.brightness = 0.3

while True:
# light value remapped to pixel position
peak = simpleio.map_range(cpx.light, 0, 320, 0, 10)
print(cpx.light)
print(int(peak))

for i in range(0, 10, 1):
if i <= peak:
cpx.pixels[i] = (0, 255, 255)
else:
cpx.pixels[i] = (0, 0, 0)
cpx.pixels.show()
time.sleep(0.05)

 

Now try shining the flashlight on your Circuit Playground Express and watch the LEDs light up!

Figure-24

Slowly remove the light to watch the number of LEDs lit up slowly go down.

Figure-25

Let's take a look at the code. First we import time, cpx, and simpleio. We'll be using a new library, simpleio, to help with this code.

Next, we set cpx.pixels.auto_write = False. This means that anything we tell the LEDs to do will not happen automatically. By default, this is set to True. This means, we tell the LEDs to turn on, and they turn on. If it's set to False, it means we have to include cpx.pixels.show() after anything we try to tell the LEDs to do. This is required for this code to work since the LEDs turn on based on the light values.

We set the brightness to 0.3, or 30%.

Our loop begins with setting peak = simpleio.map_range(cpx.light, 0, 320, 0, 10). map_range comes from the simpleio library. It is used to map one range of numbers to another. There are 10 LEDs on the Circuit Playground Express. The light values range from 0 to 320. We want the LEDs to light up based on the light range. So, we use map_range to map the cpx.light values of 0 to 320 to the number of LEDs 0 to 10.

Then we print the cpx.light values and the peak values.

The next section takes the peak value and says for the total number of LEDs, whatever number peak is equal to or less than, light up that many LEDs, and otherwise turn them off. So, if peak is 4, light up 4 LEDs!

Then we have cpx.pixels.show() to make the LEDs light up. And a time.sleep(0.05) to create a little delay.

You can change the number values in cpx.pixels[i] = (0, 255, 255) to change the color of the light meter. Give it a try!

Acceleration

The accelerometer is located at the exact center of the board. The sensor can provide acceleration values for the x, y and z axes in addition to taps and shakes. The values returned are in m/s2 (meters per second-squared). An axis is an invisible line going through the center of the accelerometer in the center of your board. The x axis is across the board, left to right. The y axis is across the board, top to bottom. The z axis is straight through the board front to back. The values can be grouped together in a Python tuple: (x, y, z).

Figure-26

An accelerometer measures acceleration. You can read more about acceleration here. When the board is held still in any given position, it is still being affected by gravity. Gravity is -9.8m/s2. So, at any given point in time, that value is being applied downward. For example, the values returned if the board is laying flat, facing up, are (0, 0, 9.8), because gravity is pulling on the sensor along the z axis. If you were to pick up the board and shake it, you'll find that you get much higher values. This is because the force with which you are shaking the board causes increased acceleration to be applied to the sensor along whichever axes you are shaking it.

Add the following code to your code.py. Remember, if you need help with this, check here.

Download: Project Zip or cpx_acceleration.py | View on Github

 

Copy Code
import time
from adafruit_circuitplayground.express import cpx

while True:
x, y, z = cpx.acceleration
print((x, y, z))
time.sleep(0.5)

 

Open the serial console (REPL) to see the x, y and z values printed out. Try moving the board around to see the values change!

Figure-27

Let's take a look at the code. First, we import time and cpx.

Inside our loop, we assign x, y, z = cpx.acceleration. Since acceleration values are a 3-member tuple (x, y, z), you need to assign three variables to cpx.acceleration to get those three values. We've chosen x, y and z because those are the three axes represented by cpx.acceleration.

Then we print((x, y, z)). We include a time.sleep(0.5) to slow down the printed values - if they print too quickly it's difficult to read.

Since (x, y, z) is already a tuple, and we aren't printing any labels for the values, we can use the Mu plotter with the code without any changes. Click on the Plotter button on the top of Mu to see the plotter. Try moving the board around to watch the plotter lines change!

Color Glow Accelerometer

You can use the acceleration values to make a fun light up project with the NeoPixels. There are three acceleration values, and the LEDs have three color values. Let's see what we can do with that!

Add the following code to your code.py.

Download: Project Zip or cpx_acceleration_neopixels.py | View on Github

Copy Code
from adafruit_circuitplayground.express import cpx

# Main loop gets x, y and z axis acceleration, prints the values, and turns on
# red, green and blue, at levels related to the x, y and z values.
while True:
if cpx.switch:
print("Slide switch off!")
cpx.pixels.fill((0, 0, 0))
continue
else:
R = 0
G = 0
B = 0
x, y, z = cpx.acceleration
print((x, y, z))
if x:
R = R + abs(int(x))
if y:
G = G + abs(int(y))
if z:
B = B + abs(int(z))
cpx.pixels.fill((R, G, B))

 

Move the slide switch to the right if it isn't already. Lights! Now move the board in different directions to see the colors change!

Let's take a look at the code. First we import cpx.

Inside our loop, we start by checking to see if the switch is to the left. If it is, we print Slide switch off! and turn off all the LEDs. This creates an "off switch" for the project in case you'd like to leave it sitting around but not have the lights on. continue tells the code to keep checking the switch until the state changes, i.e. you move the switch to the right. Once that happens, we move on to the rest of the code.

Next we have the else block. First, we create three variables, R, G and B. We're going to use these to set the colors. We assign them to 0 to start. Then, we assign x, y, z = cpx.acceleration and print the values. If you look at the serial output, you'll see how fast the values are scrolling. This is why we typically include a time.sleep() in the code, to slow those values down to a readable speed. However, this project works best without a sleep, so we've left it out.

The next section has three parts. Each do the same thing but for a different axis. We are going to take the acceleration values, and use them to represent color values. We begin with x.

Our value of x is modified a little with abs(int(x)). This returns the absolute value of the whole number value of x. Absolute values are explained here. Since color values are all whole numbers, we use int(x) to return only the nearest whole number value of x, instead of a long decimal which is often what acceleration returns. Since color values are all positive, we take the absolute value of int(x) to remove any potential negative numbers from the mix.

We add abs(int(x)) to R and reassign it to R. Now we have our R value to use for red! Then we do the same thing for y and z, except abs(int(y)) is added to G and abs(int(z)) is added to B. This gives us our three color values!

We then set cpx.pixels.fill((R, G, B)) to set all the pixels to these color values. As you move the board around, the acceleration values change, and that causes each of our color values to be different. Now, depending on what angle you hold the board, you'll get a different color combination!

Remember the earlier example, where we explained that if the board is laying flat, the returned values are (0, 0, 9.8). This means, if the board is laying flat, facing up, while this code is running, the color values are (0, 0, 9.8). So, you'll see if it's laying flat on your desk, it's blue!

Figure-28

If you hold it so the USB cable is on the top and pointed downwards, the values are, (0, 9.8, 0), so the LEDs are green.

Figure-29

If you hold it so the USB cable is sideways, pointing left or right, the values are (9.8, 0, 0) so the LEDs are red.

Figure-30

As you move the board around at different angles, you'll find every color between!

We also explained that if you shake the board, you'll get back higher values from the accelerometer. This means that the LEDs will be brighter if you shake it. Give it a try!

Accelerate Other Projects

Here are some projects that use acceleration:

Buttons

The Circuit Playground Express has two buttons. Button A is on the left and button B is on the right. These buttons can be used as inputs, which means you can use them to tell your board to do something when you press them.

Figure-31

Let's start with button A. Add the following code to your code.py. Remember, if you need help with this, check here.

Download: Project Zip or cpx_button_a.py | View on Github

Copy Code
from adafruit_circuitplayground.express import cpx

while True:
if cpx.button_a:
print("Button A pressed!")
cpx.red_led = True

Now, press button A. Red LED!

Figure-32

Let's look at the code. First, we import cpx.

Inside our loop, we check to see if button A is pressed with if cpx.button_a:. Then, if it is, we print Button A pressed! to the serial console and we turn on the red LED!

Notice the LED stays on once button A is pressed. This is because we didn't tell the code to turn it off. So, let's try something a little different.

Add the following code to your code.py:

Download: Project Zip or cpx_button_b.py | View on Github

Copy Code
from adafruit_circuitplayground.express import cpx

while True:
if cpx.button_b:
cpx.red_led = True
else:
cpx.red_led = False

Now press button B. Red LED! But only while it's pressed. Nice!

Let's take a look at the code. First we import cpx.

Inside our loop, we check to see if button B is pressed with if cpx.button_b:. If it is, we turn on the red LED. Then, with our else:, we're telling the code, "otherwise, turn off the red LED." So, when the button is not being pressed, the LED turns off!

You can use both buttons in the same program. Let's change things up.

Add the following code to your code.py:

Download: Project Zip or cpx_buttons_1_neopixel.py | View on Github

Copy Code
from adafruit_circuitplayground.express import cpx

cpx.pixels.brightness = 0.3

while True:
if cpx.button_a:
cpx.pixels[2] = (0, 255, 0)
elif cpx.button_b:
cpx.pixels[7] = (0, 0, 255)
else:
cpx.pixels.fill((0, 0, 0))

Now press button A or B. Or press them both at the same time. Green and blue NeoPixels!

Figure-33

Our code is checking to see if each button is pressed. If it is, it turns on the LED next to the button to the specified color. Button A turns the LED next to it green. Button B turns the LED next to it blue. And, if the buttons are not being pressed, the LEDs are otherwise turned off by cpx.pixels.fill((0, 0, 0)).

Let's get a little fancier. Add the following code to your code.py:

Download: Project Zip or cpx_buttons_neopixels.py | View on Github

Copy Code
from adafruit_circuitplayground.express import cpx

cpx.pixels.brightness = 0.3

while True:
if cpx.button_a:
cpx.pixels[0:5] = [(255, 0, 0)] * 5
elif cpx.button_b:
cpx.pixels[5:10] = [(0, 255, 0)] * 5
else:
cpx.pixels.fill((0, 0, 0))

Now press button A or button B. Neopixels half and half, split down the middle, matching the sides the buttons are on!

Figure-34

Here we're using a concept called slicing. Slicing allows you to specify a start point and an end point and enables us to tell the code to light up everything in between. So, instead of specifying a single LED with [0], we tell the board to light up the first half of the LEDs on pressing button A with cpx.pixels[0:5] = [(255, 0, 0)] * 5. The [0:5] is the start and end point, and the * 5 is the slice size (5 out of 10 LEDs). We do the same with button B and the second half of the LEDs with cpx.pixels[5:10]. And we tell the LEDs to otherwise be off if no buttons are pressed.

Note that the end points are 1 higher than the normal LED numbering - slice math is a little bit different than CircuitPython counting. Try playing with it a little bit. Change the first set to cpx.pixels[1:4] = [(255, 0, 0)] * 3. See which LEDs light up!

If you try to specify a set of LEDs that's different from the slice size, you code won't run and an error will be printed to the serial console. For example, cpx.pixels[1:4] = [(255, 0, 0)] * 4 will fail because your slice size should be 3. So be sure to match them up!

Temperature

The Circuit Playground Express has a temperature sensor built in, on the right side of the board next to the little thermometer printed on the board. It's right under the A9 label on the board. It returns the temperature in Celsius.

Figure-35

Add the following code to your code.py. Remember, if you need help with this, check here.

Download: Project Zip or cpx_temperture.py | View on Github

Copy Code
import time
from adafruit_circuitplayground.express import cpx

while True:
print("Temperature C:", cpx.temperature)
time.sleep(1)

Open the serial console (REPL) to see the temperature in Celsius printed out. Try holding your finger over the thermometer printed on the board to see the values change!

Figure-36

Let's take a look at the code. We import time and cpx.

Inside our loop, we print Temperature C:, followed by the temperature value, cpx.temperature. Then we have a time.sleep(1) to slow down the readings. If they're too fast, they're hard to read!

Great! But what if you're used to temperature in Fahrenheit? It's easy to display that instead with a little math. Add the following code to your code.py:

Download: Project Zip or cpx_temperture_C_F.py | View on Github

Copy Code
import time
from adafruit_circuitplayground.express import cpx

while True:
print("Temperature C:", cpx.temperature)
print("Temperature F:", cpx.temperature * 1.8 + 32)
time.sleep(1)

Open the serial console (REPL) to see the temperature in Celsius and Fahrenheit printed out. Try holding your finger over the thermometer printed on the board to see the values change!

Figure-37

Since the temperature is in Celsius by default, so we include a little math, * 1.8 + 32, to convert it to Fahrenheit.

Plotting Temperature

Let's take a look at these values on the Mu plotter! Add the following code to your code.py:

Download: Project Zip or cpx_temperture_plotter.py

Copy Code
import time
from adafruit_circuitplayground.express import cpx

while True:
print("Temperature C:", cpx.temperature)
print("Temperature F:", cpx.temperature * 1.8 + 32)
print((cpx.temperature, cpx.temperature * 1.8 + 32))
time.sleep(1)

The code is almost identical, but we've added one line: print((cpx.temperature, cpx.temperature * 1.8 + 32)).

Note that the Mu plotter looks for tuple values to plot. Tuples in Python come in parentheses () with comma separators. If you have two values, a tuple would look like (1.0, 3.14) - note the parentheses around the number set, and the comma between. That's why there's an extra set of parenthesis around and a comma between the two temperature values in print((cpx.temperature, cpx.temperature * 1.8 + 32)).

As well, the Mu plotter requires that the tuple value be on a line all its own. That's why we can't simply add extra parenthesis and a comma to the print("Temperature C:", cpx.temperature) line. The plotter doesn't know what to do with it if there's other information in there.

Click on the Plotter button on the top of Mu to see the plotter. Try breathing on your Circuit Playground Express to watch the plotter go up. Try setting it on an ice pack to watch the plotter go down!

Figure-38

Temperature Meter

You can also use the temperature values to create a fun light meter using the NeoPixels on your Circuit Playground Express! Add the following code to your code.py:

Download: Project Zip or cpx_temperature_neopixels.py | View on Github

Copy Code
import time
from adafruit_circuitplayground.express import cpx
import simpleio

cpx.pixels.auto_write = False
cpx.pixels.brightness = 0.3

# Set these based on your ambient temperature for best results!
minimum_temp = 24
maximum_temp = 30

while True:
# temperature value remapped to pixel position
peak = simpleio.map_range(cpx.temperature, minimum_temp, maximum_temp, 0, 10)
print(cpx.temperature)
print(int(peak))

for i in range(0, 10, 1):
if i <= peak:
cpx.pixels[i] = (0, 255, 255)
else:
cpx.pixels[i] = (0, 0, 0)
cpx.pixels.show()
time.sleep(0.05)

Now try holding your finger over the thermometer printed on your Circuit Playground Express and watch the LEDs light up! Remove your finger to watch the number of LEDs lit up change.

Figure-39

Let's take a look at the code. First we import time, cpx, and simpleio. We'll be using a new library, simpleio, to help with this code.

Next, we set cpx.pixels.auto_write = False. This means that anything we tell the LEDs to do will not happen automatically. By default, this is set to True. This means, we tell the LEDs to turn on, and they turn on. If it's set to False, it means we have to include cpx.pixels.show() after anything we try to tell the LEDs to do. This is required for this code to work since the LEDs turn on based on the temperature values.

We set the brightness to 0.3, or 30%.

You should be able to see what the temperature changes are from when the CPX is simply sitting on your desk and when you're holding your finger over it. For best results, change the minimum_temp and maximum_temp to fit your ambient temperature values. Otherwise, you might not get the best results from the temperature meter. When sitting here, the minimum was about 24 degrees, and when holding a finger on it, the maximum was about 30. This is how we chose the values already in the code.

Our loop begins with setting peak = simpleio.map_range(cpx.temperature, 24, 30, 0, 10). map_range comes from the simpleio library. It is used to map one range of numbers to another. There are 10 LEDs on the Circuit Playground Express. The temperature values range from 24 to 30. We want the LEDs to light up based on the temperature range. So, we use map_range to map the cpx.temperature values of 24 to 30 to the number of LEDs 0 to 10.

Then we print the cpx.temperature values and the peak values.

The next section takes the peak value and says for the total number of LEDs, whatever number peak is equal to or less than, light up that many LEDs, and otherwise turn them off. So, if peak is 4, light up 4 LEDs!

Then we have cpx.pixels.show() to make the LEDs light up. And a time.sleep(0.05) to create a little delay.

You can change the number values in cpx.pixels[i] = (0, 255, 255) to change the color of the temperature meter. Give it a try!

Capacitive Touch

The Circuit Playground Express has seven capacitive touch pads around the outside, labeled A1 - A7. These pads return True if you touch them. So you can use them as inputs to do all sorts of fun stuff!

Figure-40

Since the pads are capacitive, you can also attach alligator clips to them and any number of capacitive items and touch those to activate them as well! For example, you could attach one end of an alligator clip to one of the pads and the other end to an apple or a lime. Or place the other end in a glass of water. Then touch the fruit or the glass of water. You'll activate the pad!

Figure-41

Add the following code to your code.py. Remember, if you need help with this, check here.

Download: Project Zip or cpx_touch_a1.py | View on Github

Copy Code
import time
from adafruit_circuitplayground.express import cpx

while True:
if cpx.touch_A1:
print("Touched A1!")
time.sleep(0.1)

Open the serial console (REPL). Now, touch the pad labeled A1 on your Circuit Playground Express. Touched A1!

Figure-42

Let's look at the code. First we import time and cpx.

Inside our loop, we check to see if pad A1 is touched with if cpx.touch_A1:. If it is, we print Touched A1! to the serial console. Then we have a time.sleep(0.1) to slow down the speed of the printing.

Nice! But what about the rest of the touch pads? Add the following code to your code.py.

Download: Project Zip or cpx_touch_all.py | View on Github

Copy Code
import time
from adafruit_circuitplayground.express import cpx

while True:
if cpx.touch_A1:
print("Touched A1!")
if cpx.touch_A2:
print("Touched A2!")
if cpx.touch_A3:
print("Touched A3!")
if cpx.touch_A4:
print("Touched A4!")
if cpx.touch_A5:
print("Touched A5!")
if cpx.touch_A6:
print("Touched A6!")
if cpx.touch_A7:
print("Touched A7!")
time.sleep(0.1)

Now look at the serial console (REPL) and touch any of the touch pads. Touched!

Figure-43

The code begins the same way. But, we've added in another two lines for each touch pad. We check if each pad is touched, and if it is, we print Touched and the pad number to the serial console.

Now we've included all of the touch pads. Let's do something with them!

Touch the Rainbow

Add the following code to your code.py.

Download: Project Zip or cpx_touch_pixel_rainbow.py | View on Github

Copy Code
import time
from adafruit_circuitplayground.express import cpx

cpx.pixels.brightness = 0.3

while True:
if cpx.touch_A1:
print("Touched A1!")
cpx.pixels[6] = (255, 0, 0)
if cpx.touch_A2:
print("Touched A2!")
cpx.pixels[8] = (210, 45, 0)
if cpx.touch_A3:
print("Touched A3!")
cpx.pixels[9] = (155, 100, 0)
if cpx.touch_A4:
print("Touched A4!")
cpx.pixels[0] = (0, 255, 0)
if cpx.touch_A5:
print("Touched A5!")
cpx.pixels[1] = (0, 135, 125)
if cpx.touch_A6:
print("Touched A6!")
cpx.pixels[3] = (0, 0, 255)
if cpx.touch_A7:
print("Touched A7!")
cpx.pixels[4] = (100, 0, 155)
time.sleep(0.1)

Now touch each touch pad. You get an LED in one color of the rainbow for each of them!

Figure-44

Now let's look at the code. We import time and cpx. We set the LED brightness to 30%. We check to see if each pad is touched, and if it is, we print to the serial console. This time, though, we also light up a specific LED with each pad using cpx.pixels[#] = (r, g, b) where # is the pixel number and r, g, b are the color values. We didn't include any code to tell the LEDs to turn off, so they will stay on once you turn them on.

Now let's add more light! Add the following code to your code.py.

Download: Project Zip or cpx_touch_fill_rainbow.py | View on Github

Copy Code
import time
from adafruit_circuitplayground.express import cpx

cpx.pixels.brightness = 0.3

while True:
if cpx.touch_A1:
print("Touched A1!")
cpx.pixels.fill((255, 0, 0))
if cpx.touch_A2:
print("Touched A2!")
cpx.pixels.fill((210, 45, 0))
if cpx.touch_A3:
print("Touched A3!")
cpx.pixels.fill((155, 100, 0))
if cpx.touch_A4:
print("Touched A4!")
cpx.pixels.fill((0, 255, 0))
if cpx.touch_A5:
print("Touched A5!")
cpx.pixels.fill((0, 135, 125))
if cpx.touch_A6:
print("Touched A6!")
cpx.pixels.fill((0, 0, 255))
if cpx.touch_A7:
print("Touched A7!")
cpx.pixels.fill((100, 0, 155))
time.sleep(0.1)

Touch each pad. You get every LED lit up in one color of the rainbow for each of them!

Figure-45

The code is almost identical, except instead of cpx.pixels[#], we use cpx.pixels.fill((r, g, b)) to light up every LED instead of only one.

You can change the color values to whatever you like to create your own personal rainbow. Give it a try!

Touch More Projects

Here are projects that use the touch function:

Play Tone

The Circuit Playground Express has a built-in speaker above the music note printed on the board. It is below button A, to the left of the slide switch, and is labeled A0 (not to be confused with the pad A0, which is connected to the speaker). This speaker is capable of multiple things including the ability to play tones.

Figure-46

For this section to work, you must have installed on your Circuit Playground Express CircuitPython 2.3.1 or higher, or CircuitPython 3.0 Beta 1 or higher.

Add the following code to your code.py. Remember, if you need help with this, check here.

Download: Project Zip or cpx_play_tone.py | View on Github

Copy Code
from adafruit_circuitplayground.express import cpx

cpx.play_tone(262, 1)
cpx.play_tone(294, 1)

When you save the code, you'll have two tones!

First we import cpx. Then, we play one tone, followed by another with cpx.play_tone(262, 1) and cpx.play_tone(294, 1).

Note that we did not include a loop in this code. This is because if the code is in a loop, it will continue playing indefinitely. This is not always desirable, so we've designed the code to play each tone once.

cpx.play_tone() requires two things from you: a frequency in hertz and a length of time in seconds. So anytime you want to use it, you'll add cpx.play_tone(frequency, seconds) to your code, where frequency is the hertz of the tone you'd like to play, and seconds is the length of time you'd like it to play.

There are many tone generators available on the internet that will give you the hertz of a specific tone. The two tones we've added to the current code are middle C and the D above middle C. Try adding another tone. Have fun with it!

Two Tone Buttons

You can use any of the inputs that we've talked about to play tones. Let's try using the buttons. Add the following code to your code.py.

Download: Project Zip or cpx_play_tone_buttons.py | View on Github

Copy Code
from adafruit_circuitplayground.express import cpx

while True:
if cpx.button_a:
cpx.play_tone(262, 1)
if cpx.button_b:
cpx.play_tone(294, 1)

Now, press each button. Each one plays a tone for one second!

This code is the same as previous code using the buttons. Inside the loop, it checks to see if each button is pressed. This time, if button A is pressed, it plays a 262Hz tone for 1 second, and if button b is pressed, it plays a 294Hz tone for 1 second.

You can use any of the inputs we've discussed in this guide to trigger a tone. Try replacing the button presses with touch pads. Have fun with it!

Start and Stop Tone

Figure-46

What if, instead of playing a tone for a specified amount of time (using playtime), you want to play the tone only when you provide an input? For example, instead of playing a tone for 1 second, what if you want the tone to play while you're pressing a button? Or touching a touchpad? You can do that!

For this section to work, you must have installed on your Circuit Playground Express CircuitPython 2.3.1 or higher, or CircuitPython 3.0 Beta 1 or higher.

Add the following code to your code.py. Remember, if you need help with this, check here.

Download: Project Zip or cpx_start_stop_tone.py | View on Github

Copy Code
from adafruit_circuitplayground.express import cpx

while True:
if cpx.button_a:
cpx.start_tone(262)
elif cpx.button_b:
cpx.start_tone(294)
else:
cpx.stop_tone()

Press button A. Now, press button B. Each button plays a tone, but only while it's being pressed!

Let's look at the code. First we import cpx.

Inside our loop, we check to see if the buttons are being pressed. If button A is pressed, we start a tone with cpx.start_tone(262). If button B is pressed, we start a tone with cpx.start_tone(294). Otherwise, if they're not being pressed, we stop the tone. That's it!

cpx.start_tone() requires one thing from you, a frequency in hertz of the tone you would like to start. So anytime you want to use it, you'll add cpx.start_tone(frequency) to your code, where frequency is the hertz of the tone you'd like to start.

cpx.start_tone() requires cpx.stop_tone() to stop playing. Without it, you'll start the tone and it will play indefinitely. You'll know very quickly if you've forgotten to add cpx.stop_tone()!

Try replacing buttons A and B with touch pads A1 and A2, and change the frequencies to have different tones. Try using all the touch inputs to have more tone options!

Start and Stop More Tone Projects

Here are some projects that use start and stop tone:

Play File

The speaker is also able to play monotone music encoded in a special format called wav files!

Figure-47

For this section to work, you must have installed on your Circuit Playground Express CircuitPython 2.3.1 or higher, or CircuitPython 3.0 Beta 1 or higher.

Sound files for the CPX library should be 22,050 kHz, 16-bit, mono (or less) WAV files to play on the Express boards. If you have an MP3 or a file you downloaded and are unsure of the encoding, you can follow this audio conversion guide to get your files into the proper format.

For testing, we've prepared two WAV files in the proper format. You can download the following two .wav files and copy them to your Circuit Playground Express CIRCUITPY drive.

Coin.wav

Wild_Eep.wav

Add the following code to your code.py. Remember, if you need help with this, check here.

Download: Project Zip or cpx_play_file.py | View on Github

Copy Code
from adafruit_circuitplayground.express import cpx

cpx.play_file("Wild_Eep.wav")

Eep!

Let's look at the code. First we import cpx.

Then, we play a wav file called "Wild_Eep.wav" with cpx.play_file("Wild_Eep.wav"). That's it!

Note that we did not include a loop in this code. This is because if the code is in a loop, it will continue playing indefinitely. This is not always desirable, so we've designed the code to play the file once.

cpx.play_file() requires one thing from you: the name of the wav file you're trying to play back in quotation marks. This is how it knows what file to play. So anytime you want to use it, you'll want to add cpx.play_file("Filename.wav") to your code, replacing Filename.wav with the name of your wav file.

Let's add some inputs and another wav file. Add the following code to your code.py.

Download: Project Zip or cpx_play_file_buttons.py | View on Github

Copy Code
from adafruit_circuitplayground.express import cpx

while True:
if cpx.button_a:
cpx.play_file("Wild_Eep.wav")
if cpx.button_b:
cpx.play_file("Coin.wav")

Now press button A. Eep! Press button B. Ding!

Inside the loop, we check to see if each button is pressed. If button A is pressed, we play "Wild_Eep.wav". If button B is pressed, we play "Coin.wav".

Notice if you press button B and then immediately try to press button A, the Coin.wav file completes before you're able to Eep again. This is because you cannot begin playing another file until the first file is completed. So, if you have a really long wav file, you'll find you can't do anything else until the file is finished playing. Keep that in mind if you're going to include wav files with other code.

You can use any of the inputs we've discussed to trigger a file to play. Try replacing the button presses with touch inputs. Try adding different files to use!

If your code is running but your file doesn't sound quite right or doesn't play back, be sure to check the encoding of your sound file by following this Adafruit guide.

Play More File Projects

Here are some projects that use play file:

Time to Get Creative!

Now that you have examples of how everything works, it's time to get creative! Try combining different concepts to put together a whole new project. You could make something like a capacitive touch combination lock or a book light. The possibilities are endless!

Project Guides Using the Circuit Playground Express Library:

制造商零件编号 3333
CIRCUIT PLAYGROUND EXPRESS
Adafruit Industries LLC
¥203.09
Details
制造商零件编号 3517
CIRCUIT PLAYGRND EXPRSS BASE KIT
Adafruit Industries LLC
¥243.80
Details
制造商零件编号 2769
CIRCUIT PLAYGROUND EXPRESS EDUCA
Adafruit Industries LLC
¥813.60
Details
Add all DigiKey Parts to Cart
TechForum

Have questions or comments? Continue the conversation on TechForum, DigiKey's online community and technical resource.

Visit TechForum