The Circuit Playground Express has a 3-axis LIS3DH accelerometer on board which can be used for all sorts of projects. This chip has the advantage of being very small and fits nicely at the center of the Circuit Playground boards. Sometimes, though, "just" being a 3-axis accelerometer is a disadvantage. Times like those when you need compass-like capabilities. An accelerometer only tells you how the board is moving (the forces acting on it, to be precise), but not how it's oriented relative to the magnetic north pole of whichever planet you're on. For that, a magnetometer is needed.
Magnetometers do come as separate chips (the BBC Micro:bit has one, for example) but it doesn't seem as easy to find on a breakout board. However, breakouts containing a single chip with both an accelerometer and a magnetometer are easy to find. Specificity, there are breakouts containing the LSM303 in both the usual rectangular header-strip format as well as a Flora breakout.
In this guide we'll add the Flora LMS303 breakout to a Circuit Playground Express and use it to build a compass.
Coding in C (Arduino), you can actually use any breakout whose supporting library conforms to the Adafruit Unified Sensor Library and provides magnetometer readings. The project is also programmable in CircuitPython and demonstrates use of the accelerometer.
The NeoPixels on the Circuit Playground Express will be used to indicate North.
During calibration (when all the pixels are green) move the box in a figure eight and rotate it around the x, and y axes multiple times.
By sampling a range of readings. we can get a sense of the expected range of values. Using that, we can calculate the center on the range on both the X and Y axes. The distance of that from (0, 0) can be used to correct subsequent readings to be relative to (0, 0).
When calibrating from the original code (i.e. you haven't tweaked the min/max arrays) or if you ask for a recalibration (by pressing button A until the pixels turn green) the result will be printed on the console. You can copy these two lines and replace the similar ones near the top of the code. Rebuild it (if using the Arduino code) and load it onto your compass.
We can then map each corrected reading to the range -100 to +100, and pass these normalized values to the atan2 function that gives us a heading, the angle as shown in the range -Pi to Pi.
Then we find which 30 degree wedge the heading falls into. We start by adding 180 to the angle from above, giving us something between 0 and 360. We add 15 (because the lowest segment is centered on zero) and divide by 30.
And that's how we know which NeoPixel to light up.
For the build described here, you'll probably want a case for the Circuit Playground Express. If you have a 3D printer or have access to 3D printing facilities, this guide shows how to produce a nice one.