Guest User

DotFruit BlueFruit Goggles

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