Forum: Mikrocontroller und Digitale Elektronik Bit Angle Modulation Arduino


von Michele S. (dragonthb)


Lesenswert?

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
void loop(){
2
3
 int Zeit1=10;
4
 int Zeit2=20;
5
 int Zeit3=40;
6
 int Zeit4=80;
7
 int Zeit5=160;
8
 int Zeit6=320;
9
 int Zeit7=640;
10
 int Zeit8=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.

: Verschoben durch Moderator
von Tim  . (cpldcpu)


Lesenswert?

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.

von Michele S. (dragonthb)


Lesenswert?

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.

von Mr. Plow (Gast)


Lesenswert?

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

von Michele S. (dragonthb)


Lesenswert?

Ich weiß jetzt nicht was das mit der eigentlichen Frage zu tuen hat XDDD

von Tim  . (cpldcpu)


Lesenswert?

Mr. Plow schrieb:
> Generation Arduino?
>
> SCNR

Es gibt doch auch irgendwo einen Thread zur Frage, ob ein 
Schieberegister abnutzt?

von Tim  . (cpldcpu)


Lesenswert?

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.

von Max H. (hartl192)


Lesenswert?

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.

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Tim    schrieb:
> Falsches Forum.

Fixed.

von Max H. (hartl192)


Lesenswert?

Tim    schrieb:
> Es gibt doch auch irgendwo einen Thread zur Frage, ob ein
> Schieberegister abnutzt?
Beitrag "Wie lange "lebt" ein Schieberegister?"

von Michele S. (dragonthb)


Lesenswert?

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?

von chris (Gast)


Lesenswert?

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.

von Max H. (hartl192)


Lesenswert?

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

von Davis (Gast)


Lesenswert?

Max H. schrieb:

> Ich weiß nicht wie die Anderen das sehen, aber meiner Meinung nach ist
> die Mehrzahl von Pin Pins

Im obigen Satz fehlt ein Komma.

von Michele S. (dragonthb)


Lesenswert?

Habt ihr das so gemeint ist das besser?
1
#include "TimerOne.h"
2
int counter =0;
3
void setup(){
4
pinMode(2, OUTPUT); 
5
pinMode(3, OUTPUT); 
6
pinMode(4, OUTPUT); 
7
pinMode(5, OUTPUT); 
8
pinMode(6, OUTPUT); 
9
pinMode(7, OUTPUT); 
10
pinMode(8, OUTPUT); 
11
pinMode(9, OUTPUT); 
12
pinMode(22, OUTPUT); 
13
pinMode(23, OUTPUT); 
14
pinMode(24, OUTPUT); 
15
pinMode(25, OUTPUT); 
16
pinMode(26, OUTPUT); 
17
pinMode(27, OUTPUT); 
18
pinMode(28, OUTPUT); 
19
pinMode(29, OUTPUT); 
20
pinMode(30, OUTPUT); 
21
pinMode(31, OUTPUT); 
22
pinMode(32, OUTPUT); 
23
pinMode(33, OUTPUT); 
24
pinMode(34, OUTPUT); 
25
pinMode(35, OUTPUT); 
26
pinMode(36, OUTPUT); 
27
pinMode(37, OUTPUT); 
28
pinMode(38, OUTPUT); 
29
pinMode(39, OUTPUT); 
30
pinMode(40, OUTPUT); 
31
pinMode(41, OUTPUT); 
32
pinMode(42, OUTPUT); 
33
pinMode(43, OUTPUT); 
34
pinMode(44, OUTPUT); 
35
pinMode(45, OUTPUT); 
36
37
Timer1.initialize(1000);       
38
Timer1.attachInterrupt(callback);  overflow interrupt
39
}
40
 
41
void callback()
42
{
43
counter++;
44
}
45
void loop(){
46
 
47
if(counter=1)
48
{
49
  digitalWrite(2, HIGH);
50
digitalWrite(22, HIGH);
51
digitalWrite(23, LOW);
52
digitalWrite(24, LOW);
53
digitalWrite(25, LOW);
54
digitalWrite(26, LOW);
55
}
56
if(counter=2)
57
{
58
  digitalWrite(22, HIGH);
59
digitalWrite(23, LOW);
60
digitalWrite(24, LOW);
61
digitalWrite(25, HIGH);
62
digitalWrite(26, HIGH);
63
}
64
if(counter=4)
65
{
66
  digitalWrite(22, HIGH);
67
digitalWrite(23, HIGH);
68
digitalWrite(24, LOW);
69
digitalWrite(25, LOW);
70
digitalWrite(26, LOW);
71
}
72
if(counter=8)
73
{
74
  digitalWrite(22, HIGH);
75
digitalWrite(23, LOW);
76
digitalWrite(24, LOW);
77
digitalWrite(25, HIGH);
78
digitalWrite(26, HIGH);
79
}
80
if(counter=16)
81
{
82
  digitalWrite(22, HIGH);
83
digitalWrite(23, HIGH);
84
digitalWrite(24, HIGH);
85
digitalWrite(25, HIGH);
86
digitalWrite(26, LOW);
87
}
88
if(counter=32)
89
{
90
  digitalWrite(22, HIGH);
91
digitalWrite(23, HIGH);
92
digitalWrite(24, HIGH);
93
digitalWrite(25, LOW);
94
digitalWrite(26, LOW);
95
}
96
if(counter=64)
97
{
98
digitalWrite(22, HIGH);
99
digitalWrite(23, LOW);
100
digitalWrite(24, HIGH);
101
digitalWrite(25, HIGH);
102
digitalWrite(26, LOW);
103
}
104
if(counter=128)
105
{
106
digitalWrite(22, HIGH);
107
digitalWrite(23, HIGH);
108
digitalWrite(24, HIGH);
109
digitalWrite(25, LOW);
110
digitalWrite(26, LOW);
111
}
112
if(counter=129)
113
{
114
digitalWrite(22, LOW);
115
digitalWrite(23, LOW);
116
digitalWrite(24, LOW);
117
digitalWrite(25, LOW);
118
digitalWrite(26, LOW);
119
counter==0;
120
121
 }
122
 
123
 }

: Bearbeitet durch User
von Sebastian W. (wangnick)


Lesenswert?

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

von Max H. (hartl192)


Lesenswert?

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.

von Michele S. (dragonthb)


Lesenswert?

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.

von Sebastian W. (wangnick)


Lesenswert?

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

: Bearbeitet durch User
von Michele S. (dragonthb)


Lesenswert?

Dadurch wird die HEX auch kleiner ich habe gerade 27% an Bytes 
eingespart.

von Martin L. (maveric00)


Lesenswert?

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

von Peter D. (peda)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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).

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.