Strange class problem

Hi all,

I have a strange problem with my selfmade class. I want to use some DMX spots over WiFi, so I created a simple sketch for a client (Arduino+WiFi) and a sketch for a server (Arduino+Ethernet). For the server I wrote a class called DMX_RGB (see attached). I need to create some instances (globaly)in DMXNet_Server.ino:

DMX_RGB Bar1("192.168.1.40",4711,10,11,12,9,8);

When I create such an instance, the sketch stops and nothing happens anymore. Also no debug output on the serial monitor...

If I comment out everything which is relating to the instance Bar1 (and of course the code above) the sketch works (also it is not doing what I want :frowning: )

I think it is a simple, stupid problem - but I cannot find where. Has anyone an idea?

Thanks a lot, Holger

DMX_RGB.h (1.28 KB)

DMX_RGB.cpp (3.33 KB)

DMXNet_Server.ino (1.79 KB)

Has anyone an idea?

I'm going to guess that you are running out of memory.

I don't know what the function dbg does but I imagine it "prints" out characters over the serial link. My guess is that the UART isn't initialized yet. Try commenting out the dbg function calls in the constructor of DMX_RGB.

If its not a Mega you should check the amount of RAM in use - for instance what value is UDP_TX_PACKET_MAX_SIZE ?

I agree with mkwired. You have probably fallen prey to the "static initialization order fiasco" (Google it).

I suggest you do a minimal number of things in your constructor (for example, save the arguments into class variables). Then make a DMX_RGB::begin() method and do the rest there.

Hi all!

thanks for your hints. I wonder that one class instance would need so much memory. I will try your suggestions and write the solution to this thread as soon as possible.

Regards, Holger

I wonder that one class instance would need so much memory.

There's this:

  byte _red;
  byte _green;
  byte _blue;
  byte _dim;
  byte _red_memory;
  byte _green_memory;
  byte _blue_memory;
  byte _dim_memory;
  float _steps;
  int _addr_red;
  int _addr_green;
  int _addr_blue;
  int _addr_dim;
  int _addr_mode;
  float _stepping_red;
  float _stepping_green;
  float _stepping_blue;
  byte _queue_red[MAX_FADE_ELEMENTS];
  byte _queue_green[MAX_FADE_ELEMENTS];
  byte _queue_blue[MAX_FADE_ELEMENTS];
  float _queue_time[MAX_FADE_ELEMENTS];
  int _queue_counter;
  int _q;
  int _step_counter;
  IPAddress remote_ip;
  uint16_t remote_port;

and this:

  void _DMXNet_send(uint16_t addr,uint8_t data);
  DMX_RGB(char* ip, uint16_t port,int addr_red, int addr_green, int addr_blue, int addr_dim,int addr_mode);
  void set_rgb(byte r, byte g, byte b);
  void set_red(byte r);
  void set_green(byte g);
  void set_blue(byte b);
  void set_dim(byte d);
  int get_steps(void);
  void fade_to(byte r, byte g, byte b, float time);
  void flash(byte flashes, int min_time, int max_time, int fade_time);
  void worker(void);
  void init(int cmd);

That's not a trivial list of data fields or a trivial list of functions. For EACH instance.

Methods are shared between all instances.

And 50 bytes or so isn't "massive".

MarkT:
Methods are shared between all instances.

And 50 bytes or so isn't "massive".

50? How big is MAX_FADE_ELEMENTS?

Hi all,

ok, I see, that my Uno is not a memory giant... and my class is not very small. But with MAX_FADE_ELEMENTS set to 10 the storage for one instance should be about 180 Bytes. I tried to use only one instance and the Arduino freezes.

Nick Gammon's hint was the solution (not for everything, but now it works!): The constructor was "too big" - don't ask me why this is a problem. But when rewriting the constructor function to a DMX_RGB.begin() method it works! Also four instances are working! I took a look at Arduino Playground - AvailableMemory and checked my free memory and there were about 300 bytes empty.

If anyone can explain why the constructor was the problem and why I should use a begin()-method for initialization I would be very glad!

Thanks for helping!

Holger
8)

The constructor was "too big" - don't ask me why this is a problem.

It wasn't "too big". It was that the stuff that it did, it did when the rest of the processor was not ready for it to do things. Using the Serial instance, as an example, before the Serial instance has been created.

PaulS is right. You really need to read up on "static initialization order fiasco".

The order in which static data is instantiated is undefined, particularly between compilation units. In your case, if you are using Serial, then Serial.begin() is done in setup, but if your dbg class uses Serial it will definitely be calling it too soon (the constructor will be called before setup).

The same remark applies to timers, and indeed anything related to Arduino libraries.

Ok, I understand what my problem was.

Thanks for your help!

Holger