Hallöchen
Ich versuche zur Zeit eine RGB Matrix mit einem Arduino zu steuern und
wo es dan um das Dimmen und Mischen der Farben ging. Wurde mir
empfohlen, mir mal Bit Angle Modulation anzugucken. Ich habe da mal
einen Code geschrieben. Doch frage ich mich gerade ob ich meinen Arduino
damit nicht kille, weil ich zwischendurch immer wieder Ausgänge im
Systemtackt schalte.
1
voidloop(){
2
3
intZeit1=10;
4
intZeit2=20;
5
intZeit3=40;
6
intZeit4=80;
7
intZeit5=160;
8
intZeit6=320;
9
intZeit7=640;
10
intZeit8=1280;
11
while(1)
12
{
13
14
digitalWrite(2,HIGH);
15
digitalWrite(22,HIGH);
16
digitalWrite(23,LOW);
17
digitalWrite(24,LOW);
18
digitalWrite(25,LOW);
19
digitalWrite(26,LOW);
20
delayMicroseconds(Zeit1);
21
digitalWrite(22,HIGH);
22
digitalWrite(23,LOW);
23
digitalWrite(24,LOW);
24
digitalWrite(25,HIGH);
25
digitalWrite(26,HIGH);
26
delayMicroseconds(Zeit2);
27
digitalWrite(22,HIGH);
28
digitalWrite(23,HIGH);
29
digitalWrite(24,LOW);
30
digitalWrite(25,LOW);
31
digitalWrite(26,LOW);
32
delayMicroseconds(Zeit3);
33
digitalWrite(22,HIGH);
34
digitalWrite(23,LOW);
35
digitalWrite(24,LOW);
36
digitalWrite(25,HIGH);
37
digitalWrite(26,HIGH);
38
delayMicroseconds(Zeit4);
39
digitalWrite(22,HIGH);
40
digitalWrite(23,HIGH);
41
digitalWrite(24,HIGH);
42
digitalWrite(25,HIGH);
43
digitalWrite(26,LOW);
44
delayMicroseconds(Zeit5);
45
digitalWrite(22,HIGH);
46
digitalWrite(23,HIGH);
47
digitalWrite(24,HIGH);
48
digitalWrite(25,LOW);
49
digitalWrite(26,LOW);
50
delayMicroseconds(Zeit6);
51
digitalWrite(22,HIGH);
52
digitalWrite(23,LOW);
53
digitalWrite(24,HIGH);
54
digitalWrite(25,HIGH);
55
digitalWrite(26,LOW);
56
delayMicroseconds(Zeit7);
57
digitalWrite(22,HIGH);
58
digitalWrite(23,HIGH);
59
digitalWrite(24,HIGH);
60
digitalWrite(25,LOW);
61
digitalWrite(26,LOW);
62
delayMicroseconds(Zeit8);
63
digitalWrite(22,LOW);
64
digitalWrite(23,LOW);
65
digitalWrite(24,LOW);
66
digitalWrite(25,LOW);
67
digitalWrite(26,LOW);
Die Pinne sollen in diesem Beispiel BAM ausgeben:
PIN22=11111111=>255
PIN23=10110100=>180
PIN24=11110000=>120
PIN25=01011010=>90
PIN26=00001010=>50
Ich frage mich nur gerade ob das so richtig ist und ob ich meinen
Arduino nicht beschädige.
Falsches Forum.
Kannst Du genauer beschreiben, was Du eigentlich erreichen willst? Was
ist an den Arduino angeschlossen?
Durch Software kannst Du erst einmal nichts kaputt machen. Außerdem ist
digitalwrite ziemlich lahm. An den Systemtakt kommt man damit nicht
annährend.
An den Ausgängen sind Transistoren angeschlossen es fließt ein Strom von
0,21mA aus dem Mikrocontroller.
Eh doch ich mache zur zeit meinen Techniker in Elektronik und
tatsächlich hat es ein Kollege geschaft durch ein Programm seinen
Atmega32 zu killen, indem er ausversehen alle Ausgänge in nahezu
Systemtakt geschaltet hatte. Das hatte der Mikrocontroller ca 10
Sekunden mitgemacht.
Michele S. schrieb:> Eh doch ich mache zur zeit meinen Techniker in Elektronik und> tatsächlich hat es ein Kollege geschaft durch ein Programm seinen> Atmega32 zu killen, indem er ausversehen alle Ausgänge in nahezu> Systemtakt geschaltet hatte. Das hatte der Mikrocontroller ca 10> Sekunden mitgemacht.
Generation Arduino?
SCNR
Michele S. schrieb:> An den Ausgängen sind Transistoren angeschlossen es fließt ein Strom von> 0,21mA aus dem Mikrocontroller.
Und was sollen wir daraus erraten? Um Dir zu helfen, müssten wir schon
die Schaltung haben und eine Beschreibung von dem was DU erreichen
willst.
Michele S. schrieb:> Eh doch ich mache zur zeit meinen Techniker in Elektronik und> tatsächlich hat es ein Kollege geschaft durch ein Programm seinen> Atmega32 zu killen,
Dann nimm einen PIC24. Ich habe einen Port mit 2.66 MHz togglen lassen
und er läuft nach >1 Stunde problemlos...
Spaß bei Seite:
Am Togglen liegt’s sicher nicht. Der Kollege wir schon einen Fehler in
der Schaltung oder so gemacht haben... Wenn das schnelle Schalten der
PINs ein Problem wäre, würden moderne CPUs schon nach <1sek kaputt sein.
OK dan gehe ich mal davon aus das der Arduino es überlebt und was sagt
ihr zu der Art des Codes? Ich finde ihn eigentlich ziemlich hässlich
würdet ihr es anders schreiben?
Michele S. schrieb:> Ich finde ihn eigentlich ziemlich hässlich> würdet ihr es anders schreiben?
Ja. delay ist prinzipiell (fast) immter schlecht.
Dein µC soll ja auch was anderes nebenbei tun außer zu warten.
--> informier dich mal über die Timer die dein µC bietet.
Michele S. schrieb:> was sagt> ihr zu der Art des Codes?
1. Ich würde es mit Interrupts machen.
2. Ich würde nicht für jede Zeile der Matrix 8x ausgeben, ich würde nur
jedes Bild 8x ausgeben. Bei deiner 8x8 Matrix brauchst du nur 1/8 der
Wartezeit.
3. Die Bei den Ausgängen würde ich ganze Ports ansprechen.
Michele S. schrieb:> Pinne
Ich weiß nicht wie die Anderen das sehen, aber meiner Meinung nach ist
die Mehrzahl von Pin Pins
Michele S. schrieb:> OK dan gehe ich mal davon aus das der Arduino es überlebt und was sagt> ihr zu der Art des Codes? Ich finde ihn eigentlich ziemlich hässlich> würdet ihr es anders schreiben?
Hallo Michele,
1. Ihr benutzt vermutlich einen Arduino Mega 2560. Wenn es euch um
Geschwindigkeit geht, müsst ihr die Arduino-Welt ein wenig verlassen und
in die AVR-Welt transzendieren. Dazu müsst ihr unbedingt folgendes
Dokument lesen:
http://arduino.cc/en/uploads/Main/arduino-mega2560_R3-sch.pdf
2. Folgt man den Arduino-Pins 22-29 in diesem Dokument, so sind sie mit
den IC-Pins 78-71 eines ATMEGA2560-16AU verbunden. Dieser IC ist in
folgendem Dokument komplett beschrieben (das "heilige" Datenblatt):
http://www.atmel.com/images/doc2549.pdf
3. In der Arduino-Entwicklungsumgebung kann man direkt auf die Register
des IC zugreifen! Die Arduino-Pins 22-29 entsprechen PORTA und dort
PINA0 bis PINA7 des uC. pinMode(22,OUTPUT) kann man durch DDRA |=
1<<PINA0 ersetzen. Wenn alle pins von 22 bis 29 OUTPUT sein sollen,
reicht DDRA = 0xFF. digitalWrite(22,LOW) entspricht PORTA &=
~(1<<PINA0), und digitalWrite(22,HIGH) entspricht PORTA |= 1<<PINA0. Die
direkten Registerzugriffe werden in eine Instruktion übersetzt (SBI,
CBI) und benötigen nur zwei Prozessorzyklen (Seite 416 des "heiligen"
Datenblatts).
4.
1
digitalWrite(22,HIGH);
2
digitalWrite(23,LOW);
3
digitalWrite(24,LOW);
4
digitalWrite(25,HIGH);
5
digitalWrite(26,HIGH);
lässt sich wie folgt ersetzen:
1
PORTA=0b00011001;
Letzteres übersetzt sich in zwei Instruktionen (LDI, OUT), die jeweils
einen Zyklus benötigen. Die ganze Anweisung braucht also (bei 16MHz) nur
125ns. Im Vergleich zu den digitalWrite-Funktionsaufrufen und dem ganzen
Gedöns dort ist das mehr als 100x (!) schneller.
HTH.
LG, Sebastian
Michele S. schrieb:> Timer1.initialize(1000); // initialize timer1, and set a 1/2> second period
Das könnte etwas Langsam sein.
Das mit dem Interrupt hätte mir anders vorgestellt, wenn der µC nebenher
nichts tun muss, geht's auch so.
Mit den 10µs für die kürzeste Zeit wird das so nichts.
digitalWrite dauert zu lange:
>void setup() {> pinMode(2, OUTPUT); // LED on board>}>>void loop() {> while(1) {> digitalWrite(2, HIGH);> digitalWrite(2, LOW);> }>}>>The program is simple enough. Here is the waveform produced on>pin #2 (16MHz Arduino board).> http://billgrundmann.files.wordpress.com/2009/03/img_25311.jpg?w=675&h=450>The waveform high time is about 3.3usec (~53 clock cycles), the low>time is about 3.45usec (~55 clock cycles, picture is not shown), and>a pulsing frequency of ~148KHz.
Quelle:
http://billgrundmann.wordpress.com/2009/03/03/to-use-or-not-use-writedigital/Michele S. schrieb:> Doch frage ich mich gerade ob ich meinen Arduino> damit nicht kille, weil ich zwischendurch immer wieder Ausgänge im> Systemtackt schalte.
Von Systemtakt ist das weit entfernt.
Hallo Sebastian danke für deine Mühe ja ich kann auch in AVR C
programmieren. Das ist eigentlich auch das was ich vor einiger Zeit
gelernt habe. Ich wusste nicht das die Arduino Umsetzung so viel
langsamer ist. Dan setzte ich jetzt immer den kompletten Port in AVR C.
Michele S. schrieb:> Hallo Sebastian danke für deine Mühe ja ich kann auch in AVR C> programmieren. Das ist eigentlich auch das was ich vor einiger Zeit> gelernt habe. Ich wusste nicht das die Arduino Umsetzung so viel> langsamer ist. Dan setzte ich jetzt immer den kompletten Port in AVR C.
Hallo Michele,
du kannst alle diese Anweisungen auch in der Arduino-IDE benutzen!
LG, Sebastian
Hallo,
damit eine BCM funktioniert muss das Timing recht genau eingehalten
werden; Vorteile der BCM gegenüber einer PWM ergeben sich erst bei
vielen Kanälen und hohen Genauigkeiten.
Beispiel: 8 Kanäle, 8 Bit Auflösung, 200 Hz Wiederholfrequenz würde
bedeuten, dass bei 8 MHz Grundtakt das LSB mit rund 40 Takten
Genauigkeit angesteuert werden sollte (wenn man davon ausgeht, dass die
Helligkeitsschwankung um 1/4 des eigentlichen Wertes akzeptabel ist.
Dies lässt sich sicherlich auch mit den Arduino-Funktionen erreichen.
Allerdings lässt sich dies in einer Soft-PWM wie hier im Forum gezeigt
auch mit 0.3-1.2% CPU-Last darstellen, eine BCM bringt keine echten
Vorteile. Siehe z.B.:
http://www.mikrocontroller.net/articles/Soft-PWM
Beispiel: 8 Kanäle, 14 Bit Auflösung, 240 Hz Wiederholfrequenz: Bei 8
MHz Grundfrequenz muss das LSB genau 2 Takte lang eingeschaltet werden
(zum richtigen Zeitpunkt). Dies ist sicherlich mit den
Arduino-Funktionen nicht möglich, und wenn man ehrlich ist mit C auch
nur wenn man Glück hat.
Damit ist es mit den oben angesprochenen Arduino Funktionen nahezu
sinnlos eine BCM zu programmieren. Im Gegenteil: Eine sonnvolle BCM ist
eine der wenigen Fälle, wo Assembler wirklich eine Berechtigung hat
(auch wenn ich sonst ein heftiger Verfechter der C-Fraktion bin), denn
für alle Fälle, in denen man C oder sogar die Arduino-Funktionen nutzen
könnte, tut es auch eine geschickte PWM.
Wenn man allerdings den Schritt wagt, dann kann man damit auch 24 Kanäle
in 14 Bit mit 240 Hz Wiederholfrequenz auf einem 8 MHz AVR darstellen.
Dabei ist allerdings Taktzählen angesagt. Als Beispiel:
https://github.com/maveric00/HomeCANtrol/blob/master/src/Apps/LED/BCM.S
In einer Variante für LED-Matrizen ist es auch in dem Soft-PWM-Artikel
beschrieben.
Zu Deiner Befürchtung damit den armen Arduino zu überlasten: mit direkt
angeschlossenen Bipolartransistoren oder LEDs lässt er sich sicher nicht
aus der Ruhe bringen; anders könnte es möglicherweise aussehen, wenn
MOSFETs mit hoher Gate-Kapazität angeschlossen sind, da dann eventuell
der mittlere Strom von 20 mA überschritten werden könnte. In diesem Fall
sollte man einen Gate-Treiber zwischen Arduino und MOSFET schalten.
Schöne Grüße,
Martin
Michele S. schrieb:> Doch frage ich mich gerade ob ich meinen Arduino> damit nicht kille, weil ich zwischendurch immer wieder Ausgänge im> Systemtackt schalte.
Dem AVR ist völlig wurscht, was Du machst. Er führt immer einen Befehl
nach dem anderen aus.
Allerdings wird es sein, daß hier viele Befehle länger dauern, als Du es
Dir erhoffst.
Man kann die BCM vorzugsweise über Schieberegister machen (74HC595).
Dabei lädt ein PWM-Ausgang exakt auf den CPU-Zyklus genau das
Ausgangsregister und im Interrupthandler lädt man dann das
Schieberegister. Mit der UART als SPI kannst Du 2 Register ohne
Wartezeit laden (= 16 Ausgänge).