Need help with a personal project that uses a few leds and button; will pay

Hi.

I'm looking for help with a personal project and will pay for your time and help.

I want to be able to turn on up to 3 leds to flash on at random time intervals (depending on the mode determined by a button push to change modes) (using millis() , not delay() ).

The leds need only flash on for 1 second, but off for a random time chosen between 3 or 4 different off times (e.g 5 secs, or 2 secs, or 8 secs).

I have written code using switch statement for 1 LED using delay() and can send the code so you get an idea of what I mean...

Mode 1 - Turn Red LED off for either 3 secs, 5 secs, or 8 secs (just as an example)
Mode 2 - same as mode 1, but add a Green LED to turn off for 6 secs or 9 secs.
Mode 3 - same as mode 2, but add a Yellow LED that flashes/blinks on for 5 secs.

Eventually I would like to reduce the size of this project to as little as possible and use a small microcrontroller instead of the arduino. so if you can give advice for this thats a bonus.

DM me if you might be able to help out :slight_smile:

Thanks

Just incase you didn't get any help, this (untested) may get you started.
To test, you'll have to manually set mode in the script and code the yellow led part yourself.
If you need to ask any questions, do so in this thread.

int redLed = 13 ;
int greenLed = 12 ;

int mode = 2 ;   // increment this on button press


unsigned long clockLastMs = 0 ;
unsigned long seconds = 0 ;

// red
unsigned long redOffSeconds = 0;
unsigned long redOnSeconds = 0;
boolean redOn = false ;
const int redRandomSeconds[3] = { 1, 4, 8 } ;  // indexed 0 to 2 


// green
unsigned long greenOffSeconds = 0;
unsigned long greenOnSeconds = 0;
boolean greenOn = false ;
const int greenRandomSeconds[3] = { 6, 9 } ;  // indexed 0 to 1


void runRedCycle() {
  if ( seconds > redOffSeconds && ! redOn ) {
    redOn = true ;
    redOnSeconds = seconds ;
  }
  if ( seconds > redOnSeconds &&  redOn ) {
    redOn = false ;
    redOffSeconds = seconds +  redRandomSeconds[random(0,2)] ;
  }
  digitalWrite ( redLed , redOn ) ;
}


void runGreenCycle() {
  if ( seconds > greenOffSeconds && ! greenOn ) {
    greenOn = true ;
    greenOnSeconds = seconds ;
  }
  if ( seconds > greenOnSeconds &&  greenOn ) {
    greenOn = false ;
    greenOffSeconds = seconds +  greenRandomSeconds[random(0,1)] ;
  }
  digitalWrite ( greenLed , greenOn ) ;
}


void setup() {
  pinMode ( redLed , OUTPUT ) ;
  pinMode ( greenLed , OUTPUT ) ;
}


void loop() {

  // read push button and , if pushed, increment mode

  if ( millis() - clockLastMs > 1000UL ) {
    clockLastMs = millis() ;
    // Every Second
    seconds++ ;

    if ( mode == 1 ) {
      runRedCycle () ;
    }
    else if ( mode == 2 ) {
      runRedCycle () ;
      runGreenCycle () ;
    }
    else if ( mode == 3 ) {
      runRedCycle () ;
      runGreenCycle () ;
      // runYellowCycle () ;
    }
  }
}

Eventually I would like to reduce the size of this project to as little as possible and use a small microcrontroller instead of the arduino. so if you can give advice for this thats a bonus.

Check this out: "shrinkify"

Pat.

To have a random number chosen, for example between 2 and 10, you can use
random(2, 10)

But if you want discrete random selection like from 3, 5, 8, you can make an array

choices={3, 5, 8}

then to pick at random, it would be
choices[random(0,2)]
or use random(2) (don't have to list 0 as it's always assumed)

Since 0 is first item, 1 is second item, 2 is third item.

If you want to use a microcontroller with a smaller number of pins, consider using NeoPixels. You can drive any number of them with a single data line.

For the sketch itself, as always I would use a class for the components.

This sketch compiles. Don’t have a board with me, so I can’t really test it.

/**
   A flasher flashes a pin on and off. It can be made active or inactive - in inactive state,
   the pin stays off.

   The length of time the pin is on/off for is decided in a subclass. getOnMs and getOffMs are
   called once each time the led is turned on or off.
*/

class Flasher {
  public:
    const byte pin;
    boolean active = false;
    boolean on = false;
    unsigned long startMs;
    unsigned long durationMs;

    Flasher(byte pin) : pin(pin) {}

    virtual unsigned long getOnMs() = 0;
    virtual unsigned long getOffMs() = 0;

    void setup() {
      pinMode(pin, OUTPUT);
    }

    void loop() {
      if (!active) return;
      if (millis() - startMs < durationMs) return;
      on = !on;
      digitalWrite(pin, on ? HIGH : LOW);
      startMs = millis();
      durationMs = on ? getOnMs() : getOffMs();
    }

    void activate() {
      active = true;
      on = true;
      digitalWrite(pin, HIGH);
      startMs = millis();
      durationMs = getOnMs();
    }

    void deactivate() {
      active = false;
      on = false;
      digitalWrite(pin, LOW);
    }

};

/**
   A flasher that is on for N seconds and off for N seconds
*/
class NSecondFlasher : public Flasher {
  public:
    const unsigned long nMs;
    NSecondFlasher(byte pin, int nSec) : Flasher(pin), nMs(nSec * 1000L) {}

    unsigned long getOnMs() {
      return nMs;
    }
    unsigned long getOffMs() {
      return nMs;
    }

};

/**
   A flasher that is on for one second and off for a time picked randomly from a list
*/

class RandomFlasher: public Flasher {
  public:
    unsigned long *times;
    int nTimes;

    RandomFlasher(byte pin, unsigned long *times, int nTimes) :
      Flasher(pin), times(times), nTimes(nTimes) {}


    unsigned long getOnMs() {
      return 1000;
    }
    unsigned long getOffMs() {
      return times[random(nTimes)];
    }

};

/**
   A button listens to a pin and calls onRising and onFalling when the
   pin goes high and low, with a 20ms debounce. Subclasses should override these methods -
   the default implementations do nothing.
*/

class Button {
  public:
    static const unsigned long debounceMs = 20;
    const byte pin;
    int state;
    unsigned long stateChangeMs;

    Button(byte pin) : pin(pin) {}

    void setup() {
      pinMode(pin, INPUT_PULLUP);
      state = digitalRead(pin);
    }

    void loop() {
      if (millis() - stateChangeMs < debounceMs) return;
      int prevState = state;
      state = digitalRead(pin);
      if (state == prevState) return;
      stateChangeMs = millis();
      if (state == LOW)
        onFalling();
      else
        onRising();
    }

    virtual void onRising() {};
    virtual void onFalling() {};

};

/**
   a three flasher controller hold pointers to three flashers. As its button is pressed (ie: onFalling),
   it acivates one, twoo, three flashers and then back to one again.
*/

class ThreeFlasherControllerButton: public Button {
  public :
    Flasher *flashers[3];
    int nFlashers;

    ThreeFlasherControllerButton(byte pin, Flasher &f1, Flasher &f2, Flasher &f3) :
      Button(pin)  {
      flashers[0] = &f1;
      flashers[1] = &f2;
      flashers[2] = &f3;
    }

    void setup() {
      Button::setup();
      nFlashers = 1;
      flashers[0]->activate();
      flashers[1]->deactivate();
      flashers[2]->deactivate();
    }

    // no implementation of loop() - the superclass does the stuff we need

    void onFalling() {
      if (nFlashers < 3) {
        flashers[nFlashers]->activate();
        nFlashers ++;
      }
      else {
        while (nFlashers > 1) {
          nFlashers --;
          flashers[nFlashers]->deactivate();
        }
      }
    }

};

// PINOUT

// flashers on pins 6, 7, and 9. Controller button on 4.

unsigned long led1Times[] = {3000, 5000, 8000};
unsigned long led2Times[] = {6000, 9000};

RandomFlasher led1(6, led1Times, sizeof(led1Times) / sizeof(*led1Times));
RandomFlasher led2(7, led2Times, sizeof(led2Times) / sizeof(*led2Times));
NSecondFlasher led3(9, 5);

ThreeFlasherControllerButton controller(4, led1, led2, led3);

void setup() {
  led1.setup();
  led2.setup();
  led3.setup();
  controller.setup();
}

void loop() {
  led1.loop();
  led2.loop();
  led3.loop();
  controller.loop();
}

This code is hereby released into the public domain. However, if it works for you and you use it (either as-is or modified) then the right thing to do would be to kick twenty bucks into my paypal pmurray@bigpond.com please.

If you need a bunch of stuff done to this sketch that is going to take time and back-and-forth to work out what you want and how to do it, well - I usually ask a hundred bucks for something that doesn’t need a lot of hardware setup and will take no more than a couple of hours.

That's nice coding but I think that Topzgirl would have a big problem explaining to Teacher how 'her' beautiful functioning program actually works. :wink:

6v6gt:
That's nice coding but I think that Topzgirl would have a big problem explaining to Teacher how 'her' beautiful functioning program actually works. :wink:

The thought did cross my mind.