Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple Universes #9

Open
erod998 opened this issue Nov 2, 2017 · 23 comments
Open

Multiple Universes #9

erod998 opened this issue Nov 2, 2017 · 23 comments

Comments

@erod998
Copy link

erod998 commented Nov 2, 2017

First of all, thank you for writing such a reliable and great code. I have 2 quick questions.
Is there any way to have the device always connect with the same IP without going to my router settings? I am in an apartment and do not have access to the provided router configuration page.

Also, the beginning of the "ArtnetWifiNeoPixel" says "This example will receive multiple universes via Artnet and control a strip of ws2811 leds via...". Does this mean I can have another data pin control another independent universe? Such as Net0, Subnet0, Universe 1 and 2?
I currently have this running on a NodeMCU v2 with CH340. It controls 150 pixels of a WS2812B strip. Runs great.

Thank you!

@pinq-
Copy link

pinq- commented Nov 3, 2017

If you are using Esp8266 the you can try this for fix ip esp8266/Arduino#1959

What I understand you can set different use for universe 1 and 2 etc. if you look onDmxFrame function that "parses" all the channels, it also defines at input what universe it is parsing. You can add another noepixel leds list in the beginning of arduino code and then add on the onDmxFrame where it goes to channels, in the for loop a if condition like if (universe == 2) {leds2.setPixelColor(led, data[i * 3], data[i * 3 + 1], data[i * 3 + 2]);} else{leds.setPixelColor(led, data[i * 3], data[i * 3 + 1], data[i * 3 + 2]);}. This is simple solution. I recommend to look closer to onDmxframe function.

@rstephan
Copy link
Owner

rstephan commented Nov 9, 2017

Just a bit for clarification.
One universe can handle 170 LEDs (512/3).
The ArtnetWifiNeoPixel example has one strip with 240 LEDs. To control that amount of LEDs you need more then one universe. In this example universe 0 is LED 1-170 and universe 1 is 171-240.
If you have "short" strips, and you have to arrange one strip per universe you have to do it by yourself.
As long as the ESP has enough pins it shouldn't be a problem.

@donnib
Copy link

donnib commented Nov 27, 2017

@rstephan I am searching for a way to control 17m of WS2812b leds which in total are 510leds meaning i would need 510led * 4 (does this library support RGBW?) = 2040channels meaning 2040/512=4 universes meaning i need 4 pins on the ESP8266 right ? Do you think you library would be capable of this ?

@rstephan
Copy link
Owner

The ArtnetWifiNeoPixel example is able to this, as far as i know. You can use one long strip and need only one pin.

Configure the examples for your needs:

// Neopixel settings
const int numLeds = 510; // change for your setup
const int numberOfChannels = numLeds * 4; // Total number of channels you want to receive (1 led = 3 channels / 4 in case of RGBW)
const byte dataPin = 2;
Adafruit_NeoPixel leds = Adafruit_NeoPixel(numLeds, dataPin, NEO_GRBW + NEO_KHZ800);

Extend the byte to channel maping to 4

  // read universe and put into the right part of the display buffer
  for (int i = 0; i < length / 4; i++)
  {
    int led = i + (universe - startUniverse) * (previousDataLength / 4);
    if (led < numLeds)
      leds.setPixelColor(led, data[i * 4], data[i * 4 + 1], data[i * 4 + 2], data[i * 4 + 3]);
}

You have to transmit 4 universes in a row starting from 0 to send out all data.
I haven't tested this. I don't know the performance with than amount of pixels.
Make some tests yourself and let us know.

@donnib
Copy link

donnib commented Nov 30, 2017

@rstephan
I am in doubt now whether the WS2812b are indeed RGBW since that's what i need.

Actually the strip will indeed be a long strip of 17m so yes you are right one pin should do it.

@erod998
Copy link
Author

erod998 commented Mar 4, 2018

I still haven’t figured out how to add more strips to different pins. Can you give me a little more guidance? For instance: if I add another led strip, leds2, does that mean I need to add new functions throughout the entire code? Like setting the brightness of the entire strip would be:
led.setBrightness and
leds.setBrightness
?

@bombcheck
Copy link

Just tried the ArtnetWifiNeoPixel-Example yesterday: It works fine with my 64 (8x8) and 99 (11x9) pixel arrays. But when trying to use on my 484 (22x22) pixel array, it just turn on all leds to white, Not init-color-show either. Any ideas?

@rstephan
Copy link
Owner

rstephan commented Mar 5, 2018

@erod998
You have to be more precise. My library is able to be 1 node, with 16 universes. Currently one strip with up to (170 * 15 = 2550) LEDs (in therory) is possible. If you are looking for something like this: universe 0 = strip 0, universe 1 = strip 1, ... ?

void onDmxFrame(uint16_t universe, uint16_t length, uint8_t sequence, uint8_t* data)
{
  if (universe == 0) {
    for (int i = 0; i < length / 3; i++)
    {
      int led = i;
      if (led < leds0.numPixels())
        leds0.setPixelColor(led, data[i * 3], data[i * 3 + 1], data[i * 3 + 2]);
      }
    }
    leds0.show();
  }
  if (universe == 1) {
    // .. go on with ... leds1.numPixels() ... led1.setPixelColor() ....
  }
  if (universe == 2) {
    // .. go on with ... leds2.numPixels() ... led2.setPixelColor() ....
  }
}

It can be done more sophisticated :-) but this is not the point.

@bombcheck
My standard question, is your power supply good enough to handle 484 * 60mA ~ 30A
Try the Standtest from Adafruit and let me know what happened.

@bombcheck
Copy link

Power supply is OK: It works with another firmware, but it is not stable. So I am looking for another firmware that is more stable.

@Gdmm97
Copy link

Gdmm97 commented Mar 15, 2018

Hi there,
I am quiet new to this topic but I intend to use this code to control multiple wemos d1 mini with 6 Pixel each. For now I am running them in seperate Universes using the first 18 channels each. Is there an easy way to control them in one universe or to set the start channel in the code? Like start the second node at channel 19.

Thanks for your help

@rstephan
Copy link
Owner

@Gdmm97
For the next time, please open a new issue. The only common thing is "multiple" that is a bit less.

If you can transmit a broadcast IP packet so every node can see the same packet, which is the first step.
After that, if the node knows that it is the second, it can calculate the offset based of its address.
With address, i mean, a node-number (1, 2, 3, ...) not IP address.
How to distinguish different nodes?

  • Flash different firmware on each node.
  • Build dip-switches to it, so it can be configured later on
  • Auto configuration, this is off topic, sorry.

@MFClark
Copy link

MFClark commented Oct 16, 2018

Hello, I would like to have multiple WS2812b strips displaying as a LED matrix. The catch is I would like them to all be movable, independent of each other and the computer controlling them. My plan is to connect each strip containing 90 LEDs to it's own Adafruit esp8266 microcontroller and control them via dmx using the artnetwifi neopixel example, with each unit as it's own universe. In my case I will have 6 universes to begin with and will add more at a later date. Do I understand correctly that I should change the universe settings for leds 1-90 and give the code on each board a different universe number? Will that do it? Thank you for your help, this is my first LED project.

@erod998
Copy link
Author

erod998 commented Oct 23, 2018

Current Setup: NodeMCU running two strips. Strip 1 is 300 RGB LEDs. Strip 2 is 150 RGB LEDs.

Code: (Still needs to be cleaned up)

/*
This example will receive multiple universes via Artnet and control a strip of ws2811 leds via 
Adafruit's NeoPixel library: https://github.com/adafruit/Adafruit_NeoPixel
This example may be copied under the terms of the MIT license, see the LICENSE file for details
*/

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <ArtnetWifi.h>
#include <Adafruit_NeoPixel.h>

//Wifi settings
const char* ssid = "ssid";
const char* password = "passed";

// Neopixel settings
const int numLeds = 300; // change for your setup
const int numberOfChannels = numLeds * 3; // Total number of channels you want to receive (1 led = 3 channels)
const byte dataPin = 15;
Adafruit_NeoPixel leds = Adafruit_NeoPixel(numLeds, dataPin, NEO_GRB + NEO_KHZ800);

const int numLeds1 = 150; // change for your setup
const int numberOfChannels1 = numLeds1 * 3; // Total number of channels you want to receive (1 led = 3 channels)
const byte dataPin1 = 13;
Adafruit_NeoPixel leds1 = Adafruit_NeoPixel(numLeds1, dataPin1, NEO_GRB + NEO_KHZ800);


// Artnet settings
ArtnetWifi artnet;
const int startUniverse = 1; // CHANGE FOR YOUR SETUP most software this is 1, some software send out artnet first universe as 0.

// Check if we got all universes
const int maxUniverses = numberOfChannels / 512 + ((numberOfChannels % 512) ? 1 : 0);
bool universesReceived[maxUniverses];
bool sendFrame = 1;
int previousDataLength = 0;

// connect to wifi – returns true if successful or false if not
boolean ConnectWifi(void)
{
  boolean state = true;
  int i = 0;

  WiFi.begin(ssid, password);
  Serial.println("");
  Serial.println("Connecting to WiFi");
  
  // Wait for connection
  Serial.print("Connecting");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
    if (i > 20){
      state = false;
      break;
    }
    i++;
  }
  if (state){
    Serial.println("");
    Serial.print("Connected to ");
    Serial.println(ssid);
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());
  } else {
    Serial.println("");
    Serial.println("Connection failed.");
  }
  
  return state;
}

void initTest()
{
  for (int i = 0 ; i < numLeds ; i++)
    leds.setPixelColor(i, 127, 0, 0);
  leds.show();
  delay(100);
  for (int i = 0 ; i < numLeds ; i++)
    leds.setPixelColor(i, 0, 127, 0);
  leds.show();
  delay(100);
  for (int i = 0 ; i < numLeds ; i++)
    leds.setPixelColor(i, 0, 0, 127);
  leds.show();
  delay(100);
  for (int i = 0 ; i < numLeds ; i++)
    leds.setPixelColor(i, 0, 0, 0);
  leds.show();
}
void initTest1()
{
    for (int b = 0 ; b < numLeds1 ; b++)
    leds1.setPixelColor(b, 127, 0, 0);
  leds1.show();
  delay(100);
  for (int b = 0 ; b < numLeds1 ; b++)
    leds1.setPixelColor(b, 0, 127, 0);
  leds1.show();
  delay(100);
  for (int b = 0 ; b < numLeds1 ; b++)
    leds1.setPixelColor(b, 0, 0, 127);
  leds1.show();
  delay(100);
  for (int b = 0 ; b < numLeds1 ; b++)
    leds1.setPixelColor(b, 0, 0, 0);
  leds1.show();
}

void onDmxFrame(uint16_t universe, uint16_t length, uint8_t sequence, uint8_t* data)
{/*
  sendFrame = 1;
  // set brightness of the whole strip 
  if (universe == 15)
  {
    leds.setBrightness(data[0]);
    leds.show();
  }

  // Store which universe has got in
  if ((universe - startUniverse) < maxUniverses)
    universesReceived[universe - startUniverse] = 1;

  for (int i = 0 ; i < maxUniverses ; i++)
  {
    if (universesReceived[i] == 0)
    {
      //Serial.println("Broke");
      sendFrame = 0;
      break;
    }
  }
  */

  // read universe and put into the right part of the display buffer
  if ( (universe == 1 )  || universe == 2) {
    for (int i = 0; i < length / 3; i++)
    {
     int led = i + (universe - startUniverse) * (previousDataLength / 3);
     //int led = i;
      if (led < 300) {
        if (universe == 2) {
          leds.setPixelColor(led +169, data[i * 3], data[i * 3 + 1], data[i * 3 + 2], data[i * 3 + 3]);
        }
        else if (universe == 1) {
          leds.setPixelColor(led, data[i * 3], data[i * 3 + 1], data[i * 3 + 2], data[i * 3 + 3]);
        }
        //leds.show();
      }
   }
   leds.show();
  }
  
   if (universe == 3 ) {
    for (int i = 0; i < length / 3; i++)
    {
     //int led = i + (universe - startUniverse) * (previousDataLength / 4);
     //int led1 = c;
      if (i < numLeds1)
        leds1.setPixelColor(i, data[i * 3], data[i * 3 + 1], data[i * 3 + 2], data[i * 3 + 3]);

   }
   leds1.show();
  }
  //previousDataLength = length;     
  /*
  if (sendFrame)
  {
    //leds.show();
    //leds1.show();
    // Reset universeReceived to 0
    memset(universesReceived, 0, maxUniverses);
  }
  */
}

void setup()
{
  Serial.begin(115200);
  ConnectWifi();
  artnet.begin();
  leds.begin();
  leds1.begin();
  initTest();
  initTest1();

  // this will be called for each packet received
  artnet.setArtDmxCallback(onDmxFrame);
}

void loop()
{
  // we call the read function inside the loop
  artnet.read();
}

I struggled with the first strip. I couldn't get it to display universe 2 on the strip. U1 is LEDs 0-169 and U2 is 170-299. Couldn't get the U2 to show. Strip 1 is ran off a single pin, so is strip 2. Finally got it to display both.

Performance is good so far. I will see if I can share a video once I get everything finalized. Also, will update here to show the RGBW (SK6812) LEDs here.

You can look in the onDmxFrame and see that I have most of it commented out. Still unsure of the rest of its functionality with regards to multiple strips.

Sometimes the Node resets and goes through the initTest function again, or sometimes takes a few tries to get through it. I suspect this is the Node losing wifi.
I need to fix that, and play around with adding OTA updates.

@MFClark
Copy link

MFClark commented Oct 27, 2018

thanks!!

@Carransynth
Copy link

Carransynth commented Nov 2, 2018

Hi! I've been trying to get the Universes output through different pins, I've algo managed to do it but the board keeps reseting, same as @erod998 . I can't figure why this is happening. If anyone has some pointers, it would be great!

Code:

/*
This example will receive multiple universes via Artnet and control a strip of ws2811 leds via 
Adafruit's NeoPixel library: https://github.com/adafruit/Adafruit_NeoPixel
This example may be copied under the terms of the MIT license, see the LICENSE file for details
*/

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <ArtnetWifi.h>
#include <Adafruit_NeoPixel.h>

//Wifi settings


IPAddress ip(192, 168, 1, 20);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);
IPAddress DNS(8, 8, 8, 8);

const char* ssid = "PIXEL";
const char* password = "roygvib2";

// Neopixel strip 1 settings
const int numLeds0 = 128; // change for your setup
const int numberOfChannels0 = numLeds0 * 3; // Total number of channels you want to receive (1 led = 3 channels)
const byte dataPin0 = 4;
Adafruit_NeoPixel leds0 = Adafruit_NeoPixel(numLeds0, dataPin0, NEO_GRB + NEO_KHZ800);

// Neopixel strip 2 settings
const int numLeds1 = 128; // change for your setup
const int numberOfChannels1 = numLeds1 * 3; // Total number of channels you want to receive (1 led = 3 channels)
const byte dataPin1 = 5;
Adafruit_NeoPixel leds1 = Adafruit_NeoPixel(numLeds1, dataPin1, NEO_GRB + NEO_KHZ800);

// Neopixel strip 3 settings
const int numLeds2 = 128; // change for your setup
const int numberOfChannels2 = numLeds2 * 3; // Total number of channels you want to receive (1 led = 3 channels)
const byte dataPin2 = 15;
Adafruit_NeoPixel leds2 = Adafruit_NeoPixel(numLeds2, dataPin2, NEO_GRB + NEO_KHZ800);

const int numberOfChannelsTot = numberOfChannels0 + numberOfChannels1 + numberOfChannels2;

// Artnet settings
ArtnetWifi artnet;
const int startUniverse = 1; // CHANGE FOR YOUR SETUP most software this is 1, some software send out artnet first universe as 0.

// Check if we got all universes
const int maxUniverses = numberOfChannelsTot / 512 + ((numberOfChannelsTot % 512) ? 1 : 0);
bool universesReceived[maxUniverses];
bool sendFrame = 1;
int previousDataLength = 0;

// connect to wifi – returns true if successful or false if not
boolean ConnectWifi(void)
{
  boolean state = true;
  int i = 0;
  
  WiFi.config(ip, gateway, subnet, DNS);
  WiFi.begin(ssid, password);
  Serial.println("");
  Serial.println("Connecting to WiFi");
  
  // Wait for connection
  Serial.print("Connecting");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
    if (i > 20){
      state = false;
      break;
    }
    i++;
  }
  if (state){
    Serial.println("");
    Serial.print("Connected to ");
    Serial.println(ssid);
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());
  } else {
    Serial.println("");
    Serial.println("Connection failed.");
  }
  
  return state;
}

void initTest0()
{
  for (int i = 0 ; i < numLeds0 ; i++)
    leds0.setPixelColor(i, 127, 0, 0);
  leds0.show();
  delay(500);
  for (int i = 0 ; i < numLeds0 ; i++)
    leds0.setPixelColor(i, 0, 127, 0);
  leds0.show();
  delay(500);
  for (int i = 0 ; i < numLeds0 ; i++)
    leds0.setPixelColor(i, 0, 0, 127);
  leds0.show();
  delay(500);
  for (int i = 0 ; i < numLeds0 ; i++)
    leds0.setPixelColor(i, 0, 0, 0);
  leds0.show();
}
void initTest1()
{
    for (int b = 0 ; b < numLeds1 ; b++)
    leds1.setPixelColor(b, 127, 0, 0);
  leds1.show();
  delay(500);
  for (int b = 0 ; b < numLeds1 ; b++)
    leds1.setPixelColor(b, 0, 127, 0);
  leds1.show();
  delay(500);
  for (int b = 0 ; b < numLeds1 ; b++)
    leds1.setPixelColor(b, 0, 0, 127);
  leds1.show();
  delay(500);
  for (int b = 0 ; b < numLeds1 ; b++)
    leds1.setPixelColor(b, 0, 0, 0);
  leds1.show();
}
void initTest2()
{
    for (int c = 0 ; c < numLeds2 ; c++)
    leds2.setPixelColor(c, 127, 0, 0);
  leds2.show();
  delay(500);
  for (int c = 0 ; c < numLeds2 ; c++)
    leds2.setPixelColor(c, 0, 127, 0);
  leds2.show();
  delay(500);
  for (int c = 0 ; c < numLeds2 ; c++)
    leds2.setPixelColor(c, 0, 0, 127);
  leds2.show();
  delay(500);
  for (int c = 0 ; c < numLeds2 ; c++)
    leds2.setPixelColor(c, 0, 0, 0);
  leds2.show();
}

void onDmxFrame(uint16_t universe, uint16_t length, uint8_t sequence, uint8_t* data)
{
  sendFrame = 1;
//   set brightness of the whole strip 
  if (universe == 15)
  {
    leds0.setBrightness(data[0]);
    leds0.show();
    leds1.setBrightness(data[0]);
    leds1.show();
    leds2.setBrightness(data[0]);
    leds2.show();
  }

  // Store which universe has got in
  if ((universe - startUniverse) < maxUniverses)
    universesReceived[universe - startUniverse] = 1;

  for (int i = 0 ; i < maxUniverses ; i++)
  {
    if (universesReceived[i] == 0)
    {
      //Serial.println("Broke");
      sendFrame = 0;
      break;
    }
  }

  if (universe == 1) {
   for (int i = 0; i < length / 3; i++)
    {
      int led = i;
      if (led < leds0.numPixels())
        leds0.setPixelColor(led, data[i * 3], data[i * 3 + 1], data[i * 3 + 2]);
      }
    }
    leds0.show();

  if (universe == 2) {
    for (int i = 0; i < length / 3; i++)
    {
      int led = i;
      if (led < leds1.numPixels())
        leds1.setPixelColor(led, data[i * 3], data[i * 3 + 1], data[i * 3 + 2]);
      }
    }
    leds1.show();

  if (universe == 3) {
    for (int i = 0; i < length / 3; i++)
    {
      int led = i;
      if (led < leds2.numPixels())
        leds2.setPixelColor(led, data[i * 3], data[i * 3 + 1], data[i * 3 + 2]);
      }
    }
    leds2.show();
 
  if (sendFrame)
  {
    
    memset(universesReceived, 0, maxUniverses);
  }
}

void setup()
{
  Serial.begin(115200);
  ConnectWifi();
  artnet.begin();
  leds0.begin();
  leds1.begin();
  leds2.begin();
  initTest0();
  initTest1();
  initTest2();

  // this will be called for each packet received
  artnet.setArtDmxCallback(onDmxFrame);
}

void loop()
{
  // we call the read function inside the loop
  artnet.read();
}

@rstephan
Copy link
Owner

@Carransynth
As always, check your power supply. Sudden resets are most likely a power issue. If possible use a separate supply for the ESP and a very big one for the LEDs.

@erod998
Copy link
Author

erod998 commented Nov 14, 2018

I will try that soon with mine. I have a 20 amp power supply that also powers the Node so that could be a possibility, especially given how 450 neopixels at 60 amps is 27 amps. Granted, I am no way pulling that much as my effects through Artnet are more often off than on, and when they are on its never white. I will update soon.

@dreetie
Copy link

dreetie commented Jan 25, 2019

Hi, I'm trying out your FastLed example with a 5m ws2812 strip containing 300 leds. All goes fine when I stay within the limit of 1 universe but using the whole length of my strip (and as result multiple universes) nothing happens. When I look at the example code their are two parts:

for (int i = 0 ; i < maxUniverses ; i++) { if (universesReceived[i] == 0) { //Serial.println("Broke"); sendFrame = 0; break; } }

and

if (sendFrame) { FastLED.show(); // Reset universeReceived to 0 memset(universesReceived, 0, maxUniverses); }

It very plausible that I'm interpreting the code wrongly (I'm nowhere near being a programmer) but as I understand it, if you have 2 universes, the first piece of code will always set SendFrame to 0 and as a result FastLED.show() will never be triggered in the second piece. Or am I missing something ?

@rstephan
Copy link
Owner

rstephan commented Feb 8, 2019

@dreetie
The idea behind that pice of code is like this: your have to send all universes, and only if all are received (order don't mater) the output FastLED.show(); will be triggert. This way the output of the strip will be in sync and smooth. Otherwise the strip will be updated in parts of 170 LEDs. With "only" 300 LEDs this is maybe not a big deal.

Small example with 2 parts:
part1, part2 -> show()
part2, part1 -> show()
part1, part1, ... -> nothing
part2, part2, ... -> nothing

I hope this behavior is clear now. If you don't like/need it, change it.

@dreetie
Copy link

dreetie commented Feb 11, 2019

@rstephan Yep the behaviour is clear now, thx. It was due to an error in my setup that I became confused. I use QLC+ as light controller and forgot to enable the second universe in qlc+ while correctly setting the number of leds in my sketch to 300. So because not all universes where sending, no leds lit up. My apologies you had to take the time for my error and many thanks for sharing your library.

@BinTechLLC
Copy link

This is the closest thing I could find to the issue I am having. I have multiple ESP32 chips that I have been using for NeoPixel and work fine. My issue now is I made another one that just controls a relay and is a single channel, if > 200 on, else off. The issue I am having is this new node is reading universe 0 and 1 as universe 1 and is not distinguishing between the 2. The ring lights are working fine and read the universe number properly but this one wont. There are no differenced in my code other than I removed the NeoPixel stuff and just added logic for a relay. Was there an update to the lib that makes this break or something? This is the only node out of 10 I have built that id doing this. Any help would be great.

@rstephan
Copy link
Owner

rstephan commented Jan 9, 2023

@BinTechLLC
For the next time, it's not a problem to open a new ticket.
Your problem, your github-issue.

Maybe your transmitter is doing more than you expect?
Have you tried my ArtnetWifiDebug example?
What is the output for your universe 0 and 1 data?

Is the code looking like this?

void onDmxFrame(uint16_t universe, uint16_t length, uint8_t sequence, uint8_t* data)
{
  if (universe == 0) {
    if (length >= 1) {
      digitalWrite(PIN_RELAY, data[0] > 200 ? HIGH : LOW);
    }
  }
}

I expect your response in a newly created ticket. Thanks.

@Shotario
Copy link

hey guys. I`m using Resolume to play with Led stirps ws2812. can anyone send me a working code example. I can do only one pin

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests