jasoncoon

Bluetooth Goggles Sketch - Mark's FastLED conversion attempt

Aug 21st, 2015
136
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // Bluetooth Goggles Sketch -- shows the Adafruit Bluefruit LE UART Friend
  2. // can be used even with Trinket or Gemma!
  3.  
  4. // https://www.adafruit.com/products/2479  
  5. // Works in conjunction with Bluefruit LE Connect app on iOS or Android --
  6. // pick colors or use '1' and '2' buttons to select pinwheel or sparkle modes.
  7. // You can try adding more, but space is VERY tight...helps to use Arduino IDE
  8. // 1.6.4 or later; produces slightly smaller code than the 1.0.X releases.
  9.  
  10. // BLUEFRUIT LE UART FRIEND MUST BE SWITCHED TO 'UART' MODE
  11.  
  12. #include <SPI.h>
  13. #include <SoftwareSerial.h>
  14. #include <FastLED.h>
  15. #ifdef _AVR_ATtiny85_ // Trinket, Gemma, etc.
  16.  #include <avr/power.h>
  17. #endif
  18.  
  19. #define RX_PIN    8 // Connect this Trinket pin to BLE 'TXO' pin
  20. #define CTS_PIN   6 // Connect this Trinket pin to BLE 'CTS' pin
  21. #define LED_PIN   4 // Connect NeoPixels to this Trinket pin
  22. #define CLOCK_PIN 3
  23. #define NUM_LEDS 72 // Two 16-LED NeoPixel rings
  24. #define FPS      30 // Animation frames/second (ish)
  25. #define COLOR_ORDER BGR
  26.  
  27. CRGB leds[NUM_LEDS];      //naming our LED array
  28.  
  29. SoftwareSerial    ser(RX_PIN, -1);
  30.  
  31. int BRIGHTNESS = 255;    //0-255.  Lower number saves battery life, higher number is screamingly bright
  32. TBlendType    currentBlending;
  33.  
  34. void setup() {
  35. #if defined(__AVR_ATtiny85__) && (F_CPU == 16000000L)
  36.   // MUST do this on 16 MHz Trinket for serial & NeoPixels!
  37.   clock_prescale_set(clock_div_1);
  38. #endif
  39.   // Stop incoming data & init software serial
  40.   pinMode(CTS_PIN, OUTPUT); digitalWrite(CTS_PIN, HIGH);
  41.   ser.begin(9600);
  42.  
  43. FastLED.addLeds<DOTSTAR, LED_PIN, CLOCK_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
  44.   FastLED.setBrightness(  BRIGHTNESS );
  45.   currentBlending = BLEND;
  46. }
  47.  
  48. uint8_t  buf[3],              // Enough for RGB parse; expand if using sensors
  49.          animMode = 0,        // Current animation mode
  50.          animPos  = 0;        // Current animation position
  51. uint32_t color    = 0x400000, // Current animation color (red by default)
  52.          prevTime = 0L;       // For animation timing
  53.  
  54. void loop(void) {
  55.   int      c;
  56.   uint32_t t;
  57.  
  58.   // Animation happens at about 30 frames/sec.  Rendering frames takes less
  59.   // than that, so the idle time is used to monitor incoming serial data.
  60.   digitalWrite(CTS_PIN, LOW); // Signal to BLE, OK to send data!
  61.   for(;;) {
  62.     t = micros();                            // Current time
  63.     if((t - prevTime) >= (1000000L / FPS)) { // 1/30 sec elapsed?
  64.       prevTime = t;
  65.       break;                                 // Yes, go update LEDs
  66.     }                                        // otherwise...
  67.     if((c = ser.read()) == '!') {            // Received UART app input?
  68.       while((c = ser.read()) < 0);           // Yes, wait for command byte
  69.       switch(c) {
  70.        case 'B':       // Button (Control Pad)
  71.         if(readAndCheckCRC(255-'!'-'B', buf, 2) & (buf[1] == '1')) {
  72.           buttonPress(buf[0]); // Handle button-press message
  73.         }
  74.         break;
  75.        case 'C':       // Color Picker
  76.         if(readAndCheckCRC(255-'!'-'C', buf, 3)) {
  77.           // As mentioned earlier, setBrightness() was avoided to save space.
  78.           // Instead, results from the color picker (in buf[]) are divided
  79.           // by 4; essentially equivalent to setBrightness(64).  This is to
  80.           // improve battery run time (NeoPixels are still plenty bright).
  81.           color = pixels.Color(buf[0]/4, buf[1]/4, buf[2]/4);
  82.         }
  83.         break;
  84.        case 'Q':       // Quaternion
  85.         skipBytes(17); // 4 floats + CRC (see note below re: parsing)
  86.         break;
  87.        case 'A':       // Accelerometer
  88. #if 0
  89.         // The phone sensors are NOT used by this sketch, but this shows how
  90.         // they might be read.  First, buf[] must be delared large enough for
  91.         // the expected data packet (minus header & CRC) -- that's 16 bytes
  92.         // for quaternions (above), or 12 bytes for most of the others.
  93.         // Second, the first arg to readAndCheckCRC() must be modified to
  94.         // match the data type (e.g. 'A' here for accelerometer).  Finally,
  95.         // values can be directly type-converted to float by using a suitable
  96.         // offset into buf[] (e.g. 0, 4, 8, 12) ... it's not used in this
  97.         // example because floating-point math uses lots of RAM and code
  98.         // space, not suitable for the space-constrained Trinket/Gemma, but
  99.         // maybe you're using a Pro Trinket, Teensy, etc.
  100.         if(readAndCheckCRC(255-'!'-'A', buf, 12)) {
  101.           float x = *(float *)(&buf[0]),
  102.                 y = *(float *)(&buf[4]),
  103.                 z = *(float *)(&buf[8]);
  104.         }
  105.         // In all likelihood, updates from the buttons and color picker
  106.         // alone are infrequent enough that you could do without any mention
  107.         // of the CTS pin in this code.  It's the extra sensors that really
  108.         // start the firehose of data.
  109.         break;
  110. #endif
  111.        case 'G':       // Gyroscope
  112.        case 'M':       // Magnetometer
  113.        case 'L':       // Location
  114.         skipBytes(13); // 3 floats + CRC
  115.       }
  116.     }
  117.   }
  118.   digitalWrite(CTS_PIN, HIGH); // BLE STOP!
  119.  
  120.   // Show pixels calculated on prior pass; this ensures more uniform timing
  121.   FastLED.show();
  122.  
  123.   // Then calculate pixels for next frame...
  124.   switch(animMode) {
  125.    case 0: // Pinwheel mode
  126.     for(uint8_t i=0; i<NUM_LEDS/2; i++) {
  127.       uint32_t c = 0;
  128.       if(((animPos + i) & 7) < 2) c = color; // 4 pixels on...
  129.       leds[i](c);         // First eye
  130.       leds[NUM_LEDS-1-i](c); // Second eye (flipped)
  131.     }
  132.     animPos++;
  133.     break;
  134.    case 1: // Sparkle mode
  135.     leds[animPos](0);     // Erase old dot
  136.     animPos = random(NUM_LEDS);           // Pick a new one
  137.     leds[animPos](color); // and light it
  138.     break;
  139.   }
  140. }
  141.  
  142. boolean readAndCheckCRC(uint8_t sum, uint8_t *buf, uint8_t n) {
  143.   for(int c;;) {
  144.     while((c = ser.read()) < 0); // Wait for next byte
  145.     if(!n--) return (c == sum);  // If CRC byte, we're done
  146.     *buf++ = c;                  // Else store in buffer
  147.     sum   -= c;                  // and accumulate sum
  148.   }
  149. }
  150.  
  151. void skipBytes(uint8_t n) {
  152.   while(n--) {
  153.     while(ser.read() < 0);
  154.   }
  155. }
  156.  
  157. void buttonPress(char c) {
  158.   fill_solid(leds, NUM_LEDS, CHSV(0,0,0)); // Clear pixel data when switching modes (else residue)
  159.   switch(c) {
  160.    case '1':
  161.     animMode = 0; // Switch to pinwheel mode
  162.     break;
  163.    case '2':
  164.     animMode = 1; // Switch to sparkle mode
  165.     break;
  166.    case '3':
  167.     break;
  168.    case '4':
  169.     break;
  170.    case '5': // Up
  171.     break;
  172.    case '6': // Down
  173.     break;
  174.    case '7': // Left
  175.     break;
  176.    case '8': // Right
  177.     break;
  178.   }
  179. }
Advertisement
Add Comment
Please, Sign In to add comment