Wie bekomme ich den Schreibschutz auf eigener Library weg?

Moin zusammen,

innerhalb meines Projekte möchte ich gerne Funktionen in eine Library verschieben (also nicht als .h/.cpp im gleichen Verzeichnis wie das *.ino), da ich dann die Funktionen Projektübergreifend verwenden kann. Das lästige synchronisieren entfällt dann.

Nun habe ich mir diese Anleitung einmal angeschaut LibraryTutorial, funktioniert auch soweit (also die Library wird korrekt verwendet), aber das ganze scheint bzgl. der Erstellung eine Einbahnstraße zu sein:

Wenn die Bibliothek angelegt ist (u.a Dateien in Ordner verschoben), dann ist der ganze Kram READ-ONLY. Ich kann nicht einmal die Beispieldatei verändern. Stattdessen die Meldung, es doch woanders abzuspeichern.
Das ist nun arg doof, wenn sich die Library im Zuge des Projektes weiterentwickelt.

Meine Frage daher: Wie bekomme ich es hin, dass die IDE es mir erlaubt, meine eigene Library zu verändern?

Die im Internet gefundene Lösung eine leere Datei .development dort abzulegen, half leider nicht weiter.

Nun noch die notwendigen Infos:

  • IDE 1.8.19, Windows 10
  • Speicherort Sketches (Einstellung in der IDE) : C:\Users\Sebastian_2\Documents\Projekte\Arduino
  • Speicherort Libraries: C:\Users\Sebastian_2\Documents\Projekte\Arduino\libraries

Dateien der Library:

  • Das example-File, abgelegt unter C:\Users\Sebastian_2\Documents\Projekte\Arduino\libraries\TableLightLibrary\examples\TableLightLibrary:
#include <Arduino.h>
#include <TableLightLibrary.h>

const byte numRowsHCL         = 9;
const int hclTable [][2]                // Column 1 is time with industrial minutes
                  {                     // Column 2 is ratio of available range
                    { 800,     0},      // ... with resolution of 0.0001 (=0.01%)
                    { 900,  2000},
                    {1000,  4000},
                    {1200,  8000},
                    {1350, 10000},
                    {1500,  8000},
                    {1700,  4000},
                    {1800,  2000},
                    {1900,     0}
                  };

void setup() {
  Serial.begin(57600);
}

void loop() {
  int  delayMS  = 0;
  int  tauMSFast, tauMSSlow;
  static boolean done = false;
  if (!done) {
    for (byte idx = 0; idx < 34; idx++) {
      delayMS = computeTimeDelay(idx);
      tauMSFast = delay2tau(delayMS, true);
      tauMSSlow = delay2tau(delayMS, false);
      Serial.print("Delay:\t");     Serial.print(delayMS);
      Serial.print("\ttau_Fast:\t"); Serial.print(tauMSFast);
      Serial.print("\ttau_Slow:\t"); Serial.println(tauMSSlow);
      delay(100);
    }
    for (int hh = 0; hh < 96; hh++) {
      int colorT =  getHCLValue( hclTable, numRowsHCL, 25*hh, 0, 0, 2500, 6500, 10000);
      Serial.print("Uhrzeit:\t");   Serial.print(25*hh);
      Serial.print("\tColorTemperature:\t"); Serial.println(colorT);                             
    }
    done = true;
  }
}
  • Das h-File
#ifndef TABLELIGHTLIBRARY_h
#define TABLELIGHTLIBRARY_h

#include <Arduino.h>

  int computeTimeDelay(byte cmdDelay);      // cmdDelay is an index into a nonlinear curve, out=delay in ms
  int delay2tau(int delayMS, boolean fast); // Converts delay given in ms into time constant of filter

// InterpolationTable for HCL-Curve with both time compression/expanding and color-compression
  int getHCLValue(int const tableHCL[][2], byte const rowsHCL, int time100, int tsDelta, int teDelta,
                  int colorTMinHCL, int colorTMaxHCL, int colorTMaxRange);
  // In:  table           Table holding characteristic curve for ColorT over Time.
  //                        Col 1: Time in industrial format, e.g. 875 = 8:45 or 1733 = 17:20
  //                        Col 2: Scale factor for Temperature Range, 0..1 -> 0..10000, so that
  //                             ColorT = minT for factor = 0, and ColorT = maxT for factor 1
  //      rowsHCL         Number of rows of HCL table
  //      time100         Daytime with industrial minutes, e.g. 15:30 -> 1550
  //      tsDelta         Desired shift lower bound in minutes (60min = 1h), 0..59 
  //      teDelta                       upper 
  //      colorTMinHCL    Range of colortemperature that shall occur during a day: Lowest
  //      colorTMaxHCL                                                             Hightest
  //      colorTMaxRange  Max Value the HCL Table has been normalized to. Min is taken as 0
  //
  // Out: colorT    color temperature in [K] in range [colorTMinHCL ... colorTMaxHCL]

#endif
  • das cpp-File
#include "TableLightLibrary.h"

int computeTimeDelay(byte cmdDelay) {
  // Assumption is a cmdDelay ranging from 0..34 (hard-coded!), which is mapped on 20ms ... 10s 
  // Hereby step-width from cmdDelay = i to cmdDelay = i+1 is nonlinear:
  //    500ms steps between   3s and 10s
  //    250ms steps between   1s and  3s
  //    100ms steps between 0.1s and  1s
  //    ... and 20ms and 50ms below 0.1s
  // Returns delay in ms
  int delayMS = 20;                                     // Default value = lowest delay for cmdDelay = 0
  if (cmdDelay == 1)       delayMS = 50;                // ... catch single value between linear segments
  else if (cmdDelay >= 19) delayMS = 3000 + (cmdDelay - 19)*500;  // Step downwards: delay is above 3s
  else if (cmdDelay >= 11) delayMS = 1000 + (cmdDelay - 11)*250;  //                                1s
  else if (cmdDelay >=  2) delayMS =  100 + (cmdDelay -  2)*100;  //                              0.1s
  return(delayMS);                                      // Value in milliseconds
}

int delay2tau(int delayMS, boolean fast) {              // Two Modi for tau-Calculation
  if (fast) return(delayMS / 6);                        // Fast: tau = Switchtime / 6
  else return(delayMS >> 2);                            // slow: tau = Switchtime / 4
}

int getHCLValue(int const tableHCL[][2], byte const rowsHCL, int time100,int tsDelta, int teDelta,
                int colorTMinHCL, int colorTMaxHCL, int colorTMaxRange) {
  // In:  table           Table holding characteristic curve for ColorT over Time.
  //                        Col 1: Time in industrial format, e.g. 875 = 8:45 or 1733 = 17:20
  //                        Col 2: Scale factor for Temperature Range, 0..1 -> 0..10000, so that
  //                             ColorT = minT for factor = 0, and ColorT = maxT for factor 1
  //      rowsHCL         Number of rows of HCL table
  //      time100         Daytime with industrial minutes, e.g. 15:30 -> 1550
  //      tsDelta         Desired shift lower bound in minutes (60min = 1h), 0..59 
  //      teDelta                       upper 
  //      colorTMinHCL    Range of colortemperature that shall occur during a day: Lowest
  //      colorTMaxHCL                                                             Hightest
  //      colorTMaxRange  Max Value the HCL Table has been normalized to. Min is taken as 0
  //
  // Out: colorT    color temperature in [K] in range [colorTMinHCL ... colorTMaxHCL]
  //
  // Requires about 200us on ATMega326P @16MHz
  int colorT;                                     // Return value, ColorTemperature
  long  fac = 0;                                  // Scaling factor ColorT range 0..1
  int    ts = tableHCL[0][0];                     // Start time of HCL Table
  int    te = tableHCL[rowsHCL-1][0];             // End   time
  int tsD100 = tsDelta * 100 / 60;                // tsDelta to industrial minutes
  int teD100 = teDelta * 100 / 60;                // teDelta
  int   abn = ts - te + (tsD100 - teD100);        // Numerator of both a and b formula
  double  a =  ((double)(ts-te))/((double)(abn)); // Time correction, t_cor = a*t+b
  double  b = (((double)(te) * (double)(tsD100)) - ((double)(ts) * (double)(teD100))) /((double)(abn)); 
  int timeShifted = (int)(a*(double)(time100) + b);  // correct time
  // Check for boundaries of HCL curve, otherwise interpolate
  if (timeShifted <= ts) {                        // Below lower bound?
    fac = (long)tableHCL[0][1];                   // --> use lower value for all times below ts
  }
  else if (timeShifted >= te) {                   // Above upper bound?
    fac = (long)tableHCL[rowsHCL-1][1];           // --> use upper highest for all times above te
  }
  else {                                          // --> interpolate!
    int upper_idx = 1;
    while (timeShifted > tableHCL[upper_idx][0]) {// Find approbirate slot for interpolation
      upper_idx++;
    }
    fac =   (long)(tableHCL[upper_idx - 1][1] +   // Scaling factor (0..1), res 0.0001
          (((long)(tableHCL[upper_idx][1] - tableHCL[upper_idx - 1][1])  *
            (long)(   timeShifted         - tableHCL[upper_idx - 1][0])) /
            (long)(tableHCL[upper_idx][0] - tableHCL[upper_idx - 1][0])));
  }                                               // Compressed Fac:
  colorT = colorTMinHCL + (int)((fac * (long)(colorTMaxHCL - colorTMinHCL)) / colorTMaxRange);
  colorT = max(colorTMinHCL, min(colorT, colorTMaxHCL));
  return( colorT );                               // And copy to output
}
  • das keywords.txt
#######################################
# Methods and Functions (KEYWORD2)
#######################################

computeTimeDelay	KEYWORD2
delay2tau		KEYWORD2
getHCLValue		KEYWORD2

Also, wie beschrieben, wenn ich das examples File öffne und speichern möchte, erscheint folgende Fehlermeldung:

Gleiches gilt die .h/.cpp Dateien. Daher Einbahnstrasse: Einmal dort abgespeichert, können sie nicht mehr bearbeitet werden ... und dann wieder den Kram rausholen ist ähnlich dämlich/umständlich, wie die Files in verschiedenen Software-Sketches zu kopieren.

Wie bekomme ich diesen Schreibschutz weg?

Hi combie

die .development-Datei liegt bereits dort (siehe Screenshot oben). Hilft/Half nur leider nicht ... Fehlt ggf. was anderes?
Ich steige auch ehrlich gesagt bei den Verzeichnisstrukturen nicht so recht durch. Mal gibt es /src, mal nicht. Dann heißt mal /utilities, oder es gibt /examples ... sind hier utilities und examples das gleiche? Rein von der Wortbedeutung würde ich das verneinen ...

Gruß

Ich bin nicht Blind.
Der von mir verlinkte Beitrag enthält noch mehr. Auch die Antwort zu deiner src Verzeichnis Frage.

Doch das hilft, um die Beispiele bearbeiten zu können.
Es ist allerdings ein Neustart der IDE erforderlich, damit sie das bemerkt.

Das freut mich zu hören.

Habe ich mir angeschaut. Und, naja, wie oben geschrieben, nicht wirklich alles verstanden. Ja, es gibt viele Dateien, und viele Verzeichnisse, aber brauche ich wirklich alles? Was ist die Minimalausstattung für den Heimgebrauch (also nix GitHub)? Bei jeder Datei oder Verzeichnis was ich nicht anlegen muss, kann ich auch nix falsch machen...

Ich schaue mir das später nochmals an ...

schreib mal was in die .development

kann mich nicht mehr erinnern, aber ich glaube als leere Datei gings bei mir auch nicht.

Verwende die moderne Form.
Dann kann sie auch mit PlatformIO und anderen IDEs verwendet werden.
Das erleichtert die Weitergabe/Wiederverwendung

Doch, sollte gehen.

Als Anhang mal eine Lib welche ich gerade bearbeite.

  • die .development Datei sorgt dafür, dass man die Beispiele bearbeiten kann
  • die src.ino im src Ordner macht einen src Menüpunkt bei den Beispielen und sorgt so dafür, dass man die dortigen *.h Dateien recht einfach bearbeiten kann

Um die anderen Dateien zu bearbeiten, z.B. KEYWORDS.txt, verwende ich andere Editoren. z.B. PSPad

CombieSmartPointer.zip (4,2 KB)
Diese Lib ist nicht fertig entwickelt.
Sie ist nur ein Beispiel. Quasi ein Minimalbeispiel.

Ok. Looft. Ein paar Infos dazu:

  • .development kann/darf leer sein
  • Es sieht so aus, dass die neue Möglichkeit der editierbaren Library (durch hinzufügen von .development) eine bestimmte Dateien-Struktur erfordert (in die #1 gezeigt jedenfalls funktionierte nicht). Also *.cpp und *.h in /src (siehe unten) abspeichern
  • Ich habe auch ein library.properties-file erzeugt. Gleichzeitig mit der anderen Verzeichnis-Struktur - insofern bleibe ich meiner eigenen Frage nach Minimalausstattung schuldig. Allerdings stand auch in Arduino-IDE-1.5:-Library-specification, dass die Datei da sein soll

Verzeichnisstruktur / Datei-Struktur

../libraries/TableLightLibrary
../libraries/TableLightLibrary/.development
../libraries/TableLightLibrary/keywords.txt
../libraries/TableLightLibrary/library.properties
../libraries/TableLightLibrary/src
../libraries/TableLightLibrary/src/src.ino 
../libraries/TableLightLibrary/src/TableLightLibrary.cpp
../libraries/TableLightLibrary/src/TableLightLibrary.h
../libraries/TableLightLibrary/examples
../libraries/TableLightLibrary/examples/TableLightLibrary/TableLightLibrary.ino
  • In src.ino kann irgendwas drin stehen, damit die gewünschten Library .cpp/.h geöffnet werden können
  • Bzgl TableLightLibrary.ino (als Beispiel) gilt, dass das Verzeichnis genauso heissen muss
  • In library.properties habe ich u.a. architectures=avr, megaavr eingetragen. Damit verschwindet die Warnung, wenn die Library fur den ATmega4809 (Nano Every) verwendet wird (also, macht natürlich nur Sinn, wenn auf AVR als auch MEGAAVR funktioniert); ich verwende neben dem Nano Every noch einen Uno.

Danke @combie für den Link und das Beispiel. Es hat geholfen.

Andere Variante - verwende einen anderen Editor (ich benutze Notepad++). Damit kannst Du auch ohne diese Struktur alle Libs editieren.

Gruß Tommy

Die Verzeichnisse oder die Dateien sind aber nicht durch Zufall von Windows schreibgeschützt?
Lacht nicht, es passieren manchmal die kuriosesten Sachen... Da sucht man ewig.

Gruß, Jürgen

Nee, war auch meine erste Vermutung. Hatte ich gecheckt.

Danke für den Tipp. Doch nun habe ich herausbekommen, und bleibe wohl dabei.

Hatte ich übersehen. Gut wenn es jetzt geht. Danke für die Beschreibung wie es aussehen muss damit es geht.

Gruß, Jürgen