1

Topic: RGB Led

How about implementing leds as a class?

The current method of 3 separate variables for one led is not very simple to use.

How about

Enum ledMode {ON, OFF, FLASH_SLOW, FLASH_FAST};

Class led{
  Int color;
  ledMode mode
};
Use as follows

RemoteXY.my_led(RED, FLASH_FAST);
RemoteXY.my_led(RED, ON);
RemoteXY.my_led(BLU, OFF);
RemoteXY.my_led(MAGENTA, FLASH_SLOW);

2

Re: RGB Led

You can easily do that yourself

3 (edited by chrismolloy 2020-03-31 14:34:23)

Re: RGB Led

Guillaume wrote:

You can easily do that yourself

please show me how to flash an led

4

Re: RGB Led

I will write an example later, maybe tomorrow

5

Re: RGB Led

I have written a sketch that demonstrates using led variables in an rgbLed structure to allow simplified setting of led colors, including OFF.

here is a link to the screen design for the demo http://remotexy.com/en/editor/5befdd352 … 8dd97ee20/

here is the sketch which is set up for wifi point.  if you want another comm method, get code from start up to and including "#pragma pack(pop) " and replace up to "#pragma pack(pop) " in the sketch.

COMMENTS ARE APPRECIATED

/*
   -- rgbLedDemo by Chris Molloy --

   This source code of graphical user interface
   has been generated automatically by RemoteXY editor.
   To compile this code using RemoteXY library 2.4.3 or later version
   download by link http://remotexy.com/en/library/
   To connect using RemoteXY mobile app by link http://remotexy.com/en/download/
     - for ANDROID 4.5.1 or later version;
     - for iOS 1.4.1 or later version;

   This source code is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.
*/

//////////////////////////////////////////////
//        RemoteXY include library          //
//////////////////////////////////////////////

// RemoteXY select connection mode and include library 
#define REMOTEXY_MODE__ESP8266WIFI_LIB_POINT
#include <ESP8266WiFi.h>

#include <RemoteXY.h>

// RemoteXY connection settings 
#define REMOTEXY_WIFI_SSID "RemoteXY"
#define REMOTEXY_WIFI_PASSWORD "12345678"
#define REMOTEXY_SERVER_PORT 6377


// RemoteXY configurate  
#pragma pack(push, 1)
uint8_t RemoteXY_CONF[] =
{ 255,1,0,3,0,28,0,10,13,0,
65,7,58,18,24,24,1,2,5,17,
44,25,6,31,78,101,120,116,32,67,
111,108,111,114,0 };

// this structure defines all the variables and events of your control interface 
struct {

    // input variables
    uint8_t next_button; // =1 if button pressed, else =0 

      // output variables
    uint8_t led_1_r; // =0..255 LED Red brightness 
    uint8_t led_1_g; // =0..255 LED Green brightness 
    uint8_t led_1_b; // =0..255 LED Blue brightness 

      // other variable
    uint8_t connect_flag;  // =1 if wire connected, else =0 

} RemoteXY;
#pragma pack(pop) 


enum led_color { RED, GREEN, BLUE, PURPLE, WHITE, OFF };

struct rgbLed
{
    uint8_t* r;
    uint8_t* g;
    uint8_t* b;
};

rgbLed led;
led_color current_led_color = RED;
int debounce_start;
const int debounce_time = 333;

void setLedColor(rgbLed led, led_color c) {
    *led.r = 0;
    *led.g = 0;
    *led.b = 0;
    switch (c) {

    case RED:
        *led.r = 255;
        break;

    case GREEN:
        *led.g = 255;
        break;

    case BLUE:
        *led.b = 255;;
        break;

    case PURPLE:
        *led.r = 255;
        *led.b = 255;
        break;

    case WHITE:
        *led.r = 255;
        *led.g = 255;
        *led.b = 255;
        break;

    case OFF:
        *led.r = 0;
        *led.g = 0;
        *led.b = 0;
        break;
    default:
        break;
    }
}

led_color nextColor() {//for demo purposes
    
    led_color next_color;

    switch (current_led_color) {
    case RED:
        next_color = GREEN;
        break;
    case GREEN:
        next_color = BLUE;
        break;
    case BLUE:
        next_color = PURPLE;
        break;
    case PURPLE:
        next_color = WHITE;
        break;
    case WHITE:
        next_color = OFF;
        break;
    case OFF:
        next_color = RED;
        break;
    default:
        break;
    }

    current_led_color = next_color;
    return next_color;
}

void setup()
{
    RemoteXY_Init();
    Serial.begin(115200);

    //point led elements at red, green blue variables
    led.r = &RemoteXY.led_1_r;
    led.g = &RemoteXY.led_1_g;
    led.b = &RemoteXY.led_1_b;
    debounce_start = millis();
}





void loop()
{
    RemoteXY_Handler();

    if (millis() > debounce_start + debounce_time) {
        if (RemoteXY.next_button != 0) {
            setLedColor(led, nextColor());
            debounce_start = millis();
        }
    }
}

6 (edited by Guillaume 2020-04-10 07:32:56)

Re: RGB Led

Eww, totally forgot to reply, sorry...

I have a small class that you may find useful

class LedXY
{
  public :

    LedXY();

    void attach( uint8_t & led );
    void on();
    void off();
    void update();

    void setOnColor     ( uint8_t const r, uint8_t const g, uint8_t const b, uint8_t const a = 255 );
    void setOffColor    ( uint8_t const r, uint8_t const g, uint8_t const b, uint8_t const a = 255 );
    void setOnColorRGB  ( uint32_t const rgb,  uint8_t const a = 255 );
    void setOffColorRGB ( uint32_t const rgb,  uint8_t const a = 255 );
    void setOnColorRGBA ( uint32_t const rgba, uint8_t const a =   0 );
    void setOffColorRGBA( uint32_t const rgba, uint8_t const a =   0 );
    void calcOffColor   ( uint8_t const alpha = 75 );

    void blink( uint16_t const * const pattern, size_t const length, int8_t const count = -1 );
    void blink( uint16_t const timeOn = 1000, uint16_t const timeOff = 1000, int8_t const count = -1 );
    void flash( uint16_t const timeOn );

    void setBlinkFinishedHandler( void (* func)( LedXY const & led ) );

    bool operator == ( LedXY const & obj ) const { return this == &obj; }
    bool operator != ( LedXY const & obj ) const { return this != &obj; }
    LedXY( LedXY const & ) = delete;
    LedXY & operator = ( LedXY const & ) = delete;
    void * operator new( size_t ) = delete;
    void * operator new[]( size_t ) = delete;

  private :

    uint8_t *        m_ledPtr;
    bool             m_isOn;
    uint8_t          m_colors[2][3];
    uint32_t         m_millis;
    uint16_t         m_time;
    int8_t           m_count;
    uint16_t const * m_patternPtr;
    uint16_t         m_pattern[2];
    size_t           m_patternLength;
    size_t           m_patternIndex;

    void setState    ( bool const on );
    void updateColor ( bool const on );
    void setColor    ( bool const on, uint8_t const r, uint8_t const g, uint8_t const b, uint8_t const a = 255 );
    void setColorRGB ( bool const on, uint32_t const rgb,  uint8_t const a = 255 );
    void setColorRGBA( bool const on, uint32_t const rgba, uint8_t const a = 0 );

    void (*m_blinkFinishedHandler)( LedXY const & led );
};

LedXY::LedXY() :
  m_ledPtr              ( nullptr ),
  m_isOn                ( false ),
  m_colors              { { 255, 255, 255 }, { 0, 0, 0 } },
  m_millis              ( 0 ),
  m_time                ( 0 ),
  m_count               ( 0 ),
  m_patternPtr          ( nullptr ),
  m_pattern             { 0, 0 },
  m_patternLength       ( 0 ),
  m_patternIndex        ( 0 ),
  m_blinkFinishedHandler( nullptr )
{
}

void LedXY::attach( uint8_t & led )
{
  m_ledPtr = &led;
  updateColor( false );
}

void LedXY::setState( bool const on )
{
  if ( m_patternLength > 1 && m_blinkFinishedHandler != nullptr )
  {
    m_blinkFinishedHandler( *this );
  }

  m_count = 0;
  m_patternPtr = nullptr;
  m_patternIndex = 0;
  m_patternLength = 0;
  m_isOn = on;
  updateColor( on );
}

void LedXY::on()  { setState( true  ); }
void LedXY::off() { setState( false ); }

void LedXY::updateColor( bool const on )
{
  if ( m_ledPtr != nullptr )
  {
    uint8_t const i = on ? 0 : 1;

    for ( uint8_t j = 0; j < 3; j++ )
    {
      m_ledPtr[j] = m_colors[i][j];
    }
  }
}

void LedXY::setColor( bool const on, uint8_t const r, uint8_t const g, uint8_t const b, uint8_t const a )
{
  uint8_t const i = on ? 0 : 1;

  if ( a != 255 )
  {
    float const m = a / 255.0;
    m_colors[i][0] = uint8_t( r * m );
    m_colors[i][1] = uint8_t( g * m );
    m_colors[i][2] = uint8_t( b * m );
  }
  else
  {
    m_colors[i][0] = r;
    m_colors[i][1] = g;
    m_colors[i][2] = b;
  }
}

void LedXY::setColorRGB( bool const on, uint32_t const rgb, uint8_t const a )
{
  uint8_t const * const c = (uint8_t *) &rgb;
  setColor( on, c[2], c[1], c[0], a );
}

void LedXY::setColorRGBA( bool const on, uint32_t const rgba, uint8_t const a )
{
  uint8_t const * const c = (uint8_t *) &rgba;
  setColor( on, c[3], c[2], c[1], a == 0 ? c[0] : a );
}

void LedXY::setOnColor     ( uint8_t const r, uint8_t const g, uint8_t const b, uint8_t const a ) { setColor( true,  r, g, b, a ); }
void LedXY::setOffColor    ( uint8_t const r, uint8_t const g, uint8_t const b, uint8_t const a ) { setColor( false, r, g, b, a ); }
void LedXY::setOnColorRGB  ( uint32_t const rgb, uint8_t const a )  { setColorRGB ( true,  rgb,  a ); }
void LedXY::setOffColorRGB ( uint32_t const rgb, uint8_t const a )  { setColorRGB ( false, rgb,  a ); }
void LedXY::setOnColorRGBA ( uint32_t const rgba, uint8_t const a ) { setColorRGBA( true,  rgba, a ); }
void LedXY::setOffColorRGBA( uint32_t const rgba, uint8_t const a ) { setColorRGBA( false, rgba, a ); }
void LedXY::calcOffColor   ( uint8_t const alpha ) { setColor( false, m_colors[0][0], m_colors[0][1], m_colors[0][2], alpha ); }

void LedXY::setBlinkFinishedHandler( void (*func)( LedXY const & led ) ) { m_blinkFinishedHandler = func; }

void LedXY::blink( uint16_t const * const pattern, size_t const length, int8_t const count )
{
  if ( count != 0 && length > 0 && pattern != nullptr )
  {
    m_isOn = true;
    updateColor( true );
    m_millis = millis();
    m_count = count;
    m_patternPtr = pattern;
    m_patternLength = length;
    m_patternIndex = 0;
    m_time = m_patternPtr[0];
  }
}

void LedXY::blink( uint16_t const timeOn, uint16_t const timeOff, int8_t const count )
{
  m_pattern[0] = timeOn;
  m_pattern[1] = timeOff;
  blink( m_pattern, 2, count );
}

void LedXY::flash( uint16_t const timeOn )
{
  m_pattern[0] = timeOn;
  blink( m_pattern, 1, 1 );
}

void LedXY::update()
{
  if ( m_count != 0 && millis() - m_millis >= m_time )
  {
    if ( m_patternLength == 1 )
    {
      setState( false );
    }
    else if ( ++m_patternIndex < m_patternLength )
    {
      m_time = m_patternPtr[ m_patternIndex ];
    }
    else
    {
      if ( m_count != -1 )
      {
        m_count--;
      }
      
      if ( m_count == 0 )
      {
        setState( false );
      }
      else
      {
        m_patternIndex = 0;
        m_time = m_patternPtr[0];
      }
    }

    if ( m_count != 0 )
    {
      m_millis = millis();
      m_isOn = !m_isOn;
      updateColor( m_isOn );
    }
  }
}

Example

...
LedXY myLed;

void onBlinkFinished( LedXY const & led )
{
  if ( led == myLed )
  {
    Serial.println( "myLed finished blinking" );
  }
}
...
void setup()
{
  ...
  myLed.setOnColor( 255, 0, 0 );
  myLed.setOffColor( 255, 255, 255, 75 );
  myLed.setBlinkFinishedHandler( onBlinkFinished );
  myLed.attach( RemoteXY.led_1_r );
  
  static const uint16_t blinkPattern[] = { 250, 750, 250, 750, 250, 4750 };
  myLed.blink( blinkPattern, sizeof(blinkPattern)/sizeof(blinkPattern[0]) );
  ...
}

void loop()
{
  ...
  myLed.update();
  ...
}

Leds must be RGB

7

Re: RGB Led

Thanks.  obviously more sophisticated than what I did.  I had to learn pointers to do what I did, which is a great benefit.

in your code you use  myLed.attach( RemoteXY.led_1_r ); to attach the red led.  How do you reference the green and blue colors.  Do you assume they follow in the declarations and use an offset?

Also, what is the purpose of the myLed.setBlinkFinishedHandler( onBlinkFinished );  is it just for demonstration of flashing?

Thanks again.

8 (edited by Guillaume 2020-04-10 14:42:20)

Re: RGB Led

Yes led_r is always followed by led_g and led_b. If you prefer (like I do), you can modify the RemoteXY struct, instead of this:

struct
{
   ...
   uint8_t led_r,
   uint8_t led_g,
   uint8_t led_b,
   ...
}

You can write this:

struct
{
   ...
   uint8_t led[3],
   ...
}

Then of course you use myLed.attach( RemoteXY.led ).

onBlinkFinished (or whatever you want to name this function) is totally optional, in the given example it won't do anything because the third parameter of blink() (int8_t count) was omitted so it defaults to -1 (repeat infinitely), but if you then use myLed.on() or myLed.off() while it is blinking, then it will stop blinking and call this function so you will see the message "myLed finished blinking". Of course if you change the third parameter to > 0, then it will call this function too. It can be used like a timer.

9

Re: RGB Led

Thanks.  obviously more sophisticated than what I did.  I had to learn pointers to do what I did, which is a great benefit.

in your code you use  myLed.attach( RemoteXY.led_1_r ); to attach the red led.  How do you reference the green and blue colors.  Do you assume they follow in the declarations and use an offset?

Also, what is the purpose of the myLed.setBlinkFinishedHandler( onBlinkFinished );  is it just for demonstration of flashing?

Thanks again.

10

Re: RGB Led

Again, thanks for your Class.

Getting back to your original statement "you can easily do that yourself" is kinda untrue for me, and probably the majority of arduino coders.

213 lines of code to control an led is not easy for me.

QUESTION: What is the best way to incorporate the class, besides just adding the code to your sketch in visual studio?

11 (edited by Guillaume 2020-04-10 16:58:56)

Re: RGB Led

You use PlatformIO for VS Code ? Add a .h file to your project and put this class in it then include it in main.cpp.

Also in case that wasn't obvious, this class allows to use colors like const uint32_t COLOR_RED = 0xFF0000FF that you can use with function setOnColorRGBA, or if you prefer without alpha like 0xFF0000 then you use function setOnColorRGB, and calcOffColor just uses the ON color and sets its alpha to 75 (or parameter) to make the OFF color so that it looks more like a real LED... wink

I may improve this class because I made it years ago and now I see a few mistakes (nothing important, still can be used without problems)