Mittwoch, 31. August 2022

Tool Lagerverwaltung (Teil 3) Noch eine Wiki anlegen

Diesmal ein kurzer Post zur Vollständigkeit für die weitere Entwicklung. Nun braucht die Anwendung selbst eine eigene Wiki. Anders als bei dem Application Framework, wird die Funktionsweise und Benutzung beschrieben.

 

Benötigt

GitHub

 

Begin mit dem Benutzerhandbuch

Jede erstellte Seite soll eine Beschreibung und mindestens eine Skizze haben. Die Beschreibungen sind zunächst als Grundlage, was die Anwendung alles haben und wie sie funktionieren soll. Hier gehören keine Technischen Hintergründe, denn diese gehören entweder im Code als Kommentar oder im Ticket.

 

Am Anfang ein Konzept

Bevor die Anwendung geschrieben wird, soll mit dem Konzepthandbuch die Nutzeranforderungen ermittelt werden. Wenn später die Inhalte fertig sind, können nach und nach die Konzeptbeschreibung zur Benutzerbeschreibung umgestellt werden.

Nun könnte man sagen, dass Konzept kann man sich sparen und man erstelle die Dokumentation, wenn die Anwendung fertig ist. Wenn eine Planung vorliegt, dann ist das Ziel bekannt. Darauf los zu programmieren, führt eher dazu, dass man sein Ziel vergisst.

Die Konzeptbeschreibung ist auch die Möglichkeit die Nutzeranforderung zu spezifizieren und somit im weiteren daraus die Technischen Anforderungen zu formulieren.

Eigentlich eine einfache Sache und dennoch glauben viele, dass man diesen Schritt sich sparen kann. Doch sparen bedeutet am Ende mehr versteckter Zeitaufwand.

 

Wieder mal das GitHub Wiki

Diesmal wird keine Anleitung hinterlegt, wie die Einzelnen Steuerelemente verwendet werden. Wie bereits im vorigen Absatz, werden soll Beschreibungen angelegt. Damit Bildet sich dann Praktisch eine Vorläufige grobe Anforderung, die verfeinert werden kann.

 

Die Inhaltsangabe dient hier zunächst als grobe Richtung. (Im ersten Teil, ist das Beispiel wie das Menü im Edit aussieht)

 * Was kann die Anwendung  
 * Einleitung  
     * Hintergrund  
 * Start Seite  
     * Grundrahmen  
     * Übersichtsliste  
     * Suche  
 * Vorlage Einstellen  
     * Basisfelder  
     * Optionale Felder  
 * Neue Sache  
     * Vorlage verwenden  
     * Eigene Vorlage verwenden  
 * Sache bearbeiten  
     * Optionale Felder hinzufügen  
 * Sache archivieren  
     * Sache wiederherstellen  

Inhalt füllen

Im Ersten Teil habe ich bereits beschrieben, was man bereits mit dem Wiki erzeugen kann und deshalb geht es hier einen Schritt weiter voran mit dem erzeugen der Seite für die 'Start Seite' der Anwendung. Auf der neuen Seite, kommt zu der Textform auch Bilder. Mit diesen wenigen Details, lassen sich im Anschluss bereits die ersten Technischen Anforderungen ableiten.

 

 

Bisher noch nicht erwähnt, hatte ich das Tool Pencil. Neben Ablauf Diagrammen, können Skizzenhaft die Programmoberfläche Gestaltet werden.

 

Nächster Ansatz

Damit ist der nächste Ansatz getan. Aber bevor ich mit den weiteren Teilen der Anwendung weiter schreibe, geht es mit einer Technische Komponente weiter.

 

Übersicht

Teil 1 - Wiki anlegen in GitHub

Teil 2 - Neue Solution

Teil 3 - Noch eine Wiki anlegen

Teil 4 - Datenbank und Schnittstelle

Teil 5 - Konzept ausschreiben

Teil 6 - Umzug nach .NET MAUI

Montag, 22. August 2022

Tool Lagerverwaltung (Teil 2) Neue Solution


Welche Architektur oder welche Form soll das Projekt haben. Am liebsten setze ich auf die Drei-Schichten-Architektur. Klinkt abstrakt und hochtrabend, aber kompliziert ist die Sache nicht. Sich dran halten ist anfangs schwierig. Vorzugsweise setze ich auf Desktop Anwendung.

Benötigt

  • Visual Studio 2022 oder anderen Compiler
  • .NET 6.0
  • Codexzier's Application Framework
  • GitHub

 

Ziel für diesen Blog-Eintrag

Eine neue Solution und die benötigten Projekte einrichten mit dem Ansatz der Drei-Schichten Architektur..

 

Drei-Schichten

Wenn ich Rückblicke, in welchen Formen ein Drei-Schichten Modell aussieht, dann waren diese immer unterschiedlich gestaltet und hielten dennoch erkennbar Drei Schichten. Grundlegen haben wir das Frontend oder auch Benutzeroberfläche genannt, dann die Service-Schicht in der die Daten verarbeitet werden und als drittes die Datenhaltung in einer Datenbank.

 

Solution anlegen

Aber bevor das Projekt angelegt wird, soll eine leere Solution erstellt werden. Idealerweise gibt ihr in die Suche 'Blank' ein.

Nach der Auswahl kommen wir zur Eingabe des Solution Name und das Festlegen des Speicherortes.


Git Repository

Bevor das WPF Projekt Eingesetzt wird, gehört die Pflege der Sourcecodes in das Git System. Also fehlt der Klick auf den Button 'Create Git Repository…'.

Falls die Anmeldung von GitHub noch nicht geschehen ist, dann wird dies jetzt gefordert. In meinem Fall ist das Projekt öffentlich, weshalb der Haken für 'Private repository' raus ist.

Ist das Repository erstellt, dann sollte der aktuelle Stand bereits Online in eurem GitHub Repositories zu finde sein.

 

Einrichten der Projekte

Als erstes kommt das WPF Projekt, das die Frontend Schicht abbildet. Hier verwende ich das Projekt Template, dass bereits die Referenzen zu meinem Application Framework enthält.

Im folgenden kommen zwei Möglichkeiten, um das Template in Visual Studio 2022 einzubinden.

 

Option 1

Die Zip-Datei Codexzier Application Framework Vorlage Augsut 2022 in den Ordner ../Visual Studio 2022/Templates/ProjectTemplates einfügen (zum Download)

 

Option 2

Das Codexzier Application Framework von meinem GitHub Repository herunterladen und in Visual Studio öffnen. Dann oben auf Projekt

Dann das Projekt Template 'Codexzier.Wpf.ApplicationTemplate' auswählen..

..und im nächsten Schritt einen Namen vergeben.

Wählt nun die Solution aus und fügt diesem ein neues Projekt zu.

Das WPF Vorlagen Projekt kann bei Bedarf über die Suche gefunden werden.

Für die Benutzer Oberfläche, solltet ihr für den Namensraum den Bereich Namentlich erkenntlich Beschreiben.


Service Schicht

Das nächste Projekt soll alle Service Komponenten enthalten, die nichts mit der Benutzer Oberfläche zu tun haben. Obwohl ich von Service Schicht gesprochen habe, wird eine einfachen Klassen Bibliothek angelegt. Hier darauf achten, dass ihr die Vorlage für das aktuelle .NET Framework verwendet.

Und wieder einen passen Namen vergeben für die Service Komponenten Schicht.

Im nächsten Schritt muss noch die .NET Version angegeben werden und dann kann das Projekt erstellt werden.


Ein Projekt noch

Eins fehlt noch und zwar das für die Automatischen Tests. Für die UI kann eigentlich auch ein Test Projekt angelegt werden, aber aktuell reicht ein Unit Test Projekt für die Service Komponenten Schicht.

Der Namespace bekommt den Zusatz 'Test'. Damit sollte das Unit Test Projekt direkt unter dem zu testenden Projekt sein.

Zum Schluss wieder die .NET Version auswählen und erstellen.


Initialen Stand sichern

Hier braucht der Text schlichtweg aussagen, dass grundlegend die Projekte angelegt wurden.


Grundlage für das gesamt Projekt

Der zweite Schritt ist erledigt. Eine neue Solution mit den Grundlegenden Projekten ist angelegt. Die Inhalte habe ich nicht zu stark unterteilt, schließlich handelt es sich hier um ein sehr kleines Privat Projekt. Im nächsten Schritt geht’s dann mit dem Konzept und Funktionsumfang weiter.


Übersicht

Dienstag, 2. August 2022

Tool Lagerverwaltung (Teil 1) Wiki anlegen in GitHub

Für das Tool soll das eigene Framework verwendet werden, dass ich in den letzten Jahren immer weiter ausgebaut hatte. Jedoch ist noch offen, eine Dokumentation anzulegen, die den Funktionsumfang sowie Verwendung des Applikation Framework zeigt.

 

Benötigt

  • Visual Studio 2022 oder anderen Compiler
  • .NET 6.0
  • Codexzier's Application Framework
  • GitHub

 

Was ist mein Ziel?

Primär soll ein einfaches Tool entwickelt werden, dass zur Lagerverwaltung verwendet werden kann. Mit der der Entwicklung möchte ich beschreiben, welche Vorgehensweisen und Lösungen ich verwende. Zudem soll zu jeder Funktion aus dem Applikation Framework dokumentiert werden, das ich für den aktuellen Schritt verwendet wird.

 

Neben Produkt

Immer wenn ich eine neue Anwendung geschrieben habe, benötigte ich Grundlegende Inhalte für eine WPF Anwendung mit bestimmten Funktionen die ich selbst mal geschrieben habe. Und weil ich meine Anwendung auch ein Bestimmtes Aussehen haben sollen, habe ich auch die Styles immer mit kopiert. Damit ergaben sich Vorteile aber auch Nachteile.

 

Vorteile

  • Auf den Bisherigen Lösungen etwas Besseres oder neues entwickeln
  • Übung, Übung, Übung

Nachteil

  • Pflege älterer Anwendung erschwert
  • Doppelte Arbeit

 

Ok, gehen wir von der selbst Erklärung rüber zum ersten Schritt.

 

Henne-Ei-Problem

Fange ich mit der Dokumentation an, was funktionieren soll oder fange ich mit dem Programmieren an und dokumentiere? Die Frage, ob man mit der Dokumentation anfängt, ist davon abhängig, um was für eine Dokumentation angelegt werden soll. Bevor etwas entsteht, kann im Grunde nur ein Konzept- oder ein Grundbeschreibungen zu einer Anwendung angelegt werden.

In meinem Fall liegt der Programmcode vor und die Dokumentationsbeschreibung fehlt. Also wie in vielen Projekten.

 

GitHub Wiki

Die Sourcen zu dem Applikation Framework von mir habe ich bereits auf GitHub hochgeladen und dort kann zusätzlich ein Wiki gepflegt werden. Und damit soll's neben dem Hauptprojekt beginnen.

 

Als erstes hilft eine Grobe Inhaltsangabe anzulegen, so dass eine Grundlage vorliegt, an der man sich orientieren kann.

 Home  
 Lizenz  
 Grundlagen  
      Vorlage  
      Neues Projekt einrichten  
      Grundaufbau  
      Weiter Einstellungen  
 Components  
      Event Bus Manager  
      User Settings  
      Animation Helper  
 Styles  
      Blue Gray  
      White Gray  
      Gray White  
 Steuerelemente  
      Button  
      Diagram  
      Folder Browser  
 Game Tree 

So sieht der Text in der Bearbeitung aus in der GitHub Wiki (Zuvor hatte ich am Ende jedem Eintrag immer Page stehen gehabt, leider ist das dann auch der Name der Seite und habe das deshalb abgeändert)

 * [[Lizenz|Lizenz]]  
 * [[Grundlagen|Grundlagen]]  
 > - [[Vorlage|Grundlagen - Vorlage]]  
 > - [[Neues Projekt einrichten|Grundlagen - Neues Projekt einrichten]]  
 > - [[Grundaufbau|Grundlagen Grundaufbau]]  
 > - [[Weiter Einstellungen|Grundlagen - Weitre Einstellungen]]  
 - [[Components|Components]]  
 > - [[Event Bus Manager|Components - Event Bus Manager]]  
 > - [[User Settings|Components - User Settings]]  
 > - [[Animation Helper|Components - Animation Helper]]  
 * [[Styles|Styles]]  
 > - [[Blue Gray|Styles - Blue Gray]]  
 > - [[White Gray|Styles - White Gray]]  
 > - [[Gray White|Styles - Gray White]]  
 * [[Steuerelemente|Steuerelemente]]  
 > - [[Button|Steuerelemente - Button]]  
 > - [[Diagram|Steuerelemente - Diagram]]  
 > - [[Folder Browser|Steuerelemente - Folder Browser]]  
 > - [[Game Tree|Steuerelemente - Game Tree]]  

Und so sieht's dann nach dem Speichern aus.



Gefärbter Text
Im Bild ist zu sehen, dass nur der Text 'Lizenz' in blauer schrift hinterlegt ist. Wenn du suggestiv einen Link vermutest, dann liegst du richtig. Für die Seite Lizenz, habe ich bereits eine Seite angelegt. Alle die noch rot eingefärbten sind, müssen noch erstellt werden. Wenn man auf eines der rot gefärbten Text klickt, kommt statt einem Fehler eine Bearbeitungsmaske, um diese Seite zu erstellen.


 

Grundlage

Der erste Schritt ist damit getan. Nun muss man nur dranbleiben und hin und wieder schauen, ob die Struktur weiterhin passt.


Links

https://docs.github.com/en/communities/documenting-your-project-with-wikis/editing-wiki-content

 

Montag, 18. Juli 2022

AdSense Werbung funktioniert nicht

In den letzten zwei Monaten wurde auf meinem Blog keine Werbung angezeigt. Das war nicht schlimm, da die Einnahme wirklich sehr gering sind und ich mich schon freue, wenn wenigstens 50 Cent im Monat eingehen.

Zunächst dachte ich, das mit der Umstellung, die Formate der AdSense Werbe Banner neu eingestellt werden müssen und das man einen Tag warten muss, bis die Änderung sichtbar wären. Mein Gedanken Gang führte dazu, dass ich später nicht mehr daran gedacht hatte und erst im Urlaub mich dem Problem annahm. 

 

Dienste

  • Blog von blogger.com
  • Google AdSense

 

Ursache des Problems

Mit den Änderungen des Layouts, wurde im Anschluss, auf meinem Blog anschließend keine Werbung angezeigt. Nur in der Vorschau eines Blog-Eintrages wurden die Werbebanner angezeigt.

 

Lösung

Im Menü zum Blog, im Bereich Einnahmen muss die Verknüpfung entfernt und neu verknüpft werden.


Button Adsense entfernen klicken

Nach dem Entfernen sollten sich die Optionen auf der Seite Einnahmen sich verändern und der Button AdSense Verknüpfen sichtbar werden. Nach dem Click ist die neu Verknüpfung abgeschlossen und die Werbung wieder funktionieren.

 

Warum eigentlich

Eigentlich bringt die Menge an Werbung auf meinem Blog keinen Finanziellen Gewinn. In vielen Monaten hatte ich oft Einnahmen unter 10 Cent und da liegt der Gedanke nahe, dass gleich zu lassen.

Aber mich interessiert die Funktion und Verwendung von AdSense. Hier beobachte ich gerne, wie z.B. nach einem Blog-Eintrag in Abhängigkeit mit einem aktuellen Thema, sich die Einnahmen verändern. Das brachte mich auf die Idee, die Beobachtung aufzuschreiben.

 

Sonntag, 15. Mai 2022

Windows 11 und langsame VirtualBox


Im Wandel von Updates kommt mit der Zeit auch ein neues Windows. Und leider funktioniert nicht immer alles. Sehen wir davon ab, das VirtualBox weitgehend Kostenlos ist und deshalb nicht gewährleistet wird, dass alle Umstände funktionieren oder unterstützt werden.

 

Verwendet

  • Windows 11 (oder Windows 10)
  • VirtualBox
  • Virtualisiertes System mit Windows 2000 Professional

 

Problem Beschreibung

Nach einem größeren Update oder mit dem Wechsel von Windows 10 auf Windows 11, kann das Ausführen von Virtuell Box sehr langsam werden. Man kann praktisch sehen wie Pixel für Pixel das Bild aufgebaut wird.

 

Ursache

Nun im Grunde kenne ich nicht die eigentliche Technische Ursache, warum ein eingeschaltetes Feature in Windows 11 für Virtuelle Maschinen Probleme erzeugt. Vielleicht hilft diese Beschreibung, die ich in den Weiten des Internets gefunden habe. (https://www.pctipp.ch/praxis/virtualisierung/quaelend-langsame-virtualbox-unter-windows-11-2742835.html?page=1_abhilfe-hyper-v-sandbox-nbsp---weg-damit)

 

Lösung des Problems in Windows 10

Drücke auf die Windows Taste und gebe 'Windows-Features aktivieren oder deaktivieren' ein

 

Dann deinstalliert ihr die Features durch das Entfernen der gesetzten Hakens.

  • Hyper-V
  • Windows-Hypervisor-Plattform
  • Windows Sandbox

 

Anschließend Ok und das Betriebssystem neu starten.

 

Lösung des Problems in Windows 11

Im Grunde das gleiche. Nur halt mit runden Ecken. 

An einem anderem System konnte ich feststellen, dass nicht zwingen alle Punkte aufgeführt sein müssen. Denn je nach Hardware Unterstützung werden auch nur die Optionen wieder gegeben, die auch wirklich unterstützt werden.


Montag, 9. Mai 2022

Karosseriebeleuchtung mit PCA9685 (Zusatz)

Eine Sache ist noch offen: Bei meinem vorigen Blogpost konnte man in den Videos sehen, dass die LEDs beim Fade-OUT nie ganz aus waren.

Benötigt werden:

  • Arduino
  • PWM Modul PCA9685
  • LEDs und Widerstände

Ziel

Die LEDs sollen im Fade-OUT komplett ausgehen. Asynchrone Animationsabläufe.


Ursache

Es lag daran, dass der Wert nie den Endwert von 4095 erreicht hat. Auch, wenn das High Level nur sehr kurz anliegt, reicht die Spannungsversorgung aus, um einen LED noch glimmen zu lassen.

Daher liegt die Lösung nahe, dass am Ende eines Schleifendurchgang nochmal ein Signal-Zustand festgelegt wird, mit dem genannten Endwert. Jedoch soll das für die asynchronen Vorgänge auch funktionieren. Hier nochmal das Beispiel, in denen die LEDs nicht ganz aus sind.

 #include <Wire.h>  
 #include <Adafruit_PWMServoDriver.h>  
 Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();  
 void setup() {  
  pwm.begin();  
  pwm.setPWMFreq(1600);  
  Wire.setClock(400000);  
 }  
 void loop() {  
  int stepAdd = 10;  
  int leds = 4;  

  for (uint16_t i=0; i<4096; i += stepAdd) {  
   for (uint8_t pwmnum=0; pwmnum < leds; pwmnum++) {  
    pwm.setPWM(pwmnum, 0, 4096 - i);  
   }  
  }  
  delay(1000);  
  for (uint16_t i=0; i<4096; i += stepAdd) {  
   for (uint8_t pwmnum=0; pwmnum < leds; pwmnum++) {  
    pwm.setPWM(pwmnum, 0, i);  
   }  
  }  
  delay(2000);  
 }  

Einfache Lösung

Mit der bekannten Schrittweite kann nach dem Schleifendurchlauf bedingt die PWM Ports auf den Max Wert eingestellt werden.

 #include <Wire.h>  
 #include <Adafruit_PWMServoDriver.h>  
 Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();  
 void setup() {  
  pwm.begin();  
  pwm.setPWMFreq(1600);  
  Wire.setClock(400000);  
 }  
 void loop() {  
  int stepAdd = 10;  
  int leds = 4;  

  for (uint16_t i=0; i<4096; i += stepAdd) {  
   for (uint8_t pwmnum=0; pwmnum < leds; pwmnum++) {  
    pwm.setPWM(pwmnum, 0, 4096 - i);  
   }  
  }  
  delay(1000);  
  uint16_t iSetValue = 0;  
  for (uint16_t i=0; i < 4096; i += stepAdd) {  
   for (uint8_t pwmnum=0; pwmnum < leds; pwmnum++) {  
    pwm.setPWM(pwmnum, 0, i);  
   }  
   iSetValue = i;  
  }  
  if(iSetValue > 4095 - stepAdd) {  
   for (uint8_t pwmnum=0; pwmnum < leds; pwmnum++) {  
    pwm.setPWM(pwmnum, 0, 4095);  
   }  
  }  
  delay(2000);  
 }  

Lösung für asynchrone Vorgänge

Das gleiche kann auch für den asynchronen Vorgang verwendet werden. Jedoch hat die bisherige Lösung einen Nachteil: Dass sie schnell unübersichtlich wird. 

Die Beispiele habe ich oft nur mit zwei LEDs abgebildet, aber für 16 LEDs wird's schlecht leserlich.

Deshalb gehe ich hier mit der Beispiellösung einen Schritt weiter und lege ein Objekt an, in dem ich für die einzelne LED den Zustand hinterlegen kann.

 #include <Wire.h>  
 #include <Adafruit_PWMServoDriver.h>  
 Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();  
 unsigned long mCurrentMillis = 0;  
 void setup() {  
  pwm.begin();  
  pwm.setPWMFreq(1600);  
  Wire.setClock(400000);  
  // schaltet alle aus  
  for (uint8_t pwmnum=0; pwmnum < 16; pwmnum++) {  
    pwm.setPWM(pwmnum, 0, 4095);  
  }  
 }  
 // status objekt für eine LED  
 typedef struct {  
   unsigned long LastMillis;      // letzte Zeitstand  
   unsigned long DistanceFromNowToLast;// Intervall länge  
   uint16_t Value;           // aktuell verwendeter Wert  
   bool IsFlashing;          // soll nur an und aus  
   bool IsGoingOn;           // Schritt soll heller   
                     // oder an sein  
 } ledStateType;  
 // Konfiguration einzelner LEDs  
 ledStateType mLEDs[] = {  
  { 0, 5, 0, false, true },       // fade animation  
  { 0, 1000, 0, true, true }      // flashing  
 };  
 void PrepareLED(int ledIndex) {  
  int stepAdd = 10;  
  unsigned long rest = mCurrentMillis - mLEDs[ledIndex].LastMillis;  
  if(rest < mLEDs[ledIndex].DistanceFromNowToLast) {  
   return;  
  }  
  if(mLEDs[ledIndex].IsFlashing) {  
   if(mLEDs[ledIndex].IsGoingOn) {  
    mLEDs[ledIndex].Value = 4095;  
    mLEDs[ledIndex].IsGoingOn = false;  
   }  
   else {  
    mLEDs[ledIndex].Value = 0;  
    mLEDs[ledIndex].IsGoingOn = true;  
   }  
  }  
  else {  
   if(mLEDs[ledIndex].IsGoingOn) {  
    if(mLEDs[ledIndex].Value > stepAdd) {  
     mLEDs[ledIndex].Value -= stepAdd;  
    }  
    else {  
     mLEDs[ledIndex].Value = 0;  
     mLEDs[ledIndex].IsGoingOn = false;  
    }  
   }  
   else {  
    if(mLEDs[ledIndex].Value < 4096) {  
     mLEDs[ledIndex].Value += stepAdd;  
    }  
    if(mLEDs[ledIndex].Value > 4095 - stepAdd) {  
     mLEDs[ledIndex].Value = 4095;  
     mLEDs[ledIndex].IsGoingOn = true;  
    }  
   }  
  }  
  mLEDs[ledIndex].LastMillis = mCurrentMillis;  
 }  
 void loop() {  
  mCurrentMillis = millis();  
  for(int i = 0; i < 2; i++) {  
   PrepareLED(i);  
   pwm.setPWM(i, 0, mLEDs[i].Value);  
  }  
 }  



Natürlich ist das nur eine Möglichkeit, wie der Programmablauf aussehen könnte. Der geübte C++ Programmierer würde das sicherlich anders lösen können.



Vorheriger Blog Post:

Sonntag, 24. April 2022

Karosseriebeleuchtung mit PCA9685


Ein Teil des Ausbaus meines FPV Crawler bestand darin, die LEDs zu montieren und entsprechend mit Energie zu versorgen. Natürlich reichte nicht ein einfaches Anschließen an die Versorgungsspannung aus. Denn die LEDs sollten je nach ihrer Aufgabe eingeschaltet werden, was zunächst einfach klingt.
Vom Gedanken bis zur Umsetzung zeigte sich ein deutliche höherer Aufwand beim Verkabeln mehrere Leitungen und beim Programmieren des PWM Moduls, als gedacht.


Benötigt

  • Arduino
  • PWM Modul PCA9685
  • LEDs und Widerstände

 

Ziel

Standlicht, Fahrlicht, Blinker und Flutlichter sollten alle individull an-steuerbar sein. Hier sollen die Lichter immer durch ein Fade-Effekt abgebildet werden.

 

Initialisieren

Für die folgenden Beispiele verwendete ich immer die gleiche Initialisierung.
 #include <Wire.h>  
 #include <Adafruit_PWMServoDriver.h>  
 Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();  
 void setup() {  
  pwm.begin();  
  pwm.setPWMFreq(1600);  
  Wire.setClock(400000);  
  // schaltet alle aus  
  for (uint8_t pwmnum=0; pwmnum < 16; pwmnum++) {  
    pwm.setPWM(pwmnum, 0, 4095);  
  }  
 }  


Fade-In und Fade-Out

Leider kann man nicht einfach einen Wert von 0 bis 256 in den Controller eingeben, um Animationsverläufe darin abzubilden. Wenn man versucht auf diese Weise die LEDs anzusteuern, dann funktioniert das schlecht oder gar nicht. Zum Glück ist bereits ein Beispiel Code in den Sourcen für das PCA9685 Modul integriert, dass genau diese Funktion darstellt.


Mit dem Adafruit Beispiel  'pwmtest' wird gezeigt, wie das Zuweisen um-gesetzt wird. Dort sieht man, dass nicht immer plus eins, sondern immer plus acht addiert wird. Das ist sicherlich auf die 12Bit pro Port zurück zu führen.

 
void loop() {  
  int stepAdd = 10;  
  int leds = 4;  
  for (uint16_t i=0; i<4096; i += stepAdd) {  
   for (uint8_t pwmnum=0; pwmnum < leds; pwmnum++) {  
    pwm.setPWM(pwmnum, 0, 4096 - i);  
   }  
  }  
  delay(1000);  
  for (uint16_t i=0; i<4096; i += stepAdd) {  
   for (uint8_t pwmnum=0; pwmnum < leds; pwmnum++) {  
    pwm.setPWM(pwmnum, 0, i);  
   }  
  }  
  delay(1000);  
 }


Asynchroner Ablauf

Für mein Ziel wird mehr als eine LED und neben dem Modul noch WS2812b RGB LEDs eingesetzt. Damit ich nicht für jede LED einen eigenen Controller benötige, muss ich sicherstellen, wie schnell etwas aus- oder eingeblendet werden soll.

 unsigned long mCurrentMillis;  
 unsigned long mLastMillis_LED_1;   
 unsigned long mLastMillis_LED_2;  
 uint16_t mValueLED_1 = 0;  
 uint16_t mValueLED_2 = 0;  
 void loop() {  
  uint16_t endValue = 4096;  
  int stepAdd = 10;  
  int leds = 4;  
  mCurrentMillis = millis();  
  if(mCurrentMillis - mLastMillis_LED_1 > 5) {  
   if(mValueLED_1 < endValue) {   
    mValueLED_1 += stepAdd;  
    pwm.setPWM(0, 0, mValueLED_1);  
   }  
   else {   
    mValueLED_1 = 0;  
   }  
   mLastMillis_LED_1 = mCurrentMillis;  
  }  
  if(mCurrentMillis - mLastMillis_LED_2 > 10) {  
   if(mValueLED_2 < endValue) {   
    mValueLED_2 += stepAdd;  
    pwm.setPWM(1, 0, mValueLED_2);  
   }  
   else {   
    mValueLED_2 = 0;   
   }   
   mLastMillis_LED_2 = mCurrentMillis;  
  }  
 }   


Blinker

Einfaches Ein- und Ausschalten ist nicht schwer zu programmieren. Mit einem schnelle Fade-In, Fade-Out war nur etwas ausprobieren nötig. Zuerst hatte ich das Problem. dass die LEDs nie ganz ausgingen, womit das Blinken selbst weniger deutlich zu sehen waren, wenn der Blinker betätigt wurde.
Im Grunde war das ein Denkfehler, weil ich die Schrittweite zum Fade-Out nicht berücksichtigt habe und, um eine Iteration zu früh den Vorgang verlassen habe.

 unsigned long mCurrentMillis;  
 unsigned long mLastMillis_LED_1;   
 unsigned long mLastMillis_LED_2;  
 uint16_t mValueLED_1 = 0;  
 bool mFlashingLED_2 = false;  
 void loop() {  
  uint16_t endValue = 4096;  
  int stepAdd = 10;  
  int leds = 4;  
  mCurrentMillis = millis();  
  if(mCurrentMillis - mLastMillis_LED_1 > 5) {  
   if(mValueLED_1 < endValue) {   
    mValueLED_1 += stepAdd;  
    pwm.setPWM(0, 0, mValueLED_1);  
   }  
   else {   
    mValueLED_1 = 0;  
   }  
   mLastMillis_LED_1 = mCurrentMillis;  
  }  
  if(mCurrentMillis - mLastMillis_LED_2 > 200) {  
   mFlashingLED_2 = !mFlashingLED_2;  
   if(mFlashingLED_2) {   
    pwm.setPWM(1, 0, 4095);  
   }  
   else {   
    pwm.setPWM(1, 0, 0);  
   }   
   mLastMillis_LED_2 = mCurrentMillis;  
  }  
 } 

 

Viel aus-probieren

Erst am Ende, wenn alles im Programmcode eingegeben ist, muss die Geschwindigkeit der Animationen eingestellt werden. Damit dies geht, sollte möglichst am Anfang diese Einstellungen zentral eingehalten werden, um das Nachjustieren zu beschleunigen.

Ameisen Simulation und andere Dinge

Wer lange sich schon mit C# beschäftig, hat sicherlich schon mal was von AntMe gelesen oder gehört. Diese Idee hatte ich aufgegriffen und mi...