Moving functions into separate cpp file

Hello,

I have one sketch which works fine. Now I want to outsource the functions into separate cpp files. I have followed this so far:

But for some reason it will not compile. I got the error: leds was not declared in this scope.

This is my sketch, which works fine:

#include "FastLED.h"

#define NUM_LEDS 64

CRGB leds[NUM_LEDS];

#define DATA_PIN 11
#define CLOCK_PIN 12

#define MAX_BRIGHTNESS 12 // (0...255)

void setup()
{
  FastLED.addLeds<APA102, DATA_PIN, CLOCK_PIN, RGB>(leds, NUM_LEDS);
}

void loop()
{
  one(CRGB::Green);
  delay(2000);
  two(CRGB::Green);
  delay(2000);
}

void one(uint32_t color)
{
  FastLED.clear();
  FastLED.setBrightness(10);
  leds[2] = color;
  leds[13] = color;
  leds[14] = color;
  leds[16] = color;
  leds[18] = color;
  leds[29] = color;
  leds[34] = color;
  leds[45] = color;
  leds[48] = color;
  leds[49] = color;
  leds[50] = color;
  leds[51] = color;
  leds[52] = color;
  FastLED.show();

  return;
}

void two(uint32_t color)
{
  FastLED.clear();
  FastLED.setBrightness(10);
  leds[1] = color;
  leds[2] = color;
  leds[3] = color;
  leds[11] = color;
  leds[20] = color;
  leds[28] = color;
  leds[34] = color;
  leds[46] = color;
  leds[48] = color;
  leds[49] = color;
  leds[50] = color;
  leds[51] = color;
  leds[52] = color;
  FastLED.show();

  return;
}

And here is my code after modification:

For the sketch:

#include "FastLED.h"
#include "Alphabet.h"

#define NUM_LEDS 64

CRGB leds[NUM_LEDS];

#define DATA_PIN 11
#define CLOCK_PIN 12

#define MAX_BRIGHTNESS 12 // (0...255)

void setup()
{
  FastLED.addLeds<APA102, DATA_PIN, CLOCK_PIN, RGB>(leds, NUM_LEDS);
}

void loop()
{
  one(CRGB::Green);
  delay(2000);
  two(CRGB::Green);
  delay(2000);
}

For the cpp file:

#include "FastLED.h"
#include "Arduino.h"


void one(uint32_t color)
{
  FastLED.clear();
  FastLED.setBrightness(10);
  leds[1] = color;
  leds[2] = color;
  leds[3] = color;
  leds[11] = color;
  leds[20] = color;
  leds[28] = color;
  leds[34] = color;
  leds[46] = color;
  leds[48] = color;
  leds[49] = color;
  leds[50] = color;
  leds[51] = color;
  leds[52] = color;
  FastLED.show();

  return;
}

void two(uint32_t color)
{
  FastLED.clear();
  FastLED.setBrightness(10);
  leds[1] = color;
  leds[2] = color;
  leds[3] = color;
  leds[11] = color;
  leds[20] = color;
  leds[28] = color;
  leds[34] = color;
  leds[46] = color;
  leds[48] = color;
  leds[49] = color;
  leds[50] = color;
  leds[51] = color;
  leds[52] = color;
  FastLED.show();

  return;
}

For the header file:

#ifndef Alphabet_h
#define Alphabet_h

void one(uint32_t color);
void two(uint32_t color);

#endif

I think it is clear what I want to archive, I simply want that all the code for displaying letters and numbers are not in the main sketch as it would be too large.

I simply want that all the code for displaying letters and numbers are not in the main sketch as it would be too large.

What your current code does it to create a library. This can be very helpful if you want to use it again in other programs.

If, however, you just want the code to be split into smaller, more manageable sections then all you need to do is to add one or extra tabs in the IDE, give them a filename with the .ino extension and put the code in there. The files will be created th the same folder as the main program and will be compiled into it.

As to your current problem, where is the leds[] array declared and what is the full error message ?

I think it have somethings to do that I use the FastLED library.
I use leds in the sketch and as well in the cpp file.
Below is the full error message:

Arduino: 1.8.3 (Windows 7), Board: “Arduino/Genuino Zero (Programming Port)”

In file included from sketch\Alphabet.cpp:1:0:

C:\Users\Mark\Documents\Arduino\libraries\FastLED/FastLED.h:17:21: note: #pragma message: FastLED version 3.001.006

pragma message “FastLED version 3.001.006”

^

sketch\Alphabet.cpp: In function ‘void one(uint32_t)’:

Alphabet.cpp:9: error: ‘leds’ was not declared in this scope

leds[1] = color;

^

sketch\Alphabet.cpp: In function ‘void two(uint32_t)’:

Alphabet.cpp:31: error: ‘leds’ was not declared in this scope

leds[1] = color;

^

exit status 1
‘leds’ was not declared in this scope

This report would have more information with
“Show verbose output during compilation”
option enabled in File → Preferences.

Maybe I try the multiple ino files for now first, but I want later have a library for code organization, sharing and reuse.

No it's not.

First message is because of your pragma message aka it does what you tell it.

Next, you declare leds in your .ino so your .cpp has no knowledge of it. Because it belongs to the (badly named) functions one() and two(), declare them in your .h.

Can you explain how? I have copied it to the header file, but still the same error.

BTW: the functions displaying the numbers 1, 2, and so on on an 8x8 LED matrix. So I thought the names are ok.

Markduino: Can you explain how? I have copied it to the header file, but still the same error.

BTW: the functions displaying the numbers 1, 2, and so on on an 8x8 LED matrix. So I thought the names are ok.

rather than have a function for every digit, why not just have a single function that operates on an array which represents the digit?

BulldogLowell: rather than have a function for every digit, why not just have a single function that operates on an array which represents the digit?

I want to gain experience in writing libraries and the LED matrix was a good way to start with it. Later maybe I am looking into ways to simplify this. But the definition must be sored somewhere, I think it can not be calculated. It is similar to an character display, where numbers and letters are defined by the dots to be displayed.

Markduino:
I want to gain experience in writing libraries and the LED matrix was a good way to start with it.
Later maybe I am looking into ways to simplify this.
But the definition must be sored somewhere, I think it can not be calculated.
It is similar to an character display, where numbers and letters are defined by the dots to be displayed.

yes, but learning arrays and functions are prerequisites.

you’d define the LEDs lit for each digit in an array:

const byte zero_digit[] = {...
const byte one_digit[]  = {1,2,3,11,20,28,34,46,48,49,50,51,52};
//etc...

then you can call the function to illuminate the LEDs:

void liteNumeral(byte* num, size_t size)
{
  for (byte i = 0; i < size; i++)
  {
    leds[num[i]] = color;

kind of thing…

BUT your issue is that the functions you call in your cpp are using leds array… they are not defined in your cpp.

Try adding this to your cpp at the top of your functions:

extern CRGB leds[NUM_LEDS];

indicating to the compiler that it is declared elsewhere, but you may still have to #define NUM_LEDS in your header… making this exercise start to get very messy.

you should be looking at inheritance and simply adding your functions to the existing FastLeds class.

Markduino:
Later maybe I am looking into ways to simplify this.

Normally it’s more benifitial to spend 5 minutes more on planning and research and have an easy implementation than the other way around…

Markduino:
But the definition must be sored somewhere, I think it can not be calculated.
It is similar to an character display, where numbers and letters are defined by the dots to be displayed.

Then make a look up. Character display’s also don’t have functions for one(), two() etc.

And move to .h:

#define NUM_LEDS 64

CRGB leds[NUM_LEDS];

When I copy this code:

extern CRGB leds[NUM_LEDS];

into the cpp and header file, then it compiles and upload to the Arduino. But the loop is not running, as it displays 2, so I guess the loop is running only one time, but I can also not see the 1 as I should because of the 2s delay. Hmmm...:-)

I think, I will focus on the array approach for now, it seems to be better, then I will have a look at the library later, Its probably better to create a library from the scratch as using another library to create a library.

Markduino:
When I copy this code:

extern CRGB leds[NUM_LEDS];

into the cpp and header file, then it compiles and upload to the Arduino. But the loop is not running, as it displays 2, so I guess the loop is running only one time, but I can also not see the 1 as I should because of the 2s delay.
Hmmm…:slight_smile:

I think, I will focus on the array approach for now, it seems to be better, then I will have a look at the library later, Its probably better to create a library from the scratch as using another library to create a library.

a library surely has its nuances, you will get there…

here is a head start on the functional approach. you have to fill each digit with the appropriate array of LEDs lit and add filling your led array with the values returned in the function, but this should get you nearly all the way there:

const byte zero_digit[]  = {0,2,3,11,20,28,34,46,48,49,50,51,52};
const byte one_digit[]   = {1,2,3,11,20,28,34,46};
const byte two_digit[]   = {2,2,3,11,20,28,34,46,48,49,50,51,52};
const byte three_digit[] = {3,2,3,11,20,28};
const byte four_digit[]  = {4,2,3,11,20,28,34,46,48,49,50};
const byte five_digit[]  = {5,2,3,11,20,28,34,46,48,49};
const byte six_digit[]   = {6,2,3,11,20,28,34,46,48,49,50,51,52};
const byte seven_digit[] = {7,2,3,11,20,28,34,46,48,49,50,51,52};
const byte eight_digit[] = {8,2,3,11,20,28,34,46,48,49,50,51,52};
const byte nine_digit[]  = {9,2,3,11,20,28,34,46,48,49,50,51,52};

struct Numerals{
  byte* ledList;
  size_t size;
};

Numerals numerals[] = {
  {zero_digit,  sizeof(zero_digit)},
  {one_digit,   sizeof(one_digit)},
  {two_digit,   sizeof(two_digit)},
  {three_digit, sizeof(two_digit)},
  {four_digit,  sizeof(four_digit)},
  {five_digit,  sizeof(five_digit)},
  {six_digit,   sizeof(six_digit)},
  {seven_digit, sizeof(seven_digit)},
  {eight_digit, sizeof(eight_digit)},
  {nine_digit,  sizeof(nine_digit)},
};

void liteDigit(byte num) . // you can see each led in num printed here...
{
  for (size_t i = 0; i < numerals[num].size; i++)
  {
    Serial.println(numerals[num].ledList[i]);
  }
}

void setup() 
{
  Serial.begin(9600);
  for (int i = 0; i < 10; i++)
  {
    Serial.print(F("Printing digit: "));
    Serial.println(i);
    liteDigit(i);
    Serial.println();
  }
}

void loop() 
{

}

Thank you for all your help.
I am going for now this way, having multiple sketches(tabs), it works and I will look into libraries later.

Main sketch:

#include "FastLED.h"

#define NUM_LEDS 64
CRGB leds[NUM_LEDS];

#define DATA_PIN 11
#define CLOCK_PIN 12

void setup()
{
  FastLED.addLeds<APA102, DATA_PIN, CLOCK_PIN, RGB>(leds, NUM_LEDS);
}

void loop()
{
  FastLED.setBrightness(5);

  FastLED.clear();
  one(CRGB::White);
  FastLED.show();
  delay(2000);

  FastLED.clear();
  two(CRGB::Red);
  FastLED.show();
  delay(2000);

  FastLED.clear();
  three(CRGB::Blue);
  FastLED.show();
  delay(2000);
  
}

Second sketch:

const byte one_digit[] = {19, 11, 20, 27, 36, 43, 52, 59, 58, 60};
const byte two_digit[] = {13, 12, 11, 10, 9, 22, 25, 38, 37, 36, 35, 34, 45, 50, 61, 60, 59, 58, 57};
const byte three_digit[] = {13, 12, 11, 10, 9, 22, 25, 38, 37, 36, 35, 41, 54, 57, 58, 59, 60, 61};

/*----------------------------------------*/    
/* Number 1 */
void one(uint32_t color)
{
  for (byte i = 0; i < sizeof(one_digit); i++)
  {
    leds[one_digit[i]] = color;
  } 
  return;
}

/*----------------------------------------*/
/* Number 2 */
void two(uint32_t color)
{
  for (byte i = 0; i < sizeof(two_digit); i++)
  {
    leds[two_digit[i]] = color;
  }
  return;
}

/*----------------------------------------*/
/* Number 3 */
void three(uint32_t color)
{
  for (byte i = 0; i < sizeof(three_digit); i++)
  {
    leds[three_digit[i]] = color;
  }
  return;
}