Help! I cannot get my code to compile for the life of me. FastLED seems to work fine in a simple file, but as soon as I incorporate into a larger project with separate files I'm getting this error.
In staff.h I have:
#ifndef _STAFF_H
#define _STAFF_H
#include <Arduino.h>
#include <SPI.h>
#include <Adafruit_DotStar.h>
#include <FastLED.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_MPU6050.h>
#include <Wire.h>
#include "config.h"
#include "flashstorage.h"
#include "bmpimage.h"
class POVstaff {
public:
void begin();
void setPixel(uint16_t i, uint32_t c);
void clear();
void show();
CRGB leds[NUM_PIXELS];
/* quickly blink each 8th LED red, for "I am alive" indication */
void blink();
/* returns supply voltage (higher of battery or USB) in mV */
uint16_t batteryVoltage();
/* Is the staff connected to USB power? */
bool USBconnected() { return (batteryVoltage()>VOLTAGE_MAX+100); }
/* Shows battery voltage by lighting the LEDs on staff for 2 seconds */
void showVoltage();
/* Shows one line. line should be pointer to array which holds pixel colors, in BGR order.
* size shoudl be size of array (number of pixels, not number of bytes)
*/
void showLine(byte * line, uint16_t size);
/* Set active image. The image must have been loaded to memory */
void setImage(BMPimage * image);
/* Show next line of active image */
void showNextLine();
uint32_t timeSinceUpdate();
float rotationSpeed(); //returns total rotation speed, in (deg/s)
float rotationSpeedAxial();
bool atRest();
float getCurrent(BMPimage image); //returns average current in mA
private:
BMPimage * currentImage=NULL;
int16_t currentLine=-1;
uint32_t lastUpdate=0; //time in microseconds
//sensor objects
Adafruit_Sensor *accel, *gyro;
};
//extern CRGB leds[NUM_PIXELS_TOT];
//extern CRGB leds[NUM_PIXELS_TOT];
//extern CRGB leds[NUM_PIXELS_TOT];
extern POVstaff staff;
extern Adafruit_MPU6050 _mpu;
#endif
and in staff.cpp I have
#include "staff.h"
void POVstaff::begin(){
pinMode(PIN_VSENSE, INPUT);
#ifdef PIN_CLOCK
pinMode(PIN_CLOCK, OUTPUT);
pinMode(PIN_DATA, OUTPUT);
pinMode(MOSI, OUTPUT);
pinMode(SCK, OUTPUT);
#endif
//Serial.println("Starting...");
FastLED.clear();
FastLED.show();
//init external flash
flash.begin();
// Open file system on the flash
if ( !fatfs.begin(&flash) ) {
Serial.begin(9600);
Serial.println("Error: filesystem doesn't not exist. Please try SdFat_format example to make one.");
while(1) yield();
}
//initialize the IMU, using I2C address 0x69
if (!_mpu.begin(0x69)) {
Serial.begin(9600);
Serial.println("Failed to find MPU6050 chip");
}
//configure IMU
_mpu.setAccelerometerRange(MPU6050_RANGE_4_G);
_mpu.setGyroRange(MPU6050_RANGE_2000_DEG);
_mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);
accel = _mpu.getAccelerometerSensor();
gyro = _mpu.getGyroSensor();
//Serial.println("POVstaff initilaized");
}
uint16_t POVstaff::batteryVoltage(){
//because of voltage divider, VREF corresponds to read value of 1023/2=512
//since battery is connected to VHI through a diode, we need to add back 100mV lost on the diode.
return ((analogRead(PIN_VSENSE)*VREF)/512 + 100) ;
}
void POVstaff::showVoltage(){
uint16_t level=0;
uint8_t i, value;
uint32_t c;
FastLED.clear();
//how many pixels should be lighted?
if (batteryVoltage()<=VOLTAGE_MIN) {
level=1;
} else {
level = ((uint32_t)NUM_PIXELS*(batteryVoltage()-VOLTAGE_MIN))/(VOLTAGE_MAX-VOLTAGE_MIN);
}
if (level>NUM_PIXELS) level=NUM_PIXELS;
//Serial.println(level);
//fill strip with gradient color
for (i=0; i< level; i++){
leds[i].r = 255-255*i/NUM_PIXELS;
leds[i].g = 255*i/NUM_PIXELS;
}
FastLED.show();
//Serial.println("Showing level");
delay(2000); //keep for 2 seconds
FastLED.clear();
FastLED.show();
lastUpdate=micros();
//Serial.println("Showing levle done");
}
void POVstaff::clear(){
FastLED.clear();
FastLED.show();
lastUpdate=micros();
}
void POVstaff::show(){
FastLED.show();
lastUpdate=micros();
}
void POVstaff::setPixel(uint16_t i, uint32_t c){
leds[i] = c;
}
void POVstaff::showLine(byte * line, uint16_t size){
uint16_t i,pos;
uint8_t r,g,b;
for (i=0; i<NUM_PIXELS; i++) {
if (i<size) {
pos=3*i;
//using bgr order
b=line[pos++];
g=line[pos++];
r=line[pos];
leds[i].setRGB(r,g,b);
} else {
leds[i] = CRGB::Black;
}
}
FastLED.show();
lastUpdate=micros();
}
void POVstaff::blink(){
uint16_t i;
uint8_t line[3*NUM_PIXELS];
for (i=0; i<3*NUM_PIXELS; i++) line[i]=0;
FastLED.clear();
for (i=0; 8*i<NUM_PIXELS; i++) {
line[24*i+2]=255;//set pixel with index 8i red. Recall that the color order is BGR
}
showLine(line, 3*NUM_PIXELS);
delay(500);
FastLED.clear(); FastLED.show();
delay(500);
showLine(line, 3*NUM_PIXELS);
delay(500);
FastLED.clear(); FastLED.show();
}
void POVstaff::setImage(BMPimage * image){
if (image->isLoaded()) {
currentImage = image;
currentLine=-1;
lastUpdate = micros();
} else {
Serial.println("Image not loaded in memory yet");
}
}
void POVstaff::showNextLine(){
if (currentImage) {
//move to next line
currentLine++;
if (currentLine == currentImage->height()) {currentLine=0;}
showLine(currentImage->line(currentLine), currentImage->width());
}
}
uint32_t POVstaff::timeSinceUpdate(){
return (micros()-lastUpdate);
}
float POVstaff::rotationSpeedAxial(){
/*IMU.readGyroscope(x, y, z);
return sqrtf(x*x+y*y+z*z);*/
sensors_event_t g;
gyro->getEvent(&g);
return (RAD_TO_DEG*sqrtf(g.gyro.x*g.gyro.x +g.gyro.y*g.gyro.y+g.gyro.z*g.gyro.z));
}
float POVstaff::rotationSpeed(){
/*IMU.readGyroscope(x, y, z);
return sqrtf(x*x+y*y+z*z);*/
sensors_event_t g;
gyro->getEvent(&g);
return (RAD_TO_DEG*sqrtf(g.gyro.x*g.gyro.x +g.gyro.y*g.gyro.y+g.gyro.z*g.gyro.z));
}
bool POVstaff::atRest(){
sensors_event_t a;
accel->getEvent(&a);
return ( (fabs(a.acceleration.x)<3.0) && (rotationSpeed()<30.0)); //x-component of accel< 3m/s^2 and rotation speed < 30 deg/s
}
float POVstaff::getCurrent(BMPimage image){
float currentTotal=0.0;
float currentLine=0.0;
int height=image.height();
int width=image.width();
uint8_t b,g,r;//levels
byte * pos;
if (! image.isLoaded()){
return 0.0;
}
for (int i=0; i<height; i++){
//compute total current for line i
currentLine=0.0;
for (int j=0; j<width; j++){
pos=image.line(i); //pointer to start of i-th line
b=*pos; pos++;
g=*pos; pos++;
r=*pos; pos++;
currentLine+=b*CURRENT_B+g*CURRENT_G+r*CURRENT_R;
}
//now, remember to divide by 255
currentLine/=255.0;
currentTotal+=currentLine;
}
return currentTotal;
}
FastLED.addLeds<APA102,MOSI,SCK,BGR,DATA_RATE_KHZ(3000)>(leds, NUM_PIXELS);
// LEDS.addLeds<APA102,13,12,BGR,DATA_RATE_KHZ(3000)>(leds, NUM_PIXELS);
POVstaff staff;
Adafruit_MPU6050 _mpu
And in my main file I have:
#include "staff.h"
/*
* Gloabl variables
*/
int mode; //staff operating mode. Possible values are
// MODE_SHOW (default when not connected to USB), MODE_UPLOAD, MODE_DEBUG
uint32_t lastCheck=0; //time in ms since last check of "staff at rest"
float speed=0; //current rotation speed, in deg/s
//setting this true will force the staff, if connected to USB, go into MODE_DEBUG mode
//otherwise, when connected to USB, the staff will go into upload mode.
bool FORCE_DEBUG = false;
BMPimageList imageList; // list of all image files (can store up to MAX_FILES entries)
// initially empty, will be populated by reading from file imagelist.txt during setup()
BMPimage * currentImg; // pointer to current image
uint32_t imageStart=0; //when did we start showing current image? (in ms)
bool paused; //indicates that the show must be paused
uint32_t timePaused=0; //when did we pause the show? (in ms)
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);
staff.begin();
//SPI.setClockDivider(1); //Just for testing fast LEDS
//set up mode - depending on whether we are connected to USB
if (!staff.USBconnected()) {
// we are not connected to USB
// then we do not have a choice
mode=MODE_SHOW;
} else {
//we are connected to USB
if (FORCE_DEBUG) {
mode=MODE_DEBUG;
} else {
mode=MODE_UPLOAD;
}
}
//mode=MODE_DEBUG;
//now let us do appropriate setup depending on the mode
if (mode==MODE_UPLOAD) {
// start mass storage protocol
msc_init();
Serial.begin(9600);
delay(1000);
Serial.println("Mass storage device started ");
Serial.print("JEDEC ID: "); Serial.println(flash.getJEDECID(), HEX);
Serial.print("Flash size: "); Serial.println(flash.size());
} else {
//we are running the show or debug
staff.showVoltage();
if (mode==MODE_DEBUG) {
Serial.begin(9600);
delay(2000);
Serial.println("Starting in debug mode...");
}
// read the image list
imageList.addFromFile("imagelist.txt");
if (mode==MODE_DEBUG) {
imageList.print();
Serial.print("Voltage: "); Serial.print(staff.batteryVoltage()); Serial.println(" mV");
}
//load first image
currentImg=imageList.first();
currentImg->load();
staff.setImage(currentImg);
//wait until we start rotating the staff
paused=true;
}
}
void loop(){
if (mode==MODE_UPLOAD){
//do nothing
delay(10);
} else {
if (millis()-lastCheck>200){
//more than 0.2 seconds since last update
lastCheck=millis();
// update speed and if necessary pause/restart the show or load next image
// setting all global varaibles
updateState();
}
//show new line if necessary
checkNextLine();
}
}
/* ************************************************************
* Utility functions
* ************************************************************
*/
//if necessary, show next line
void checkNextLine(){
float rotAngle=speed*staff.timeSinceUpdate()*0.000001; //how much have we turned since last update, in degrees?
if ( (!paused) && (rotAngle>DEG_PER_LINE) ) {
if (mode==MODE_DEBUG) {delay(50);Serial.println("showing next line");}
staff.showNextLine();
}
}
//move to next image in list
void nextImage(){
char name[MAX_FILENAME];
staff.clear();
currentImg->unload(); //unload from RAM
currentImg=imageList.next(); //move to next image in list
currentImg->load(); //load to RAM
staff.setImage(currentImg);
if (mode==MODE_DEBUG) {
currentImg->getFilename(name);
Serial.print("Moving to next image: "); Serial.println(name);
}
}
// update speed and check if we need to pause/restart the show,
// or move to next image
void updateState(){
//update speed, using low-pass filter
speed=0.6*speed+0.4*staff.rotationSpeed();
//now, let us determine our next actions
if (paused) {
//check if we have started rotating - then we need to restart the show
if (speed>150) {
paused=false;
imageStart=millis();
if (mode==MODE_DEBUG){Serial.println("Restaring show after pause");}
} else {
//if we have been paused for more than 30 seconds, blink to remind the user
if ((millis()-timePaused>30000) && (!staff.USBconnected())) {
staff.blink();
//reset paused time
timePaused=millis();
}
}
return;
}
//if we are here, the show was not paused
// have the staff been stopped in horizontal position?
bool staffStopped = (speed<50) &&(staff.atRest());
if (staffStopped) {
paused=true;
timePaused=millis();
//load next image into staff
nextImage();
return;
}
//have we been showing current image too long?
bool imageExpired = (imageList.currentDuration()>0) && (millis()-imageStart>1000*imageList.currentDuration());
if (imageExpired) {
nextImage();
imageStart=millis();
}
return;
}
Error message is:
staff.cpp:197:3: error: 'FastLED' does not name a type
197 | FastLED.addLeds<APA102,MOSI,SCK,BGR,DATA_RATE_KHZ(3000)>(leds, NUM_PIXELS);
| ^~~~~~~
exit status 1
'FastLED' does not name a type