Forum: Compiler & IDEs Code Explodiert - Tiny13


von Ste M. (joker)


Lesenswert?

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

von guenni (Gast)


Lesenswert?

Ersetze die IF-Schleife durch eine FOR-Abfrage!

von Floh (Gast)


Lesenswert?

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.

von strunz (Gast)


Lesenswert?

Zufällig delay_ms mit einer Variable aufgerufen?

von Ste M. (joker)


Lesenswert?

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

von Marius W. (mw1987)


Lesenswert?

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

von Ste M. (joker)


Lesenswert?

Alles klar.

Melde mich später wieder.

Tut mir Leid. Wollte keine Glaskugelfragen stellen ;)

Grüße Stefan

von Ste M. (joker)


Lesenswert?

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
}

von Patrick (Gast)


Lesenswert?

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

von Peter II (Gast)


Lesenswert?

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?

von Ste M. (joker)


Lesenswert?

Wieso explodiert der code erst wenn ich die If-Abfrage einkommentiere?

von Sparfuchs (Gast)


Lesenswert?

Stefan Marquardt schrieb:
> int clk_servo_u;
> int clk_servo_o;

Reichen nicht uint8_t? Sonst platzt auch noch das RAM. ;-)

von Roland P. (pram)


Lesenswert?

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

von Peter II (Gast)


Lesenswert?

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.

von Ste M. (joker)


Lesenswert?

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

von Edi R. (edi_r)


Lesenswert?

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

von Ste M. (joker)


Lesenswert?

Er soll ja auch bei einem Low Pegel reagieren. So Kann ich die Internen 
Pullups aktivieren und brauche keine externen

von Marcus B. (raketenfred)


Lesenswert?

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

von Peter II (Gast)


Lesenswert?

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.

von Peter II (Gast)


Lesenswert?

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

von Ste M. (joker)


Lesenswert?

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
}

von Ste M. (joker)


Lesenswert?

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

von Peter II (Gast)


Lesenswert?

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.

von Ste M. (joker)


Lesenswert?

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?

von Trolljäger (Gast)


Lesenswert?

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.

von Peter II (Gast)


Lesenswert?

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.

von Marcus B. (raketenfred)


Lesenswert?

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?! 
;-)

von Ste M. (joker)


Lesenswert?

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

von Ste M. (joker)


Lesenswert?

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

von Peter II (Gast)


Lesenswert?

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.

von Ste M. (joker)


Lesenswert?

Ich lerne eher an Codebeispielen.

Die Stumpfe Theorie ist nichts für mich.

von Rolf M. (rmagnus)


Lesenswert?

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.

von Peter II (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.