Example_4_Accelerometer_LED.ino
1 // SPDX-FileCopyrightText: 2019 Tony DiCola for Adafruit Industries 2 // 3 // SPDX-License-Identifier: MIT 4 5 // Example of rotating accelerometer to change NeoPixel color. 6 // Author: Tony DiCola 7 // License: MIT 8 #include <Adafruit_NeoPixel.h> 9 #include <Wire.h> 10 #include <SPI.h> 11 #include <Adafruit_LIS3DH.h> 12 #include <Adafruit_Sensor.h> 13 14 15 #define PIXEL_PIN 8 // Pin connected to NeoPixels. Use 8 for the NeoPixel built into Flora V2. 16 17 #define PIXEL_COUNT 1 // Number of NeoPixels. 18 19 #define PIXEL_TYPE NEO_GRB + NEO_KHZ800 // NeoPixel type, stick with default unless using different pixels. 20 // See the NeoPixel Uberguide for information on different types: 21 // https://learn.adafruit.com/adafruit-neopixel-uberguide/overview 22 23 #define COLOR_MIN Adafruit_NeoPixel::Color(255, 0, 0) // RGB color for minimum axis value. 24 25 #define COLOR_MAX Adafruit_NeoPixel::Color(0, 0, 255) // RGB color for maximum axis value. 26 27 #define AXIS_MIN -2000 // Minimum axis value, when at this or below the pixel color is the minimum color above. 28 29 #define AXIS_MAX 2000 // Maximum axis value, when at this or above the pixel color is the maximum color above. 30 31 #define ACCEL_RANGE LIS3DH_RANGE_4_G // Range of acceleration values for the LIS3DH. Can 32 // change to 2G, 4G, 8G, or 16G values. 33 34 #define SAMPLE_SIZE 4 // Number of samples to use for a moving average of 35 // on each accelerometer axis. This smoothes out the 36 // readings so they're less noisey. 37 38 39 // Create NeoPixel object. 40 Adafruit_NeoPixel pixels = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE); 41 42 // Create LIS3DH accelerometer library object, this will by default use an I2C connection. 43 Adafruit_LIS3DH accel = Adafruit_LIS3DH(); 44 45 // Keep a moving average of the last few accelerometer samples to smooth out the readings. 46 // This helps reduce random noise and spikes/jumps in the data. 47 long x_samples[SAMPLE_SIZE] = { 0 }; 48 long y_samples[SAMPLE_SIZE] = { 0 }; 49 long z_samples[SAMPLE_SIZE] = { 0 }; 50 51 52 void lightPixels(uint32_t color, Adafruit_NeoPixel& strip) { 53 // Light all the NeoPixels in the strip with the provided color. 54 for (int i=0; i < strip.numPixels(); ++i) { 55 strip.setPixelColor(i, color); 56 } 57 strip.show(); 58 } 59 60 uint32_t colorLerp(float x, float x0, float x1, uint32_t c0, uint32_t c1) 61 { 62 // Simple linear interpolation of a color within the range c0, c1 based on 63 // a value x that falls within the range of x0, x1. The Arduino map function 64 // is similar but only works on signed integer values. 65 // First clamp x to be in the provided range. 66 x = constrain(x, x0, x1); 67 // Next compute the scaling factor based on X's position between x0 and x1. 68 float scale = (x-x0)/(x1-x0); 69 // Pull out the red, green, blue component values from each min/max color. 70 uint8_t c0_red = (c0 >> 16) & 0xFF; 71 uint8_t c1_red = (c1 >> 16) & 0xFF; 72 uint8_t c0_green = (c0 >> 8) & 0xFF; 73 uint8_t c1_green = (c1 >> 8) & 0xFF; 74 uint8_t c0_blue = c0 & 0xFF; 75 uint8_t c1_blue = c1 & 0xFF; 76 // Scale each color component independently, then reassemble into a new color. 77 uint8_t red = c0_red + (c1_red - c0_red ) * scale; 78 uint8_t green = c0_green + (c1_green - c0_green) * scale; 79 uint8_t blue = c0_blue + (c1_blue - c0_blue ) * scale; 80 return Adafruit_NeoPixel::Color(red, green, blue); 81 } 82 83 void addSample(long newSample, long* samples) { 84 // Add a new sample to the array of samples. Will shift out the earliest sample 85 // to make room for the new sample. 86 memmove(samples, samples+1, SAMPLE_SIZE-1); 87 samples[SAMPLE_SIZE-1] = newSample; 88 } 89 90 long avgSample(long* samples) { 91 // Return the average sample value in the provided array of samples. 92 long result = 0; 93 for (int i=0; i < SAMPLE_SIZE; ++i) { 94 result += samples[i]; 95 } 96 return result/SAMPLE_SIZE; 97 } 98 99 void setup() { 100 // Initialize serial port to print accelerometer output. 101 Serial.begin(9600); 102 // Initialize LIS3DH accelerometer library. 103 if (!accel.begin()) { 104 Serial.println("Couldn't find LIS3DH, is it connected?"); 105 while(1); 106 } 107 accel.setRange(ACCEL_RANGE); 108 // Initialize NeoPixels. 109 pixels.begin(); 110 } 111 112 void loop() { 113 // Take an accelerometer reading and add to lists of samples. 114 accel.read(); 115 addSample(accel.x, x_samples); 116 addSample(accel.y, y_samples); 117 addSample(accel.z, z_samples); 118 // Now print out the average X, Y, Z sample values. 119 long x = avgSample(x_samples); 120 long y = avgSample(y_samples); 121 long z = avgSample(z_samples); 122 Serial.print("X: "); 123 Serial.print(x); 124 Serial.print(" \tY: "); 125 Serial.print(y); 126 Serial.print(" \tZ: "); 127 Serial.println(z); 128 // Map the Y axis accelerometer value to a pixel color and light the pixels. 129 uint32_t color = colorLerp(y, AXIS_MIN, AXIS_MAX, COLOR_MIN, COLOR_MAX); 130 lightPixels(color, pixels); 131 // Delay to slow things down and prevent spamming serial port. 132 delay(100); 133 } 134