Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 6 of 6

Thread: Help with Coding to get LED's Working as I would Like

  1. #1
    Junior Member Sound Man's Avatar
    Join Date
    Dec 2016
    Location
    Nottingham, UK
    Posts
    2

    Help with Coding to get LED's Working as I would Like

    Hi everyone.

    I am putting together a Midi Keypad which has 3 push switches to send midi notes to a computer to operate software. The midi side of things is working ok but what I am having trouble with is getting the LED's which are built into the push switches to work as I would like them to. The push switches have built in RGB indicator LED's and my plan is to arrange the coding so that for example the first switch lights up Green normally. When the switch is pressed the Green LED will go off briefly and the Blue LED will flash about 3 times indicating that the midi note has been sent to the computer.

    I have managed to get the Blue LED's to flash ok when the switch is pressed but what I am having trouble with is getting the Green LED to go Off while the Blue LED is flashing. I first tried doing it with the Delay () coding and found out that that causes the program to also delay. After searching the net I came across the following Timer Library here and swapped Delay () for t.pulse () to add the delay to the Green LED. The result is that the LED goes Off ok when the switch is pressed but sometimes it doesn't come back on and when it does it's not always when the Blue LED has stopped flashing.

    I've come to the thinking that the best way to do this would be to put the coding together so that the Green LED goes off for the duration that the Blue LED is pulsing but I don't know how to do this. Any help with this would be very much appreciated. Sorry for the long winded description.

    Below is the coding that I have put together so far:-

    Code:
    /*
      Palladium Remote Keypad with twin LED's
    
      Created: 3 Dec 2016 by Sims Sound Systems
    
      You must select MIDI from the "Tools > USB Type" menu
    */
    
    #include <Timer.h>
    #include <Bounce.h>
    
    
    // the MIDI channel number to send messages
    const int channel = 1;
    
    Timer t;
    
    int blinkNextCue = 0;           // Button pressed
    int blinkPreviousCue = 0;
    int blinkFXaux = 0;
    
    int NextCueLEDstate = LOW;
    int PreviousCueLEDstate = LOW;
    int FXauxLEDstate = LOW;
    
    long previousNextCueMillis = 0;
    long previousPreviousCueMillis = 0;
    long previousFXauxMillis = 0;
    
    long NextCueBlinkInt = 200;
    long PreviousCueBlinkInt = 200;
    long FXauxBlinkInt = 200;
    
    int NextCueButtonLED = 8;  // Green LED
    int NextCueLED = 9;  // Blue LED
    int PreviousCueButtonLED = 6;  // Red LED
    int PreviousCueLED = 7;  // Blue LED
    int FXauxButtonLED = 5;    // Amber LED (Red & Green LED's connected together)
    int FXauxLED = 4;  // Blue LED
    
    
    // Create Bounce objects for each button.  The Bounce object
    // automatically deals with contact chatter or "bounce", and
    // it makes detecting changes very simple.
    Bounce NextCueButton = Bounce(10, 5);
    Bounce PreviousCueButton = Bounce(11, 5);
    Bounce FXauxButton = Bounce(12, 5);
    
    
    void setup() {
      // Setup input pins for "active low"
      pinMode(10, INPUT_PULLUP);
      pinMode(11, INPUT_PULLUP);
      pinMode(12, INPUT_PULLUP);
    
      // Setup output pins
      pinMode(NextCueButtonLED, OUTPUT);     // Button not pressed
      pinMode(NextCueLED, OUTPUT);                 // Button pressed
      pinMode(PreviousCueButtonLED, OUTPUT);
      pinMode(PreviousCueLED, OUTPUT);
      pinMode(FXauxButtonLED, OUTPUT);
      pinMode(FXauxLED, OUTPUT);
      
      // Set initial LED values.
           // HIGH = LED OFF,   LOW = LED ON  (Common Anode LEDs)
    
      digitalWrite(NextCueButtonLED, LOW);
      digitalWrite(NextCueLED, HIGH);
      digitalWrite(PreviousCueButtonLED, LOW);
      digitalWrite(PreviousCueLED, HIGH);
      digitalWrite(FXauxButtonLED, LOW);
      digitalWrite(FXauxLED, HIGH);
    }
    
    
    void loop() {
      // Update all the buttons.
      NextCueButton.update();
      PreviousCueButton.update();
      FXauxButton.update();
    
    
      // Check each button for "falling" edge.
      // Send a 'MIDI Note On' message when each button is pressed
      if (NextCueButton.fallingEdge()) {
        usbMIDI.sendNoteOn(126, 99, channel);  // Midi Channel 126 = F#10
        t.pulse(NextCueButtonLED, 10 * 400, HIGH); // Green LED off delay
        blinkNextCue = 6;   // Blue LED flash rate
      }
      
      if (PreviousCueButton.fallingEdge()) {
        usbMIDI.sendNoteOn(127, 99, channel);  // Midi Channel 127 = G10
        t.pulse(PreviousCueButtonLED, 10 * 400, HIGH); // Red LED off delay
        blinkPreviousCue = 6;   // Blue LED flash rate
      }
    
      if (FXauxButton.fallingEdge()) {
        usbMIDI.sendNoteOn(0, 99, channel);  // Midi Channel 0 = C0
        t.pulse(FXauxButtonLED, 10 * 400, HIGH); // Amber LED off delay
        blinkFXaux = 6;   // Blue LED flash rate
      }
    
      t.update();
      
      // Check each button for "rising" edge
      // Send a 'MIDI Note Off' message when each button is released
      if (NextCueButton.risingEdge()) {
        usbMIDI.sendNoteOff(126, 0, channel);  // Midi Channel 126 = F#10
      }
      if (PreviousCueButton.risingEdge()) {
        usbMIDI.sendNoteOff(127, 0, channel);  // Midi Channel 127 = G10
      }
      if (FXauxButton.risingEdge()) {
        usbMIDI.sendNoteOff(0, 0, channel);  // Midi Channel 0 = C0
      }
    
    
      // MIDI Controllers should discard incoming MIDI messages.
      while (usbMIDI.read()) {
        // Ignore incoming messages
      }
      unsigned long currentNextCueMillis = millis();
      unsigned long currentPreviousCueMillis = millis();
      unsigned long currentFXauxMillis = millis();
      
      if ((blinkNextCue > 0) || (NextCueLEDstate == LOW)) {  
        if(currentNextCueMillis - previousNextCueMillis > NextCueBlinkInt) {  
          // save the last time you blinked the LED  
          previousNextCueMillis = currentNextCueMillis;    
      
      
          // if the LED is off turn it on and vice-versa:  
          if (NextCueLEDstate == LOW) {  
            NextCueLEDstate = HIGH;  
          } else {  
            NextCueLEDstate = LOW;  
          }  
          // set the LED with the ledState of the variable:  
          digitalWrite(NextCueLED, NextCueLEDstate);  
          blinkNextCue--;  
        }  
      }  
    
      if ((blinkPreviousCue > 0) || (PreviousCueLEDstate == LOW)) {  
        if(currentPreviousCueMillis - previousPreviousCueMillis > PreviousCueBlinkInt) {  
          // save the last time you blinked the LED  
          previousPreviousCueMillis = currentPreviousCueMillis;    
      
      
          // if the LED is off turn it on and vice-versa:  
          if (PreviousCueLEDstate == LOW) {  
            PreviousCueLEDstate = HIGH;  
          } else {  
            PreviousCueLEDstate = LOW;  
          }  
          // set the LED with the ledState of the variable:  
          digitalWrite(PreviousCueLED, PreviousCueLEDstate);  
          blinkPreviousCue--;  
        }  
      }  
    
      if ((blinkFXaux > 0) || (FXauxLEDstate == LOW)) {  
        if(currentFXauxMillis - previousFXauxMillis > FXauxBlinkInt) {  
          // save the last time you blinked the LED  
          previousFXauxMillis = currentFXauxMillis;    
      
      
          // if the LED is off turn it on and vice-versa:  
          if (FXauxLEDstate == LOW) {  
            FXauxLEDstate = HIGH;  
          } else {  
            FXauxLEDstate = LOW;  
          }  
          // set the LED with the ledState of the variable:  
          digitalWrite(FXauxLED, FXauxLEDstate);  
          blinkFXaux--;  
        }  
      }  
    
    }

  2. #2
    Senior Member
    Join Date
    Jan 2013
    Posts
    966
    The key to this is likely elapsedMillis.

  3. #3
    Senior Member+ MichaelMeissner's Avatar
    Join Date
    Nov 2012
    Location
    Ayer Massachussetts
    Posts
    3,004
    This is one of the fundamental things you need to learn to go from simple linear sketches (where you do one thing, wait for a response, and do the next) and go on to a more complicated system where you are controlling multiple things, and you have to juggle doing all of the things on a single processor.

    This Adafruit tutorial is one of many to discuss how to control things independently without going to a fully threaded system: https://learn.adafruit.com/multi-tas...r-now?view=all

  4. #4
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    8,842

    LED FLASHER class using elapsedMillis

    @MichaelMeissner pointed to where I was going to point - but I paused to make a Teensy Specific elapsedMillis example version of that LED FLASHER class code that follows as changed from this :: multi-tasking-the-Arduino >> a-classy-solution.

    Changes:
    > Took out the manual math to watch time and added PJRC Teensy elapsedMillis to the class
    > elapsedMillis is also usefully shown in the loop code to change the test state output changes
    > The FLASHER class code seemed limiting - no way to start/stop/change the cycle rate after compile time - except to not call .Update and manually read/set pin.
    - Added :: void UpdateTimes( uint32_t on, uint32_t off )
    - Added :: void UpdateState( FlashState setState ) // enum FlashState { fOFF = 0, fON, fStayOFF, fStayON };
    > Changed to unsigned 32 bit times values, and used enum for State
    The class is below and sample usage of the two new interfaces to update the FLASHER object at runtime. I only have the LED on pin13, and a spare Teensy on pin 12 that is reporting Frequency with FreqMeasure.countToFrequency() :: numbers on led12 [50 to 500 Hz] a bit fast for watching an LED.

    Code:
    // https://learn.adafruit.com/multi-tasking-the-arduino-part-1/all-together-now?view=all#a-classy-solution
    
    // fOFF / fON :: Turn [Off /On] but continue cycle on next update
    // fStayOFF / fStayON :: Turn [Off / On] and ignore calls to .Update
    enum FlashState { fOFF = 0, fON, fStayOFF, fStayON };
    
    class Flasher
    {
        // Class Member Variables
        // These are initialized at startup
        int ledPin;      // the number of the LED pin
        uint32_t OnTime;     // milliseconds of on-time
        uint32_t OffTime;    // milliseconds of off-time
    
        // These maintain the current state
        FlashState ledState;                 // ledState used to set the LED
        elapsedMillis LEDem;   // will store last time LED was updated
    
        // Constructor - creates a Flasher
        // and initializes the member variables and state
      public:
        Flasher(int pin, uint32_t on, uint32_t off)
        {
          ledPin = pin;
          pinMode(ledPin, OUTPUT);
    
          OnTime = on;
          OffTime = off;
    
          ledState = fOFF;
          LEDem = 0;  // Reset the time
        }
        void UpdateTimes( uint32_t on, uint32_t off )
        {
          OnTime = on;
          OffTime = off;
        }
        void UpdateState( FlashState setState )
        {
          ledState = setState;
          LEDem = 0;  // Reset the time
          if ( ledState == fON || ledState == fStayON )
            digitalWrite(ledPin, HIGH);
          else
            digitalWrite(ledPin, LOW);
        }
        void Update()
        {
          // check to see if it's time to change the state of the LED
          if ((ledState == fON) && (LEDem >= OnTime))
          {
            ledState = fOFF;  // Turn it off
            LEDem = 0;  // Reset the time
            digitalWrite(ledPin, LOW);  // Update the actual LED
          }
          else if ((ledState == fOFF) && (LEDem >= OffTime))
          {
            ledState = fON;  // turn it on
            LEDem = 0;  // Reset the time
            digitalWrite(ledPin, HIGH);   // Update the actual LED
          }
        }
    };
    
    Flasher led12(12, 100, 200);
    Flasher led13(13, 350, 350);
    
    void setup()
    {
      Serial.begin(57600);
      while ( !Serial && millis() < 4000);
      Serial.println( "::+-" );
      Serial.println( millis() );
      Serial.println( "::+- v0.8" );
    }
    
    elapsedMillis Testing;
    uint32_t TestNext = 0;
    uint32_t TestCount = 0;
    void loop()
    {
      led13.Update();
      led12.Update();
      if ( Testing > TestNext ) {
        TestNext += 4000; // next test in 4 seconds
        TestCount++;
        switch ( TestCount )  {
          case 1:
            led12.UpdateTimes( 1 , 1 );
            led13.UpdateTimes( 60 , 240 );
            Serial.println( "500Hz 12 and short on 13" );
            break;
          case 2:
            led12.UpdateTimes( 2 , 2 );
            led13.UpdateTimes( 240 , 60 );
            Serial.println( "250Hz 12 and long on 13" );
            break;
          case 3:
            led12.UpdateState( fStayON );
            led13.UpdateTimes( 500 , 500 );
            Serial.println( "0Hz 12 and .5s on/off 13" );
            break;
          case 4:
            led12.UpdateState( fON );
            led13.UpdateState( fStayON );
            Serial.println( "return to 250Hz 12 and on 13" );
            break;
          case 5:
            led12.UpdateTimes( 1 , 1 );
            led13.UpdateState( fStayOFF );
            Serial.println( "500Hz 12 and off 13" );
            break;
          case 6:
            led12.UpdateTimes( 10 , 10 );
            led13.UpdateState( fON );
            Serial.println( "50Hz 12 and return to .5s on/off 13" );
            break;
        default:
            TestCount = 0;
            TestNext = 0;
            Testing = 0;
            Serial.println( "\nrestarting test series" );
            break;
        }
      }
    }
    Updated Adafruit link to no delay() coding in Wiki_coming to show this.
    Last edited by defragster; 12-05-2016 at 11:20 AM.

  5. #5
    Junior Member Sound Man's Avatar
    Join Date
    Dec 2016
    Location
    Nottingham, UK
    Posts
    2
    Thanks for the replies. I will look into your suggestions.

    David

  6. #6
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    8,842
    Good luck. The code above doesn't do a blink - I added "UpdateCycle( uint32_t cnt )" to the class and it seems to test out okay. Does the specified # of cycles with time watched for transition - counts them through and stops. Only other thing I can think of would be having .Update() return the state : On, Off, JustWentOn, JustWentOff, SetOn, SetOff, CountN done. Re-Reading OP I think that would get you working.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •