Controlling WS2812 to form 7 two segment displays

Hello all-

I am very new to coding and looking for some help. I have coded one project successfully but can't figure out how to go about this one. I have searched the internet without much luck. Also paid a freelancer $100 and got nothing in return. I really don't know where to start. Any help would be appreciated.

The idea is to essentially create a large (8" tall) counter to use as a scoreboard using a strip of WS 2811 lights. This would be for 2 scoreboards that could go up to 21. I have carved two pairs of 7 segment numbers into wood. I would like to put a strip of 3 LEDS into each segment, wire them end to end then selectively turn on the correct segments to form a counter. I would need to be able to add 1 or subtract 1 with the push of a button. So, 2 counters from 0-21 and two push buttons for each so you could add or subtract.

I am using Arduino IDE and an Arduino UNO board along with the lights. My lights are WS2811, 3 pixels per segment and 12Volt.
I am open to switching to a Nano if that is a better option. I corrected the type of lights, I am using 2811 not 2812 as was in my original post.

That seems like a totally doable project. If you have 3 leds per segment and there are 7 segments per digit and each counter has 2 digits, you basically have 1 led strip with 3 x 7 x 2 = 42 leds. You will also need a good 5V power supply to run that many leds (or twice as much when you add the second counter. 60ma/LED x 84 = 5A)

Start by getting them wired up and working with any example code. You can use the FastLED library. It has many, many examples.

After you verify that works, you would need to create a function that can "build" each digit. For example, a 0 would light all the segments, except for the middle one, etc.

As for your button presses, look at the bounce2.h library. It can take care of all the debouncing, etc. that buttons require. Make sure to wire your button up properly - one side to a pin, the other to ground and declare the pin as INPUT_PULLUP.

If/When you get stuck, post your best effort here along with any error messages and a description of what is should do vs. what it is actually doing and people will help. Read this: How to get the best out of this forum - Using Arduino / Installation & Troubleshooting - Arduino Forum to get the most out of the forum.

Thank you so much. I like your thought process. I was afraid to install things until I was sure that was the right thing to do. I will work on that then post my progress/need for help. Thanks again for the advice.

This zip file contains the code that I wrote for my brother's project. It is a counter that uses 4 each 7 segment displays to display a counter. Each display is made up of 7 segments of 3 WS2812 pixels each. Each digit has its own controller (pin) as do the decimal points. The number of pixels per segment and the number of segments is easily changed. There is also Bluetooth control to set each digit color and some other options. It is not exactly what you want but there may be parts that you can use. ws2812_7_seg_4_4_steps_BT.ino is the main file and the others are tabs, a schematic and instructions on setting up and using the Bluetooth part.

ws2812_7_seg_4_4_steps_BT.zip (180.8 KB)

Hope this helps some.

Well, there's a thought!

If you use the WS2811 strips which operate on 12 V and have three LEDs in series with each WS2811 chip, then three LEDs would form one "pixel" and the code would be particularly neat.

That's nasty! Was that through the "Gigs and Collaborations" forum here?

Bleah! Nanos are more practical. :grin:

I think my library should be able to let you define a seven segment display with 3 pixels per segment:
https://werner.rothschopf.net/202005_arduino_neopixel_display_en.htm

example 40_scoreboard should be 97% of what you need and is a good starting point.

The freelancer was through Freelancer .com.
If Nano’s are a better option, I am not against changing.

Thank you. I do need to clarify, my lights are 12V and 1 pixel per segment (they can be cut after every third light).

no problem, than just follow the first layout

typedef uint8_t segsize_t;
const segsize_t segment[8] {
 0b00000001, // SEG_A
 0b00000010, // SEG_B
 0b00000100, // SEG_C
 0b00001000, // SEG_D
 0b00010000, // SEG_E
 0b00100000, // SEG_F
 0b01000000, // SEG_G
 0b00000000 // SEG_DP
};

OK, Arduino forum not to blame then. :sunglasses:

Functionally almost identical, but the Nano is more physically practical for a project as you will see if you compare them.

Nano clones much cheaper.

As I suspected. Very convenient. :grin:

Noiasca - I have this working!!! Your code with the additional layout works perfectly. I am very thankful for your help thus far and willingness to share. I was able to change the color of the lights and eliminate the extra "addpixels" which I do not want to use. I am now trying to add two more buttons to the project. I would like to be able to decrease the value of the number displayed without resetting all the way to zero. I have started to edit the code from your library in a manner I think is correct, but I think I need something that actually makes the reduction happen. Attached is the code at it's current state. Any advice would be appreciated.

/* Noiasca Neopixel Display
   40 scoreboard
   a simple scoreboard for two players (A and B)
   separate displays for A and B on the same strip pin
   
   Wire three buttons from the GPIO to GND. Input pullups are activated
   
   http://werner.rothschopf.net/202005_arduino_neopixel_display.htm

   by noiasca
   2020-05-04
*/

const byte ledPin = 12;                // Which pin on the Arduino is connected to the NeoPixels?
const byte numDigits = 2;              // How many digits (numbers) are available on each display
const byte pixelPerDigit = 7;         // all pixels, including decimal point pixels if available at each digit
const byte addPixels = 0;              // unregular additional pixels to be added to the strip

const byte startPixelA = 0;            // start pixel of display A
const byte startPixelB = 14;           // start pixel of display B (assumption: 2 x 14 used by displayA + 4 additional Pixels)

const byte buttonApin = A3;            // button pin player A, connects to GND
const byte buttonApin1 = A4;           // button pin player A subtract, connects to GND
const byte buttonBpin = A0;            // button pin player B, connects to GND
const byte buttonBpin1 = A2;           // button pin player B subtract, connects to GND
const byte buttonResetPin = A1;        // button to reset scores, connects to GND
byte counterA;                         // counts/goals/score for player A
byte counterB;                         // counts/goals/score for player B

const uint16_t ledCount(pixelPerDigit * numDigits * 2 + addPixels);
/*
   Segments are named and orded like this

          SEG_A
   SEG_F         SEG_B
          SEG_G
   SEG_E         SEG_C
          SEG_D          SEG_DP

  in the following constant array you have to define
  which pixels belong to which segment
*/

typedef uint8_t segsize_t;
const segsize_t segment[8] {
 0b00000001, // SEG_A
 0b00000010, // SEG_B
 0b00000100, // SEG_C
 0b00001000, // SEG_D
 0b00010000, // SEG_E
 0b00100000, // SEG_F
 0b01000000, // SEG_G
 0b00000000 // SEG_DP
};

#include <Adafruit_NeoPixel.h>                                       // install Adafruit library from library manager
Adafruit_NeoPixel strip(ledCount, ledPin, NEO_GRB + NEO_KHZ800);     // create neopixel object like you commonly used with Adafruit

#include <Noiasca_NeopixelDisplay.h>                                      // download library from: http://werner.rothschopf.net/202005_arduino_neopixel_display.htm
// in this sketch we handle displayA and displayB as two individual displays:
Noiasca_NeopixelDisplay displayA(strip, segment, numDigits, pixelPerDigit, startPixelA);  // create display object, handover the name of your strip as first parameter!
Noiasca_NeopixelDisplay displayB(strip, segment, numDigits, pixelPerDigit, startPixelB);  // create display object, handover the name of your strip as first parameter!

#include <OneButton.h>                                               // install OneButton library from library manager
OneButton buttonA(buttonApin, true);
OneButton buttonA1(buttonApin1, true);
OneButton buttonB(buttonBpin, true);
OneButton buttonB1(buttonBpin1, true);
OneButton buttonReset(buttonResetPin, true);

void clickA()
{
  counterA++;
  Serial.print(F("PlayerA ")); Serial.println(counterA);
  displayA.setCursor(0);
  if (counterA < 10) displayA.print(" ");
  displayA.print(counterA);
}

void clickB()
{
  counterB++;
  Serial.print(F("PlayerB ")); Serial.println(counterB);
  displayB.setCursor(0);
  if (counterB < 10) displayB.print(" ");
  displayB.print(counterB);
}

void resetScore()
{
  Serial.println(F("Reset Score"));
  counterA = 0;
  counterB = 0;
  displayA.clear();
  displayA.print(" 0");
  displayB.clear();
  displayB.print(" 0");
}

void setup()
{
  Serial.begin(115200);
  Serial.println(F("\nNoiascaNeopixelDisplay\n40 scoreboard two displays"));

  strip.begin();                       // INITIALIZE NeoPixel strip object (REQUIRED)
  strip.show();                        // Turn OFF all pixels ASAP
  strip.setBrightness(50);             // Set BRIGHTNESS to about 1/5 (max = 255)
  strip.clear();

  displayA.setColorFont(0xAA0000);     // each display gets its own color, e.g. corresponding to the button color
  displayB.setColorFont(0xAA0000);

  Serial.println(F("test display"));
  for (byte i = 99; i > 0; i = i - 11)
  {
    displayA.print(i);
    displayB.print(i);
    delay(200);
  }
  displayA.print(" 0");
  displayB.print(" 0");
  buttonA.attachClick(clickA);
  buttonB.attachClick(clickB);
  buttonReset.attachLongPressStart(resetScore);
}

void loop()
{
  // put here other code which needs to run:
  buttonA.tick();
  buttonB.tick();
  buttonReset.tick();
}

you also need to
add some callback functions and
attach this callback functions to the new buttons
and tick the new buttons in loop!

pseudo code ...

void clickA1(); // for decrease
...
buttonA1.attachClick(clickA1);
...
buttonA1.tick()

that's why I've written in #6, it's 97% what you need! :wink:

I'm getting errors now after trying to add the subtraction button information. Any thoughts on how I can correct this?

Arduino: 1.8.19 (Windows Store 1.8.57.0) (Windows 10), Board: "Arduino Uno"

C:\Users\Mike_\AppData\Local\Temp\cctEf0bL.ltrans0.ltrans.o: In function `attachClick':

C:\Users\Mike_\OneDrive\One Note\Arduino\libraries\OneButton\src/OneButton.cpp:85: undefined reference to `clickA()'

C:\Users\Mike_\OneDrive\One Note\Arduino\libraries\OneButton\src/OneButton.cpp:85: undefined reference to `clickA()'

C:\Users\Mike_\OneDrive\One Note\Arduino\libraries\OneButton\src/OneButton.cpp:85: undefined reference to `clickB()'

C:\Users\Mike_\OneDrive\One Note\Arduino\libraries\OneButton\src/OneButton.cpp:85: undefined reference to `clickB()'

collect2.exe: error: ld returned 1 exit status

exit status 1

Error compiling for board Arduino Uno.



This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.
/* Noiasca Neopixel Display
   40 scoreboard
   a simple scoreboard for two players (A and B)
   separate displays for A and B on the same strip pin

   Wire three buttons from the GPIO to GND. Input pullups are activated

   http://werner.rothschopf.net/202005_arduino_neopixel_display.htm

   by noiasca
   2020-05-04
*/

const byte ledPin = 12;                // Which pin on the Arduino is connected to the NeoPixels?
const byte numDigits = 2;              // How many digits (numbers) are available on each display
const byte pixelPerDigit = 7;         // all pixels, including decimal point pixels if available at each digit
const byte addPixels = 0;              // unregular additional pixels to be added to the strip

const byte startPixelA = 0;            // start pixel of display A
const byte startPixelB = 14;           // start pixel of display B (assumption: 2 x 14 used by displayA + 4 additional Pixels)

const byte buttonApin = A3;            // button pin player A, connects to GND
const byte buttonApin1 = A4;           // button pin player A subtract, connects to GND
const byte buttonBpin = A0;            // button pin player B, connects to GND
const byte buttonBpin1 = A2;           // button pin player B subtract, connects to GND
const byte buttonResetPin = A1;        // button to reset scores, connects to GND
byte counterA;                         // counts/goals/score for player A
byte counterB;                         // counts/goals/score for player B

const uint16_t ledCount(pixelPerDigit * numDigits * 2 + addPixels);
/*
   Segments are named and orded like this

          SEG_A
   SEG_F         SEG_B
          SEG_G
   SEG_E         SEG_C
          SEG_D          SEG_DP

  in the following constant array you have to define
  which pixels belong to which segment
*/

typedef uint8_t segsize_t;
const segsize_t segment[8] {
  0b00000001, // SEG_A
  0b00000010, // SEG_B
  0b00000100, // SEG_C
  0b00001000, // SEG_D
  0b00010000, // SEG_E
  0b00100000, // SEG_F
  0b01000000, // SEG_G
  0b00000000 // SEG_DP
};

#include <Adafruit_NeoPixel.h>                                       // install Adafruit library from library manager
Adafruit_NeoPixel strip(ledCount, ledPin, NEO_GRB + NEO_KHZ800);     // create neopixel object like you commonly used with Adafruit

#include <Noiasca_NeopixelDisplay.h>                                      // download library from: http://werner.rothschopf.net/202005_arduino_neopixel_display.htm
// in this sketch we handle displayA and displayB as two individual displays:
Noiasca_NeopixelDisplay displayA(strip, segment, numDigits, pixelPerDigit, startPixelA);  // create display object, handover the name of your strip as first parameter!
Noiasca_NeopixelDisplay displayB(strip, segment, numDigits, pixelPerDigit, startPixelB);  // create display object, handover the name of your strip as first parameter!

#include <OneButton.h>                                               // install OneButton library from library manager
OneButton buttonA(buttonApin, true);
OneButton buttonA1(buttonApin1, true);
OneButton buttonB(buttonBpin, true);
OneButton buttonB1(buttonBpin1, true);
OneButton buttonReset(buttonResetPin, true);

void clickA();
void clickA1()  //for decrease
{
  counterA++;
  Serial.print(F("PlayerA ")); Serial.println(counterA);
  displayA.setCursor(0);
  if (counterA < 10) displayA.print(" ");
  displayA.print(counterA);
}

void clickB();
void clickB1()  //for decrease
{
  counterB++;
  Serial.print(F("PlayerB ")); Serial.println(counterB);
  displayB.setCursor(0);
  if (counterB < 10) displayB.print(" ");
  displayB.print(counterB);
}

void resetScore()
{
  Serial.println(F("Reset Score"));
  counterA = 0;
  counterB = 0;
  displayA.clear();
  displayA.print(" 0");
  displayB.clear();
  displayB.print(" 0");
}

void setup()
{
  Serial.begin(115200);
  Serial.println(F("\nNoiascaNeopixelDisplay\n40 scoreboard two displays"));

  strip.begin();                       // INITIALIZE NeoPixel strip object (REQUIRED)
  strip.show();                        // Turn OFF all pixels ASAP
  strip.setBrightness(50);             // Set BRIGHTNESS to about 1/5 (max = 255)
  strip.clear();

  displayA.setColorFont(0xAA0000);     // each display gets its own color, e.g. corresponding to the button color
  displayB.setColorFont(0xAA0000);

  Serial.println(F("test display"));
  for (byte i = 99; i > 0; i = i - 11)
  {
    displayA.print(i);
    displayB.print(i);
    delay(200);
  }
  displayA.print(" 0");
  displayB.print(" 0");
  buttonA.attachClick(clickA);
  buttonA1.attachClick(clickA1);
  buttonB.attachClick(clickB);
  buttonB1.attachClick(clickB1);
  buttonReset.attachLongPressStart(resetScore);
}

void loop()
{
  // put here other code which needs to run:
  buttonA.tick();
  buttonA1.tick();
  buttonB.tick();
  buttonB1.tick();
  buttonReset.tick();
}

how should this decrease the counter?
counterA++ will increase the counter.
Furthermore you have no code for clickA() any more!

void clickA()
{
  counterA++;
  Serial.print(F("PlayerA increase ")); Serial.println(counterA);
  displayA.setCursor(0);
  if (counterA < 10) displayA.print(" ");
  displayA.print(counterA);
}

void clickA1()  //for decrease
{
  if (counterA > 0) counterA--;
  Serial.print(F("PlayerA decrease ")); Serial.println(counterA);
  displayA.setCursor(0);
  if (counterA < 10) displayA.print(" ");
  displayA.print(counterA);
}

sjmilar error is with clickB() and clickB1()

That makes perfect sense. I could not see it. I made the changes and it is perfect.

As of now, the code works perfectly on the serial monitor and appears to work perfect with a length of lights hooked to it. I hope to get it all installed and working this weekend.

Thank you to everyone who helped me with this. I could never have imagined you all could get me to this point this quickly. THANK YOU! I will post an update once I have it working.

1 Like

good to hear you made it working. If you don't mind please post a picture of your final installation, I would like to add this as example project on my homepage if you agree.

I certainly will and you are more than welcome to use them. You helped me, I am more than willing to help you (what little I can).

I do have one more question. One twist to this project I have not mentioned yet is that I actually intend to have two scoreboards operating at the same time displaying the same information. Is it possible to use one Arduino to control two different sets of numbers? Is it as simple as splitting the output from the Arduino to two different locations?

I think it should be no programming problem *) to add a second stripB on a different pin and two new "displays" displayC and displayD.

duplicate the "strip." code to stripB

duplicate the .setCursor/.print to the new displays...

*) one Arduino Uno will have enough resources to drive all 4 displays.
But you might consider some special measures, if the wring from the Arduino to the first Pixel is to far. This distance can't be endless!

Here is what I have now. No errors are showing up but I have not tried it yet with lights. Does this look correct to add the second scoreboard display? The two displays will be about 30' apart. Does that distance seem okay? The scoreboards will be built into corn hole boards. As always, thanks for the help!

/* Noiasca Neopixel Display
   40 scoreboard
   a simple scoreboard for two players (A and B)
   separate displays for A and B on the same strip pin

   Wire three buttons from the GPIO to GND. Input pullups are activated

   http://werner.rothschopf.net/202005_arduino_neopixel_display.htm

   by noiasca
   2020-05-04
*/

const byte ledPin = 12;                // Which pin on the Arduino is connected to the NeoPixels?
const byte ledPin1 = 11;                // Which pin on the Arduino is connected to the NeoPixels second strip?
const byte numDigits = 2;              // How many digits (numbers) are available on each display
const byte pixelPerDigit = 7;         // all pixels, including decimal point pixels if available at each digit
const byte addPixels = 0;              // unregular additional pixels to be added to the strip

const byte startPixelA = 0;            // start pixel of display A
const byte startPixelB = 14;           // start pixel of display B (assumption: 2 x 14 used by displayA + 4 additional Pixels)
const byte startPixelC = 0;            // start pixel of display C
const byte startPixelD = 14;           // start pixel of display D (assumption: 2 x 14 used by displayA + 4 additional Pixels)

const byte buttonApin = A3;            // button pin player A, connects to GND
const byte buttonApin1 = A4;           // button pin player A subtract, connects to GND
const byte buttonBpin = A0;            // button pin player B, connects to GND
const byte buttonBpin1 = A2;           // button pin player B subtract, connects to GND
const byte buttonResetPin = A1;        // button to reset scores, connects to GND
byte counterA;                         // counts/goals/score for player A
byte counterB;                         // counts/goals/score for player B

const uint16_t ledCount(pixelPerDigit * numDigits * 2 + addPixels);
/*
   Segments are named and orded like this

          SEG_A
   SEG_F         SEG_B
          SEG_G
   SEG_E         SEG_C
          SEG_D          SEG_DP

  in the following constant array you have to define
  which pixels belong to which segment
*/

typedef uint8_t segsize_t;
const segsize_t segment[8] {
  0b00000001, // SEG_A
  0b00000010, // SEG_B
  0b00000100, // SEG_C
  0b00001000, // SEG_D
  0b00010000, // SEG_E
  0b00100000, // SEG_F
  0b01000000, // SEG_G
  0b00000000 // SEG_DP
};

#include <Adafruit_NeoPixel.h>                                       // install Adafruit library from library manager
Adafruit_NeoPixel strip(ledCount, ledPin, NEO_GRB + NEO_KHZ800);     // create neopixel object like you commonly used with Adafruit
Adafruit_NeoPixel strip1(ledCount, ledPin1, NEO_GRB + NEO_KHZ800);

#include <Noiasca_NeopixelDisplay.h>                                      // download library from: http://werner.rothschopf.net/202005_arduino_neopixel_display.htm
// in this sketch we handle displayA and displayB as two individual displays:
Noiasca_NeopixelDisplay displayA(strip, segment, numDigits, pixelPerDigit, startPixelA);  // create display object, handover the name of your strip as first parameter!
Noiasca_NeopixelDisplay displayB(strip, segment, numDigits, pixelPerDigit, startPixelB);  // create display object, handover the name of your strip as first parameter!
Noiasca_NeopixelDisplay displayC(strip1, segment, numDigits, pixelPerDigit, startPixelC);  // create display object, handover the name of your strip as first parameter!
Noiasca_NeopixelDisplay displayD(strip1, segment, numDigits, pixelPerDigit, startPixelD);

#include <OneButton.h>                                               // install OneButton library from library manager
OneButton buttonA(buttonApin, true);
OneButton buttonA1(buttonApin1, true);
OneButton buttonB(buttonBpin, true);
OneButton buttonB1(buttonBpin1, true);
OneButton buttonReset(buttonResetPin, true);

void clickA()
{
  counterA++;
  Serial.print(F("PlayerA increase ")); Serial.println(counterA);
  displayA.setCursor(0);
  if (counterA < 10) displayA.print(" ");
  displayA.print(counterA);
  displayC.setCursor(0);
  if (counterA < 10) displayC.print(" ");
  displayC.print(counterA);
}

void clickA1()  //for decrease
{
  if (counterA > 0) counterA--;
  Serial.print(F("PlayerA decrease ")); Serial.println(counterA);
  displayA.setCursor(0);
  if (counterA < 10) displayA.print(" ");
  displayA.print(counterA);
  displayC.setCursor(0);
  if (counterA < 10) displayC.print(" ");
  displayC.print(counterA);
}

void clickB()
{
  counterB++;
  Serial.print(F("PlayerB increase ")); Serial.println(counterB);
  displayB.setCursor(0);
  if (counterB < 10) displayB.print(" ");
  displayB.print(counterB);
  displayD.setCursor(0);
  if (counterB < 10) displayD.print(" ");
  displayD.print(counterB);
}

void clickB1()  //for decrease
{
  if (counterB > 0) counterB--;
  Serial.print(F("PlayerB decrease ")); Serial.println(counterB);
  displayB.setCursor(0);
  if (counterB < 10) displayB.print(" ");
  displayB.print(counterB);
  displayD.setCursor(0);
  if (counterB < 10) displayD.print(" ");
  displayD.print(counterB);
}

void resetScore()
{
  Serial.println(F("Reset Score"));
  counterA = 0;
  counterB = 0;
  displayA.clear();
  displayA.print(" 0");
  displayB.clear();
  displayB.print(" 0");
  displayC.clear();
  displayC.print(" 0");
  displayD.clear();
  displayD.print(" 0");
}

void setup()
{
  Serial.begin(9600);
  Serial.println(F("\nNoiascaNeopixelDisplay\n40 scoreboard two displays"));

  strip.begin();                       // INITIALIZE NeoPixel strip object (REQUIRED)
  strip.show();                        // Turn OFF all pixels ASAP
  strip.setBrightness(50);             // Set BRIGHTNESS to about 1/5 (max = 255)
  strip.clear();

  displayA.setColorFont(0xAA0000);     // each display gets its own color, e.g. corresponding to the button color
  displayB.setColorFont(0xAA0000);
  displayC.setColorFont(0xAA0000);     
  displayD.setColorFont(0xAA0000);

  Serial.println(F("test display"));
  for (byte i = 99; i > 0; i = i - 11)
  {
    displayA.print(i);
    displayB.print(i);
    displayC.print(i);
    displayD.print(i);
    delay(200);
  }
  displayA.print(" 0");
  displayB.print(" 0");
  displayC.print(" 0");
  displayD.print(" 0");
  buttonA.attachClick(clickA);
  buttonA1.attachClick(clickA1);
  buttonB.attachClick(clickB);
  buttonB1.attachClick(clickB1);
  buttonReset.attachLongPressStart(resetScore);
}

void loop()
{
  // put here other code which needs to run:
  buttonA.tick();
  buttonA1.tick();
  buttonB.tick();
  buttonB1.tick();
  buttonReset.tick();
}

the code parts for strip1 are missing in setup (begin, show, setBrightness, clear)

google brought me to
https://quinled.info/2021/03/10/maximum-length-data-wire-leds-ws2812b-sk6812-ws2815/

I think you have to test.
If the result is unstable, cut the line and add a pixel in the middle of the extension line to "boost" the signal.

edit:
instead of duplicating code, you could use arrays and call code in for loops

something like:

/* Noiasca Neopixel Display
   based on 40 scoreboard
  
   http://werner.rothschopf.net/202005_arduino_neopixel_display.htm

   by noiasca
   2022-01-21
*/

const byte ledPin = 12;                // Which pin on the Arduino is connected to the NeoPixels?
const byte ledPin1 = 11;                // Which pin on the Arduino is connected to the NeoPixels second strip?
const byte numDigits = 2;              // How many digits (numbers) are available on each display
const byte pixelPerDigit = 7;         // all pixels, including decimal point pixels if available at each digit
const byte addPixels = 0;              // unregular additional pixels to be added to the strip

const byte startPixelA = 0;            // start pixel of display A
const byte startPixelB = 14;           // start pixel of display B 
const byte startPixelC = 0;            // start pixel of display C
const byte startPixelD = 14;           // start pixel of display D

const byte buttonApin = A3;            // button pin player A, connects to GND
const byte buttonApin1 = A4;           // button pin player A subtract, connects to GND
const byte buttonBpin = A0;            // button pin player B, connects to GND
const byte buttonBpin1 = A2;           // button pin player B subtract, connects to GND
const byte buttonResetPin = A1;        // button to reset scores, connects to GND
byte counterA;                         // counts/goals/score for player A
byte counterB;                         // counts/goals/score for player B

const uint16_t ledCount(pixelPerDigit * numDigits * 2 + addPixels);
/*
   Segments are named and orded like this

          SEG_A
   SEG_F         SEG_B
          SEG_G
   SEG_E         SEG_C
          SEG_D          SEG_DP

  in the following constant array you have to define
  which pixels belong to which segment
*/

typedef uint8_t segsize_t;
const segsize_t segment[8] {
  0b00000001, // SEG_A
  0b00000010, // SEG_B
  0b00000100, // SEG_C
  0b00001000, // SEG_D
  0b00010000, // SEG_E
  0b00100000, // SEG_F
  0b01000000, // SEG_G
  0b00000000 // SEG_DP
};

#include <Adafruit_NeoPixel.h>                                       // install Adafruit library from library manager
Adafruit_NeoPixel strip[] {
  {ledCount, ledPin, NEO_GRB + NEO_KHZ800},
  {ledCount, ledPin1, NEO_GRB + NEO_KHZ800}
};

#include <Noiasca_NeopixelDisplay.h>                                      // download library from: http://werner.rothschopf.net/202005_arduino_neopixel_display.htm
// in this sketch we handle displayA and displayB as two individual displays
// you can also use a array of displays
Noiasca_NeopixelDisplay displayA[] {
  {strip[0], segment, numDigits, pixelPerDigit, startPixelA},
  {strip[1], segment, numDigits, pixelPerDigit, startPixelC}
};  

Noiasca_NeopixelDisplay displayB[] {
  {strip[0], segment, numDigits, pixelPerDigit, startPixelB},
  {strip[1], segment, numDigits, pixelPerDigit, startPixelD}
};

#include <OneButton.h>                                               // install OneButton library from library manager
OneButton buttonA(buttonApin, true);
OneButton buttonA1(buttonApin1, true);
OneButton buttonB(buttonBpin, true);
OneButton buttonB1(buttonBpin1, true);
OneButton buttonReset(buttonResetPin, true);

void clickA()
{
  counterA++;
  Serial.print(F("PlayerA increase ")); Serial.println(counterA);
  for (auto &i : displayA)
  {
    i.setCursor(0);
    if (counterA < 10) i.print(" ");
    i.print(counterA);
  }
}

void clickA1()  //for decrease
{
  if (counterA > 0) counterA--;
  Serial.print(F("PlayerA decrease ")); Serial.println(counterA);
  for (auto &i : displayA)
  {
    i.setCursor(0);
    if (counterA < 10) i.print(" ");
    i.print(counterA);
  }
}

void clickB()
{
  counterB++;
  Serial.print(F("PlayerB increase ")); Serial.println(counterB);
  for (auto &i : displayB)
  {
    i.setCursor(0);
    if (counterB < 10) i.print(" ");
    i.print(counterB);
  }
}

void clickB1()  //for decrease
{
  if (counterB > 0) counterB--;
  Serial.print(F("PlayerB decrease ")); Serial.println(counterB);
  for (auto &i : displayB)
  {
    i.setCursor(0);
    if (counterB < 10) i.print(" ");
    i.print(counterB);
  }
}

void resetScore()
{
  Serial.println(F("Reset Score"));
  counterA = 0;
  counterB = 0;
  for (auto &i : displayA)
  {
    i.clear();
    i.print(" ");
    i.print(counterA);
  }
  for (auto &i : displayB)
  {
    i.clear();
    i.print(" ");
    i.print(counterB);
  }
}

void setup()
{
  Serial.begin(9600);
  Serial.println(F("\nNoiascaNeopixelDisplay\n40 scoreboard two displays"));

  for (auto & i : strip)
  {
    i.begin();                       // INITIALIZE NeoPixel strip object (REQUIRED)
    i.show();                        // Turn OFF all pixels ASAP
    i.setBrightness(50);             // Set BRIGHTNESS to about 1/5 (max = 255)
    i.clear();
  }

  displayA[0].setColorFont(0xAA0000);     // each display gets its own color, e.g. corresponding to the button color
  displayA[1].setColorFont(0xAA0040);
  displayB[0].setColorFont(0xAA0080);
  displayB[1].setColorFont(0xAA00F0);

  Serial.println(F("test display"));
  for (byte j = 99; j > 0; j = j - 11)
  {
    for (auto &i : displayA) i.print(j);
    for (auto &i : displayB) i.print(j);
    delay(200);
  }
  for (auto & i : displayA) i.print(" 0");
  for (auto & i : displayB) i.print(" 0");
  buttonA.attachClick(clickA);
  buttonA1.attachClick(clickA1);
  buttonB.attachClick(clickB);
  buttonB1.attachClick(clickB1);
  buttonReset.attachLongPressStart(resetScore);
}

void loop()
{
  buttonA.tick();
  buttonA1.tick();
  buttonB.tick();
  buttonB1.tick();
  buttonReset.tick();
}

Has still duplicated lines of code, but you get the idea ...