View difference between Paste ID: B9xbXdWP and RWGgckuk
SHOW: | | - or go back to the newest paste.
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
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-
#include <Adafruit_DotStar.h>
15+
#ifdef _AVR_ATtiny85_ // Trinket, Gemma, etc.
16-
#ifdef __AVR_ATtiny85__ // Trinket, Gemma, etc.
16+
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 NUM_LEDS 72 // DotStar Strip
24+
25
#define COLOR_ORDER BGR
26
27
CRGB leds[NUM_LEDS];      //naming our LED array
28-
Adafruit_DotStar pixels(NUM_LEDS, LED_PIN, CLOCK_PIN, DOTSTAR_BGR );
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-
  pixels.begin(); // NeoPixel init
39+
40-
  // Flash space is tight on Trinket/Gemma, so setBrightness() is avoided --
40+
41-
  // it adds ~200 bytes.  Instead the color picker input is 'manually' scaled.
41+
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-
  // Show pixels calculated on *prior* pass; this ensures more uniform timing
116+
117-
  pixels.show();
117+
118
  digitalWrite(CTS_PIN, HIGH); // BLE STOP!
119-
  // Then calculate pixels for *next* frame...
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-
      pixels.setPixelColor(   i, c);         // First eye
125+
126-
      pixels.setPixelColor(NUM_LEDS-1-i, c); // Second eye (flipped)
126+
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-
    pixels.setPixelColor(animPos, 0);     // Erase old dot
131+
132
    animPos++;
133-
    pixels.setPixelColor(animPos, color); // and light it
133+
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-
  pixels.clear(); // Clear pixel data when switching modes (else residue)
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-
    animMode = animMode+1;
167+
168
   case '4':
169
    break;
170-
    animMode = animMode-1;
170+
171
    break;
172
   case '6': // Down
173
    break;
174
   case '7': // Left
175
    break;
176
   case '8': // Right
177
    break;
178
  }
179
}