Hallo zusammen, so Ostern ist da. Das heißt wieder Zeit zum Basteln ;) Ich habe folgendes Problem: Ich will einen Tiny 13 als Taktgeber für zwei Servos nehmen. Wenn ich aber eine Pinabfrage mit einer if schleife mache explodiert mir der Code auf über 4 kB. Kommentiere ich sie aus, dann ist alles kein Problem. Die Abfrage ist dazu da, um einen Variablenwert zu ändern. Also alle If (Pin Low) { Variable = Wert X } Woran liegt das? Im Netz gibt es so viele codes für den Tiny13, die auch if Schleifen enthalten. Auf eure Hilfe freue ich mich Gruß Stefan
Stefan Marquardt schrieb: > Wenn ich aber eine Pinabfrage mit einer if schleife mache explodiert mir > > der Code auf über 4 kB. Wahrscheinlich baust du in die if eine float-Variable ein? Zeig mal den richtigen Code.
Hallo, bin gerade unterwegs. Aber: die Variablen sind alt int deklariert. Wie schon richtig erraten: Ich habe Delay_ms drinne. Aber nur das hbelegt mir gerade mal 6 % im Flash. sobald ich aber eine If-Abfrage wieder einkommentiere sprengt's den Tiny Grüße Stefan
Dann hast du sicherlich delay_ms mit nicht-konstanten Parametern aufgerufen... Dann kommt automatisch das ganze Floating-Point-Zeug mit in den Code und sprengt den Flash. Aber ohne Code können wir hier eigentlich nur die Glaskugel befragen und die ist im Osterurlaub. Gruß Marius
Alles klar. Melde mich später wieder. Tut mir Leid. Wollte keine Glaskugelfragen stellen ;) Grüße Stefan
So jetzt: das ist der Code:
1 | #include <avr/io.h> |
2 | #include <stdlib.h> |
3 | #include <stdint.h> |
4 | #ifndef F_CPU
|
5 | #define F_CPU 1000000UL
|
6 | #endif
|
7 | #include <util/delay.h> |
8 | |
9 | int clk_servo_u; |
10 | int clk_servo_o; |
11 | |
12 | |
13 | int main (void) |
14 | {
|
15 | |
16 | clk_servo_u = 1.5; |
17 | |
18 | DDRB = 0b00000011; // PINB0, PINB1 sind Augänge --- PINB2 - PINB7 Eingänge |
19 | PORTB = 0b11111100; // Interne Pullups an PINB2 - PINB7 aktiv |
20 | |
21 | |
22 | while(1) |
23 | {
|
24 | if (PINB &= ~ (1<<PINB2)) |
25 | {
|
26 | clk_servo_u = 20; |
27 | }
|
28 | //
|
29 | // else if (PINB & (1<<PB2))
|
30 | // {
|
31 | // clk_servo_u = 1.5;
|
32 | // }
|
33 | |
34 | |
35 | |
36 | // if (PINB &= ~ (1<<PINB3))
|
37 | // {
|
38 | // clk_servo_o = 20;
|
39 | // }
|
40 | // else if (PINB & (1<<PB3))
|
41 | // {
|
42 | // clk_servo_o = 1.5;
|
43 | // }
|
44 | |
45 | |
46 | PORTB |= (1<<PB0); |
47 | _delay_ms(clk_servo_u); |
48 | PORTB &= ~ (1<<PB0); |
49 | _delay_ms(20-clk_servo_u); |
50 | |
51 | PORTB |= (1<<PB1); |
52 | _delay_ms(clk_servo_u); |
53 | PORTB &= ~ (1<<PB1); |
54 | _delay_ms(20-clk_servo_u); |
55 | }
|
56 | |
57 | |
58 | }
|
Stefan Marquardt schrieb: > _delay_ms(clk_servo_u); Na, da haben wir's ja auch schon, was bereits die Vorposter vermuteten: Delay mit nicht-konstanten Parametern aufgerufen...
wie schon oben vermutet, _delay_ms muss mit einer konstanden aufgerufen werden! > int clk_servo_u; > clk_servo_u = 1.5; was soll das, glaubst du wirklich das in ein int soetwas reinpasst?
Stefan Marquardt schrieb: > int clk_servo_u; > int clk_servo_o; Reichen nicht uint8_t? Sonst platzt auch noch das RAM. ;-)
ist die IF-Abfrage weg, kann zur Compilezeit schon bestimmt werden, dass _delay_ms IMMER mit dem gleichen Parameter aufgerufen wird und wird wegoptimiert. Rufe _delay_ms immer nur mit konstanten Werten auf. Setze dir Flags oder mach es in etwa so: if (clk_servo_u == 20) _delay_ms(20); if (clk_servo_u == 2) _delay_ms(1.5); Sowas ist ebenso sinnfrei (Mischung int/float): int clk_servo_u; clk_servo_u = 1.5; Gruß Roland
Stefan Marquardt schrieb: > Wieso explodiert der code erst wenn ich die If-Abfrage einkommentiere? weil du damit clk_servo_u änderst, damit kann es der optimerer für _delay_ms nicht mehr sinnvoll verwenden. Das Problem ist also nicht das IF sonder der code in der {} vom If.
wie kann ich meinen Code so Optimieren? es soll ja nur der wert geändert werden der High-zeit bei einer 0 am PB2 bzw PB3
Bist Du Dir sicher, dass Du weißt, was in der Zeile
1 | if (PINB &= ~ (1<<PINB2)) |
passiert? Das ist nämlich eine Zuweisung. Meinst Du vielleicht:
1 | if (PINB & (1<<PINB2)) |
Er soll ja auch bei einem Low Pegel reagieren. So Kann ich die Internen Pullups aktivieren und brauche keine externen
1 | while(1) |
2 | { |
3 | bool pin_low=PINB &= ~ (1<<PINB2); |
4 | |
5 | |
6 | |
7 | PORTB |= (1<<PB0); |
8 | if(pin_low){ |
9 | _delay_ms(20); |
10 | } |
11 | else |
12 | { |
13 | _delay_ms(1.5);//TODO: Float ändern |
14 | } |
15 | PORTB &= ~ (1<<PB0); |
16 | if(!pin_low) |
17 | _delay_ms(20-1.5); |
18 | |
19 | PORTB |= (1<<PB1); |
20 | if(pin_low){ |
21 | _delay_ms(20); |
22 | } |
23 | else |
24 | { |
25 | _delay_ms(1.5);//TODO: Float ändern |
26 | } |
27 | PORTB &= ~ (1<<PB1); |
28 | if(!pin_low) |
29 | _delay_ms(20-1.5); |
30 | } |
Nicht getestet, sollte aber kompakten Flash liefern. Den Floatwert (1.5) musst du unbedingt noch irgendwie ändern(Takt verdoppeln-> 3 raus machen z.b. - ist aber auch wieder mehr Strom...) Ganz elegant würde man das ganze mit Timern(überhaupt vorhanden?!) lösen, die einen Interupt zum wieder aufwachen auslösen und der Controller ist solange im Sleepmodus-> sehr Strom effektiv
Marcus B. schrieb: > Den Floatwert (1.5) > musst du unbedingt noch irgendwie ändern(Takt verdoppeln-> 3 raus machen warum sollte er das machen? Das sollte keine auswirkung auf den größe von dem code haben. Es hat schon einen sinn das jemand _delay_ms mit float zugelassen hat.
Marcus B. schrieb: > Den Floatwert (1.5) > musst du unbedingt noch irgendwie ändern(Takt verdoppeln-> 3 die zeit im ms ist auch mit den 10 fachen takt gleich
Meint ihr das funktioniert auch so???
1 | #include <avr/io.h> |
2 | #include <stdlib.h> |
3 | #include <stdint.h> |
4 | #ifndef F_CPU
|
5 | #define F_CPU 1000000UL
|
6 | #endif
|
7 | #include <util/delay.h> |
8 | |
9 | uint8_t clk_servo_u; |
10 | uint8_t clk_servo_o; |
11 | |
12 | |
13 | int main (void) |
14 | {
|
15 | |
16 | clk_servo_u = 1.5; |
17 | |
18 | DDRB = 0b00000011; // PINB0, PINB1 sind Augänge --- PINB2 - PINB7 Eingänge |
19 | PORTB = 0b11111100; // Interne Pullups an PINB2 - PINB7 aktiv |
20 | |
21 | |
22 | while(1) |
23 | {
|
24 | if (PINB &= ~ (1<<PINB2)) |
25 | {
|
26 | PORTB |= (1<<PB0); |
27 | _delay_ms(18.5); |
28 | PORTB &= ~ (1<<PB0); |
29 | _delay_ms(1.5); |
30 | }
|
31 | |
32 | else if (PINB & (1<<PB2)) |
33 | {
|
34 | PORTB |= (1<<PB0); |
35 | _delay_ms(18); |
36 | PORTB &= ~ (1<<PB0); |
37 | _delay_ms(2); |
38 | }
|
39 | |
40 | |
41 | |
42 | if (PINB &= ~ (1<<PINB3)) |
43 | {
|
44 | PORTB |= (1<<PB1); |
45 | _delay_ms(18.5); |
46 | PORTB &= ~ (1<<PB1); |
47 | _delay_ms(1.5); |
48 | }
|
49 | else if (PINB & (1<<PB3)) |
50 | {
|
51 | PORTB |= (1<<PB1); |
52 | _delay_ms(18); |
53 | PORTB &= ~ (1<<PB1); |
54 | _delay_ms(2); |
55 | }
|
56 | |
57 | }
|
58 | |
59 | |
60 | }
|
Ich kenne mich mit Timern nicht aus und kapier das mit den Registern auch nicht. Sonst würde ich das ganze (wenns geht) 2 mal im atmega32 laufen lassen und bräuchte den Tiny nicht
Stefan Marquardt schrieb: > Ich kenne mich mit Timern nicht aus und kapier das mit den Registern > auch nicht. Sonst würde ich das ganze (wenns geht) 2 mal im atmega32 > laufen lassen und bräuchte den Tiny nicht warum lernst du es dann nicht? Oder fragst wenn du nicht weiter kommst? Man kann bequem 8 servos mit einem AtMega32 oder sogar einen Tiny wenn er genug anschlüsse hätte betreiben.
Weil ich es nicht versteh wie es im GCC Tutorial geschrieben ist. In dem Fall anders gesagt. Wir programmieren einen roboter. Die Servus brauchen wir für einen Greifarm. Nur sollte das Hauptprogramm nicht unterbrochen werden weil sonst Schritte verloren gehen könnten bei den Schrittmotoren. Kann mir jemand das in anderen worten erklären?
Stefan Marquardt schrieb: > Weil ich es nicht versteh wie es im GCC Tutorial geschrieben ist. Und 'Servus' ist eine bayrische Begrüßung, keine Bezeichnung für einen Servomotor. Ich schäme mich mitlerweile, in diesem Land zu leben.
Stefan Marquardt schrieb: > Nur sollte das Hauptprogramm nicht unterbrochen werden weil > sonst Schritte verloren gehen könnten bei den Schrittmotoren. eigentlich braucht man dafür gar kein Hauptprogramm. Die Motoren werden in TIMER ISR angesteuert. Die Servos können dann eventuell der geleichen ISR oder auch ein der vom 2. Timer angesprochen werden. Dann hast du im hauptprogramm zeit zu berechnen was die Motoren und Servos machen sollen, musst dich aber nicht um die ansteuerung kümmern. eine Timer ISR wird einfach alles X ms aufgerufen. Dazu sollte man erstmal gedanken machen wie gross X gewählt wird. Das ist abhänging der der kleinsten Zeiteinheit die du überbrücken musst. Wenn also dein Schrittmotor alls min 2ms einen neuen Takt braucht, dann kann man stellt man den Timer so das er alles 2ms aufgerufen wird. > Kann mir jemand das in anderen worten erklären? wird schwer wenn es an den Grundlagen fehlt. Dafür musst du schon konrekte Frage stellen.
Peter II schrieb: > Marcus B. schrieb: >> Den Floatwert (1.5) >> musst du unbedingt noch irgendwie ändern(Takt verdoppeln-> 3 raus machen > > warum sollte er das machen? Das sollte keine auswirkung auf den größe > von dem code haben. Es hat schon einen sinn das jemand _delay_ms mit > float zugelassen hat. Idee war einfach gar nicht sich mit der Fließkomma-lib sich rum zu schlagen, weil es unnötig ist, dass der Compiler das auch schafft direkt weg zu optimieren wusste ich nicht. Trolljäger schrieb: > Und 'Servus' ist eine bayrische Begrüßung Servus lat. Sklave, auch wenn wir die schon längst abgeschafft haben?! ;-)
Trolljäger schrieb > Und 'Servus' ist eine bayrische Begrüßung, keine Bezeichnung für einen > Servomotor. Ich schäme mich mitlerweile, in diesem Land zu leben. Ach ja so schlimm ist es auch nicht
Es läuft ein Hauptptogramm in dem ein schrittmotr angesteuert wird. Der robo Fährt seine Strecke. Am Wettkampf fährt er seine Strecke ab und schiebt die Spielzeuge hin und Her. Für eine Aufgabe haben wir einen Greifarm konstruiert. Dieser Soll mit einem Servo hoch und runter fahren. Der Servo braucht aber immer einen Takt. Wie programmier ich einen Timer? Kann mir jemand einen beispielcode schreiben? Also mit Variablen die dann halt geändert werden im Hauptprogramm (1 ms für bsp unten und 2 ms für arm oben
Stefan Marquardt schrieb: > Wie programmier ich > einen Timer? Kann mir jemand einen beispielcode schreiben? einfach mal ins datenblatt lesen oder in der Artikelübersicht suchen. Fang am besten erstmal mit einer LED an die blinkt und das ganze ohne _delay_ms, dann sollte dir die verwendung vom Timer klar werden. Klar könnte ich dir ein Beispiel schreiben, aber ich finde da lernt man nichts. erarbeitet es dir lieber selber, dann weisst du auch warum man es so macht. Und alles Infos die du dafür braucht stehen im Datenblatt zu deinem controler und wie man im GCC eine ISR definiert steht in dem GCC artikel auf dieser webseite mehr braucht man dafür nicht.
Ich lerne eher an Codebeispielen. Die Stumpfe Theorie ist nichts für mich.
Stefan Marquardt schrieb: > uint8_t clk_servo_u; > clk_servo_u = 1.5; Wie dir schon einmal erklärt wurde, funktioniert das nicht. Ein int kann nur ganze Zahlen aufnehmen. Deine 1.5 werden abgerundet auf 1, und die wird dann in clk_servo_u gespeichert.
Stefan Marquardt schrieb: > Ich lerne eher an Codebeispielen. nein machst du nicht, du probierst so lange rum bis du einen vorhandenen code zu abänderst damit er macht was du willst. Lernen ist das aber nicht. Ausserdem kannst du damit nur sachen Programmieren die jemand vor dir schon mal geamcht hat, da kommt nie etwas neue raus. > Die Stumpfe Theorie ist nichts für mich. ein Datenblatt ist nicht Theorie das ist die Praixis, und man sollte es auf jeden Fall mal geslesen haben damit man weiss was der controller kann und wir er arbeitet.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.