Good response today as I posted on social media the picture below - the Adafruit Circuit Playground low cost experimenter board and a 3xAAA battery pack fit well in a Pringles potato chip (crisp) can:
So I have been playing with the accelerometer sensor in the Circuit Playground. You can do some sophisticated things with an accelerometer. Let's see what I did with the can.
Use some Blu-Tack, silly putty, clay, etc. to attach Circuit Playground to the battery pack. Just be sure the adhesive is not permanent and non-conductive. Plug the battery pack into the Circuit Playground and turn it on. Slide it into the can, it'll fit fine and not slide around (yay!).
First, I'll light up one Circuit Playground LED NeoPixel green. Program Circuit Playground with the first sketch below (which turns on NeoPixel #2). Then I put the Circuit Playground into the can so it is fixed to the bottom. Then I roll the can. The LED will do loop-de-loops in circles similar to the following diagram:
And in the dark it looks like this:
Now, say I want the LED to always be at the top of the can. I can try to time the lighting of the LED to the rate at which I spin the can but I'm not a good can roller and it would get all messy.
So I use the accelerometer on Circuit Playground to tell which way is "up" as the can rolls at any speed. An accelerometer measures both the pull of gravity on the sensor and changes in movement. If you roll Circuit Playground like we did above, there will be changes in the X and Y directions (the Z axis doesn't change rolling the can as I have mounted it). See the board for which ways are
Is keeping the LED lit at the top of the ring as the can rolls even possible? Yes. It takes some math though. You can read the acceleration values as the can rolls in rolling distance and as the can presses on the ground due to gravity. Kind of like the figure below from the Wikipedia article Circular Motion under the non-uniform heading
Program the Circuit Playground with the second sketch below. The code boils down to finding the angle between the x and y values of the accelerometer reading, calculating an angle. That angle is used to determine which of the 10 NeoPixels on Circuit Playground needs to be lit to remain at the top of the ring. That method allows for the rate of rolling the can (shown as v in the diagram) to vary and the rate of rolling does not matter (except a tiny bit for code speed).
The LED at the top of the circle is lit at all times. It looks like this in the Pringles can:
So with little more than an empty can, Circuit Playground and a battery pack, we've used a bit of sensing and programming to make something do what intuitively it shouldn't do. This behavior is actually VERY useful and can be used to make bigger and better things.
And that's the beauty of Circuit Playground. You can do so much with the capabilities onboard and you don't need to buy a lot of stuff to make it do great things, just look in the cupboard perhaps.
Code
Code for one LED:
// CPoneLED
//
// Set for Circuit Playground to display one LED Continually
// CPaccelerometerLED // // Set the LED at the "top" of the Circuit Playground NeoPixel ring // no matter the x or y orientation (like when rolling) // // Mike Barela August 23, 2016 MIT License #include <Adafruit_CircuitPlayground.h> #define NUMBER_OF_LEDS_ON_RING 10 const int brightness = 16; int ledPosition, currentQueueSize; void setup() { CircuitPlayground.begin(); CircuitPlayground.setBrightness(brightness); CircuitPlayground.clearPixels(); } int led, previousLed=0; float x, y, nx, ny, angle; void loop(){ x = CircuitPlayground.motionX(); // Read the accelerometer X & Y y = CircuitPlayground.motionY(); nx = x / 10.0; // Scale to -1 to +1 in ny = y / 10.0; // both directions angle = atan((ny/nx)) * 180 / 3.14; // get the angle from "down" if(angle > 0.0){ // As Arctangent won't give the angle over the if(nx < 0.0) // entire 360 degrees, adjust depending angle += 180; // on direction the acceleration was going } else { if(ny > 0.0) angle += 180; else angle += 360; } if(angle == 360.0) angle = 0; // We have 10 LEDs in a circle - need to light the right one led = circularize(angle / (360 / NUMBER_OF_LEDS_ON_RING)); // make led movement smooth if(previousLed == led){ // no movement, just reloop // nothing to do } else if (counterClockwiseDistanceBetweenLeds(previousLed, led) <= 8) { led = circularize(previousLed + 1); // change detected, makeLightShow(previousLed, led); // change LED previousLed = led; } else { led = circularize(previousLed - 1); makeLightShow(previousLed, led); previousLed = led; } delay(25); } void makeLightShow(int previousLed, int led) { // light NeoPixel CircuitPlayground.strip.setPixelColor(previousLed,0,0,0); CircuitPlayground.strip.setPixelColor(led, 0, brightness, 0); CircuitPlayground.strip.show(); } int circularize(int pos){ // if a position gets to be < 0 or > 9 if(pos >= NUMBER_OF_LEDS_ON_RING) return(pos - NUMBER_OF_LEDS_ON_RING); else if(pos < 0) return(pos + NUMBER_OF_LEDS_ON_RING); else return(pos); } int counterClockwiseDistanceBetweenLeds(int prevPos, int nextPos){ int distance; distance = nextPos - prevPos; if(distance < 0) distance += NUMBER_OF_LEDS_ON_RING; return(distance); } An exercise for the student / magician is to make one sketch, it acts one way with the slide switch at the + position, another when switched to -. Code heavily modified from https://petervojtek.github.io/diy/2015/01/24/neopixel-gravitation.html, the page gives some good info on the subject also.
My latest work was posted yesterday on the Adafruit Learning System. Their new Circuit Playground experimenting board has alot of uses. I explored using the onboard speaker to make sound and music. It progresses using the onboard light, temperature, and motion sensors. Finally it is programmed to play a Simon lights and sound game using the capacitive touch pads. It's a very flexible board.
Unless you've been stuck upgrading all your computers to Windows 10 before the deadline of July 29th, you may have heard that the 2000's sensation Pokemon has been reborn in a new augmented reality game Pokemon Go.
Poke Balls are the red and white spheres that a person uses to catch Pokemon.
Adafruit's NeoPixel light rings can be set to half red and half white to simulate a Poke Ball.
The code below has been set for the 10 pixels on Circuit Playground. The code can be used on any Adafruit NeoPixel ring with quick changes to the constants at the start.
Have fun!
// CPpokeball Paints your Adafruit NeoPixel ring in Poke Ball colors // // Set for Circuit Playground but works for all Adafruit NeoPixel Rings with // correct pixel pin number and pixel count // // Mike Barela July 23, 2016 MIT License #include <Adafruit_NeoPixel.h> const int pixelPin = 17; // NeoPixel pin number for Circuit Playground const int pixelCount = 10; // Number of Neopixels (10 for Circuit Playground) const int pixelBrightness = 30; // 0 to 255 Adafruit_NeoPixel strip = Adafruit_NeoPixel(pixelCount, pixelPin, NEO_GRB + NEO_KHZ800); uint32_t red = strip.Color(255, 0, 0); uint32_t white = strip.Color(255, 255, 255); uint32_t black = strip.Color(0, 0, 0); void setup() { // this resets all the neopixels to an off state strip.begin(); strip.show(); strip.setBrightness(pixelBrightness); } void loop() { setPixelsPokeBall(); // set Pokeball colors delay(5000); // delay 5 deconds for( int8_t j=1; j<=5; j++) { // blink Pokeball colors 5 times setPixelsOff(); delay(700); setPixelsPokeBall(); delay(700); } delay(2000); // wait a bit and start again } void setPixelsOff(void) { for(int8_t i=0; i<=9; i++) { strip.setPixelColor(i, black); } strip.show(); } void setPixelsPokeBall(void) { for(int8_t i=0; i<(pixelCount/2); i++) { strip.setPixelColor(i, red); } for(int8_t i=(pixelCount/2); i<pixelCount; i++) { strip.setPixelColor(i, white); } strip.show(); }