Hey all, I'm trying to port the existing code from the AdaFruit Trinket Goggles

Hey all,

I’m trying to port the existing code from the AdaFruit Trinket Goggles w/ BlueFruit page (Overview | Bluetooth-Controlled NeoPixel Goggles | Adafruit Learning System) over to FastLED instead of the DotStar library, however I’m running into trouble getting it to work…

Can anyone take a look at my code and see where I went wrong? I’m new to this, so a healthy push is appreciated as I’m trying to finish a project.

Hardware (Adafruit Trinket Pro 5V, with BlueFruit LE module, connected to a strand of 72 DotStar Pixels)
Running the latest and greatest FastLED Library

Code for review:

// Bluetooth Goggles Sketch – shows the Adafruit Bluefruit LE UART Friend
// can be used even with Trinket or Gemma!

// Adafruit Bluefruit LE UART Friend - Bluetooth® Low Energy : ID 2479 : Adafruit Industries, Unique & fun DIY electronics and kits

// Works in conjunction with Bluefruit LE Connect app on iOS or Android –
// pick colors or use ‘1’ and ‘2’ buttons to select pinwheel or sparkle modes.
// You can try adding more, but space is VERY tight…helps to use Arduino IDE
// 1.6.4 or later; produces slightly smaller code than the 1.0.X releases.

// BLUEFRUIT LE UART FRIEND MUST BE SWITCHED TO ‘UART’ MODE

#include <SPI.h>
#include <SoftwareSerial.h>
#include <FastLED.h>
#ifdef AVR_ATtiny85 // Trinket, Gemma, etc.
#include <avr/power.h>
#endif

#define RX_PIN 8 // Connect this Trinket pin to BLE ‘TXO’ pin
#define CTS_PIN 6 // Connect this Trinket pin to BLE ‘CTS’ pin
#define LED_PIN 4 // Connect NeoPixels to this Trinket pin
#define CLOCK_PIN 3
#define NUM_LEDS 72 // Two 16-LED NeoPixel rings
#define FPS 30 // Animation frames/second (ish)
#define COLOR_ORDER BGR

CRGB leds[NUM_LEDS]; //naming our LED array

SoftwareSerial ser(RX_PIN, -1);

int BRIGHTNESS = 255; //0-255. Lower number saves battery life, higher number is screamingly bright
TBlendType currentBlending;

void setup() {
#if defined(AVR_ATtiny85) && (F_CPU == 16000000L)
// MUST do this on 16 MHz Trinket for serial & NeoPixels!
clock_prescale_set(clock_div_1);
#endif
// Stop incoming data & init software serial
pinMode(CTS_PIN, OUTPUT); digitalWrite(CTS_PIN, HIGH);
ser.begin(9600);

FastLED.addLeds<DOTSTAR, LED_PIN, CLOCK_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
FastLED.setBrightness( BRIGHTNESS );
currentBlending = BLEND;
}

uint8_t buf[3], // Enough for RGB parse; expand if using sensors
animMode = 0, // Current animation mode
animPos = 0; // Current animation position
uint32_t color = 0x400000, // Current animation color (red by default)
prevTime = 0L; // For animation timing

void loop(void) {
int c;
uint32_t t;

// Animation happens at about 30 frames/sec. Rendering frames takes less
// than that, so the idle time is used to monitor incoming serial data.
digitalWrite(CTS_PIN, LOW); // Signal to BLE, OK to send data!
for(;:wink: {
t = micros(); // Current time
if((t - prevTime) >= (1000000L / FPS)) { // 1/30 sec elapsed?
prevTime = t;
break; // Yes, go update LEDs
} // otherwise…
if((c = ser.read()) == ‘!’) { // Received UART app input?
while((c = ser.read()) < 0); // Yes, wait for command byte
switch(c) {
case ‘B’: // Button (Control Pad)
if(readAndCheckCRC(255-‘!’-‘B’, buf, 2) & (buf[1] == ‘1’)) {
buttonPress(buf[0]); // Handle button-press message
}
break;
case ‘C’: // Color Picker
if(readAndCheckCRC(255-‘!’-‘C’, buf, 3)) {
// As mentioned earlier, setBrightness() was avoided to save space.
// Instead, results from the color picker (in buf) are divided
// by 4; essentially equivalent to setBrightness(64). This is to
// improve battery run time (NeoPixels are still plenty bright).
color = pixels.Color(buf[0]/4, buf[1]/4, buf[2]/4);
}
break;
case ‘Q’: // Quaternion
skipBytes(17); // 4 floats + CRC (see note below re: parsing)
break;
case ‘A’: // Accelerometer
#if 0
// The phone sensors are NOT used by this sketch, but this shows how
// they might be read. First, buf must be delared large enough for
// the expected data packet (minus header & CRC) – that’s 16 bytes
// for quaternions (above), or 12 bytes for most of the others.
// Second, the first arg to readAndCheckCRC() must be modified to
// match the data type (e.g. ‘A’ here for accelerometer). Finally,
// values can be directly type-converted to float by using a suitable
// offset into buf (e.g. 0, 4, 8, 12) … it’s not used in this
// example because floating-point math uses lots of RAM and code
// space, not suitable for the space-constrained Trinket/Gemma, but
// maybe you’re using a Pro Trinket, Teensy, etc.
if(readAndCheckCRC(255-‘!’-‘A’, buf, 12)) {
float x = *(float *)(&buf[0]),
y = *(float *)(&buf[4]),
z = *(float *)(&buf[8]);
}
// In all likelihood, updates from the buttons and color picker
// alone are infrequent enough that you could do without any mention
// of the CTS pin in this code. It’s the extra sensors that really
// start the firehose of data.
break;
#endif
case ‘G’: // Gyroscope
case ‘M’: // Magnetometer
case ‘L’: // Location
skipBytes(13); // 3 floats + CRC
}
}
}
digitalWrite(CTS_PIN, HIGH); // BLE STOP!

// Show pixels calculated on prior pass; this ensures more uniform timing
FastLED.show();

// Then calculate pixels for next frame…
switch(animMode) {
case 0: // Pinwheel mode
for(uint8_t i=0; i<NUM_LEDS/2; i++) {
uint32_t c = 0;
if(((animPos + i) & 7) < 2) c = color; // 4 pixels on…
ledsi; // First eye
ledsNUM_LEDS-1-i; // Second eye (flipped)
}
animPos++;
break;
case 1: // Sparkle mode
ledsanimPos; // Erase old dot
animPos = random(NUM_LEDS); // Pick a new one
ledsanimPos; // and light it
break;
}
}

boolean readAndCheckCRC(uint8_t sum, uint8_t *buf, uint8_t n) {
for(int c;:wink: {
while((c = ser.read()) < 0); // Wait for next byte
if(!n–) return (c == sum); // If CRC byte, we’re done
*buf++ = c; // Else store in buffer
sum -= c; // and accumulate sum
}
}

void skipBytes(uint8_t n) {
while(n–) {
while(ser.read() < 0);
}
}

void buttonPress(char c) {
fill_solid(leds, NUM_LEDS, CHSV(0,0,0)); // Clear pixel data when switching modes (else residue)
switch(c) {
case ‘1’:
animMode = 0; // Switch to pinwheel mode
break;
case ‘2’:
animMode = 1; // Switch to sparkle mode
break;
case ‘3’:
break;
case ‘4’:
break;
case ‘5’: // Up
break;
case ‘6’: // Down
break;
case ‘7’: // Left
break;
case ‘8’: // Right
break;
}
}

Switch to the FastLED3.1 branch - and if it still doesnt work can you give a little bit more detail about what it is or isn’t doing.

(Also, as mentioned in the sidebar for the community - please use gist or pastebin for code - code in g+ posts and comments is irritating to read (especially on mobile clients))

Alright, using FastLED3.1 branch. I’ve also switched over to using PasteBin per your suggestion. Sorry about missing that portion. I tried to be thorough but failed.

So, ultimately the main part of my goal is this. To convert the following code from a DotStar.h gallery to FastLED, while retaining the Bluetooth button functionality. There aren’t many calls inside of this specifically for the LEDs, but I’m a novice. Is there any chance you can simply make the changes and I can test and verify?

I greatly appreciate any help you can offer.

I can’t test it, but I went ahead and got this compiling without error in Arduino. Your pastebin wasn’t the same as the code you posted here, so I cloned your pastebin, updated it to what you had here, and then fixed the compiler errors. You can see what I changed here: http://pastebin.com/diff.php?i=cftMr5v6

Jason, you nailed it. Thank you so much. So, I’m now working on combining two sketches that I have. One of them is a sketch with about 9 different visualizations. The other is this one. I’m going to put some time in and try to get it to work, but if I have any difficulties, I’ll paste my work here. Would you be willing to help again? I need to get this done and finalized by Monday.

I can’t thank you all enough for your help.

No problem, glad it works. I can’t promise I’ll be available, but I don’t mind trying to help as long as you give it your all first. Just remember to use pastebin or gist to share the code. You’re also more likely to get assistance if you post (again, in pastebin or gist if they’re long) any compiler errors you get. Good luck!

Alright, so I was able to successfully copy the necessary animations from one sketch to another, however the problem is they run significantly slower now. The existing two animations from the sketch Jason helped me with, continue to run at normal/the same speed. The new animations, which ran just fine on their own, run slower and I can see rapid flickering in the LEDs. (EDIT: Had the FPS set to 30 instead of 60. However, now the two animations which were in the original file that was meant for 30 fps run waaaay too fast. If I use a delay, it causes problems with the polling to the Bluetooth module, so is there a way to conditionally divide the FPS in half when displaying certain animation modes?)

Additionally I have been having problems figuring out how to get the Solid() portion to write a color from the color picker module. When going to that mode, the strip is black/off. I’ve been banging my head on these issues for hours. Any guidance is greatly appreciate.

Alright, I fixed my speed problem. Stupid mistake on my part… but assistance with the other two would be awesome. Also, is there a way to limit the button presses to a certain number, so it wraps up and down between those values? Example: I have 8 animations modes, but if I press the button to change modes up, it keeps counting beyond 8 and displays nothing. If I press the button to change modes down from 1, it also displays nothing.

animMode = mod8(animMode+1,8);

And

animMode = mod8(animMode-1,8);

Your Solid function is creating a CRGB color, but not doing anything with it. You need to actually set all the LEDs to that color:

CRGB color = CRGB(buf[0], buf[1], buf[2]);

for(uint8_t i = 0; i < NUM_LEDS; i++) {
leds[i] = color;
}

OR, FastLED has a convenience method for this (which it looks like you’re using elsewhere in the same sketch):

fill_solid(leds, NUM_LEDS, CRGB(buf[0], buf[1], buf[2]));

Hi all,

I can’t express to you how thankful I am for your help and support on this project. I’ve been burning the midnight oil and have switched all my animations to use a millis() call instead of delay, which allows the bluetooth module to properly be polled for button presses without being locked out by the endless delays. The Solid function code you gave me worked like a charm (the first version… for some reason, the fill_solid call which works elsewhere, does not work when using the buf variable calls. Regardless, it works using the first method.

I’ve added more animations, and re-timed the existing ones and everything looks great. The only thing I am stuck on is this code for the button to wrap around when it runs out of cases. I tried Daniels suggestion, but it returns:

Test.ino: In function ‘void buttonPress(char)’:
Test:426: error: ‘mod8’ was not declared in this scope
‘mod8’ was not declared in this scope

I will be adding animations periodically. Is there a way that when it runs out of cases, it just goes back to the first case?

Thanks again!

You need to be using the FastLED3.1 branch to have mod8. (mod8 doesn’t exist on the master branch) - make sure you don’t have multiple copies of FastLED checked out - arduino might be using the wrong one for its work.

Bingo! Project is 100%. Thanks again.