Can I include a library in my own library?

Hello all!

I am trying to write my own library (my first!) for using WS2812 LEDs with a IR remote.

I followed the Arduino tutorial on how to write an Arduino library, but their example is so simple!

I would like to utilize two other Arduino libraries, inside my own. Is this possible? I tried to do that, but I totally fudged it and it, of course, doesn't compile.

Any ideas?
Thanks in advance!

WS2812IR.h:

/*
	WS2812IR.h - Library for using WS2812 with IR.
	Created by K Gray, December 18, 2022.
	Released into the public domain.
*/
#ifndef WS2812IR_h
#define WS2812IR_h
	
#include "Arduino.h"
	
class WS2812IR
{
	public:
	  WS2812IR(int NUMPIXELS, int ledpin, int irpin);
	  void begin();
	  void strip(int R, int G, int B, int speed);
    	  void striphue(int hue, int speed);
    	  void rainbow(int loopnumber, int speed);
    	  void lightning(int ledoffdelay, int ledondelay);
    	  void chase(int R, int G, int B, int speed);
    	  void pulse(int R, int G, int B, int speed);
    	  void mess(int speed);
	private:
	  int _ledpin;
    	  int _irpin;
    	  int _NUMPIXELS;
  	  int results;
          //IRrecv irrecv(int irpin);
 	  //Adafruit_NeoPixel pixels(NUMPIXELS, ledpin, NEO_GRB + NEO_KHZ800);
};
	
#endif

WS2812IR.cpp:

/*
	WS2812IR.cpp - Library for using WS2812 with IR.
	Created by K Gray, December 18, 2022.
	Released into the public domain.
*/
	
#include "Arduino.h"
#include "WS2812IR.h"
#include <IRremote.h>
#include <Adafruit_NeoPixel.h>

WS2812IR::WS2812IR(int NUMPIXELS, int ledpin, int irpin)
{
  IRrecv irrecv(irpin);
  decode_results results;
  Adafruit_NeoPixel pixels(NUMPIXELS, ledpin, NEO_GRB + NEO_KHZ800);
  _NUMPIXELS = NUMPIXELS;
}

void WS2812IR::begin()
{
  irrecv.enableIRIn();
  irrecv.blink13(true);
  pixels.begin();

  WS2812IR::strip(0,0,0,0);
}

void WS2812IR::strip(int R, int G, int B, int speed)
{
	for(int i=0; i<_NUMPIXELS; i++) {
    pixels.setPixelColor(i, pixels.Color(R, G, B));
    pixels.show();
    delay(speed);
  }
}

void WS2812IR::striphue(int hue, int speed)
{
  for(int i=0; i<_NUMPIXELS; i++) {
    pixels.setPixelColor(i, pixels.gamma32(pixels.ColorHSV(hue)));
    pixels.show();
    delay(speed);
  }
}

void WS2812IR::rainbow(int loopnumber,int speed)
{
  // Hue of first pixel runs 5 complete loops through the color wheel.
  // Color wheel has a range of 65536 but it's OK if we roll over, so
  // just count from 0 to 5*65536. Adding 256 to firstPixelHue each time
  // means we'll make 5*65536/256 = 1280 passes through this outer loop:
  for(long firstPixelHue = 0; firstPixelHue < loopnumber*65536; firstPixelHue += 256) {
    for(int i=0; i<pixels.numPixels(); i++) { // For each pixel in strip...
      // Offset pixel hue by an amount to make one full revolution of the
      // color wheel (range of 65536) along the length of the strip
      // (strip.numPixels() steps):
      int pixelHue = firstPixelHue + (i * 65536L / pixels.numPixels());
      // strip.ColorHSV() can take 1 or 3 arguments: a hue (0 to 65535) or
      // optionally add saturation and value (brightness) (each 0 to 255).
      // Here we're using just the single-argument hue variant. The result
      // is passed through strip.gamma32() to provide 'truer' colors
      // before assigning to each pixel:
      pixels.setPixelColor(i, pixels.gamma32(pixels.ColorHSV(pixelHue)));
      if (irrecv.decode(&results)){return;} //IR interrupt
    }
    pixels.show(); // Update strip with new contents
    delay(speed);  // Pause for a moment
  }
}

void WS2812IR::lightning(int ledoffdelay,int ledondelay){//recommended lower delays for a longer strip
  while (!irrecv.decode(&results)){ //IR interrupt
    int pixelN = random(1,_NUMPIXELS);
    pixels.setPixelColor(pixelN, pixels.Color(255, 255, 255)); //white lightning
    pixels.show();
    delay(random(4,ledondelay));
    pixels.setPixelColor(pixelN, pixels.Color(0, 0, 0));
    pixels.show();
    delay(random(10,ledoffdelay));
  }
}

void WS2812IR::chase(int R,int G,int B,int speed){
  while (!irrecv.decode(&results)){//IR interrupt
    for(int b=0; b<3; b++) { //  'b' counts from 0 to 2...
      pixels.clear();         //   Set all pixels in RAM to 0 (off)
      // 'c' counts up from 'b' to end of strip in steps of 3...
      for(int c=b; c<_NUMPIXELS; c += 3) {
        pixels.setPixelColor(c, pixels.Color(R,G,B)); // Set pixel 'c' to value 'color'
      }
      pixels.show(); // Update strip with new contents
      delay(speed);  // Pause for a moment
    }
  }
}

void WS2812IR::pulse(int R,int G,int B,int speed){
  int pixel=0;
  while (!irrecv.decode(&results)){//IR interrupt
    for (int p=1;p<5;p++){
      pixel++;
      if (pixel > _NUMPIXELS){
        pixel = 0;
      }
      int m = map(p,2,5,1,135);
      pixels.setPixelColor(pixel, pixels.Color(0,m,0));//m
      pixels.show();
    }
    pixel++;
    pixels.setPixelColor(pixel, pixels.Color(0,255,0));
    for (int p=1;p<5;p++){
      pixel++;
      if (pixel > _NUMPIXELS){
        pixel = 0;
      }
      int m = map(p,2,5,135,1);
      pixels.setPixelColor(pixel, pixels.Color(0,m-20,0));
      pixels.show();
    }
    for (int p=0;p<10;p++){
      pixel++;
      if (pixel > _NUMPIXELS){
        pixel = 0;
      }
      pixels.setPixelColor(pixel, pixels.Color(0,0,0));
      pixels.show();
    }
    pixel++;
    if (pixel > _NUMPIXELS){
      pixel = 0;
    }
    delay(speed);
  }
}

void WS2812IR::mess(int speed){
  while (!irrecv.decode(&results)){//IR interrupt
    int R = random(1,255);
    int G = random(1,255);
    int B = random(1,255);
    int p = random(1,_NUMPIXELS);
    int t = random(1,speed);
    pixels.setPixelColor(p, pixels.Color(R,G,B));
    pixels.show();
    delay(t);
  }
}

irrecv is a local variable that will get disposed of when the constructor terminates. so no chance you can use that in another method like begin()

same goes for results

may be you need to play a bit with variable scope and classes in C++ before attempting to build your library

Hey @J-M-L !

Funny enough, you nailed the main issue already.

How would I fix that? Like make irrecv a global variable?

if you make a class and you want multiple instances of it, then it has to be an instance variable

now I would question the class structure you are shooting for. the pixels strip and IR could be instantiated separately and passed by reference to your library that will make use of those, rather than create those instances.

Ah, that makes sense; I thought there was a variable type I didn't realize. How would you write an instance variable?

Sorry, pretty new here :man_shrugging: .

Oh, that might work also!

I'm not sure exactly how I should add those two libraries to my library; I only know that I would just like to utilize them.

that was the point I was trying to make here:

you do already have a few (private) instance variables

	private:
	  int _ledpin;
    	  int _irpin;
    	  int _NUMPIXELS;

but again think about that:

1 Like

Wait, int _ledpin is an instance variable? So how would I make irrecv a instance variable? I didn't think that int irrecv would be correct.

How would I do this? Would I just create instances of the two libraries right after including the libraries in my .cpp file? I tried that, but it did not work as the variables needed to create instances of them were not correct.

well you are unlucky for your first try as IRremote is poorly written and IRremote.hpp can only be included in one compilation unit. this means you can't have #include <IRremote.h> multiple times...

the solution to this is to make your class a .hpp (merge the .h and .cpp into one file basically) and don't include IRremote.h (which is called nowadays IRremote.hpp) in your .ino but just include your class hpp.

1 Like

here is an example in the simulator

the POWER, MENU, TEST, PLUS and BACK keys will change the stripe's color. (BACK goes black)

sketch.ino

#include "WS2812IR.hpp"

constexpr byte IRPin =  2;   // Signal Pin of IR receiver
IRrecv receiver(IRPin);

constexpr byte pixelCount = 30;
CRGB pixels[pixelCount];

constexpr byte stripPin = 3;
WS2812IR wsir(&receiver, pixels, pixelCount);

void setup() {
  FastLED.addLeds<WS2812B, stripPin, GRB>(pixels, pixelCount);
  Serial.begin(115200);
  wsir.begin();
}

void loop() {
  wsir.listenIR();
}

WS2812IR.hpp

#ifndef WS2812IR_h
#define WS2812IR_h

#include "Arduino.h"
#include <IRremote.hpp>
#include <FastLED.h>

class WS2812IR
{
  public:
    IRrecv* receiver;
    CRGB* pixels;
    size_t pixelsCount;

    WS2812IR(IRrecv* r, CRGB *p, size_t n) : receiver(r), pixels(p), pixelsCount(n) {}

    void begin() {
      receiver->enableIRIn(); // Start the receiver
      fill(CRGB::Black);
    }

    void listenIR() {
      if (receiver->decode()) {
        handleKey();
        receiver->resume();  // Receive the next value
      }
    }

  private:

    void fill(CRGB color) {
      fill_solid(pixels, pixelsCount, color);
      FastLED.show();
    }

    void handleKey() {
      uint16_t command = receiver->decodedIRData.command;
      switch (command) {
        case 162: Serial.println("POWER");  fill(CRGB::White);  break;
        case 226: Serial.println("MENU");   fill(CRGB::Blue);   break;;
        case  34: Serial.println("TEST");   fill(CRGB::Red);    break;
        case   2: Serial.println("PLUS");   fill(CRGB::Purple); break;
        case 194: Serial.println("BACK");   fill(CRGB::Black);  break;
        case 224: Serial.println("PREV.");  break;
        case 168: Serial.println("PLAY");   break;
        case 144: Serial.println("NEXT");   break;
        case 104: Serial.println("num: 0"); break;
        case 152: Serial.println("MINUS");  break;
        case 176: Serial.println("key: C"); break;
        case  48: Serial.println("num: 1"); break;
        case  24: Serial.println("num: 2"); break;
        case 122: Serial.println("num: 3"); break;
        case  16: Serial.println("num: 4"); break;
        case  56: Serial.println("num: 5"); break;
        case  90: Serial.println("num: 6"); break;
        case  66: Serial.println("num: 7"); break;
        case  74: Serial.println("num: 8"); break;
        case  82: Serial.println("num: 9"); break;
        default: break;
      }
    }
};

#endif
1 Like

Wow, thank you so much @J-M-L ! I can use your example to help me build my library; the way you formatted it and built it etc.

Ill try building my library based off of your example and report back how it goes!

Edit:
Your example actually cleared up several questions I had on how I should format a library.

glad it helped

Note that .hpp is not the usual way. The usual way is with separate files, a .cpp and a .h as you were trying to do.

here I was forced to put everything in the .hpp and not even have the right includes in the .ino because of the way the IRremote library is built

Yeah.

Oh :thinking: .

I tried changing the FastLED stuff to the adafruit library, but I'm confused.

Post your code

WS2812IR.hpp:

#ifndef WS2812IR_h
#define WS2812IR_h

#include "Arduino.h"
#include <IRremote.hpp>
#include <Adafruit_NeoPixel.h>

class WS2812IR
{
  public:
    IRrecv* receiver;
    Adafruit_NeoPixel pixels;
    size_t pixelsCount;

    WS2812IR(IRrecv* r, Adafruit_NeoPixel *p, size_t n) : receiver(r), pixels(p), pixelsCount(n) {}

    void begin() {
      receiver->enableIRIn(); // Start the receiver
      strip(0,0,0,0);
    }

    void listenIR() {
      if (receiver->decode()) {
        handleKey();
        receiver->resume();  // Receive the next value
      }
    }
    
    void strip(int R, int G, int B, int speed)
    {
	    for(int i=0; i<_NUMPIXELS; i++) {
        pixels.setPixelColor(i, pixels.Color(R, G, B));
        pixels.show();
        delay(speed);
      }
    }

    void striphue(int hue, int speed)
    {
      for(int i=0; i<_NUMPIXELS; i++) {
        pixels.setPixelColor(i, pixels.gamma32(pixels.ColorHSV(hue)));
        pixels.show();
        delay(speed);
      }
    }

    void rainbow(int loopnumber,int speed)
    {
      // Hue of first pixel runs 5 complete loops through the color wheel.
      // Color wheel has a range of 65536 but it's OK if we roll over, so
      // just count from 0 to 5*65536. Adding 256 to firstPixelHue each time
      // means we'll make 5*65536/256 = 1280 passes through this outer loop:
      for(long firstPixelHue = 0; firstPixelHue < loopnumber*65536; firstPixelHue += 256) {
       for(int i=0; i<pixels.numPixels(); i++) { // For each pixel in strip...
          // Offset pixel hue by an amount to make one full revolution of the
          // color wheel (range of 65536) along the length of the strip
          // (strip.numPixels() steps):
          int pixelHue = firstPixelHue + (i * 65536L / pixels.numPixels());
          // strip.ColorHSV() can take 1 or 3 arguments: a hue (0 to 65535) or
          // optionally add saturation and value (brightness) (each 0 to 255).
          // Here we're using just the single-argument hue variant. The result
          // is passed through strip.gamma32() to provide 'truer' colors
          // before assigning to each pixel:
          pixels.setPixelColor(i, pixels.gamma32(pixels.ColorHSV(pixelHue)));
          if (receiver->decode()){return;} //IR interrupt
        }
        pixels.show(); // Update strip with new contents
        delay(speed);  // Pause for a moment
      }
    }
    
    void WS2812IR::lightning(int ledoffdelay,int ledondelay){//recommended lower delays for a longer strip
      while (!receiver->decode()){ //IR interrupt
        int pixelN = random(1,_NUMPIXELS);
        pixels.setPixelColor(pixelN, pixels.Color(255, 255, 255)); //white lightning
        pixels.show();
        delay(random(4,ledondelay));
        pixels.setPixelColor(pixelN, pixels.Color(0, 0, 0));
        pixels.show();
        delay(random(10,ledoffdelay));
      }
    }

  private:
    void handleKey() {
      uint16_t command = receiver->decodedIRData.command;
      switch (command) {
        case 162: Serial.println("POWER");  strip(0,255,0,20);   break;
        case 226: Serial.println("MENU");   strip(127,255,0,20); break;;
        case  34: Serial.println("TEST");   strip(255,255,0,20); break;
        case   2: Serial.println("PLUS");   strip(255,127,0,20); break;
        case 194: Serial.println("BACK");   strip(255,0,0,20);   break;
        case 224: Serial.println("PREV.");  break;
        case 168: Serial.println("PLAY");   break;
        case 144: Serial.println("NEXT");   break;
        case 104: Serial.println("num: 0"); break;
        case 152: Serial.println("MINUS");  break;
        case 176: Serial.println("key: C"); break;
        case  48: Serial.println("num: 1"); break;
        case  24: Serial.println("num: 2"); break;
        case 122: Serial.println("num: 3"); break;
        case  16: Serial.println("num: 4"); break;
        case  56: Serial.println("num: 5"); break;
        case  90: Serial.println("num: 6"); break;
        case  66: Serial.println("num: 7"); break;
        case  74: Serial.println("num: 8"); break;
        case  82: Serial.println("num: 9"); break;
        default:  Serial.println(command);  break;
      }
    }
};

#endif

Example:

#include "WS2812IR.hpp"

constexpr byte IRPin =  3;   // Signal Pin of IR receiver
IRrecv receiver(IRPin);

constexpr byte pixelCount = 40;
constexpr byte PIN = 2;
Adafruit_NeoPixel pixels(pixelCount, PIN, NEO_GRB + NEO_KHZ800);

constexpr byte stripPin = 3;
WS2812IR wsir(&receiver, pixels, pixelCount);

void setup() {
  pixels.begin();
  Serial.begin(115200);
  wsir.begin();
}

void loop() {
  wsir.strip(0,255,0,20);
  delay(1000);
  wsir.strip(0,0,255,40);
  delay(1000);
}

Im not sure exactly how to transfer a Adafruit Neopixel example to replace the fast led example; they are very different.

in the class you want a pointer to the pixels

    Adafruit_NeoPixel *pixels;

and when you create your instance, you pass the address of your Adafruit_NeoPixel

WS2812IR wsir(&receiver, &pixels, pixelCount);

then in the methods whenever you want to do something with the strip, you will call pixels->method(...) and not pixels.method(...) `

if you need to play with the strip in the loop, then it means your class is probably not bringing much value

you need to really read about Object Oriented Programming concepts and think about your WS2812IR class. What it is really ? if this is meant to be a collection of function dealing with IR and a Strip, then it does not need to be a class. it could be a bunch of helper functions

1 Like

Oh, do you mean like this?

#include <IRremote.h>
#include <Adafruit_NeoPixel.h>

#define RECV_PIN 3
#define PIN      2
#define NUMPIXELS 180


unsigned const long maxcolorcount = 65536;
int incrementAmount = 1200;

IRrecv irrecv(RECV_PIN);
decode_results results;
unsigned long key_value = 0;

int bright = 255;
int modeSelect = 1;

unsigned long stripcolor = 100;

boolean strip = false;
boolean off = true;
boolean on = false;
boolean mode = false;
boolean update = false;

Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

void setup(){
  Serial.begin(9600);
  irrecv.enableIRIn();
  irrecv.blink13(true);

  pixels.begin();
  wholeStrip(0,0,0,2);
}

void loop(){
  if (irrecv.decode(&results)){
 
        if (results.value == 0XFFFFFFFF)
          results.value = key_value;

        if (!off && mode){
          results.value = 0xFD00FF;
        }
        switch(results.value){
          case 0xFD00FF:
          strip = !strip;
          Serial.println(strip);
          delay(200);
          /*if (strip){
            //wholeStrip(0,255,0,10);
            rainbow(10,2);
          }
          else {
            wholeStrip(0,0,0,10);
          }*/
          break;
          case 0xFD807F:
          Serial.print("UP");
          bright+=10;
          if (bright > 255){
            bright = 255;
            wholeStrip(0,0,0,0);
            delay(200);
          }
          Serial.println(bright);
          update = true;
          break;
          case 0xFD906F:
          Serial.print("DOWN");
          bright-=10;
          if (bright < 0){
            bright = 0;
          }
          Serial.println(bright);
          update = true;
          break;
          case 0xFD40BF:
          Serial.println("FUNC");
          mode = !mode;
          for (int i=0;i<modeSelect;i++){
            wholeStrip(50,50,50,0);
            delay(200);
            wholeStrip(0,0,0,0);
            delay(500);
          }
          update = true;
          break;
          case 0xFD609F:
          Serial.print("Right");
          if (!mode){
            stripcolor+=incrementAmount;
            if (stripcolor > maxcolorcount){
              stripcolor = 0;
            }
            Serial.println(stripcolor);
          }
          else {
            modeSelect++;
            if (modeSelect > 5){
              modeSelect = 5;
            }
            for (int i=0;i<modeSelect;i++){
              wholeStrip(50,50,50,0);
              delay(100);
              wholeStrip(0,0,0,0);
              delay(200);
            }
            Serial.println(modeSelect);
          }
          update = true;
          delay(30);
          break; 
          case 0xFD20DF:
          Serial.print("Left");
          if (!mode){
            stripcolor-=incrementAmount;
            if (stripcolor < 0){
              stripcolor = maxcolorcount;
            }
            Serial.println(stripcolor);
          }
          else {
            modeSelect--;
            if (modeSelect < 1){
              modeSelect = 1;
            }
            for (int i=0;i<modeSelect;i++){
              wholeStrip(50,50,50,0);
              delay(100);
              wholeStrip(0,0,0,0);
              delay(200);
            }
            Serial.println(modeSelect);
          }
          update = true;
          delay(30);
          break;
          default:
          Serial.println(results.value,HEX);
          break;
        }
        key_value = results.value;
        irrecv.resume(); 
        delay(100);
  }

  if (strip){
    if (!mode){//mode 1
      if (!on || update){
        wholeStripHue(stripcolor,2);
        on = true;
        update = false;
      }
    }
    else {
      if (modeSelect == 1){
        //rainbow mode
        rainbow(10,2);
        update = false;
      }
      else if (modeSelect == 2){
        lightning(1500,100);
        update = false;
      }
      else if (modeSelect == 3){
        chase(0,255,0,50);
        update = false;
      }
      else if (modeSelect == 4){
        pulse(0,255,0,10);
        update = false;
      }
      else if (modeSelect == 5){
        mess(40);
        update = false;
      }
    }

    if (bright != pixels.getBrightness()){
      pixels.setBrightness(bright);
      update = false;
    }
    
    //wholeStrip(0,255,0,15);
    //rainbow(10,2);
    off = false;
  }
  else {
    if (!off){
      wholeStrip(0,0,0,15);
      off = true;
      on = false;
      update = false;
    }
  }

}

void wholeStrip(int R,int G,int B,int d){
  for(int i=0; i<NUMPIXELS; i++) {
    pixels.setPixelColor(i, pixels.Color(R, G, B));
    pixels.show();
    delay(d);
    /*if (irrecv.decode(&results)){
      return;
    }*/
  }
}

void wholeStripHue(int hue,int d){
  for(int i=0; i<NUMPIXELS; i++) {
    pixels.setPixelColor(i, pixels.gamma32(pixels.ColorHSV(hue)));
    pixels.show();
    delay(d);
    /*if (irrecv.decode(&results)){
      return;
    }*/
  }
}

void rainbow(int wait,int lo) {
  // Hue of first pixel runs 5 complete loops through the color wheel.
  // Color wheel has a range of 65536 but it's OK if we roll over, so
  // just count from 0 to 5*65536. Adding 256 to firstPixelHue each time
  // means we'll make 5*65536/256 = 1280 passes through this outer loop:
  for(long firstPixelHue = 0; firstPixelHue < lo*65536; firstPixelHue += 256) {
    for(int i=0; i<pixels.numPixels(); i++) { // For each pixel in strip...
      // Offset pixel hue by an amount to make one full revolution of the
      // color wheel (range of 65536) along the length of the strip
      // (strip.numPixels() steps):
      int pixelHue = firstPixelHue + (i * 65536L / pixels.numPixels());
      // strip.ColorHSV() can take 1 or 3 arguments: a hue (0 to 65535) or
      // optionally add saturation and value (brightness) (each 0 to 255).
      // Here we're using just the single-argument hue variant. The result
      // is passed through strip.gamma32() to provide 'truer' colors
      // before assigning to each pixel:
      pixels.setPixelColor(i, pixels.gamma32(pixels.ColorHSV(pixelHue)));
      if (irrecv.decode(&results)){return;}
    }
    pixels.show(); // Update strip with new contents
    delay(wait);  // Pause for a moment
  }
}

void lightning(int d1,int d2){
  while (!irrecv.decode(&results)){
    int pixelN = random(1,NUMPIXELS);
    pixels.setPixelColor(pixelN, pixels.Color(255, 255, 255));
    pixels.show();
    delay(random(4,d2));
    pixels.setPixelColor(pixelN, pixels.Color(0, 0, 0));
    pixels.show();
    delay(random(10,d1));
  }
}

void chase(int R,int G,int B,int speed){
  while (!irrecv.decode(&results)){
    for(int b=0; b<3; b++) { //  'b' counts from 0 to 2...
      pixels.clear();         //   Set all pixels in RAM to 0 (off)
      // 'c' counts up from 'b' to end of strip in steps of 3...
      for(int c=b; c<NUMPIXELS; c += 3) {
        pixels.setPixelColor(c, pixels.Color(R,G,B)); // Set pixel 'c' to value 'color'
      }
      pixels.show(); // Update strip with new contents
      delay(speed);  // Pause for a moment
    }
  }
}

void pulser(int R,int G,int B,int speed){
  int pixel=0;
  while (!irrecv.decode(&results)){
    for (int p=1;p<5;p++){
      pixel++;
      if (pixel > NUMPIXELS){
        pixel = 0;
      }
      int m = map(p,2,5,1,135);
      pixels.setPixelColor(pixel, pixels.Color(0,m,0));//m
      pixels.show();
    }
    pixel++;
    pixels.setPixelColor(pixel, pixels.Color(0,255,0));
    for (int p=1;p<5;p++){
      pixel++;
      if (pixel > NUMPIXELS){
        pixel = 0;
      }
      int m = map(p,2,5,135,1);
      pixels.setPixelColor(pixel, pixels.Color(0,m-20,0));
      pixels.show();
    }
    for (int p=0;p<10;p++){
      pixel++;
      if (pixel > NUMPIXELS){
        pixel = 0;
      }
      pixels.setPixelColor(pixel, pixels.Color(0,0,0));
      pixels.show();
    }
    pixel++;
    if (pixel > NUMPIXELS){
      pixel = 0;
    }
    delay(speed);
  }
}

void pulse(int R,int G,int B,int speed){
  int pixel=0;
  while (!irrecv.decode(&results)){
    for (int i=0;i<5;i++){
      pixel++;
      if (pixel >= NUMPIXELS){pixel=0;}
      pixels.setPixelColor(pixel, pixels.Color(0,(G/10)*i,0));
      pixels.show();
    }
    for (int i=5;i>0;i--){
      pixel++;
      if (pixel >= NUMPIXELS){pixel=0;}
      pixels.setPixelColor(pixel, pixels.Color(0,(G/10)*i,0));
      pixels.show();
    }
    for (int i=0;i<10;i++){
      pixel++;
      if (pixel >= NUMPIXELS){pixel=0;}
      pixels.setPixelColor(pixel, pixels.Color(0,0,0));
      pixels.show();
    }
    pixel++;
    if (pixel >= NUMPIXELS){pixel=0;}
    delay(speed);
  }
}

void mess(int speed){
  while (!irrecv.decode(&results)){
    int R = random(1,255);
    int G = random(1,255);
    int B = random(1,255);
    int p = random(1,NUMPIXELS);
    int t = random(1,speed);
    pixels.setPixelColor(p, pixels.Color(R,G,B));
    pixels.show();
    delay(t);
  }
}

I already wrote this code which works perfectly, but I was thinking that if I made it into a library, it would be easier to use.

Yeah, that is really what it is. I was just thinking between ease of use, and doing it just to do it for the first time, it would be a good idea!

Ok, definitely will do! I have much more to learn too by the sounds of it.

Thanks for your explanation on how to change it to the adafruit neopixel!

a library does not need to be a class. it can just offer a bunch of functions.

What? Really :thinking: ? I didn't know that.

Ah, now that I think about it, it makes sense that that is possible, and how that is possible. Ill just try doing that, and see if I can get something working!

in the .h you keep the prototypes of the functions you want to make available.
in the .cpp you put all the code for public APIs and hidden ones that only your library can see

1 Like

Makes sense!

Would the .h file look something like this?

/*
	WS2812IR.h - Library for using WS2812 with IR.
	Created by K Gray, December 18, 2022.
	Released into the public domain.
*/
#ifndef WS2812IR_h
#define WS2812IR_h
	
#include "Arduino.h"
	
public:
  void begin();
  void strip(int R, int G, int B, int speed);
  void striphue(int hue, int speed);
  void rainbow(int loopnumber, int speed);
  void lightning(int ledoffdelay, int ledondelay);
  void chase(int R, int G, int B, int speed);
  void pulse(int R, int G, int B, int speed);
  void mess(int speed);
private:
  int _ledpin;
  int _irpin;
  int _NUMPIXELS;
  int results;
	
#endif

Edit:
I got my previous .hpp version to work! It compiles and runs the LED strip perfectly.