rstephan / ArtnetWifi

Arduino library for Art-Net (artnet) over WiFi, send and receive DMX data. Runs on ESP8266, ESP32, Pi Pico W, WiFi101 and WiFiNINA devices.
Other
353 stars 59 forks source link

Const variables to Int variables #49

Closed Juanmi18 closed 1 year ago

Juanmi18 commented 1 year ago

Hello, first of all thank you very much for the library, it has served me perfectly so far.

I want to improve my project and add WifiManager (Tzapu). In addition to requesting the Wifi to which the arduino must connect, I want to request the startUniverse and the numLeds through custom fields.

It is giving me the problem that the variables:

numLeds numberOfChannels startUniverse maxUniverses

They are constants and I can't change them to int because universesReceived[maxUniverses]; it gives me the following error:

array bound is not an integer constant before ']' token

Can you think of how I could modify the library to be able to set those values ​​as variables and not as constants?

Thanks in advance

rstephan commented 1 year ago

Hi,

first of all, the universesReceived variable is part oy my example, not the library itself. What you are doing with this example is on your own. I use static allocation.

But you can rewrite it to use dynamic memory allocation:

bool universesReceived[maxUniverses];

Change the type and add initialization into setup() to something like this:

bool* universesReceived;
...
void setup() {
...
  // place before artnet.begin(); !!!!
  universesReceived = new bool[maxUniverses];
...
  artnet.begin();
}

NOT TESTED!! But should be fine.

Juanmi18 commented 1 year ago

Thanks!!!! Work perfect!!!

I have needed update the length of the led strip with the var of the json with this:

leds.updateLength(numLeds);

This is the final 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 <FS.h>                   //this needs to be first, or it all crashes and burns...
#if defined(ARDUINO_ARCH_ESP32)
#include <WiFi.h>
#else
#include <ESP8266WiFi.h>
#endif
#include <WiFiUdp.h>
#include <ArtnetWifi.h>
#include <Adafruit_NeoPixel.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>         //https://github.com/tzapu/WiFiManager
#ifdef ESP32
  #include <SPIFFS.h>
#endif
#include <ArduinoJson.h>          //https://github.com/bblanchon/ArduinoJson

//define your default values here, if there are different values in config.json, they are overwritten.
char numero_leds[3]= "50";
char numero_universo[2]= "2";

//flag for saving data
bool shouldSaveConfig = false;

//callback notifying us of the need to save config
void saveConfigCallback () {
  Serial.println("Should save config");
  shouldSaveConfig = true;
}

// Neopixel settings
int numLeds = 2; // change for your setup
int numberOfChannels = numLeds * 3; // Total number of channels you want to receive (1 led = 3 channels)
const byte dataPin = 4;
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
Adafruit_NeoPixel leds = Adafruit_NeoPixel(numLeds, dataPin, NEO_GRB + NEO_KHZ400);

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

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

void fs_wifi ()
{
   //clean FS, for testing
  //SPIFFS.format();

  //read configuration from FS json
  Serial.println("mounting FS...");

  if (SPIFFS.begin()) {
    Serial.println("mounted file system");
    if (SPIFFS.exists("/config.json")) {
      //file exists, reading and loading
      Serial.println("reading config file");
      File configFile = SPIFFS.open("/config.json", "r");
      if (configFile) {
        Serial.println("opened config file");
        size_t size = configFile.size();
        // Allocate a buffer to store contents of the file.
        std::unique_ptr<char[]> buf(new char[size]);

        configFile.readBytes(buf.get(), size);

 #if defined(ARDUINOJSON_VERSION_MAJOR) && ARDUINOJSON_VERSION_MAJOR >= 6
        DynamicJsonDocument json(1024);
        auto deserializeError = deserializeJson(json, buf.get());
        serializeJson(json, Serial);
        if ( ! deserializeError ) {
#else
        DynamicJsonBuffer jsonBuffer;
        JsonObject& json = jsonBuffer.parseObject(buf.get());
        json.printTo(Serial);
        if (json.success()) {
#endif
          Serial.println("\nparsed json");
          strcpy(numero_leds, json["numero_leds"]);
          strcpy(numero_universo, json["numero_universo"]);
        } else {
          Serial.println("failed to load json config");
        }
        configFile.close();
      }
    }
  } else {
    Serial.println("failed to mount FS");
  }
  //end read

  // The extra parameters to be configured (can be either global or just in the setup)
  // After connecting, parameter.getValue() will get you the configured value
  // id/name placeholder/prompt default length
  WiFiManagerParameter custom_numero_leds("leds", "numero leds", numero_leds, 3);
  WiFiManagerParameter custom_numero_universo("universo", "numero universo", numero_universo, 2);

  //WiFiManager
  //Local intialization. Once its business is done, there is no need to keep it around
  WiFiManager wifiManager;
  String stringNombreAp = "nodoArtnet-" + String(ESP.getChipId());
  char nombreAp[50];
  stringNombreAp.toCharArray(nombreAp,50);

  //set config save notify callback
  wifiManager.setSaveConfigCallback(saveConfigCallback);

  //add all your parameters here
  wifiManager.addParameter(&custom_numero_leds);
  wifiManager.addParameter(&custom_numero_universo);

  //reset settings - for testing
  //wifiManager.resetSettings();

  //set minimu quality of signal so it ignores AP's under that quality
  //defaults to 8%
  //wifiManager.setMinimumSignalQuality();

  //sets timeout until configuration portal gets turned off
  //useful to make it all retry or go to sleep
  //in seconds
  //wifiManager.setTimeout(120);

  //fetches ssid and pass and tries to connect
  //if it does not connect it starts an access point with the specified name
  //here  "AutoConnectAP"
  //and goes into a blocking loop awaiting configuration
  wifiManager.autoConnect(nombreAp);

  //if you get here you have connected to the WiFi
  Serial.println("apName");
  Serial.print("Connected to ");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  //read updated parameters
  strcpy(numero_leds, custom_numero_leds.getValue());
  strcpy(numero_universo, custom_numero_universo.getValue());

  Serial.println("The values in the file are: ");
  Serial.println("\tnumero_leds : " + String(numero_leds));
  Serial.println("\tnumero_universo : " + String(numero_universo));

  //save the custom parameters to FS
  if (shouldSaveConfig) {
    Serial.println("saving config");
 #if defined(ARDUINOJSON_VERSION_MAJOR) && ARDUINOJSON_VERSION_MAJOR >= 6
    DynamicJsonDocument json(1024);
#else
    DynamicJsonBuffer jsonBuffer;
    JsonObject& json = jsonBuffer.createObject();
#endif
    json["numero_leds"] = numero_leds;
    json["numero_universo"] = numero_universo;

    File configFile = SPIFFS.open("/config.json", "w");
    if (!configFile) {
      Serial.println("failed to open config file for writing");
    }

#if defined(ARDUINOJSON_VERSION_MAJOR) && ARDUINOJSON_VERSION_MAJOR >= 6
    serializeJson(json, Serial);
    serializeJson(json, configFile);
#else
    json.printTo(Serial);
    json.printTo(configFile);
#endif
    configFile.close();
    //end save
  }

  Serial.println("local ip");
  Serial.println(WiFi.localIP());

  //int n_leds = String(numero_leds).toInt();
  //int n_universo = String(numero_universo).toInt();

  //Serial.println("Los valores numéricos son: ");
  //Serial.print("\tnumero_leds : ");
  //Serial.println(n_leds);
  //Serial.print("\tnumero_universo : ");
  //Serial.println(n_universo); 
  //startUniverse = n_universo;
  //numLeds = n_leds;
}

void initTest()
{
  for (int i = 0 ; i < numLeds ; i++)
    leds.setPixelColor(i, 127, 0, 0);
  leds.show();
  delay(500);
  for (int i = 0 ; i < numLeds ; i++)
    leds.setPixelColor(i, 0, 127, 0);
  leds.show();
  delay(500);
  for (int i = 0 ; i < numLeds ; i++)
    leds.setPixelColor(i, 0, 0, 127);
  leds.show();
  delay(500);
  for (int i = 0 ; i < numLeds ; i++)
    leds.setPixelColor(i, 0, 0, 0);
  leds.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
  for (int i = 0; i < length / 3; i++)
  {
    int led = i + (universe - startUniverse) * (previousDataLength / 3);

    if (led < numLeds)
      leds.setPixelColor(led, data[i * 3], data[i * 3 + 1], data[i * 3 + 2]);
  }
  previousDataLength = length;     

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

void setup() {
  Serial.begin(115200);
  Serial.println();
  fs_wifi ();
  universesReceived = new bool[maxUniverses];
  int n_leds = String(numero_leds).toInt();
  int n_universo = String(numero_universo).toInt();

  startUniverse = n_universo;
  numLeds = n_leds;
  numberOfChannels = numLeds * 3; 

  Serial.print("numLeds: ");
  Serial.println(numLeds);
  Serial.print("dataPin: ");
  Serial.println(dataPin);

  leds.updateLength(numLeds);

  artnet.begin();

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

}

void loop() {
  // put your main code here, to run repeatedly:
  artnet.read();
}