Problem with unsigned long arrays in library

Hi all,

I am in the process of cleaning up a program I am working with, basically it was just one long sketch, and now I am putting components in separate libraries. I encountered a problem in the process that seems simple but I can't fix. I am using an array containing unsigned longs, as a kind of lookup table for a segment display with several shift registers. In the sketch these arrays worked fine, but in the libraries they don't. This is my first attempt at making libraries so that will likely have a lot to do with this problem.
Anyway, when I Serial print the values from the array completely different values come out. I thought perhaps this has something to do with libraries handling unsigned long inside arrays differently than arduino sketches, but I couldn't find anything by googling. Here are the sketch and the libraries:

Sketch:

#include "Display.h"

Display mydisplay(6,9,10); // dataPin_BlueLed = 6, // latchPin_GreenLed = 9, clockPin_RedLed = 10


void setup() {
  Serial.begin(9600);
  mydisplay.output(0,0);
}

void loop() {

}

Header of library:

/*
  Video_control - Library for showing display values with different displays on the Pursuit Wristband.
 */

#ifndef Display_h
#define Display_h

#include "Arduino.h"

class Display
{
public:
  Display(int dataPin_BlueLed, int latchPin_GreenLed, int clockPin_RedLed);
  void output(int displaydata, uint8_t displayType);
  
private:
  void OutputSegment();
  int _dataPin;
  int _latchPin;
  int _clockPin;

   unsigned long FirstDigit[];
   unsigned long SecondDigit[];
  
  unsigned long Segmentoutput;

};

#endif

Source of library:

#include "Arduino.h"
#include "Display.h"

Display::Display(int dataPin_BlueLed, int latchPin_GreenLed, int clockPin_RedLed)
{
  pinMode(clockPin_RedLed, OUTPUT);
  pinMode(latchPin_GreenLed, OUTPUT);
  pinMode(dataPin_BlueLed, OUTPUT);
  _dataPin_BlueLed = dataPin_BlueLed;
  _latchPin_GreenLed = latchPin_GreenLed;
  _clockPin_RedLed = clockPin_RedLed;
}

//*** Arrays for Segment display
unsigned long FirstDigit[12] ={
  339738624, 392691712, 471859200, 354418688, 386400256, 352583680, 335806464, 392167424, 335544320, 352321536, 527171584, 470024192  };

unsigned long SecondDigit[13] ={
  2147614722, 3758309378, 2147549187, 2684420098, 3758112770, 2684362754, 2147491842, 3758292994, 2147483650, 2684354562, 3758317571, 3221364737, 3221225475  };


void Display::output(int displaydata, uint8_t displayType){
  _displaydata = displaydata;
  _displayType = displayType;

  for (int i = 0; i < 12; i++) {
    Serial.print(i);
    Serial.print(": ");
    Serial.println(FirstDigit[i]);
  }
  
  for (int i = 0; i < 13; i++) {
    Serial.print(i);
    Serial.print(": ");
    Serial.println(SecondDigit[i]);
  } 
  
}

So I was expecting to find the values of the array in the serial monitor, but instead I got three times zero, then a small number like 412, etc. Anyone an idea what might be wrong?

The FirstDigit and SecondDigit member variables you declared in your Display class shadow your global variables of the same names.

You're not actually accessing those global, initialized variables within Display::output() -- instead, you're accessing whatever happens to be in memory just after the _clockPin variable of your mydisplay object (starting with the contents of mydisplay.Segmentoutput).

Thanks for your reply, Michael. So where should I put them instead?

Your choice.

You can keep them as class members and get rid of the global arrays, but then you'll have to declare them with their actual size within the class and you'll have to initialize them somewhere. Since those arrays seem to be constant lookup tables that can be shared by all Display instances, I'd make them static members (and keep them in program memory, but that's another story).

Or you can get rid of the array member declarations in the class to actually access the global array variables from your Display::output() method. That's arguably less elegant (because those global arrays pollute the global namespace even though they conceptually belong to the Display class), but it'll work just the same.

You also need to change all of the things like this:
339738624
To:
339738624UL

Otherwise they will be truncated to 16bit constants. This may be the reason you are seeing small numbers.
EDIT:
Actually, ignore me, they won't as they are in an initialiser list. But regardless, it is a good habit to get into - if you are using unsigned longs, at a UL suffix.

Thanks guys, it works perfectly again :slight_smile: