// Copyright 2020 Lukas Haubaum // // Licensed under MIT license // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // uncomment next line if you want to use NEOPIXEL (3 pins) instead of APA102 (4 pins) //#define NEOPIXEL // uncomment next line for image test modus, this will change the segments every 1/2 second //#define TEST_STRIPES #include "images.h" #ifdef NEOPIXEL #include #else #include #define APA102_USE_FAST_GPIO #include #endif // CONFIGURE please configure next lines depending on your stripes arragmentment #define HALL_PIN 5 // digital pin of hall sensor #define ROUND_COUNT 1 // how many rounds to take time (minimum 1) #define NUM_SEGMENTS 360 // how much segements to divide image (gives an angle precision of 360 / NUM_SEGMENTS) #define LED_COUNT 26 // how many LEDs on one stripe #define LED_STRIPES 2 // how many LEDs stripes on wheel int strip_matrix_offset[LED_STRIPES] = {0, 0}; // given offset in segments for stripe bool strip_matrix_invert[LED_STRIPES] = {false, true}; // set LEDs in revert order for stripe // \CONFIGURE // LED stripes #ifdef NEOPIXEL #define LED_PIN 6 // data pin for neopixel LED stripe #define BRIGHTNESS 10 // brightness for LED strip [0-255] Adafruit_NeoPixel ledStrip(LED_COUNT *LED_STRIPES, LED_PIN, NEO_GRB + NEO_KHZ800); #else #define LED_DATA_PIN 3 // data pin for LED strip #define LED_CLOCK_PIN 2 // clock pin for LED strip APA102 ledStrip; #define BRIGHTNESS 1 // brightness for LED strip [0-31] rgb_color color_buffer[LED_COUNT * LED_STRIPES]; // color buffer to write to LED stripe #endif float passed = 0; int current_image_index = 0; uint8_t *current_palette; uint8_t *current_pixels; int current_segment = 0; void setup() { Serial.begin(115200); // debug serial print pinMode(HALL_PIN, INPUT); // set hall pin as input pinMode(LED_BUILTIN, OUTPUT); // set build-in LED as output current_palette = (uint8_t *)pgm_read_word(&images[current_image_index].palette); // init palette for current image current_pixels = (uint8_t *)pgm_read_word(&images[current_image_index].pixels); // init pixels for current image #ifdef NEOPIXEL ledStrip.begin(); ledStrip.show(); ledStrip.setBrightness(BRIGHTNESS); #else for (int i = 0; i < LED_COUNT * 4; i++) // loop over all LEDs { color_buffer[i] = rgb_color(0, 0, 0); // set to black } ledStrip.write(color_buffer, LED_COUNT * LED_STRIPES, 0); // write buffer to stripes #endif } void loop() { float start = micros(); int count = 0; bool detected = false; while (count <= ROUND_COUNT) // keep in loop while not ROUND_COUNT reached { if (digitalRead(HALL_PIN) == LOW) // if hall sensor detect magnet { digitalWrite(LED_BUILTIN, HIGH); // use build-in LED as indicator for present magnet if (!detected) // check if magnet present first time { detected = true; count++; // count round } } else // if hall sensor not detect magnet { digitalWrite(LED_BUILTIN, LOW); // build-in LED indicator detected = false; // reset magnet state } float current_diff = micros() - start; // get time passed in current loop #ifdef TEST_STRIPES // testing stripes int segment = (micros() / 500000) % NUM_SEGMENTS; // calculate current segment as half seconds passed since runtime if (segment == current_segment) // do nothing if still in old segment { return; } Serial.println(current_segment); // debug print of current segment current_segment = segment; #else current_segment = ((float)passed / current_diff * NUM_SEGMENTS); // calculate current segment as percentage of time passed #endif for (int strip = 0; strip < LED_STRIPES; strip++) // loop over all stripes { uint8_t pixel_color_index; // get pointer to current pixel of image as offset of current strip and offset of current segment uint8_t *current_pixel = (uint8_t *)¤t_pixels[((current_segment + strip_matrix_offset[strip]) % NUM_SEGMENTS) * LED_COUNT]; for (int i = 0; i < LED_COUNT; i++) // loop over all LEDs of current strip { pixel_color_index = pgm_read_byte(current_pixel++) * 3; // read color palette index for current pixel uint8_t pixel_index = strip * LED_COUNT + (strip_matrix_invert[strip] ? (LED_COUNT - i) : i); // calculate index of LED with offset and inversion #ifdef NEOPIXEL // set pixel of NEOPIXEL ledStrip.setPixelColor(pixel_index, pgm_read_byte(¤t_palette[pixel_color_index]), pgm_read_byte(¤t_palette[pixel_color_index + 1]), pgm_read_byte(¤t_palette[pixel_color_index + 2])); #else // set pixel of buffer color_buffer[pixel_index] = rgb_color( pgm_read_byte(¤t_palette[pixel_color_index]), pgm_read_byte(¤t_palette[pixel_color_index + 1]), pgm_read_byte(¤t_palette[pixel_color_index + 2])); #endif } } #ifdef NEOPIXEL ledStrip.show(); // update pixel #else ledStrip.write(color_buffer, LED_COUNT * LED_STRIPES, BRIGHTNESS); // write buffer to stripes #endif } passed = (micros() - start); // rounds done, caluclate duration }