How many different things can the arduino uno/nano/pro mini handle?

I've got an arduino uno that's running 37 neopixel lights, and then another 8 regular LEDs controlled with a TLC5940 IC inside of a plastic model. So far so good. I'd like to play some sounds/short songs and then control all of this via a Bluetooth BLE4 ( CC2540) controller. Is this possible for the one arduino to handle all of this, or should I have 2 of them (I'll be using nano's or pro mini's in the model itself)?

thanks!

You would be the one to judge, so try it and see! Get each part of the project working before adding another.

This description is too vague:

I'd like to play some sounds/short songs

1 Like

Yeah, sorry, brain short! OK I have a DF Player Mini that works great, found a nice small speaker that still have good volume. I'm like to play either short WAV files (such as for engine noises), or longer mp3 files, like a couple of minutes of the star wars theme or something similar.
The neopixel lights use the Adafruit NeoPixel library, and the Arduino TLC5940 Library. I think both those use timer interrupts and I'm not sure if the dfplayer will work with all of that going on.

Consider the Wemos D1 Mini with an 80MHz clock.

Or 160MHz.

I lost a lengthy response, no great tragedy, but it amounted to my feeling that

there is nothing you are up to that in any way at all is without the capability of an Arduino UNO.

Weather you have the coding chops it could possibly require to fit comfortably within the available resources is the unknown factor.

A bad approach might not even work on the suggested alternate boards…

Post some code you think is coming anywhere close to outgrowing the UNO and we can get an idea if you are up to the challenge, such as it may be.

a7

OK I'll do that. I'm currently in the process of consolidating all the different experiments and tests into one code base. I'll post something when I get that ready.

Thanks

Making some progress consolidating the code. So far the neopixels and tlc5940 libs work just fine together. I've added the DFPlayer and SoftwareSerial libs and that all compiles ok, not sure if the hardware will work yet. One question:
Between the neopixel and tlc5940, I'm using pins 13, 11, 10, 9, 5, and 3. In the sample code for the DFPlayer the RX and TX pin numbers they used were PWN pins (passed into the SoftwareSerial object), but I now only have one PWM pin left (pin 6). Does it matter if the pins used are NOT PWM? I looked online and at least one person suggested that it didn't matter.

Software serial does not need PWM capable pins.

Give us a head start by posting supine functioning code that does all what you’ve managed to get working so far and some of the sharper eyes might be able to see software on rather verge of becoming the or a problem.

a7

OK so last night got some more testing done and so far so good! The DFPlayer does indeed work just fine with other pins (using pins 7 & 8). And it still plays back OK when some of the lights are turned on, so that's awesome, so far so good.

Nice.

I don’t think we’ve seen your code so I can’t tell you how in your case, but it is possible to insert some lines that will show you how much of your loot time is actually being consumed.

The result might surprise you. Often times the loop is just looping, code doesn’t really take much time at all.

It would also give some info about how close to the edge you are skating.

So… that’s why we want to. See the code, ha ha.

a7

Code so far, be warned it's a little long:

in the main section


#include "libISD.h"


using namespace libISD;


void setup() {
  Serial.begin(ISDController::SERIAL_BAUD);
  // put your setup code here, to run once:
  isdModel.init();
  Serial.println("called isd modele init");
}

void loop() {
  // put your main code here, to run repeatedly:
  isdModel.loop();
}

Header for "libISD.h":

#ifndef _LIB_ISD_H__
#define _LIB_ISD_H__

#define TLC_5940_ENABLED  1

#define NEOPIXELS_ENABLED  1


#include <time.h> 


#if NEOPIXELS_ENABLED
  #include <Adafruit_NeoPixel.h>
  #ifdef __AVR__
   #include <avr/power.h> // Required for 16 MHz Adafruit Trinket
  #endif
#endif //NEOPIXELS_ENABLED


#if TLC_5940_ENABLED
  #include "Tlc5940.h"
#endif //TLC_5940_ENABLED


#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"


namespace libISD {



class LedController {
public:  
  int idx;
  bool modified;
  LedController(): idx(0), modified(false) {
    
  }

  virtual ~LedController() {
    
  }

  virtual bool enabled(unsigned long timeFromStart) const {    
    return false;
  }
  
  virtual void updateLed() {}
  virtual void preUpdate() {}
  
  void update() {    
    if (modified) {
      updateLed();
    }
    modified = false;
  }
};



class LedCollection {
  public:
  LedController** collectionPtr;
  int size; 
  unsigned long startTime;
  bool enabled;
  
  LedCollection():
    collectionPtr(NULL),
    size(0),
    startTime(0),
    enabled(true){
    
  }

  virtual ~LedCollection() {
    
  }

  void init(LedController** coll, int sz) {
    collectionPtr = coll;
    size = sz;
    startTime = millis();
    enabled = true;
  }

  bool isEnabled() const { return enabled; }
  void setEnabled(bool v) { 
    enabled = v; 
  }
  
  
  bool empty() const { return size;}

  void loop() {
    unsigned long now = millis();
    if (enabled == false) {
      return;
    }
    
    //only loop every X millseconds. simulate delay()
    int delayFactor = 20;
    unsigned long  delta = now-startTime;
    if (now % delayFactor == 0 ) {
    
      for (int i=0;i<size;i++ ) {
        LedController* led = collectionPtr[i];
        if ( led->enabled(delta) ) {
          led->preUpdate();
          led->update();          
        }
      }
    }
  }
};

#if TLC_5940_ENABLED

void writeLED(Tlc5940& tlcIC, int idx, float value, float intensity)
{
  int v = min( (intensity * value) * 4095.0, 4095);
  tlcIC.set(idx, v);
  
  tlcIC.update();
}
#endif //TLC_5940_ENABLED



class Led : public LedController {
public:
  int startTime;
  int idxOffset;
  float intensityIncr;
  float value;
  float intensity;
  #if TLC_5940_ENABLED
  Tlc5940* tlcICPtr;
  #endif

  Led():LedController(),startTime(0),idxOffset(0),intensityIncr(0.0025),value(0),intensity(0)
  #if TLC_5940_ENABLED
  ,tlcICPtr(NULL)  
  #endif
  {
    
  }

  virtual ~Led() {
    
  }
#if TLC_5940_ENABLED  
  void init(Tlc5940& ic, int index, int offset, float v, int st, float intensIncr=0.0025 ) {
    tlcICPtr = &ic;
    startTime = st;
    idx = index;
    idxOffset = offset;
    intensityIncr = intensIncr;
    setValue(v);
    modified = true;
  }
#endif //TLC_5940_ENABLED


  void setValue(float v) {
    if ( value != v ) {
      value = v;
      modified = true;
    }
  }

  setIntensity(float v) {
    if ( intensity != v ) {
      intensity = v;
      modified = true;
    }
  }
  
  void setIntensityIncr(float v) {
    intensityIncr = v;
  }
  
  void incrIntensity() {
    if (intensity < 1.0) {
      intensity = min(intensity + intensityIncr,1.0);
      modified = true;
    }
  }
  
  virtual bool enabled(unsigned long timeFromStart) const {    
    if (-1 == startTime) {
      return false;
    }
    
    return timeFromStart >= startTime;
  }

  virtual void preUpdate() {
    incrIntensity();
  }

  void stop() {
    setIntensity(0);
    #if TLC_5940_ENABLED
    if (tlcICPtr) {
      writeLED(*tlcICPtr, idx + idxOffset,0,intensity);
    }
    #endif
  }
  
  virtual void updateLed() {
    #if TLC_5940_ENABLED
    if (tlcICPtr) {      
      writeLED(*tlcICPtr, idx + idxOffset,value,intensity);
    }
    #endif
    
  }
};

enum BigEngines {
  LEFT_ENGINE=1,
  CENTER_ENGINE=3,
  RIGHT_ENGINE=5,
};


enum MiniEngines {
  LEFT_ENGINE_TOP=0,
  LEFT_ENGINE_BOTTOM=2,
  RIGHT_ENGINE_TOP=4,
  RIGHT_ENGINE_BOTTOM=6,
};

#if NEOPIXELS_ENABLED
void writeRgbLED(Adafruit_NeoPixel& pixels, int led, float r, float g, float b, float intensity)
{

  int rval = (intensity * r) * 255.0;//min( (intensity * r) * 255, 255);
  int gval = (intensity * g) * 255.0;//min( (intensity * g) * 255, 255);
  int bval = (intensity * b) * 255.0;//min( (intensity * b) * 255, 255);

  pixels.setPixelColor(led, pixels.Color(rval, gval, bval));
  pixels.show();   // Send the updated pixel colors to the hardware.
/*
  Serial.print("writeRgbLED called, led: ");Serial.print(led);
  Serial.print(" r: ");Serial.print(rval);
  Serial.print(", g: ");Serial.print(gval);
  Serial.print(", b: ");Serial.print(bval);Serial.println("");
  */
}
#endif //NEOPIXELS_ENABLED

#define ENGINE_BASE_COLOR_R  100
#define ENGINE_BASE_COLOR_G  90
#define ENGINE_BASE_COLOR_B  255

#define ENGINE_BASE_COLORF_R  float(ENGINE_BASE_COLOR_R)/255.0
#define ENGINE_BASE_COLORF_G  float(ENGINE_BASE_COLOR_G)/255.0
#define ENGINE_BASE_COLORF_B  float(ENGINE_BASE_COLOR_B)/255.0


struct rgb_color {
  enum {
    MAX_COLOR_VAL = 255  
  };
  
  float intensity;
  float r;
  float g;
  float b;
  
  rgb_color():intensity(0), r(0),g(0),b(0) {}

};



class RgbLed : public LedController {
  public:
  int startTime;
  int idxOffset;
  rgb_color color;

  float r,g,b;

  float intensityIncr;
#if NEOPIXELS_ENABLED
  Adafruit_NeoPixel* pixelsPtr;
#endif //NEOPIXELS_ENABLED
  
  RgbLed():
    startTime(-1),
    idxOffset(0),
    r(0),g(0),b(0),
    intensityIncr(0.0025)
    #if NEOPIXELS_ENABLED
    ,pixelsPtr(NULL) 
    #endif //NEOPIXELS_ENABLED
    {
    
  }

  virtual ~RgbLed() {
    
  }

#if NEOPIXELS_ENABLED
  void init(Adafruit_NeoPixel& pixels, int index, int offset, float rr, float gg, float bb, int st, float intensIncr=0.0025 ) {
    pixelsPtr = &pixels;
    startTime = st;
    idx = index;
    idxOffset = offset;
    intensityIncr = intensIncr;
    color.r = color.g = color.b = 0.0;
    color.intensity = 0.0;
    setRGB(rr,gg,bb);
    modified = true;
  }
#endif //NEOPIXELS_ENABLED

  virtual bool enabled(unsigned long timeFromStart) const {    
    bool result = false;
    if (-1 == startTime) {
      return result;
    }

    result = (timeFromStart >= startTime) ? true : false;
    
    return result;
  }

  void setIntensityIncr(float v) {
    intensityIncr = v;
  }
  
  void setIntensity( float i ) {
    if (color.intensity != i) {
      color.intensity = i;
      modified = true;
    }
  }

  void incrIntensity() {
    if (color.intensity < 1.0) {
      color.intensity = min(color.intensity + intensityIncr,1.0);
      modified = true;
    }
  }

  void setRGB( float rv, float gv, float bv) {
    r=rv;
    g=gv;
    b=bv;
    setColor(r,g,b);
    modified = true;
  }
  
  void setColor( float rv, float gv, float bv) {
    if (rv != color.r) {
      color.r = rv;
      modified = true;
    }
    if (gv != color.g) {
      color.g = gv;
      modified = true;
    }
    if (bv != color.b) {
      color.b = bv;
      modified = true;
    }
  }


  virtual void preUpdate() {
    incrIntensity();
  }

  void stop() {
    setIntensity(0);
    if (pixelsPtr) {
      writeRgbLED(*pixelsPtr, idx + idxOffset,0,0,0,color.intensity);
    }
  }
  
  virtual void updateLed() {
#if NEOPIXELS_ENABLED    
    if (pixelsPtr) {      
      writeRgbLED(*pixelsPtr, idx + idxOffset,color.r,color.g,color.b,color.intensity);
      //Serial.print(" led ");Serial.print(idx);Serial.print(" intens: ");Serial.print(color.intensity);Serial.println(" updateLed() ");
    }
#endif //NEOPIXELS_ENABLED
  }
};


class Engine : public RgbLed {
  public:
  
  Engine():
    RgbLed() {
    
  } 

  virtual ~Engine() {
    
  }
  
  void pulse() {
    int range  = 50;

    float rv = min(r + (float((rand() % range) - (range/2)) / 255.0), 1.0);
    float gv = min(g + (float((rand() % range) - (range/2))) / 255.0, 1.0);
    float bv = min(b + (float((rand() % range) - (range/2))) / 255.0, 1.0);

    setColor(rv,gv,bv);
  }

  virtual void preUpdate() {
    incrIntensity();          
    pulse();
  }

  
};





class ISDEngines : public LedCollection {
public:
#if NEOPIXELS_ENABLED
  Adafruit_NeoPixel& pixels;
#endif
  

  enum {
    ENGINE_COUNT = 7
  };
  
  Engine* engines[ENGINE_COUNT];
  int engineIdxOffset;
  
#if NEOPIXELS_ENABLED
  ISDEngines(Adafruit_NeoPixel& p):pixels(p),
#else
  ISDEngines():
#endif //#if NEOPIXELS_ENABLED
  engineIdxOffset(0) {
    for (int i=0;i<ENGINE_COUNT;i++ ) {
      engines[i] = new Engine();
    }
  }

  ~ISDEngines() {
    for (int i=0;i<ENGINE_COUNT;i++ ) {
      delete engines[i];
    }
  }

  void stop() {
    for (int i=0;i<ENGINE_COUNT;i++ ) {
      engines[i]->stop();
    }
    setEnabled(false);
  }
  
  void start() {
    for (int i=0;i<ENGINE_COUNT;i++ ) {
      engines[i]->stop();
    }
    setEnabled(true);
    startTime = millis();
  }

  
  void initEngines(int offset)
  {
    engineIdxOffset = offset;
    
    srand (time(NULL)); 

    init( &engines[0], ENGINE_COUNT );

    int engineId = 0;
    int engStart = 0;
    
    for (int i=0;i<ENGINE_COUNT;i++ ) {
      Engine* engine = engines[i];
      
      switch(i) {
        case 0:{
          engineId = CENTER_ENGINE;
          engStart = 2500;
        }
        break;

        case 1:{
          engineId = LEFT_ENGINE;
          engStart = 1500;
        }
        break;

        case 2:{
          engineId = RIGHT_ENGINE;
          engStart = 1800;
        }
        break;

        case 3:{
          engineId = LEFT_ENGINE_TOP;
          engStart = 0;
        }
        break;

        case 4:{
          engineId = LEFT_ENGINE_BOTTOM;
          engStart = 500;
        }
        break;

        case 5:{
          engineId = RIGHT_ENGINE_TOP;
          engStart = 200;
        }
        break;

        case 6:{
          engineId = RIGHT_ENGINE_BOTTOM;
          engStart = 700;
        }
        break;
      }
#if NEOPIXELS_ENABLED
      engine->init(pixels, engineId,engineIdxOffset,
                    ENGINE_BASE_COLORF_R,ENGINE_BASE_COLORF_G,ENGINE_BASE_COLORF_B,
                    engStart);   
#endif //NEOPIXELS_ENABLED

      int range  = 50;
      float rn = float((rand() % range) - (range/2)) / 255.0;
      float gn = float((rand() % range) - (range/2)) / 255.0;
      float bn = float((rand() % range) - (range/2)) / 255.0;

      engine->setRGB(ENGINE_BASE_COLORF_R+rn,ENGINE_BASE_COLORF_G+gn,ENGINE_BASE_COLORF_B+bn);
    }
  }
};



class ShipSection : public RgbLed {
  public:
  
  virtual ~ShipSection() {
    
  }
};

class ISDSections : public LedCollection {
public:

  enum Parts {
    TOWER = 8,
    TOP_SECTION = 13,
    BOTTOM_SECTION = 7,
    SECTION_COUNT = TOWER + TOP_SECTION + BOTTOM_SECTION
  };
#if NEOPIXELS_ENABLED
  Adafruit_NeoPixel& pixels;
  #endif 
  
  ShipSection* sections[SECTION_COUNT];//[SECTION_COUNT];
  
#if NEOPIXELS_ENABLED
  ISDSections(Adafruit_NeoPixel& p):pixels(p) {
#else
  ISDSections(){
#endif //#if NEOPIXELS_ENABLED
    for (int i=0;i<SECTION_COUNT;i++ ) {
      sections[i] = new ShipSection();
    }
  }

  ~ISDSections() {
    for (int i=0;i<SECTION_COUNT;i++ ) {
      delete sections[i];
    }
  }

  void initSections() {
    srand (time(NULL)); 
    
    init( &sections[0], SECTION_COUNT );
    
    for (int i=0;i<SECTION_COUNT;i++ ) {
#if NEOPIXELS_ENABLED
      sections[i]->init(pixels, i,0,
                    1.0,1.0,1.0,
                    0);   
#endif //NEOPIXELS_ENABLED
      sections[i]->setRGB(1.0,1.0,1.0);
    }
  }

  void stop() {
    for (int i=0;i<SECTION_COUNT;i++ ) {
      sections[i]->stop();
    }
    setEnabled(false);
  }
  
  void start() {
    for (int i=0;i<SECTION_COUNT;i++ ) {
      sections[i]->stop();
    }
    setEnabled(true);
    startTime = millis();
  }
};


class ISDSpecialSections : public LedCollection {
public:

  enum Parts {
    GARBAGE_CHUTE = 1,
    SIDE_LIGHTS = 6,
    SECTION_COUNT = GARBAGE_CHUTE + SIDE_LIGHTS
  };
#if TLC_5940_ENABLED
  Tlc5940& tlcIc;
  #endif 
  
  Led* sections[SECTION_COUNT];
  
#if TLC_5940_ENABLED
  ISDSpecialSections(Tlc5940& p):tlcIc(p) {
    for (int i=0;i<SECTION_COUNT;i++ ) {
      sections[i] = new Led();
    }
  }
#else
  ISDSpecialSections() {
    for (int i=0;i<SECTION_COUNT;i++ ) {
      sections[i] = new Led();
    }
  }  
#endif //TLC_5940_ENABLED


  ~ISDSpecialSections() {
    for (int i=0;i<SECTION_COUNT;i++ ) {
      delete sections[i];
    }
  }

  void stop() {
    for (int i=0;i<SECTION_COUNT;i++ ) {
      sections[i]->stop();
    }
    setEnabled(false);
  }
  
  void start() {
    for (int i=0;i<SECTION_COUNT;i++ ) {
      sections[i]->stop();
    }
    setEnabled(true);
    startTime = millis();
  }
  
  void initSections() {
    srand (time(NULL)); 
    
    init( &sections[0], SECTION_COUNT );
    
    for (int i=0;i<SECTION_COUNT;i++ ) {
      #if TLC_5940_ENABLED
      sections[i]->init(tlcIc, i,0,1.0,5000, 0.01);
      #endif //TLC_5940_ENABLED
    }
  }

};



class Sound {
  public:

  enum Constants{
    MAX_VOLUME = 20,
  };
  
  int startTime;
  int idx;  
  float intensityIncr;  
  float intensity;
  float value;
  bool modified;
  bool playStarted;
  bool loopMode;
  int playCount;
  DFRobotDFPlayerMini* playerPtr;
  
  Sound():
    startTime(-1),
    idx(0),
    intensityIncr(0.00),
    intensity(0),
    value(0),
    modified(false),
    playStarted(false),
    loopMode(false),
    playCount(0),
    playerPtr(NULL)
    {
    
  }

  void setIntensityIncr(float v) {
    intensityIncr = v;
  }
  
  void incrIntensity() {
    if (intensity < 1.0) {
      intensity = min(intensity + intensityIncr,1.0);
      modified = true;
    }
  }
  
  virtual bool enabled(unsigned long timeFromStart) const {    
    if (-1 == startTime) {
      return false;
    }
    
    return timeFromStart >= startTime;
  }

  void init(DFRobotDFPlayerMini& p, int index, float v, int st, float initialIntensity, float intensIncr=0.0025 ) {
    playerPtr = &p;
    startTime = st;
    idx = index;    
    intensityIncr = intensIncr;
    intensity = initialIntensity;
    setValue(v);
    modified = true;
  }

  void setValue(float v) {
    if (v != value) {
      value = v;
      modified = true;
    }
  }

  void setLoop( bool v) {
    if (v != loopMode) {
      loopMode = v;
      modified = true;
    }
  }
    
  void playStopped() { playStarted = false; }
  bool isPlaying() const { return true == playStarted; }

  void stop() {
    startTime = -1;
    if (playerPtr) {
      if (playerPtr->readCurrentFileNumber() == idx) {
        playerPtr->pause();
      }
    }
  }
  
  void update() {
    incrIntensity();
    
    if (modified) {
      if (playerPtr) {
        int vol = min(value*intensity,1.0) * float(MAX_VOLUME);
        
        playerPtr->volume(vol);  //Set volume value. From 0 to 30
        Serial.print("vol changed to ");Serial.println(vol);

        if (!playStarted) {
          if ( (playCount==0) || ((playCount > 0) && loopMode)) {
            playerPtr->play(idx); 
            Serial.print("Playing item ");Serial.println(idx);
            playStarted = true;
            playCount ++;
          }
        }
      }
    }
    modified = false;
  }
};

class SoundController {
public:
  enum Constants {
    SERIAL_CTRL_BAUD  = 9600,
    MAX_SOUND_COUNT = 5   
  };


  
  Sound* sounds[MAX_SOUND_COUNT];

  SoftwareSerial serialControl;
  DFRobotDFPlayerMini soundPlayer;

  unsigned long startTime;

  SoundController( int rxPin, int txPin ):
    serialControl(rxPin,txPin),startTime(0) {
      
    for (int i=0;i<MAX_SOUND_COUNT;i++ ) {
      sounds[i] = new Sound();
    }
  }

  ~SoundController() {
    for (int i=0;i<MAX_SOUND_COUNT;i++ ) {
      delete sounds[i];
    }
  }


  Sound* getSound(int idx) {
    Sound* result = NULL;
    if (idx >= 0 && idx <MAX_SOUND_COUNT) {
      result = sounds[idx];
    }
    return result;  
  }

  void stopSounds() {
    for (int i=0;i<MAX_SOUND_COUNT;i++ ) {
      sounds[i]->stop();
    }
  }

  void playSound( int idx ) {
    stopSounds();
    Sound* sound = getSound(idx);
    if (NULL != sound ) {
      sound->startTime = millis();
    }
  }

  void init() {
     serialControl.begin(SERIAL_CTRL_BAUD);
    
    Serial.println();    
    Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));
    
    if (!soundPlayer.begin(serialControl)) {  //Use softwareSerial to communicate with mp3.
      Serial.println(F("Unable to begin:"));
      Serial.println(F("1.Please recheck the connection!"));
      Serial.println(F("2.Please insert the SD card!"));
      while(true){
        delay(0); // Code to compatible with ESP8266 watch dog.
      }
    }
    Serial.println(F("Sound controller online."));
    soundPlayer.EQ(DFPLAYER_EQ_CLASSIC);
    soundPlayer.volume(0);

    for (int i=0;i<MAX_SOUND_COUNT;i++ ) {
      Sound* sound = sounds[i];
      sound->init(soundPlayer, i, 1, -1, 1 );
    }
    sounds[0]->init(soundPlayer, 1, 1, 3000, 0, 0.01 );
    
    startTime = millis();
  }


  
  void soundStatus(uint8_t type, int value){
    switch (type) {
      case TimeOut:
        Serial.println(F("Time Out!"));
        break;
      case WrongStack:
        Serial.println(F("Stack Wrong!"));
        break;
      case DFPlayerCardInserted:
        Serial.println(F("Card Inserted!"));
        break;
      case DFPlayerCardRemoved:
        Serial.println(F("Card Removed!"));
        break;
      case DFPlayerCardOnline:
        Serial.println(F("Card Online!"));
        break;
      case DFPlayerUSBInserted:
        Serial.println("USB Inserted!");
        break;
      case DFPlayerUSBRemoved:
        Serial.println("USB Removed!");
        break;
      case DFPlayerPlayFinished:
        Serial.print(F("Number:"));
        Serial.print(value);
        Serial.println(F(" Play Finished!"));

        Sound* sound = getSound(value);
        if (sound != NULL) {
          sound->playStopped();
        }
        break;
      case DFPlayerError:
        Serial.print(F("DFPlayerError:"));
        switch (value) {
          case Busy:
            Serial.println(F("Card not found"));
            break;
          case Sleeping:
            Serial.println(F("Sleeping"));
            break;
          case SerialWrongStack:
            Serial.println(F("Get Wrong Stack"));
            break;
          case CheckSumNotMatch:
            Serial.println(F("Check Sum Not Match"));
            break;
          case FileIndexOut:
            Serial.println(F("File Index Out of Bound"));
            break;
          case FileMismatch:
            Serial.println(F("Cannot Find File"));
            break;
          case Advertise:
            Serial.println(F("In Advertise"));
            break;
          default:
            break;
        }
        break;
      default:
        break;
    } 
  }


  void loop() {    
    if (soundPlayer.available()) {
      //Print the detail message from DFPlayer to handle different errors and states.
      soundStatus(soundPlayer.readType(), soundPlayer.read()); 
    }

    unsigned long now = millis();

    //only loop every X millseconds. simulate delay()
    int delayFactor = 20;
    unsigned long  delta = now-startTime;
    if (now % delayFactor == 0 ) {
    
      for (int i=0;i<MAX_SOUND_COUNT;i++ ) {
        Sound* sound = sounds[i];          
        if ( sound->enabled(delta) ) {
          sound->update();    
          if (sound->isPlaying()) {
            break;//don't check anyone else, busy now
          }
        }
      }
    }    
  }
};



class ISDController {
public:
  enum Constants{
    /*
     * note that 3 is the default here for neopixels, but we
     * can't use that because it'salready needed by the
     * tlc5940 lib. If we try and use it here it will cause
     * a conflict and the neopixels won't work correctly
     * tlc5940 lib uses the following pins:
     * 13
     * 11
     * 10
     * 9
     * 3
     * these can't be changed AFAIK, unless rebuild the library
     * so for all practical purposes we need to NOT use these IO pins
     */
    NEOPIXELS_PIN = 5, 
    SOFTWARE_SERIAL_RX = 7, //does this need to be PWM???
    SOFTWARE_SERIAL_TX = 8,
    NEOPIXELS_LEDCOUNT = ISDEngines::ENGINE_COUNT + ISDSections::SECTION_COUNT,

    SERIAL_BAUD  = 115200,
  };
#if NEOPIXELS_ENABLED
  Adafruit_NeoPixel rgbNeoPixels;
  #endif //NEOPIXELS_ENABLED

  //sections 
  ISDSpecialSections miscLights;

  ISDSections mainLights;

  ISDEngines engines;

  SoundController sndController;
  
  ISDController():
#if NEOPIXELS_ENABLED
    rgbNeoPixels(NEOPIXELS_LEDCOUNT, NEOPIXELS_PIN, NEO_RGB + NEO_KHZ800),    
#endif //NEOPIXELS_ENABLED
    
#if TLC_5940_ENABLED
    miscLights(Tlc),
#else
    miscLights(),
#endif //TLC_5940_ENABLED
    
#if NEOPIXELS_ENABLED    
    mainLights(rgbNeoPixels),
    engines(rgbNeoPixels),
#else
    mainLights(),
    engines(),
#endif //NEOPIXELS_ENABLED
    sndController(SOFTWARE_SERIAL_RX,SOFTWARE_SERIAL_TX)
    {
      
    }

    void init() {
       
#if NEOPIXELS_ENABLED
      //neo pixels initialization

// These lines are specifically to support the Adafruit Trinket 5V 16 MHz.
// Any other board, you can remove this part (but no harm leaving it):
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
  clock_prescale_set(clock_div_1);
#endif
  // END of Trinket-specific code.
      rgbNeoPixels.begin(); 
      rgbNeoPixels.clear();
#endif //NEOPIXELS_ENABLED

      //tlc5940 init 
      #if TLC_5940_ENABLED
      Tlc.init();
      Tlc.clear();
      Tlc.update();
      #endif //TLC_5940_ENABLED

      miscLights.initSections();
      mainLights.initSections();

      engines.initEngines(0);

      Serial.println("ISDController::init() done");

      sndController.init();
    }

    void startMainLights() {
        mainLights.start();
    }

    void startMiscLights() {
        miscLights.start();
    }

    void startEngines() {
        engines.start();
    }
    
    void loop() {
      
      miscLights.loop();
      //mainLights.loop();
      engines.loop(); 

      sndController.loop();
    }
};


ISDController isdModel;




} //namespace libISD


#endif //_LIB_ISD_H__

@anon15785262…

well I asked for it. Clearly above my pay grade, so pay little attention to what I say.

If you get into trouble with resources, it will be because you are using some kind of nifty mechanisms to make writing code easier for you. I am guessing that the framework is not without overhead.

And it is beyond me as to how to "instrument" your code to reveal the leftover time.

Simple programs can do something like (pseudocode here)

void loop()
{
// mechanism to attain a frame rate of 100 Hz
 wait until the frame time arrives (millis, external clock, whatever)

-- turn on the monitor LED

<real stuff you need to do>

-- turn off the monitor LED

<leftover time> wasted here or in the frame rate mecahism
}

Then use a frequency meter with duty cycle to be very happy to see

100 Hz @ 13 %

Or hang your logic analzser on the LED output pin.

a7

OK thanks! Yeah the use of classes/objects probably has some overhead, but I'm guessing it's not a huge amount? There is the use of virtual functions, which I know do eat up a little more time, but so far so good.

So far the only problems I have left are wiring up my battery harness, and figuring out why the transistor that I'm using isn't delivering as much power as I'd like, and what to replace it with.

Good to hear. You might sleep better if you did put some kinda way of being sure you haven’t taxed out the arduino, but done right they can handle quite a bit of stuff.

Your description did not mention any transistor, so if you need/want help it is time to post the schematic you are working from, even a celly of it if it is hand drawn will do.

a7

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.