Code Explodiert - Tiny13

OP #2625173
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
OP #2625186
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
#2625195
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
OP #2625354
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
}
#2625374
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
#2625402
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
OP #2625420
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
}
Gast #2625431
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.
OP #2625440
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?
Gast #2625448
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.
#2625449
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?! 
;-)
OP #2625508
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
Gast #2625514
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.
Gast #2625703
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren