Forum: Mikrocontroller und Digitale Elektronik C: Variable aus einer Schleife | Call by Value sehr langsam?!


von Michael N. (garril)


Lesenswert?

Hallo,
ich habe folgenden Code:
1
void buchstabe(char buchstabe[]) {
2
  int leds[18]={1,2,3,4,5,6,11,16,17,18,19,21,26,31,32,33,34,35};
3
  if (buchstabe[0]=="E") {
4
    //Hier sollte eigentlich LED-Array gesetzt werden
5
  }
6
  int len=(sizeof(leds)/sizeof(*leds));
7
  for (int i=0; i<100; i++) {
8
    LEDsan(leds, len, 100);
9
  }
10
}

Damit habe ich nur leider 2 Probleme:

1. Wenn ich das "leds"-Array zwei Zeilen weiter unten setze (also im 
IF-Block) scheint es keine Gültigkeit mehr außerhalb des IF-Blocks zu 
haben.
Eigentlich wollte ich das irgendwie in den IF-Block bringen, damit ich 
andere ELSE IFs noch machen kann (andere Buchstaben also).
Dachte, dass ich vielleicht nur ein public vor "int leds[18]=..." setzen 
muss, aber das wird beim compilen als Fehler angezeigt.

2. Ich rufe die Funktion wie folgt auf. Stimmt das?:
1
char string[1]="E";
2
buchstabe(string);

So und dann zu guter letzt noch eine Frage (hat jetzt nicht unbedingt 
mit dem Code zu tun):
Da ich immer nur eine LED an einer LED-Matrix anschalte bin ich darauf 
angewiesen, dass das Programm schnell abläuft (da die LEDs ja sonst 
flackern).
Wenn ich nun an die Funktion LEDan() zusätzlich einen Parameter 
übergebe, wie lange nach dem Anschalten einer LED gewartet werden soll, 
bis die nächste angeht, dauert das anscheinend ewig und die LED-Matrix 
flackert also... Wenn ich aber nun in der LEDan()-Funktion den Wert fest 
programmiere, dann funktioniert das ganze super.
Liegt das daran, dass erst ne Kopie des Integers angelegt wird (Call by 
Value)? Oder hat das einen anderen Grund? Denn u.A. übergebe ich auch 
wie man oben sieht ein 18-stelliges Array, und das stört anscheinend 
nicht.

Michael

von P. S. (Gast)


Lesenswert?

Michael N. schrieb:

> Dachte, dass ich vielleicht nur ein public vor "int leds[18]=..." setzen
> muss, aber das wird beim compilen als Fehler angezeigt.

"Denken" ist was Anderes, du hast nur rumprobiert.

http://www.mikrocontroller.net/buecher/

von Der S. (derschelm)


Lesenswert?

Ohne das Problem wirklich verstanden zu haben, und auch ohne zu wissen, 
auf welchem µC das laufen soll und wieviel Speicher der Dinger hat, mal 
folgende Idee:

Wie wäre es, wenn Du ein LED-Array anlegst von der Größe der Buchstaben 
anlegst, also led[0] steht für 'A', led[1] für 'B' usw.

dann sieht der Zugriff vielleicht so aus:

l = led [ string [index] - 'A' ].

Das sollte dann deutlich schneller sein.

Ciao und viel Spaß noch mit Deinen LEDs

von Michael N. (garril)


Lesenswert?

Peter Stegemann schrieb:
> "Denken" ist was Anderes, du hast nur rumprobiert.

Ich habe mir gedacht, dass die Variablendeklaration anscheinend nur 
innerhalb der geschweiften Klammern des IF-Blocks gilt. Deshalb dachte 
ich mir, dass ich die Variable public setze, dann wäre sie ja überall 
gültig.

Was würdest du denn denken um das Problem zu lösen?

Der Schelm schrieb:
> ohne zu wissen,
> auf welchem µC das laufen soll und wieviel Speicher der Dinger hat

Es handelt sich um einen ATmega8-16 mit folgenden Daten:
MHz: 16
Flash: 8
EEProm: 512
RAM: 1K
I/O: 23

Dachte ich hab mich verständlich ausgedrückt. Aber ich erkläre es auch 
gerne nochmal (Vielleicht auch mit ein bisschen mehr Hintergrundinfos):
-LEDan(int) macht die LEDs 1-35 an (int ist also zwischen 0 und 35) und 
danach wieder aus
-LEDsan(int-array) macht mehrere LEDs hintereinander an (also bei 
Arrayinhalt {1,2,3} macht er einfach LEDan(1), LEDan(2), LEDan(3)

Und nun wollte ich eben die Funktion Buchstabe(char) machen. Diese 
Funktion soll lediglich zB bei der Übergabe von "A" dann 
LEDsan(int-array) ausführen. Nur eben mit dem passenden Array damit der 
Buchstabe A erscheint.

Hintergrund warum ich das gerne mit Buchstabe ansprechen würde:
Möchte dann noch eine Funktion Text(string bzw. char-array) schreiben, 
die dann die Funktion Buchstabe(char) für jeden Buchstaben nacheinander 
aufruft.

Wenn mir jemand Frage 1 beantworten könnte, wäre mir schon sehr viel 
weitergeholfen (wie ich das "leds"-array richtig im IF-Block setze)

von Oliver (Gast)


Lesenswert?

Hallo Michael,

da gibt's ja einiges zu sagen.

>Wenn ich das "leds"-Array zwei Zeilen weiter unten setze ...
>scheint es keine Gültigkeit mehr außerhalb des IF-Blocks zu haben.

Das ist auch richtig so. In C gibt es Block-lokale Variablen. Diese sind 
nur innerhalb des Blocks, in dem sie definiert sind, sichtbar und 
gültig.

>Dachte, dass ich vielleicht nur ein public vor "int leds[18]=..." setzen
>muss

In C gibt es kein public oder private, das gibt es erst in C++ (und in 
vielen anderen Sprachen).

>2. Ich rufe die Funktion wie folgt auf. Stimmt das?:

Bist Du Dir klar, dass Du hier einen Zeiger auf das erste Element eines
char-Arrays übergibst? Wenn Du nur einen Buchstaben brauchst, solltest 
Du auch nur einen übergeben.

>int len=(sizeof(leds)/sizeof(*leds));

Du teilst hier die Länge des Arrays durch die Länge eines Pointers. Da 
im Array aber keine Pointer sind, muss das nicht die Anzahl der 
Arrayelemente sein.

>Denn u.A. übergebe ich auch
>wie man oben sieht ein 18-stelliges Array

Arrays werden immer by reference übergeben, genauer gesagt wird die 
Adresse des ersten Arrayelements by value übergeben.

Ich würde Dir raten, mal ein gutes C-Buch genau durchzuarbeiten, da sind 
Dir wohl einige Grundlagen noch nicht so ganz vertraut. Das ist aber 
nicht schlimm, jeder hat mal angefangen.

Viel Erfolg beim Lernen,
Oliver

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Michael N. schrieb:
>   if (buchstabe[0]=="E") {

Du vergleichst einen char mit einem char*. Der Vergleich ist immer 
falsch, und du solltest die Warnungen des Compilers aktivieren und auch 
beachten.
1
   if (buchstabe[0] == 'E')

> Hallo,
> ich habe folgenden Code:
>
1
> void buchstabe(char buchstabe[]) {
2
>   int leds[18]={1,2,3,4,5,6,11,16,17,18,19,21,26,31,32,33,34,35};
3
>   if (buchstabe[0]=="E") {
4
>     //Hier sollte eigentlich LED-Array gesetzt werden
5
>   }
6
>   int len=(sizeof(leds)/sizeof(*leds));
7
>   for (int i=0; i<100; i++) {
8
>     LEDsan(leds, len, 100);
9
>   }
10
> }
11
>
>
> Damit habe ich nur leider 2 Probleme:

Nur zwei? ;-)

> 1. Wenn ich das "leds"-Array zwei Zeilen weiter unten setze (also im
> IF-Block) scheint es keine Gültigkeit mehr außerhalb des IF-Blocks zu
> haben.

Nicht verwunderlich, weil der if-Block nie ausgeführt wird, s.o.
Zudem wird leds auch nicht mehr verwendet, was einem Compiler bei 
Kenntnis von LEDsan ermöglicht, Zuweisungen an leds wegzuoptimiern.

> Eigentlich wollte ich das irgendwie in den IF-Block bringen, damit ich
> andere ELSE IFs noch machen kann (andere Buchstaben also).

Ist ja auch ok.

> Dachte, dass ich vielleicht nur ein public vor "int leds[18]=..." setzen
> muss, aber das wird beim compilen als Fehler angezeigt.

"public"??? Es geht doch um C, oder?

> So und dann zu guter letzt noch eine Frage (hat jetzt nicht unbedingt
> mit dem Code zu tun):
> Da ich immer nur eine LED an einer LED-Matrix anschalte bin ich darauf
> angewiesen, dass das Programm schnell abläuft (da die LEDs ja sonst
> flackern).

Mache einen Unterschied zwischen LEDs ansteuern und ein bestimmtes 
Muster setzen. Beim Ansteuern musst du schnell sein, so daß nix 
flackert. Ein neues Muster Schreiben kann langsamer sein, weil man zB 
nicht so schnell neue Zeichen auf einem Display erkennt.

ZB:

1) In einer ISR werden die einzelnen Muster angezeigt.
2) In der Hauptschleife werden neue Muster generiert, etwa in einen
   Puffer, aus dem dann in einer schnellen ISR dargestellt wird.

Du brauchst ja nicht bei jedem PWM-Zyklus das Muster neu zu generieren.
Zudem musst du dir überlegen, wie's mit der Konsistenz der Daten steht 
und ob eine Inkonsistenz stört. Etwa dann, wenn das Muster erst halb 
geschrieben ist, aber gerade angezeigt werden soll. Was dann adäquat 
ist, kannst nur du selbst entscheiden. Mögliche Losungen sind:
- es macht nix
- nur komplette Puffer dürfen auch dargestellt werden. In dem Fall muss
  man mehrere Puffer vorhalten (mindestens einen zum Anzeigen und einen
  zu Beschreiben, evtl. noch mehr). Der Zugriff wird dann über den
  jeweiligen Pointer gemacht, damit nicht der genze Puffer kopiert 
werden
  muss.

> Wenn ich nun an die Funktion LEDan() zusätzlich einen Parameter
> übergebe, wie lange nach dem Anschalten einer LED gewartet werden soll,

Warten ist immer schlecht, weil das dein Programm lahmlegt. Überleg dir
was mit Timern die ablaufen oder was auch immer (Lösungen gibt's hier
zuhauf) aber delay ist eine der einfachsten aber auch der übelsten 
Lösungen, weil es alles ausser Interrupts blockiert. Und mit Interrupts 
ist es ungenau.

> bis die nächste angeht, dauert das anscheinend ewig und die LED-Matrix
> flackert also... Wenn ich aber nun in der LEDan()-Funktion den Wert fest
> programmiere, dann funktioniert das ganze super.
> Liegt das daran, dass erst ne Kopie des Integers angelegt wird (Call by
> Value)?

Das geht schnell, wobei du nicht wirklich int zu brauchen scheinst. Ein 
char/unsigned char tut's wohl auch. Wenn das Anzeige-Array statisch ist, 
muss es auch nicht immer wieder angelegt werden. Momentan muss das Array 
bei jedem Aufruf neu angelegt und initialisiert werden!!

> Oder hat das einen anderen Grund? Denn u.A. übergebe ich auch
> wie man oben sieht ein 18-stelliges Array, und das stört anscheinend
> nicht.

Nein, du übergibst nicht das Array, du übergibst seine Startadresse. Das 
Anlegen ist teuer, nicht seine Adresse zu übergeben.

> Michael

Johann

von Michael N. (garril)


Lesenswert?

Oliver schrieb:
> In C gibt es kein public oder private, das gibt es erst in C++ (und in
> vielen anderen Sprachen).

Würde also heißen, dass ich am besten noch eine Funktion schreibe und 
das Array an diese Übergebe... Sonst kann ich mir nicht vorstellen wie 
ich das hinbekommen soll, dass ich außerdem des IFs darauf zugreifen 
kann.

Oliver schrieb:
> Bist Du Dir klar, dass Du hier einen Zeiger auf das erste Element eines
> char-Arrays übergibst? Wenn Du nur einen Buchstaben brauchst, solltest
> Du auch nur einen übergeben.

Genau das wollte ich. Dazwischen kommt dann die im vorherigen Post 
beschriebene Funktion, die den String (bzw. das char Array zerlegt)

Oliver schrieb:
> Du teilst hier die Länge des Arrays durch die Länge eines Pointers. Da
> im Array aber keine Pointer sind, muss das nicht die Anzahl der
> Arrayelemente sein.

Oh, das ist dann echt nen Fehler... Müsste dann ja
int len=(sizeof(leds)/sizeof(int));
heißen, wenn ich mich richtig informiert habe.

Oliver schrieb:
> Arrays werden immer by reference übergeben

Das ist mir vollkommen klar. Ich wundere mich nur, warum die Funktion so 
viel langsamer wird (komischerweiße schon beim kopieren auf den 
Mikrocontroller) wenn ich einen normalen Integer, an die Funktion 
übergebe!
Ein int wird ja in C bestimmt auch wie in anderen Sprachen per Call by 
Value übergeben. Deshalb dachte ich, dass eben hier womöglich das 
Problem liegt.
Sobald ich nicht mehr den übergebenen Integer benutze, sondern einfach 
den Wert fest einprogrammiere funktioniert alles super schnell.

Oliver schrieb:
> Ich würde Dir raten, mal ein gutes C-Buch genau durchzuarbeiten, da sind
> Dir wohl einige Grundlagen noch nicht so ganz vertraut. Das ist aber
> nicht schlimm, jeder hat mal angefangen.

Dachte, dass ich vielleicht ein schönes Online-Tutorial finde. Aber 
etwas super passendes habe ich leider noch nicht gefunden. (Das Tut auf 
dieser Seite hat mir aber auch schon gut geholfen)

Oliver schrieb:
> Viel Erfolg beim Lernen,

Dankeschön, ich hoffe den werd ich haben.

von Karl H. (kbuchegg)


Lesenswert?

Oliver schrieb:

>
>>int len=(sizeof(leds)/sizeof(*leds));
>
> Du teilst hier die Länge des Arrays durch die Länge eines Pointers. Da
> im Array aber keine Pointer sind, muss das nicht die Anzahl der
> Arrayelemente sein.

Das passt schon so wie er das hatte.
Hier ist *leds kein Pointer sondern evaluiert zum ersten Array-Element 
und der sizeof nimmt sich dann von dem den Datentyp. Man hätte es auch 
als

 int len=(sizeof(leds)/sizeof(leds[0]));

schreiben können, da sieht man dann besser was passiert.


> Ich würde Dir raten, mal ein gutes C-Buch genau durchzuarbeiten

Dem kann ich nur beipflichten. Aus der Fragestellung und der ganzen Art 
wie sie gestellt wurde, zeigen sich da enorme Defizite im 
Grundlagenbereich.

von Karl H. (kbuchegg)


Lesenswert?

Michael N. schrieb:
> Oliver schrieb:
>> In C gibt es kein public oder private, das gibt es erst in C++ (und in
>> vielen anderen Sprachen).
>
> Würde also heißen, dass ich am besten noch eine Funktion schreibe und
> das Array an diese Übergebe... Sonst kann ich mir nicht vorstellen wie
> ich das hinbekommen soll, dass ich außerdem des IFs darauf zugreifen
> kann.

Nope.
Das ganze sieht wie ein Zeichensatz für eine LED-Matrix aus.
Das Mittel der Wahl wäre für dich eine 2-dimensionales Array. In der 
einen Dimension ist der Buchstabe der Index, in der anderen Dimension 
stehen die Codes, die du an die LED-Matrix weiter geben musst.

von Karl H. (kbuchegg)


Lesenswert?

Michael N. schrieb:

>> Bist Du Dir klar, dass Du hier einen Zeiger auf das erste Element eines
>> char-Arrays übergibst? Wenn Du nur einen Buchstaben brauchst, solltest
>> Du auch nur einen übergeben.
>
> Genau das wollte ich.

warum tust du es dann nicht?

Die Funktion soll 1 Buchstaben anzeigen. Also bekommt sie auch nur 1 
Buchstaben.
1
void buchstabe(char buchstabe)
2
{
3
   ...
4
}


und der Aufrufer entscheidet, welchen Buchstaben aus einem String er 
sehen möchte
1
   ....
2
3
   buchstabe( string[0] );
4
   buchstabe( string[1] );
5
   ...

oder vielleicht nacheinander alle Buchstaben des STrings
1
  int len = strlen( string );
2
3
  for( i = 0; i < len; ++i )
4
    buchstabe( string[i] );

von Michael N. (garril)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Das ganze sieht wie ein Zeichensatz für eine LED-Matrix aus.
> Das Mittel der Wahl wäre für dich eine 2-dimensionales Array. In der
> einen Dimension ist der Buchstabe der Index, in der anderen Dimension
> stehen die Codes, die du an die LED-Matrix weiter geben musst.

Hm, das müsste tatsächlich eine wesentlich bessere Lösung sein.
Array[A][]={1,5,11,23}
Da hätte ich dann für jeden Buchstaben ein eigenes Array mit den LEDs 
die geschaltet werden müssen.
Das würde jetzt erstmal das Problem lösen (bzw. übergehen)

von Karl H. (kbuchegg)


Lesenswert?

Michael N. schrieb:

> Da ich immer nur eine LED an einer LED-Matrix anschalte bin ich darauf
> angewiesen, dass das Programm schnell abläuft (da die LEDs ja sonst
> flackern).
> Wenn ich nun an die Funktion LEDan() zusätzlich einen Parameter
> übergebe, wie lange nach dem Anschalten einer LED gewartet werden soll,
> bis die nächste angeht, dauert das anscheinend ewig und die LED-Matrix
> flackert also... Wenn ich aber nun in der LEDan()-Funktion den Wert fest
> programmiere, dann funktioniert das ganze super.

Der ganze Ansatz taugt nichts.
Du musst die eigentliche Anzeigeroutine von dem Teil der auswählt welche 
LED leuchten soll und welche nicht, komplett trennen.
Die Anzeigeschleife einer LED-Matrix wird in eine Interruptfunktion 
gelegt, die sich aus einem Array (welches einen virtuellen Bildschirm 
realisiert) in schneller Folge rausholt was im Moment in einer 
Zeile/Spalte gerade anzuzeigen ist.

D.h. die LED-Matrix wird im Hintergrund angesteuert. Dein eigentliches 
Programm hat dann alle Zeit der Welt, die LED symbolisch ein/aus zu 
schalten, in dem sie in diesem virtuellen Bildschirm die entsprechenden 
Bits setzt/löscht.

von Karl H. (kbuchegg)


Lesenswert?

Michael N. schrieb:
> Karl Heinz Buchegger schrieb:
>> Das ganze sieht wie ein Zeichensatz für eine LED-Matrix aus.
>> Das Mittel der Wahl wäre für dich eine 2-dimensionales Array. In der
>> einen Dimension ist der Buchstabe der Index, in der anderen Dimension
>> stehen die Codes, die du an die LED-Matrix weiter geben musst.
>
> Hm, das müsste tatsächlich eine wesentlich bessere Lösung sein.
> Array[A][]={1,5,11,23}
> Da hätte ich dann für jeden Buchstaben ein eigenes Array mit den LEDs
> die geschaltet werden müssen.

Nicht für jeden Buchstaben.
Für alle Buchstaben ein einziges Array!
(oder maximal eine Kombination aus einem Pointerarray und zusätzlichen 
Arrays, wenn du unterschiedliche Spaltenzahlen pro Buchstabe hast).
Du willst diesen Quatsch mit den 100-tausend if ja gar nicht haben, wenn 
es nicht sein muss. Und es muss nicht sein.

von Michael N. (garril)


Lesenswert?

Karl Heinz Buchegger schrieb:
>>> Bist Du Dir klar, dass Du hier einen Zeiger auf das erste Element eines
>>> char-Arrays übergibst? Wenn Du nur einen Buchstaben brauchst, solltest
>>> Du auch nur einen übergeben.
>>
>> Genau das wollte ich.
>
> warum tust du es dann nicht?

Habe ich falsch formuliert. Ich wollte nen Pointer übergeben und nicht 
nur nen Zeichen...Von daher war das für mich schon passend.
Aber könnte natürlich auch einfach nur einen Buchstaben übergeben und 
das halt für jeden machen.

von Michael N. (garril)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Michael N. schrieb:
>> Karl Heinz Buchegger schrieb:
>>> Das ganze sieht wie ein Zeichensatz für eine LED-Matrix aus.
>>> Das Mittel der Wahl wäre für dich eine 2-dimensionales Array. In der
>>> einen Dimension ist der Buchstabe der Index, in der anderen Dimension
>>> stehen die Codes, die du an die LED-Matrix weiter geben musst.
>>
>> Hm, das müsste tatsächlich eine wesentlich bessere Lösung sein.
>> Array[A][]={1,5,11,23}
>> Da hätte ich dann für jeden Buchstaben ein eigenes Array mit den LEDs
>> die geschaltet werden müssen.
>
> Nicht für jeden Buchstaben.
> Für alle Buchstaben ein einziges Array!
> (oder maximal eine Kombination aus einem Pointerarray und zusätzlichen
> Arrays).
> Du willst diesen Quatsch mit den 100-tausend if ja gar nicht haben, wenn
> es nicht sein muss. Und es muss nicht sein.

Stimmt, das will ich wirklich nicht haben (so viele ifs).
Naja ich meine halt EIN Array... (Sind aber ja wie mehrere Arrays in 
einem eben...)

von Karl H. (kbuchegg)


Lesenswert?

Michael N. schrieb:
> Karl Heinz Buchegger schrieb:
>>>> Bist Du Dir klar, dass Du hier einen Zeiger auf das erste Element eines
>>>> char-Arrays übergibst? Wenn Du nur einen Buchstaben brauchst, solltest
>>>> Du auch nur einen übergeben.
>>>
>>> Genau das wollte ich.
>>
>> warum tust du es dann nicht?
>
> Habe ich falsch formuliert. Ich wollte nen Pointer übergeben

Wozu?

> nur nen Zeichen...Von daher war das für mich schon passend.
> Aber könnte natürlich auch einfach nur einen Buchstaben übergeben und
> das halt für jeden machen.

Du kannst aufbauend auf deiner Buchstaben-Funktion ganz leicht eine 
Funktion machen, die einen beliebigen String ausgeben kann
1
void string( char* str )
2
{
3
  while( *str )
4
    buchstabe( *str++ );
5
}

Fertig. Jetzt hast du das beste aus 2 Welten. Eine Funktion, die einen 
einzelnen Buchstaben ausgeben kann und eine Funktion, die einen 
kompletten String ausgeben kann.
1
int main()
2
{
3
  ...
4
5
  buchstabe( '*' );
6
  string ( "Hallo" );
7
  ...
8
}


Das Geheimnis der Programmierung besteht nicht darin sich eierlegende 
Wollmilchsau-Funktionen zu bauen, sondern aufbauend auf einfachen 
Funktionen sich damit einen Baukasten von immer mächtigeren Funktionen 
zurecht zu legen.


Einschub:
Wenn du mit Pointern noch nicht so weit bist. Die Funktion string kann 
man auch so schreiben
1
void string( char * str )
2
{
3
  int len = strlen( str );
4
  int i;
5
6
  for( i = 0; i < len; ++i )
7
    buchstabe( str[i] );
8
}

Ist aber
* nicht so schön wegen der zusätzlichen Variablen
* langsamer, wegen des zusätzlichen Aufrufs von strlen
* nicht die C-typische Art und Weise, wie man mit Strings in C arbeitet,
  wenn man auf die einzelnen Buchstaben runter muss.

von Oliver (Gast)


Lesenswert?

Karl-Heinz schrieb:

>Das passt schon so wie er das hatte.
>Hier ist *leds kein Pointer sondern evaluiert zum ersten Array-Element
>und der sizeof nimmt sich dann von dem den Datentyp

Stimmt, da habe ich Unsinn erzählt. sizeof(*leds) entspricht 
sizeof(int), sizeof(&leds) würde sizeof(int*), also der Pointergröße, 
entsprechen.

von Michael N. (garril)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Michael N. schrieb:
>> Karl Heinz Buchegger schrieb:
>>>>> Bist Du Dir klar, dass Du hier einen Zeiger auf das erste Element eines
>>>>> char-Arrays übergibst? Wenn Du nur einen Buchstaben brauchst, solltest
>>>>> Du auch nur einen übergeben.
>>>>
>>>> Genau das wollte ich.
>>>
>>> warum tust du es dann nicht?
>>
>> Habe ich falsch formuliert. Ich wollte nen Pointer übergeben
>
> Wozu?

Naja für die eierlegend Wollmilchsau. Die braucht ja nen char-Array (hab 
gelesen, dass es keine normalen Strings in C gibt) um ihn dann zu 
zerlegen.

Karl Heinz Buchegger schrieb:
> void string( char* str )
> {
>   while( *str )
>     buchstabe( *str++ );
> }

WOW. Das nenn ich mal kurz und knackig. Werd ich gleich mal 
ausprobieren.

von Michael N. (garril)


Lesenswert?

Wie befülle ich nun das zweidimensionale Array?

In einem Array können ja nur Werte das gleichen Typs gespeichert werden.
D.h. Array[A][0] würde ja schonmal gar nicht gehen.

Ich müsste also Beispielsweise mit Array[0][0] arbeiten (Dann kann ich 
aber leider auch nicht direkt ein A eingeben und komme dahin. Höchstens 
wieder über den Umweg der ascii-Werte.

Oder geht das mit gemischten Werten irgendwie?

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Michael N. schrieb:
> Naja für die eierlegend Wollmilchsau

Besonders am Anfang sollte man von unötigen "Tricks" Abstand nehmen und 
lieber solide Programmieren...

Und die Doku lesen!

Michael N. schrieb:
> Wenn ich nun an die Funktion LEDan() zusätzlich
> einen Parameter übergebe
vermutlich nutzt du die delay funktionen und die funktionieren nicht so 
sehr gut mit variablen Argumenten! Siehe Doku!

von Michael N. (garril)


Lesenswert?

"Die Bibliotheksfunktionen funktionieren allerdings nur dann korrekt, 
wenn sie mit zur Übersetzungszeit (beim Compilieren) bekannten 
konstanten Werten aufgerufen werden. Der Quellcode muss mit 
eingeschalteter Optimierung übersetzt werden, sonst wird sehr viel 
Maschinencode erzeugt, und die Wartezeiten stimmen nicht mehr mit dem 
Parameter überein."

Tatsächlich da stehen wirklich zwei Sätze darüber in der Doku. Die hab 
ich leider beim Durchlesen (da hatte ich das Problem noch nicht) einfach 
überlesen.

von Udo (Gast)


Lesenswert?

Wenn Du Platz hast im Speicher, dann schon. Hinter jedem Buchstaben 
verbirgt sich ja sein ASCII-Code. Also: Array['p'][0]
Sollen nicht alle Zeichen dargestellt werden, dann Array komprimieren.
Zahlen beginnen bei Index 0: Aufruf => Array[Ziffer][0]
Danach meinetwegen die Großbuchstaben ab Index 10: Aufruf => 
Array[GBuchstabe-'A'+10][0] (kann man auch kürzer schreiben, so ist's 
aber übersichtlich und der Compiler verfeinert das sowieso.)

von Udo (Gast)


Lesenswert?

Udo schrieb:
> Zahlen beginnen bei Index 0: Aufruf => Array[Ziffer][0]

mir fällt grad auf: Ziffern sind ja hier auch nur Zeichen, also: 
Array[Ziffer-'0'][0]

von Michael N. (garril)


Lesenswert?

So ganz wills noch nicht:
1
//Neuer Code: Hier kommt später noch mehr, deshalb ist das Array so groß
2
//Funktioniert allerdings nicht
3
int buchstabenarray[50][35]={
4
{1,2,3,4,5,6,11,16,17,18,19,21,26,31,32,33,34,35},
5
{1,2,3}
6
};
7
LEDsan(buchstabenarray[0]);
Vor der mehrdimensionalen Array hab ich das ganze so aufgerufen:
1
//Vorher funktionierender Code:
2
int leds[]={1,2,3,4,5,6,11,16,17,18,19,21,26,31,32,33,34,35};
3
LEDsan(leds);

von Karl H. (kbuchegg)


Lesenswert?

1
int charCodes[50][5]=
2
{
3
  {  1,  2,  3,  4,  5 },     // die Codes für 'A'
4
  {  6,  7,  8,  9, 10 },     // die Codes für 'B'
5
  { 11, 12, 13, 14, 15 },     // die Codes für 'C'
6
  ...
7
};
8
9
void buchstabe( char c )
10
{
11
  LEDsan( charCodes[c - 'A'] );   // - 'A', weil der erste Datensatz in
12
                                  // charCodes für den Buchstaben 'A' ist
13
}


Sind das bei dir eigentlich LED-Nummern?
1
int buchstabenarray[50][35]={
2
{1,2,3,4,5,6,11,16,17,18,19,21,26,31,32,33,34,35},

ungeschickt. Eine LED kann nur entweder ein oder aus sein. Man kann 
daher immer 8 LED zu einem Byte zusammenfassen und mit 1 Byte den 
Zustand von jeweils 8 LED beschreiben.

zb bei spaltenweiser Beschreibung

   +---+---+---+---+---+
7  |   |   | 1 |   |   |
   +---+---+---+---+---+
6  |   | 1 |   | 1 |   |
   +---+---+---+---+---+
5  | 1 |   |   |   | 1 |
   +---+---+---+---+---+
4  | 1 |   |   |   | 1 |
   +---+---+---+---+---+
3  | 1 | 1 | 1 | 1 | 1 |
   +---+---+---+---+---+
2  | 1 |   |   |   | 1 |
   +---+---+---+---+---+
1  | 1 |   |   |   | 1 |
   +---+---+---+---+---+
0  |   |   |   |   |   |
   +---+---+---+---+---+

   0x3E    0x88    0x3E
       0x48    0x48

die 5 Codes beschreiben, welche LED leuchten müssen, damit du das als 
'A' liest. Und so kann man das für jedes Zeichen machen, indem man es in 
eine 8*5 Matrix verpackt und jeweils die 8 übereinander liegenden Bits 
zu einem Byte zusammenfasst.

   +---+---+---+---+---+
7  | 1 | 1 | 1 | 1 |   |
   +---+---+---+---+---+
6  | 1 |   |   |   | 1 |
   +---+---+---+---+---+
5  | 1 |   |   |   | 1 |
   +---+---+---+---+---+
4  | 1 | 1 | 1 | 1 |   |
   +---+---+---+---+---+
3  | 1 |   |   |   | 1 |
   +---+---+---+---+---+
2  | 1 |   |   |   | 1 |
   +---+---+---+---+---+
1  | 1 | 1 | 1 | 1 |   |
   +---+---+---+---+---+
0  |   |   |   |   |   |
   +---+---+---+---+---+

   0xFE    0x92    0x6C
       0x92    0x92

1
unsigned char charCodes[50][5]=
2
{
3
  { 0x3E, 0x48, 0x88, 0x48, 0x3E },   // 'A'
4
  { 0xFE, 0x92, 0x92, 0x92, 0x6C },   // 'B'
5
  ...
6
};

von Thomas E. (thomase)


Lesenswert?

Michael N. schrieb:
> int buchstabenarray[50][35

50 x 35 x 2 = 1500 Byte. Bisschen viel.

Michael N. schrieb:
> int buchstabenarray[50][35]={
> {1,2,3,4,5,6,11,16,17,18,19,21,26,31,32,33,34,35},
> {1,2,3}
> };

So steuert man doch keine Matrix an.

das ist ein "A":
00010000
00101000
01000100
11111110
10000010
10000010
10000010
00000000

Das kommt ins Array rein. Das wird Zeilenweise ausgegeben und jeder 
Buchstabe hat 8 Byte. Macht bei 52 Buchstaben 416 Byte.

mfg.

Edit: Da war mal wieder einer schneller
Immerhin die Variante für 8x8 zeilenweise.

von Michael N. (garril)


Lesenswert?

Ich sehe schon, dass ich von Anfang an einiges hätte besser machen 
können.
Aber dafür hab ich ja mit Mikrocontrollern angefangen. Möchte ja was 
lernen.

Karl Heinz Buchegger schrieb:
> int buchstabenarray[50][35]={
> {1,2,3,4,5,6,11,16,17,18,19,21,26,31,32,33,34,35},
Ja da gehen dann die LEDs 1,2,3 usw. nacheinander an (so war es 
zumindest ursprünglich geplant)

Thomas Eckmann schrieb:
> 50 x 35 x 2 = 1500 Byte. Bisschen viel.
Das ist tatsächlich recht viel. Ich werde mich mal mit der 8 Byte-Lösung 
beschäftigen (bei mir sinds sogar nur 5 Byte, da ich nur 5x7 LEDs habe)

Allerdings hab ich meine Matrix komplett ohne Transistoren gebaut. 
Deshalb möchte ich immer nur eine LED angeschaltet haben.(Lässt sich 
damit aber ja natürlich auch machen)

Habe jetzt auch nen super C-Tutorial gefunden. Ich probier jetzt mal, ob 
ichs zum laufen bekomme...

von Karl H. (kbuchegg)


Lesenswert?

Michael N. schrieb:
> Ich sehe schon, dass ich von Anfang an einiges hätte besser machen
> können.
> Aber dafür hab ich ja mit Mikrocontrollern angefangen. Möchte ja was
> lernen.

Dein Problem ist, dass eine LED Matrix nicht wirklich etwas für Anfänger 
ist. Um das vernünftig hinzukriegen, muss man schon etwas können und 
Erfahrung haben.

> Allerdings hab ich meine Matrix komplett ohne Transistoren gebaut.
> Deshalb möchte ich immer nur eine LED angeschaltet haben.(Lässt sich
> damit aber ja natürlich auch machen)

Autsch. Das wird eng. Deine Matrix wird sehr dunkel werden und ob du das 
Flackern in den Griff kriegst, ist eine andere Frage. Murks ist es 
allemal.

von Thomas E. (thomase)


Lesenswert?

Michael N. schrieb:
> Deshalb möchte ich immer nur eine LED angeschaltet haben.(

Das bringt nichts.

Du hast 35 LEDs. Eine braucht dauerhaft 2 mA, damit sie normal hell 
leuchtet. Zusammen also 70mA.

Und das sind nur die Low Current.

In einer Matrix sollen die LEDs aber genauso hell leuchten, obwohl sie 
immer wieder nur kurz angeschaltet werden. Das erreicht man dadurch, daß 
man den Strom in einer 5x7 Matrix, die Zeilenweise angesteuert wird, auf 
das siebenfache erhöht. Dann leuchtet sie für unser Auge bei 
ausreichender Wiederholrate ständig. Erhöht man den Strom nicht, glimmt 
sie nur leicht.

Steuerst du nacheinander alle 35 LEDs einzeln an, muss der Strom auf das 
35-fache erhöht werden. Das macht die LED aber nicht mit. Da gibt es 
auch eine Grenze. Der Controllerport kann dir auch keine 70mA liefern.

Wie Karl Heinz schon andeutete, ist das komplizierter als es auf den 
ersten Blick scheint.

Karl Heinz Buchegger schrieb:
> Dein Problem ist, dass eine LED Matrix nicht wirklich etwas für Anfänger
> ist. Um das vernünftig hinzukriegen, muss man schon etwas können und
> Erfahrung haben.


mfg.

von Michael N. (garril)


Lesenswert?

Thomas Eckmann schrieb:
> Du hast 35 LEDs. Eine braucht dauerhaft 2 mA, damit sie normal hell
> leuchtet. Zusammen also 70mA.
>
> Und das sind nur die Low Current.

Ich benutze nicht die lc-Variante sondern gescheide^^ Laut Datenblatt 
also 20-30mA/LED

Thomas Eckmann schrieb:
> Das erreicht man dadurch, daß
> man den Strom in einer 5x7 Matrix, die Zeilenweise angesteuert wird, auf
> das siebenfache erhöht. Dann leuchtet sie für unser Auge bei
> ausreichender Wiederholrate ständig. Erhöht man den Strom nicht, glimmt
> sie nur leicht.

Ist mir auch bekannt.
Habe das ganze allerdings getestet und es funktioniert (selbst mit allen 
35 LEDs auf einmal) auch recht gut (Die LED wird an der oberen Grenze 
betrieben, die laut Datenblatt möglich ist. Andere Widerstände hatte ich 
eh nicht zur Hand^^).
Habe halt ein bisschen am Timer rumgeschraubt, und es geschafft, dass 
die LEDs ausreichend stark leuchten und nicht flackern.
Das klappt also soweit schon. (Auch wenn es womöglich heller gehen 
würde, so reicht es, sonst blendet es sowieso)

Eine Zeilenweise Ansteuerung wäre bei meiner Matrix aufgrund der Bauart 
sowieso nicht möglich (diese Bauweise wurde mir aber hier im Forum 
empfohlen, weil ich weniger IO-Pins verbrauche, auch wenn ich genug 
gehabt hätte)

Karl Heinz Buchegger schrieb:
> Dein Problem ist, dass eine LED Matrix nicht wirklich etwas für Anfänger
> ist. Um das vernünftig hinzukriegen, muss man schon etwas können und
> Erfahrung haben.

Was wäre denn ein Anfängerprojekt?
Bin gerne für Vorschläge offen.

von Karl H. (kbuchegg)


Lesenswert?

Michael N. schrieb:
> Thomas Eckmann schrieb:
>> Du hast 35 LEDs. Eine braucht dauerhaft 2 mA, damit sie normal hell
>> leuchtet. Zusammen also 70mA.
>>
>> Und das sind nur die Low Current.
>
> Ich benutze nicht die lc-Variante sondern gescheide^^ Laut Datenblatt
> also 20-30mA/LED

noch schlimmer. Thomas hat schon zu deinen Gunsten 2mA Low Current LED 
angenommen.
denk drann. Deine LED leuchtet nur 1/35 der Zeit. Damit sie wieder auf 
normale Helligkeit kommt, muss sie in dieser kurzen Zeit 35 mal so hell 
leuchten. D.h. du musst den 35 fachen Strom durchjagen. 35 * 20 = 700mA

Das hält deine LED nicht aus und dein µC auch nicht.

Deshalb sagte ich: deine Matrix wird sehr dunkel werden :-)

> Eine Zeilenweise Ansteuerung wäre bei meiner Matrix aufgrund der Bauart
> sowieso nicht möglich (diese Bauweise wurde mir aber hier im Forum
> empfohlen, weil ich weniger IO-Pins verbrauche, auch wenn ich genug
> gehabt hätte)

Ob zeilenweise oder spaltenweise ist erst mal egal. Hauptsache mehrere 
auf einmal. Dann reduziert sich der Multiplex von 1:35 auf 1:7 oder 1:5 
und der Strom den du durch jede LED jagen musst reduziert sich.

> Was wäre denn ein Anfängerprojekt?

Lauflichter.
Irgendwann kann man zb mit einer 7-Segment Anzeige das erst mal sich 
ansehen, wie Multiplexing überhaupt sinnvoll funktioniert. Und dann 
kommt irgendwann die Matrix.

von Michael N. (garril)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Ob zeilenweise oder spaltenweise ist erst mal egal. Hauptsache mehrere
> auf einmal. Dann reduziert sich der Multiplex von 1:35 auf 1:7 oder 1:5
> und der Strom den du durch jede LED jagen musst reduziert sich.
Werde mal schauen, was ich an Transistoren da habe, könnte dafür 
reichen. Dann bau ich das so um, dass ich wirklich jede Spalte (Wäre am 
sinnvollsten weil die Spalten ja länger sind als die Zeilen, nämlich 7 
LEDs)

Karl Heinz Buchegger schrieb:
> Lauflichter.
> Irgendwann kann man zb mit einer 7-Segment Anzeige das erst mal sich
> ansehen, wie Multiplexing überhaupt sinnvoll funktioniert. Und dann
> kommt irgendwann die Matrix.

Ein bisschen Spektakulärer dürfte es schon sein :)
Lauflichter habe ich schon ein paar gebaut (allerdings halt ohne 
Mikrocontroller).
Aber ein Lauflicht würde ich ohne Probleme hinbekommen, jetzt auch mit 
Mikrocontroller.
Dann wäre also jetzt deine Empfehlung eine 7-Segment-Anzeige (hab ich 
auch schon drüber nachgedacht).
Mal schauen, dann zieh ich vielleicht ein anderes Projekt der jetzigen 
LED-Anzeige vor.

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.