Go Down

Topic: TLC5940 wildes blinken und Servo (Read 1 time) previous topic - next topic

summ

Kann mir, einem blutigen Anfänger, jemand einen Hinweis geben, warum in diesem Code die Leds ziemlich durcheinander blinken, nachdem ich den Modus per Tastatureingabe ändere? Ich wähle case 1, alles wunderbar, dann case 2 und schon blinken die 3 Leds im Array, wie sie wollen. Selbst wenn sie zunächst gleichmäßig auf und ab Faden ... irgendwann geraten sie durcheinander.
Und ich möchte mit dem Sketch auch einen Servo steuern. Der Servo-Teil funktioniert in einem eigenen Sketch zum Testen so, wie er soll. Nur hier tut sich einfach garnichts.

Code: [Select]

#include "Tlc5940.h"
#include "tlc_fades.h"
#include <Servo.h>
#define interval 500
int fadingMode = 0; //Beginn mit TLC Reset
int ledPins[] = {2,3,4};
int pinCount = sizeof(ledPins)/sizeof(int);
int max = 100;
unsigned char x;
unsigned long startTime = 0;
unsigned long waitUntil=0;
Servo myServo;
int grad = 0;


TLC_CHANNEL_TYPE channel;

void setup()   {               
   myServo.attach(5);
   Tlc.init();
   Serial.begin(115200);
}



void loop()
{   
  if(Serial.available()){
    if(Serial.peek() == 'l'){
      Serial.flush();
    }
    else{
      fadingMode = Serial.parseInt();
      Serial.print("Mode set to ");
      Serial.print(fadingMode);
      Serial.print(": ");
      startTime = millis();
      switch(fadingMode){
      case 0:
        Serial.println("allet uff Null");
        break;
      case 1:
        Serial.println("Flash");
        break;
      case 2:
        Serial.println("Slow Blinker");
        break;
      case 3:
        Serial.println("mover");
        break;
      }
    }
  }
  unsigned char brightness;
  switch(fadingMode){
  case 0:
    // TLC Resert, alles aus
    for (int thisPin = 0; thisPin < pinCount; thisPin++) {
    Tlc.clear();
    tlc_removeFades(ledPins[thisPin]);
   // Tlc.update();
    }
    break;
  case 1:
    Flash();
    break;
  case 2:
    slowBlink();
    break;
  case 3:
    mover();
    break;     
  default:
    Serial.println("Unknown Mode!");
    delay(1000);
    break;
  }
}

void Flash(void){ // Flasher Variante
      for (int thisPin = 0; thisPin < pinCount; thisPin++) {
      uint16_t duration = 150;
      uint32_t startMillis = millis()+ 2000;
      uint32_t endMillis = startMillis + duration;
      tlc_addFade(ledPins[thisPin], 4095, max, startMillis, endMillis);
      tlc_updateFades();
}
    }

void slowBlink(void){ //slower blinkin
       
    for (int thisPin = 0; thisPin < pinCount; thisPin++) {
          // tlc_removeFades(ledPins[thisPin]);
      uint16_t duration = 2000;
      uint32_t startMillis = millis()+ 2000;
      uint32_t endMillis = startMillis + duration;
      tlc_addFade(ledPins[thisPin], 0, 4095, startMillis, endMillis);
      tlc_addFade(ledPins[thisPin], 4095, 0, startMillis, endMillis + duration);
      tlc_updateFades();
    }
}


void mover(void){ // schaltet einfach nur die Led ein
   for (int grad=0; grad<=100; grad=grad+1)
{
   myServo.write(grad);
   //Serial.println(grad);
   delay(200);
}
}


pylon

Die TLC5940 Bibliothek braucht alle Timer des ATmega328 für ihre Funktionen. Da die Server-Bibliothek auch einen Timer brauchen will, kommt es hier zum Konflikt. Du musst Deine Schaltung vielleicht aufteilen und dem TLC5940 einen eigenen ATmega328 spendieren, den Du dann z.B. über I2C kontrollieren kannst.

uwefed

Meines Wissens braucht die TLC5940 Bibliothek 2 Timer, aber wenn einer dieser 2 Timer auch von der Servo Bibliothek verwendet wird, ist es egal ob der 3. Timer gebraucht wird oder nicht.

Grüße Uwe

pylon

Die TLC5940 Bibliothek braucht Timer1 und Timer2 für die Ansteuerung der PWM pins. Zudem verwendet es aber auch millis() und braucht somit den Timer0, damit die millis()-Funktion überhaupt hochzählt. Somit braucht es alle 3. Da die Servo-Bibliothek aber sowieso Timer1 braucht, ist der Konflikt sowieso vorhanden. Ausweichen könnte man auf den Mega2560, dort könnte man beide Bibliotheken so konfigurieren, dass sie sich vertragen (habe ich nicht selbst versucht, aber nach dem Überfliegen des Codes spricht nichts dagegen).

summ

#4
Feb 28, 2013, 04:33 pm Last Edit: Feb 28, 2013, 04:38 pm by summ Reason: 1
Ich glaube, die Timer beim Meg2560 umzubasteln, liegt ausserhalb meines Verständnisses. Hier bin ich ja schon froh, dass sich überhaupt was tut.
Abgesehen vom Servo ... kann jemand mir sagen, warum die Leds nach umschalten des Modes mehr oder weniger durcheinanderblinken?
Dem Servo einen eigenen Controller zu verpassen scheitert daran, dass das alles in ein Modell soll und dann per Bluetooth gesteuert werden soll. Per I2C überfordert mich leider. Es sei denn, jemand kann mir das gut und einfach beschreiben.

pylon

Die Kommunikation per I2C ist auf der Seite von Nick Gammon gut beschrieben mit einem Beispiel für Master/Slave: http://gammon.com.au/i2c (nur in Englisch, aber auch mit wenig Kenntnissen gut verständlich).

Quote
Ich glaube, die Timer beim Meg2560 umzubasteln, liegt ausserhalb meines Verständnisses.


Die Hauptarbeit ist da in den Bibliotheken schon gemacht, mit ein paar #defines solltest Du eigentlich wegkommen, evtl. sind nicht mal die notwendig.

Quote
Abgesehen vom Servo ... kann jemand mir sagen, warum die Leds nach umschalten des Modes mehr oder weniger durcheinanderblinken?


Der Timer1 wird von der Servo-Bibliothek umprogrammiert und dadurch die Ansteuerung der PWM-Pins für den TCL5940 verändert. Dessen Verhalten ist danach nicht mehr wie gewünscht, eine genaue Analyse weshalb dann genau dieses Verhalten eintritt dürfte den Aufwand nicht wert sein, ausser Du lieferst einen Grund dafür.

summ

Quote
Der Timer1 wird von der Servo-Bibliothek umprogrammiert und dadurch die Ansteuerung der PWM-Pins für den TCL5940 verändert. Dessen Verhalten ist danach nicht mehr wie gewünscht, eine genaue Analyse weshalb dann genau dieses Verhalten eintritt dürfte den Aufwand nicht wert sein, ausser Du lieferst einen Grund dafür.


Das falsche Blinken passiert auch, wenn ich den Servo komplett aus dem Sketch entferne.

pylon

Das ist nach meiner Interpretation des Codes auch das gewünschte Verhalten. Falls dem nicht so ist, solltest Du genau beschreiben, was "falsches Blinken" ist und welchen Modus Du genau eingestellt hast.

Solange der Modus 2 z.B. läuft, werden ständig neue Fader erstellt, bis der Puffer voll ist (was auch nicht geprüft wird). Dass dieses verwobene Faden dann als wildes Blinken ausartet, wundert mich nicht, ist aber genau das, was Du programmiert hast. Da Du uns noch nicht mitgeteilt hast, was Du eigentlich erwartest, muss ich davon ausgehen, dass dies von Dir gewollt ist.

summ

dann versuche ich es gerne zu beschreiben: hier handelt es sich erstmal um einen Testaufbau. Ich möchte, dass die Leds, welche an ledPins hängen, alle zusammen ein bestimmtes "Blink-Muster" haben. Im case 'a' blitzen alle Leds gleichzeitig. Dann möchte ich dieses Muster per Tasteneingabe abändern auf ein längeres Fade von 0 bis 4049 und zurück. Im case 'a' blitzen auch alle Leds gleichzeitig, wie gewünscht. Dann gebe ich b im Terminal ein und anstatt ebenfalls alle Leds den neuen Ablauf durchführen, geht es leider durcheinander. Einige Leds blitzen immernoch, anstatt von 0 zu faden und wahlweise beteiligen sich auch nur zwei der drei Leds daran. Welche das sind, scheint zufällig zu geschehen.
Wenn ich case 'b' zuerst aufrufe, dann läuft case 'b' sauber und case 'a' benimmt sich nicht synchron.

Ich hoffe, es ist klar geworden, was ich erreichen möchte.

pylon

Ich würde es mal damit versuchen (ungetestet, nur zusammengehackt):

Code: [Select]
#include "Tlc5940.h"
#include "tlc_fades.h"
#define interval 500
int fadingMode = 0; //Beginn mit TLC Reset
TLC_CHANNEL_TYPE ledPins[] = {2,3,4};
int pinCount = sizeof(ledPins)/sizeof(TLC_CHANNEL_TYPE);
int max = 100;

void setup()   {               
   Tlc.init();
   Serial.begin(115200);
}

void loop()
{   
  if(Serial.available()){
    if(Serial.peek() == 'l'){
      Serial.flush();
    }
    else{
      fadingMode = Serial.parseInt();
      Serial.print("Mode set to ");
      Serial.print(fadingMode);
      Serial.print(": ");
      switch(fadingMode){
      case 0:
        Serial.println("allet uff Null");
        for (int thisPin = 0; thisPin < pinCount; thisPin++) {
          tlc_removeFades(ledPins[thisPin]);
          Tlc.clear();
        }
        break;
      case 1:
        Serial.println("Flash");
        break;
      case 2:
        Serial.println("Slow Blinker");
        break;
      case 3:
        Serial.println("mover");
        mover();
        break;
      default:
        Serial.println("Unknown Mode!");
        break;
      }
    }
  }
  tlc_updateFades(); // execute the next fade step(s)
  if (! tlc_isFading(ledPins[0])) { // restart fades when they are finished
    switch(fadingMode) {
      case 1:
        Flash();
        break;
      case 2:
        slowBlink();
        break;
    }
  }
}

void Flash(void){ // Flasher Variante
  for (int thisPin = 0; thisPin < pinCount; thisPin++) {
    uint16_t duration = 150;
    uint32_t startMillis = millis()+ 2000;
    uint32_t endMillis = startMillis + duration;
    tlc_addFade(ledPins[thisPin], 4095, max, startMillis, endMillis);
  }
}

void slowBlink(void){ //slower blinkin
       
  for (int thisPin = 0; thisPin < pinCount; thisPin++) {
    uint16_t duration = 2000;
    uint32_t startMillis = millis();
    uint32_t endMillis = startMillis + duration;
    tlc_addFade(ledPins[thisPin], 0, 4095, startMillis, endMillis);
    tlc_addFade(ledPins[thisPin], 4095, 0, startMillis + duration, endMillis + duration << 1);
  }
}


void mover(void){
  // Servo does not make sense with TLC
}

Go Up