1284p und FastLED - Taktfrequenzen völlig daneben

Hallo Leute,

ich arbeite im Moment mit einem 1284P und dem Mighty 1284P Core. Ich benutze die 8 MHz Version und habe die Fuses entsprechend auf internen Oszilator gesetzt, so dass ich auf PIN B1 auch einen Clockausgang habe.

mighty8.name=1284p 8MHz internal clockout
mighty8.upload.protocol=stk500v1
mighty8.upload.maximum_size=129024
mighty8.upload.speed=28800
mighty8.bootloader.low_fuses=0x92
mighty8.bootloader.high_fuses=0xdc
mighty8.bootloader.extended_fuses=0xfd
mighty8.bootloader.path=standard
mighty8.bootloader.file=ATmegaBOOT_1284P_8MHz.hex
mighty8.bootloader.unlock_bits=0x3F
mighty8.bootloader.lock_bits=0x0F
mighty8.build.mcu=atmega1284p
mighty8.build.f_cpu=8000000L
#mighty8.build.core=arduino:arduino
mighty8.build.core=standard
mighty8.build.variant=standard

Das läuft auch gut, ich bekomme ein schönes 8 Mhz Signal an PIN B1.
Versuche ich nun mit FastLED die WS2812 anzusteuern, so klappt das nicht.

#include "FastLED.h"

#define NUM_LEDS 2
#define DATA_PIN 0

CRGB leds[NUM_LEDS];

void setup() { 
   FastLED.addLeds<WS2812, DATA_PIN, GRB>(leds, NUM_LEDS);
   LEDS.setBrightness(50);
     
}

void loop() { 
   static uint8_t hue = 0;
   leds[0].setHue(hue-128);
   leds[1].setHue(hue++);
   FastLED.show();
   delay(40);
}

Die LEDs leuchten nur weiß.
Wenn ich OSCCAL entsprechend hoch setzte (auf 127 z.B.) geht es. Allerdings messe ich dann am an PB1 exakt 10 Mhz :o

Alternativ kann ich auch das #define von F_CPU auf 7500000 abändern.

Hat irgendwer eine Idee woran das liegen könnte, dass wenn beide Einstellungen auf 8 Mhz sind, FastLED nicht funkioniert? Doch die Fuses falsch? Ich habe leider keinen 8 Mhz Quarz zum Testen ob es mit externem Oszilator geht.

Gruß,
Marv

hi,

wieso denkst Du, daß die fastled mit 8MHz funktioniert?

die timings zur ansteuerung der led-kette sind sehr eng, und das wird mit assembler-programmierung gelöst. der programmierer weiß, wieviele takte jeder befehl braucht, er kann also auf eine 16-millionstel-sekunde genau sagen, was wann passiert. ist die library dann schneller, als es der stripe braucht, hat er gewonnen. dann werden an den zu schnellen stellen NOP-befehle eingefügt (das sind sowas wie delays von einer 16-millionstel sekunde), und fertig.

wenn Du jetzt mit 8MHz taktest, laufen diese teile nur halb so schnell, und der WS2811-chip wird zu langsam angesprochen.

optionen:
eine library, die für 8MHz geschrieben wurde (wenn sich das zeitlich ausgeht).
ein anderer stripe, der takt- UND datenleitung hat.
mit 16MHz arbeiten.

gruß stefan

PS: gib mal bei google “WS2811 8MHZ” ein. da steht vieles…

EDIT: er scheints geschafft zu haben, mit beschreibung:
http://rurandom.org/justintime/index.php?title=Driving_the_WS2811_at_800_kHz_with_an_8_MHz_AVR

Hallo Stefan,

selbst mit 8MHz sollte das ganze laufen. Ich habe jetzt schon lange nicht mehr die Fastled Lib genutzt oder installiert, aber bei den LightWeight Alternativen wird das nicht anders gemacht.

Die Taktfrequenz ist bei der Kompilierung bereits bekannt. Dann werden halt über eine Präprozessor Anweisung weniger nop() hintereinander gesendet.

Mit light_ws2812 gehen die Stripes sogar auf einem Attiny mit 4 MHz!

https://github.com/cpldcpu/light_ws2812

Wobei ich darauf tippe, dass die Fastled es schaffen sollte. Habe leider gerade auf deren Seite keine Übersicht/Rahmenbedingungen gefunden.

Ich hab mal die LightWeight Bibliothek ausprobiert, klappt mit 8 Mhz auf Anhieb. Jedoch ist mir der Funktionsumfang der FastLED doch ganz geschickt, auf dem 1284P hab ich ja genug Speicher.

Meine Frage ist jetzt, wie ich am elegantesten die Frequenzdifferenz bei der FastLED mit 8 Mhz umgehe. Ansich funktioniert es ja, aber dass sich F_CPU und die tatsächliche Taktfrequenz des AVRs unterscheiden, halte ich für unschön. Das betrifft ja nämlich auch millis() und Serial.

Notfalls bau ich mir eine eigene Bibliothek mit den nötigen Funktionen aus der LightWeight und FastLED zusammen.

Gruß, Marv

hi,

stefan, ich hab’ am ende ja geschrieben, daß es prinzipiell geht. aber keinen hinweis gefunden, daß es mit der fastled geht.

aber dass sich F_CPU und die tatsächliche Taktfrequenz des AVRs unterscheiden, halte ich für unschön.

was meinst Du damit?

gruß stefan

Hast du auch mal ältere Versionen von Fastled getestet? Was hindert dich ansonsten daran, einen 16MHz Resonator an den 1284 zu hängen?

Eisebaer: was meinst Du damit?

Das Verwunderliche - bzw. der Grund warum ich diesen Thread gestartet habe - war, dass FastLED nur dann richtig geht, wenn der Wert von F_CPU um ca. 10% niedriger ist als die tatsächliche Taktfreqenz. F_CPU ist ja eine Konstante, die eigentlich mit der Oszilatorfrequenz übereinstimmt, damit Funktionen in denen es auf Timing ankommt wie Serial/SoftSerial, millis(), etc., richtig funktionieren.

sschultewolter: Hast du auch mal ältere Versionen von Fastled getestet?

Es ist eine ältere Version, ein Release von Januar 2014. Ich habe grade eine aktuelle heruntergeladen, da geht gar nichts mehr... :slightly_frowning_face: Es kommt nicht mal ein Signal aus dem Digitalpin raus. Beim Uno hingegen alles wie gehabt ohne Probleme.

sschultewolter: Was hindert dich ansonsten daran, einen 16MHz Resonator an den 1284 zu hängen?

Eigentlich der Geiz am Platz :D das soll eine sehr kompakte Schaltung werden, der 1284P wird später durch die TQFP Version ersetzt. Aber vermutlich kriege ich schon noch einen kleinen SMD-Quarz unter.

i had the same Problems with fastLED and m1284p with 16MHz

with a single ws2812b i find out

the Timing is 10% to slow with fastLED and m1284p: http://www.mikrocontroller.net/attachment/244099/m1284p_timing.jpg

so i fixed it with

#ifdef F_CPU
#undef F_CPU
#define F_CPU 1440000

// statt 16MHz,
// sind die Impulse 10% zu lahm
// definiere die CPU 10% langsamer,
// dann passt es wieder,
// natürlich gibt es Seiteneffekte
// bei UART und anderswo,
// aber wo es stört kann man immer noch
// (F_CPU+1600000) setzen.

#endif

but this is only a workaround, in every LIB there must be a

[color=#557799]#if[/color] ((F_CPU == [color=#0000dd][b]14400000L[/b][/color]) && defined(__AVR_ATmega1284P__)) 
TWBR = (( (F_CPU+[color=#0000dd][b]1600000L[/b][/color]) / TWI_FREQ) - [color=#0000dd][b]16[/b][/color]) / [color=#0000dd][b]2[/b][/color];
[color=#557799]#else[/color]
TWBR = ((F_CPU / TWI_FREQ) - [color=#0000dd][b]16[/b][/color]) / [color=#0000dd][b]2[/b][/color];
[color=#557799]#endif[/color]

and so on.....

see https://github.com/FastLED/FastLED/issues/121

see http://forum.arduino.cc/index.php?topic=234895.msg2056485#msg2056485

Mir ist es nur etwas rätselhaft wo dieser Unterschied herkommt. Der 1284 ist im Prinzip der gleiche CPU Kern wie der 328 und der 2560. Lediglich die Peripherie sollte sich unterscheiden.

Serenifly:
Mir ist es nur etwas rätselhaft wo dieser Unterschied herkommt. Der 1284 ist im Prinzip der gleiche CPU Kern wie der 328 und der 2560. Lediglich die Peripherie sollte sich unterscheiden.

nee

der m328 hat nur 32k im Adressraum von 64k zur Sprungberechnung reichen da 2 Byte
der m1284p hat 128k zur Sprungberechnung reichen da 2 Byte nicht es kommt ein drittes Byte dazu das muss im Timing berücksichtigt werden, beim m2560 gehe ich davon aus das es getan wurde weil das ein offizieller Arduino ist, der m1284p eben nicht.

jar_: der m328 hat nur 32k im Adressraum von 64k zur Sprungberechnung reichen da 2 Byte der m1284p hat 128k zur Sprungberechnung reichen da 2 Byte nicht es kommt ein drittes Byte dazu das muss im Timing berücksichtigt werden, beim m2560 gehe ich davon aus das es getan wurde weil das ein offizieller Arduino ist, der m1284p eben nicht.

Wow, super logische Erklärung, danke. Die 800kHz sind ja ein zehntel der 8 Mhz, folglich macht ein zusätzliches Byte die 10% Unterschied.

Der Entwickler von FastLED schreibt als Kommentar zur show-Funktion der Clockless-Controller:

TODO: hand rig asm version of this method. The timings are based on adjusting/studying GCC compiler ouptut. This will bite me in the ass at some point, I know it.

Mich verwundert nur, dass er so viel mit Asm optimiert hat, aber die einzige Funktion bei der es auf das Timing wirklich ankommt noch nicht in Asm implementiert hat. In der Light weight library wird das ganze mit Branch-Befehlen gemacht, die unabhängig vom Addressraum relative Sprünge bis maximal 63 Befehl zurück machen können. Somit sollte das auf allen AVRs problemlos funktionieren.

MGOS:
Wow, super logische Erklärung, danke. Die 800kHz sind ja ein zehntel der 8 Mhz, folglich macht ein zusätzliches Byte die 10% Unterschied.

auch bei 16MHz sind es 10%

egal, Lösung gefunden und verankert:

"endgültige" Lösung gefunden,

welche nur [iurl=http://www.mikrocontroller.net/articles/AVR]AVR[/iurl] m1284p und fastled anspricht und alle anderen F_CPU 
unangefasst lässt:

in delay.h in der fastLED LIB aus:
[color=#888888]// #define NS(_NS) (_NS / (1000 / (F_CPU / 1000000L)))[/color]
[color=#557799]#if[/color] F_CPU < [color=#0000dd][b]96000000[/b][/color]
 [color=#557799]#define[/color] NS(_NS) ( (_NS * (F_CPU / [color=#0000dd][b]1000000L[/b][/color]))) / [color=#0000dd][b]1000[/b][/color]
 [color=#557799]#define[/color] CLKS_TO_MICROS(_CLKS) (([color=#007744][b]long[/b][/color])(_CLKS)) / (F_CPU / [color=#0000dd][b]1000000L[/b][/color])
[color=#557799]#else[/color]
[color=#557799]#define[/color] NS(_NS) ( (_NS * (F_CPU / [color=#0000dd][b]2000000L[/b][/color]))) / [color=#0000dd][b]1000[/b][/color]
einfach folgendes gemacht:
[color=#888888]// #define NS(_NS) (_NS / (1000 / (F_CPU / 1000000L)))[/color]
[color=#557799]#if[/color] F_CPU < [color=#0000dd][b]96000000[/b][/color]
[color=#557799]#if[/color] defined(__AVR_ATmega1284P__) && (F_CPU==[color=#0000dd][b]16000000[/b][/color])
 [color=#557799]#define[/color] NS(_NS) ( (_NS * ( (F_CPU-[color=#0000dd][b]1600000L[/b][/color]) / [color=#0000dd][b]1000000L[/b][/color]))) / [color=#0000dd][b]1000[/b][/color]
 [color=#557799]#define[/color] CLKS_TO_MICROS(_CLKS) (([color=#007744][b]long[/b][/color])(_CLKS)) / ((F_CPU-[color=#0000dd][b]1600000L[/b][/color]) / [color=#0000dd][b]1000000L[/b][/color])
[color=#557799]#else[/color]
 [color=#557799]#define[/color] NS(_NS) ( (_NS * (F_CPU / [color=#0000dd][b]1000000L[/b][/color]))) / [color=#0000dd][b]1000[/b][/color]
 [color=#557799]#define[/color] CLKS_TO_MICROS(_CLKS) (([color=#007744][b]long[/b][/color])(_CLKS)) / (F_CPU / [color=#0000dd][b]1000000L[/b][/color])
[color=#557799]#endif[/color]
[color=#557799]#else[/color]
[color=#557799]#define[/color] NS(_NS) ( (_NS * (F_CPU / [color=#0000dd][b]2000000L[/b][/color]))) / [color=#0000dd][b]1000[/b][/color]
für [iurl=http://www.mikrocontroller.net/articles/AVR]AVR[/iurl] 1284p und 16 MHz

könnte auf 8MHz erweitert werden

so nun egal ob 16MHz oder 8 MHz oder anderes, getestet für 16 MHz
in fastLED delay.h

// Macro to convert from nano-seconds to clocks and clocks to nano-seconds
// AVR_ATmega1284P
// #define NS(_NS) (_NS / (1000 / (F_CPU / 1000000L)))
#if F_CPU < 96000000
#if defined(AVR_ATmega1284P)
#define NS(_NS) ( (_NS * ( ((long)(F_CPU9L/10L)) / 1000000L))) / 1000
#define CLKS_TO_MICROS(_CLKS) ((long)(_CLKS)) / (((long)(F_CPU
9L/10L)) / 1000000L)
#else
#define NS(_NS) ( (_NS * (F_CPU / 1000000L))) / 1000
#define CLKS_TO_MICROS(_CLKS) ((long)(_CLKS)) / (F_CPU / 1000000L)
#endif
#else
#define NS(_NS) ( (_NS * (F_CPU / 2000000L))) / 1000
#define CLKS_TO_MICROS(_CLKS) ((long)(_CLKS)) / (F_CPU / 2000000L)
#endif

Hallo,
Ich stehe genau vor dem Selben Problem.
Was muss ich wo genau ändern?

LightWS2812 bringt:
conflicting declaration ‘WS2812 LED’

In fastLED hab ich keine delay.h die ich ändern könnte.
Nur fastled_delay.h
Ist die gemeint und muss da einfach den Tel ersetzen oder hinzufügen?
Danke

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.