Codeverbesserung ?

#3686449
Lesenswert?

Hi,

ich bin grade dabei von Bascom auf C umzusteigen.
Nun hab ich folgenden Code fuer meinen Robo gebastelt.
Intressanterweise funktioniert er nicht auf WinAVR mit gcc 4.3
Unter Linux mit gcc 4.8 geht er astrein.

Er enthaelt hoechstwahrscheinlich einige Fehler.
Anbei noch der Programmablauf, Schaltplan.
1
 
2
#define F_CPU 3688000UL 
3
#include <avr/io.h>
4
#include <util/delay.h>
5
#include <stdlib.h>
6
 
7
int main(void) {
8
   DDRB |= (1 << PB0); // Ausgang setzen
9
   DDRB |= (1 << PB1);
10
   DDRB |= (1 << PB2);
11
   DDRB |= (1 << PB3); 
12

13
   DDRD |= (1 << PD5); //  Ausgang LED
14
   DDRD |= (1 << PD4); //  Ausgang Piezzo
15

16
  void long_delay(uint16_t ms)
17
  {
18
  for(; ms>0; ms--) _delay_ms(1);
19
  }
20

21
   while(1) {
22
    if ( PIND & (1 <<3) ){
23
    unsigned char min = 1;
24
        unsigned char max = 2;
25
        unsigned char zufall = 0;
26
       zufall = (rand() % (max-min+1) +min);
27

28
    PORTD |= (1 << PD5); // LED an
29
    PORTB |= (1 << PB0); // Rueckwaerts (default)
30
                PORTB &= ~(1 << PB1);
31
                PORTB |= (1 << PB2);
32
                PORTB &= ~(1 << PB3);
33
    long_delay(1000);
34

35
    if ( zufall == 1 ) {
36
          PORTB |= (1 << PB0); // Drehen (default)
37
          PORTB &= ~(1 << PB1);
38
          PORTB &= ~(1 << PB2);
39
          PORTB |= (1 << PB3);
40
      long_delay(800);
41
    }
42
    else {
43
      PORTB &= ~(1 << PB0); // Drehen (default)
44
                  PORTB |= (1 << PB1);
45
                  PORTB |= (1 << PB2);
46
                  PORTB &= ~(1 << PB3);
47
                  long_delay(800);
48
    }
49

50
    }   
51
       else {
52
    PORTD &= ~(1 << PD5); // led AUS
53
  
54
    PORTB &= ~(1 << PB0); // Vorwaerts (default)
55
    PORTB |= (1 << PB1);
56
    PORTB &= ~(1 << PB2);
57
    PORTB |= (1 << PB3);
58
    }
59
     }
60
   return 0;
61
}
Vieleicht kann mir ja der eine oder andere ein paar Tipps geben.


Gruss Matze
Angehängte Dateien:
Gast #3686473
Lesenswert?

Random ... schrieb:
> Kommentare und Funktions-/Variablennamen auf Englisch. Liesst sich
> leichter.
Wenn man davon absieht, dass wir in einem deutschsprachigen Forum sind.


Was funktioniert denn nicht? Lässt es sich nicht compilieren oder 
funktioniert es nicht wie es soll? Was für Fehler treten auf?
#3686672
Lesenswert?

Matthias I. schrieb:

> Intressanterweise funktioniert er nicht auf WinAVR mit gcc 4.3
> Unter Linux mit gcc 4.8 geht er astrein.

Ich bin jetzt nicht im Bilde, ob es im 4.3 ein paar bekannte Bugs gab 
oder nicht.

>
>    DDRD |= (1 << PD5); //  Ausgang LED
>    DDRD |= (1 << PD4); //  Ausgang Piezzo


Wenn du dir ein paar #define machst
1
#define F_CPU 3688000UL 
2
#include <avr/io.h>
3
#include <util/delay.h>
4
#include <stdlib.h>
5

6
#define LED    (1<<PD5)
7
#define PIEZO  (1<<PD4)

dann kannst du durch die Textersetzung erreichen, dass sich dieser 
Original-Abschnitt hier so liest
1
   DDRD |= LED;
2
   DDRD |= PIEZO;

(es ginge auch
1
#define LED   PD5
2
#define PIEZO PD4
3
....
4

5
   DDRD |= (1 << LED);
6
   DDRD |= (1 << PIEZO);
)
was den Vorteil hat, dass du dir den Kommentar ganz offensichtlich 
sparen kannst, was an und für sich eine gute Sache ist. Hast du die Wahl 
zwischen einem Kommentar und einer Möglichkeit den Code so 
umzuformulieren, dass der Kommentar überflüssig wird, dann bevorzuge 
letzteres! Denn der Code ist immer das was compiliert wird - sprich: 
Kommentare können auch falsch sein ohne das es jemandem auffällt, der 
nicht genau überprüft ob der Kommentar mit dem Code zusammenstimmt.
Wenn ich hier im Forum Codefehler suche, dann ignoriere ich Kommentare 
zb vollständig. Eben weil sie immer wieder sich mal als falsch 
herausstellen.

>
>   void long_delay(uint16_t ms)
>   {
>   for(; ms>0; ms--) _delay_ms(1);
>   }

Funktionen in Funktionen zu definieren ist in C eigentlich nicht 
zulässig.
Aber eigentlich brauchst du gar keine Funktion long_delay. _delay_ms 
kann derartige Zeiten wunderbar ganz für sich alleine abhandlen. einfach 
_delay_ms( 1000 ); aufrufen und gut ists.

>
>    while(1) {
>     if ( PIND & (1 <<3) ){

Hier dasselbe. An deinem Portbit 3 hängt ein Taster, der vielleicht 
sogar eine Beschriftung hat (sagen wir mal "Bumper") bzw. wenn er nicht 
beschriftet ist, dann hat er zumindest eine logische Funktion (in deinem 
Fall ist das eben der Front-Bumper
1
....
2
#define FRONT_BUMPER    PD3
3

4
....
5

6

7
       if( PIND & ( 1 << FRONT_BUMPER ) )
8
...
liest sich doch gleich viel besser. Und wenn mal mehrere Bumper oder 
Tasten im Spiel sind, dann erleichtert dir ein entsprechender 
Makro-Ersatz auch das Auseinanderhalten im Code, mit welchem externen 
Bumper oder Taster du es hier an dieser Codestelle zu tun hast.

>     unsigned char min = 1;
>         unsigned char max = 2;
>         unsigned char zufall = 0;
>        zufall = (rand() % (max-min+1) +min);
>
>     PORTD |= (1 << PD5); // LED an

Das wäre dann (mit der 2.ten Makro Variante)
1
      PORTD |= ( 1 << LED );
... und wieder ist der Kommentar überflüssig geworden

>     PORTB |= (1 << PB0); // Rueckwaerts (default)
>                 PORTB &= ~(1 << PB1);
>                 PORTB |= (1 << PB2);
>                 PORTB &= ~(1 << PB3);

selbiges auch hier: "Benenne" deine Ausgänge je nach Funktionalität mit 
hilfe eines Makros. Du willst derartige Bezeichnungen wie PB1, PB2, aber 
auch PORTB etc. eigentlich nicht direkt im Code stehen haben!
#3686686
Lesenswert?

Ich würde mir auch Funktionen für die Beschaltung der MOtoren für 
"typische Bewegungsmuster" machen. Eine Funktion frü Vorwärts, eine 
Funktion für Rückwärts, eine für Rechts, eine für Links.
1
void Forward()
2
{
3
  PORTB &= ~(1 << PB0);
4
  PORTB |= (1 << PB1);
5
  PORTB &= ~(1 << PB2);
6
  PORTB |= (1 << PB3);
7
}
8

9
void Backward()
10
{
11
  PORTB |= (1 << PB0);
12
  PORTB &= ~(1 << PB1);
13
  PORTB |= (1 << PB2);
14
  PORTB &= ~(1 << PB3);
15
}
16

17
void TurnRight()
18
{
19
  PORTB |= (1 << PB0);
20
  PORTB &= ~(1 << PB1);
21
  PORTB &= ~(1 << PB2);
22
  PORTB |= (1 << PB3);
23
}
24

25
void TurnLeft()
26
{
27
  PORTB &= ~(1 << PB0);
28
  PORTB |= (1 << PB1);
29
  PORTB |= (1 << PB2);
30
  PORTB &= ~(1 << PB3);
31
}
32

33
int random( int min, max )
34
{
35
  return rand() % (max-min+1) + min;
36
}
37

38
int main()
39
{
40
  ....
41

42
  while( 1 ) {
43
    if ( PIND & (1 << FRONT_BUMPER) ) {
44

45
      PORTD |= (1 << LED);
46
      Backward();
47

48
      _delay_ms( 1000 );
49

50
      if( random( 1, 2 ) == 1 ) {
51
        TurnLeft();
52
      else
53
        TurnRight();
54

55
      _delay_ms( 800 );
56
    }
57

58
    else {
59
      PORTD &= ~(1 << LED);
60
      Forward();
61
   }
62

63
   return 0;

siehst du, um wieviel leichter die Hauptschleife in main() zu verfolgen 
und zu verstehen ist? Das liegt daran, dass ich mich als Leser nicht 
mehr mit den Details von zb. dem Rückwärtsfahren beschäftigen muss. Im 
Code in der Hauptschleife steht einfach Backward() und das genügt mir 
beim Lesen des Codes um zu verstehen, das an dieser Stelle im Code das 
Fahrzeug zurück setzen soll. Wenn mich die Details interessieren, wie 
dieses Rückwärts fahren funktioniert, dann kann ich mir die Funktion 
ansehen. WEnn es aber darum geht, die Logik zu verstehen, wie das 
Fahrzeug einem Hindernis ausweicht, dann muss ich nur wissen, dass das 
Fahreug mit dem Aufruf dieser Funktion rückwärts fährt.

Die in der Hauptschleife kodierte Logik des Ausweichens ist so viel 
kürzer formuliert und auch in problembezogeneren Ausdrücken, so dass es 
viel leichter fällt sich davon zu überzeugen, dass diese Logik 
eigentlich funktionieren müsste, ohne das ich ständig über irgendwelche 
technischen Details stolpere.
#3686688
Lesenswert?

J. L. schrieb:
>> Wenn ich hier im Forum Codefehler suche, dann ignoriere ich Kommentare
>> zb vollständig. Eben weil sie immer wieder sich mal als falsch
>> herausstellen.
>
> Na, immerhin steht im Kommentar, was der Code tun SOLL.

Dein Wort in Gottes Ohr.
Alles schon gehabt:
Code richtig, Kommentar falsch
Code falsch, Kommentar von der Idee her richtig
Code falsch, Kommentar falsch
Code falsch, Kommentar passt überhaupt nicht dazu und redet von etwas 
ganz anderem
Code richtig, Kommentar richtig. Allerdings: Kommentar überflüssig
und natürlich auch
Code richtig, Kommentar richtig und tatsächlich hilfreich
Gast #3686722
Lesenswert?

J. L. schrieb:
>> Wenn ich hier im Forum Codefehler suche, dann ignoriere ich
> Kommentare
>> zb vollständig. Eben weil sie immer wieder sich mal als falsch
>> herausstellen.
>
> Na, immerhin steht im Kommentar, was der Code tun SOLL.

Ein guter Kommentar sollte nicht nur das Was sondern das WARUM 
dokumentieren. Das was steht schon da in Form von Code.

Zum Thema verbessern: "Clean code" lesen.
#3695193
Lesenswert?

So ich hab mal einiges nach den Vorschlaegen hier geaendert :)
Das ganze ist so etwas uebersichtlicher!
Jetzt muss ich noch den Buzzer zum Piepen bringen.
Mit Bascom ist das ja ganz einfach, so wie es wohl aussieht brauch ich 
unter C eine PWM und einen Timer.
Mal sehen ob ich das zum laufen bekomme.
1
#define F_CPU 3688000UL 
2
#include <avr/io.h>
3
#include <util/delay.h>
4
#include <stdlib.h>
5

6
#define LED (1<<PD5)
7
#define SPEAKER (1<<PD4)
8
#define FRONT_BUMPER PD3
9
#define MOTOR_A (1<<PB0)
10
#define MOTOR_B (1<<PB1)
11
#define MOTOR_C (1<<PB2)
12
#define MOTOR_D (1<<PB3)
13

14

15
void rueckwaerts(){
16
    PORTB |= (1 << PB0);
17
    PORTB &= ~(1 << PB1);
18
    PORTB |= (1 << PB2);
19
    PORTB &= ~(1 << PB3);
20
}
21

22
void vorwaerts(){
23
    PORTB &= ~(1 << PB0);
24
    PORTB |= (1 << PB1);
25
    PORTB &= ~(1 << PB2);
26
    PORTB |= (1 << PB3);
27
}
28

29
void links(){
30
    PORTB |= (1 << PB0);
31
    PORTB &= ~(1 << PB1);
32
    PORTB &= ~(1 << PB2);
33
    PORTB |= (1 << PB3);
34
}
35

36
void rechts(){
37
    PORTB &= ~(1 << PB0);
38
    PORTB |= (1 << PB1);
39
    PORTB |= (1 << PB2);
40
    PORTB &= ~(1 << PB3);
41
}
42

43
int main(void) {
44
   DDRB |= MOTOR_A; // Ausgang setzen
45
   DDRB |= MOTOR_B;
46
   DDRB |= MOTOR_C;
47
   DDRB |= MOTOR_D; 
48

49
   DDRD |= LED;
50
   DDRD |= SPEAKER;
51

52

53
while(1){
54

55
    if ( PIND & (1 << FRONT_BUMPER) )
56
    {
57
    unsigned char min = 1;
58
        unsigned char max = 2;
59
        unsigned char zufall = 0;
60
       zufall = (rand() % (max-min+1) +min);
61

62
    PORTD |= LED; // LED an
63
    rueckwaerts();
64
    _delay_ms(1000);
65

66
    if ( zufall == 1 ) {
67
          links();
68
     _delay_ms(800);
69
    }
70
    
71
    else {
72
     rechts();
73
           _delay_ms(800);
74
    }
75

76
    }   
77
       else {
78

79
    PORTD &= LED; // led AUS
80
    vorwaerts();  
81
    }
82
  }
83
   return 0;
84
}
#3695221
Lesenswert?

@ Matthias I. (matze5)

>Jetzt muss ich noch den Buzzer zum Piepen bringen.
>Mit Bascom ist das ja ganz einfach, so wie es wohl aussieht brauch ich
>unter C eine PWM und einen Timer.

Kann man machen. Aber du bist ja anscheinend Mr. Jan Delay ;-)

>Mal sehen ob ich das zum laufen bekomme.

Versuchs mal mit einer gescheiten Einrückung, das kann (WILL!) doch 
keiner lesen!

http://www.mikrocontroller.net/articles/Strukturierte_Programmierung_auf_Mikrocontrollern#Formatierung_des_Quelltextes
#3695255
Lesenswert?

Der richtige Code:


#define F_CPU 3688000UL
#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include <motorun.h>

#define LED (1<<PD5)
#define SPEAKER (1<<PD4)
#define FRONT_BUMPER PD3
#define MOTOR_A (1<<PB0)
#define MOTOR_B (1<<PB1)
#define MOTOR_C (1<<PB2)
#define MOTOR_D (1<<PB3)

void rueckwaerts(){
    PORTB |= MOTOR_A;
    PORTB &= MOTOR_B;
    PORTB |= MOTOR_C;
    PORTB &= MOTOR_D;
}

void vorwaerts(){
    PORTB &= ~MOTOR_A;
    PORTB |= MOTOR_B;
    PORTB &= ~MOTOR_C;
    PORTB |= MOTOR_D;
}

void links(){
    PORTB |= MOTOR_A;
    PORTB &= ~MOTOR_B;
    PORTB &= ~MOTOR_C;
    PORTB |= MOTOR_D;
}

void rechts(){
    PORTB &= ~MOTOR_A;
    PORTB |= MOTOR_B;
    PORTB |= MOTOR_C;
    PORTB &= ~MOTOR_D;
}

int main(void) {
   DDRB |= MOTOR_A; // Ausgang setzen
   DDRB |= MOTOR_B;
   DDRB |= MOTOR_C;
   DDRB |= MOTOR_D;

   DDRD |= LED;
   DDRD |= SPEAKER;


while(1){

    if ( PIND & (1 << FRONT_BUMPER) )
    {
    unsigned char min = 1;
        unsigned char max = 2;
        unsigned char zufall = 0;
       zufall = (rand() % (max-min+1) +min);

    PORTD |= LED; // LED an
    rueckwaerts();
    _delay_ms(1000);

    if ( zufall == 1 ) {
          links();
     _delay_ms(800);
    }

    else {
     rechts();
           _delay_ms(800);
    }

    }
       else {

    PORTD &= ~LED; // led AUS
    vorwaerts();
    }
  }
   return 0;
}

Und die Datei motorun.h:
#ifndef MOTORUN_H_INCLUDED
#define MOTORUN_H_INCLUDED

void links();

void rechts();

void rueckwaerts();

void vorwaerts();
#endif


Tjo funktioniert nicht.
Lass ich den Header weg und pack die Funktionen mit in Main() gehts..
Verstehe ich nicht das er die Funktionen nicht aufrufen kann.

Der Weg ist lang und steinig :)

Btw. kann man im Forum irgendwie Syntax Highlight anmachen ?
#3695262
Lesenswert?

So funktionierts uebrigens.. obwohls offensichtlich falsch ist... :
1
#define F_CPU 3688000UL 
2
#include <avr/io.h>
3
#include <util/delay.h>
4
#include <stdlib.h>
5
// #include "motorun.h"
6

7
#define LED (1<<PD5)
8
#define SPEAKER (1<<PD4)
9
#define FRONT_BUMPER PD3
10
#define MOTOR_A (1<<PB0)
11
#define MOTOR_B (1<<PB1)
12
#define MOTOR_C (1<<PB2)
13
#define MOTOR_D (1<<PB3)
14

15

16
int main(void) {
17
   DDRB |= MOTOR_A; // Ausgang setzen
18
   DDRB |= MOTOR_B;
19
   DDRB |= MOTOR_C;
20
   DDRB |= MOTOR_D; 
21

22
   DDRD |= LED;
23
   DDRD |= SPEAKER;
24

25
void rueckwaerts(){
26
    PORTB |= MOTOR_A;
27
    PORTB ~&= MOTOR_B;
28
    PORTB |= MOTOR_C;
29
    PORTB ~&= MOTOR_D;
30
}
31

32
void vorwaerts(){
33
    PORTB &= ~MOTOR_A;
34
    PORTB |= MOTOR_B;
35
    PORTB &= ~MOTOR_C;
36
    PORTB |= MOTOR_D;
37
}
38

39
void links(){
40
    PORTB |= MOTOR_A;
41
    PORTB &= ~MOTOR_B;
42
    PORTB &= ~MOTOR_C;
43
    PORTB |= MOTOR_D;
44
}
45

46
void rechts(){
47
    PORTB &= ~MOTOR_A;
48
    PORTB |= MOTOR_B;
49
    PORTB |= MOTOR_C;
50
    PORTB &= ~MOTOR_D;
51
}
52

53

54
while(1){
55

56
    if ( PIND & (1 << FRONT_BUMPER) )
57
    {
58
    unsigned char min = 1;
59
        unsigned char max = 2;
60
        unsigned char zufall = 0;
61
       zufall = (rand() % (max-min+1) +min);
62

63
    PORTD |= LED; // LED an
64
    rueckwaerts();
65
    _delay_ms(1000);
66

67
    if ( zufall == 1 ) {
68
          links();
69
     _delay_ms(800);
70
    }
71
    
72
    else {
73
     rechts();
74
           _delay_ms(800);
75
    }
76

77
    }   
78
       else {
79

80
    PORTD &= ~LED; // led AUS
81
    vorwaerts();  
82
    }
83
  }
84
   return 0;
85
}
#3695305
Lesenswert?

1
#define F_CPU 3688000UL 
2
#include <avr/io.h>
3
#include <util/delay.h>
4
#include <stdlib.h>
5
// #include "motorun.h"
6

7
#define LED_ON      PORTD |=  (1<<PD5);
8
#define LED_OFF     PORTD &= ~(1<<PD5);
9
#define SPEAKER_ON  PORTD |=  (1<<PD4);
10
#define SPEAKER_OFF PORTD &= ~(1<<PD4);
11
#define FRONT_BUMPER (PIND & (1<<PD3))
12
#define MOTOR_A (1<<PB0)
13
#define MOTOR_B (1<<PB1)
14
#define MOTOR_C (1<<PB2)
15
#define MOTOR_D (1<<PB3)
16

17

18
void rueckwaerts(){
19
    PORTB |=  MOTOR_A;
20
    PORTB ~&= MOTOR_B;
21
    PORTB |=  MOTOR_C;
22
    PORTB ~&= MOTOR_D;
23
}
24

25
void vorwaerts(){
26
    PORTB &= ~MOTOR_A;
27
    PORTB |=  MOTOR_B;
28
    PORTB &= ~MOTOR_C;
29
    PORTB |=  MOTOR_D;
30
}
31

32
void links(){
33
    PORTB |=  MOTOR_A;
34
    PORTB &= ~MOTOR_B;
35
    PORTB &= ~MOTOR_C;
36
    PORTB |=  MOTOR_D;
37
}
38

39
void rechts(){
40
    PORTB &= ~MOTOR_A;
41
    PORTB |=  MOTOR_B;
42
    PORTB |=  MOTOR_C;
43
    PORTB &= ~MOTOR_D;
44
}
45

46

47
int main(void) {
48
    DDRB |= MOTOR_A;        // Ausgang setzen
49
    DDRB |= MOTOR_B;
50
    DDRB |= MOTOR_C;
51
    DDRB |= MOTOR_D; 
52

53
    LED_ON
54
    SPEAKER_OFF
55

56
    while(1){
57

58
        if ( FRONT_BUMPER )
59
        {
60
            unsigned char min = 1;
61
            unsigned char max = 2;
62
            unsigned char zufall = 0;
63
            zufall = (rand() % (max-min+1) +min);
64
    
65
            LED_ON
66
            rueckwaerts();
67
            _delay_ms(1000);
68
        
69
            if ( zufall == 1 )
70
            {
71
                links();
72
                _delay_ms(800);
73
            }
74
            else
75
            {
76
                rechts();
77
                _delay_ms(800);
78
            }
79
        
80
        }   
81
        else
82
        {
83
            LED_OFF
84
            vorwaerts();  
85
        }
86
    } 
87
    
88
    return 0;
89
}
Persönliche Seite #3695336
Lesenswert?

Random ... schrieb:
> ist das compilierbar? Funktion in einer Funktion?

Ja, lokale Fnuktionen sind eine GCC-Erweiterung, die in GNU-C zur 
Verfügung steht.  Harrig wird's, wenn die lokale Funktion auf Variablen 
der enthaltenden Funktion zugreift und diese die Adresse der lokalen 
Funktion nimmt.  Instruktives Beispiel:
1
extern void dispatch (void(*)(void));
2

3
int fun (int x)
4
{
5
    void callback (void)
6
    {
7
        x++;
8
    }
9
    
10
    dispatch (callback);
11
    return x;
12
}

callback bekommt von dispatch keine Argumente; es hat das Call-Interface 
jeder anderen void-Funktion.  Die Adresse von x ist zur Ladezeit nicht 
bekannt, und zwischen fun und callback können beliebig viele Callframes 
liegen.  Trotzdem muß callback irgendwie an x rankommen.

Mit avr-gcc ist das übrigens nicht übersetzbar, da dort kein Code auf 
dem Stack ausführbar ist.
Gast #3695675
Lesenswert?

Matthias I. schrieb:
> Falk: mit deinen Code funktionierts auch nicht.
>
> Das erklaert auch nicht warum das Programm nicht ablaueft wenn die
> Funktionen ausserhalb von Main sind, wo sie hingehoeren.
1
main.c: In function ‘rueckwaerts’:
2
main.c:20:11: error: expected ‘;’ before ‘~’ token
3
     PORTB ~&= MOTOR_B;
4
           ^
5
main.c:22:11: error: expected ‘;’ before ‘~’ token
6
     PORTB ~&= MOTOR_D;
7
           ^
#3695734
Lesenswert?

Das hab ich schon alles gefunden und behoben, dennoch lauefts nicht :)
Speaker wird eh nicht benutzt im Moment.

Kompilieren tut es astrein, aber die funktionen laufen nur wenn sie in 
main() sind...
Das ist das einzige Problem, egal wie ich da was formatiere.. oder 
Tabulatoren setze..
#3695737
Lesenswert?

So funktioniert alles:
1
#define F_CPU 3688000UL 
2
#include <avr/io.h>
3
#include <util/delay.h>
4
#include <stdlib.h>
5

6
#define LED (1 << PD5)
7
#define SPEAKER (1 << PD4)
8
#define FRONT_BUMPER PD3
9
#define MOTOR_A (1 << PB0)
10
#define MOTOR_B (1 << PB1)
11
#define MOTOR_C (1 << PB2)
12
#define MOTOR_D (1 << PB3)
13

14

15
int main(void) {
16
DDRB |= MOTOR_A;
17
DDRB |= MOTOR_B;
18
DDRB |= MOTOR_C;
19
DDRB |= MOTOR_D;
20

21
DDRD |= LED;
22
DDRD |= SPEAKER;
23

24
void rueckwaerts(){
25
  PORTB |= MOTOR_A;
26
  PORTB &= ~MOTOR_B;
27
  PORTB |= MOTOR_C;
28
  PORTB &= ~MOTOR_D;
29
}
30

31
void vorwaerts(){
32
  PORTB &= ~MOTOR_A;
33
  PORTB |= MOTOR_B;
34
  PORTB &= ~MOTOR_C;
35
  PORTB |= MOTOR_D;
36
}
37

38
void links(){
39
  PORTB |= MOTOR_A;
40
  PORTB &= ~MOTOR_B;
41
  PORTB &= ~MOTOR_C;
42
  PORTB |= MOTOR_D;
43
}
44

45
void rechts(){
46
  PORTB &= ~MOTOR_A;
47
  PORTB |= MOTOR_B;
48
  PORTB |= MOTOR_C;
49
  PORTB &= ~MOTOR_D;
50
}
51

52
while(1){
53
  if ( PIND & (1 << FRONT_BUMPER) )
54
  {
55
  unsigned char min = 1;
56
  unsigned char max = 2;  unsigned char zufall = 0;
57
  zufall = (rand() % (max-min+1) +min);
58
  PORTD |= LED; 
59
  
60
  rueckwaerts();
61
  _delay_ms(1000);
62
  
63
  if ( zufall == 1 ) {
64
  links();
65
  _delay_ms(800);
66
  }
67
  
68
  else {
69
  rechts();
70
  _delay_ms(800);
71
  }
72

73
  }   
74
  else {
75
  PORTD &= ~LED;
76
  vorwaerts();  
77
  }
78
  }
79

80
return 0;
81
}


So funktioniert nichts:
1
#define F_CPU 3688000UL 
2
#include <avr/io.h>
3
#include <util/delay.h>
4
#include <stdlib.h>
5

6
#define LED (1 << PD5)
7
#define SPEAKER (1 << PD4)
8
#define FRONT_BUMPER PD3
9
#define MOTOR_A (1 << PB0)
10
#define MOTOR_B (1 << PB1)
11
#define MOTOR_C (1 << PB2)
12
#define MOTOR_D (1 << PB3)
13

14
void rueckwaerts(){
15
  PORTB |= MOTOR_A;
16
  PORTB &= ~MOTOR_B;
17
  PORTB |= MOTOR_C;
18
  PORTB &= ~MOTOR_D;
19
}
20

21
void vorwaerts(){
22
  PORTB &= ~MOTOR_A;
23
  PORTB |= MOTOR_B;
24
  PORTB &= ~MOTOR_C;
25
  PORTB |= MOTOR_D;
26
}
27

28
void links(){
29
  PORTB |= MOTOR_A;
30
  PORTB &= ~MOTOR_B;
31
  PORTB &= ~MOTOR_C;
32
  PORTB |= MOTOR_D;
33
}
34

35
void rechts(){
36
  PORTB &= ~MOTOR_A;
37
  PORTB |= MOTOR_B;
38
  PORTB |= MOTOR_C;
39
  PORTB &= ~MOTOR_D;
40
}
41

42

43
int main(void) {
44
DDRB |= MOTOR_A;
45
DDRB |= MOTOR_B;
46
DDRB |= MOTOR_C;
47
DDRB |= MOTOR_D;
48

49
DDRD |= LED;
50
DDRD |= SPEAKER;
51

52

53
while(1){
54
  if ( PIND & (1 << FRONT_BUMPER) )
55
  {
56
  unsigned char min = 1;
57
  unsigned char max = 2;  unsigned char zufall = 0;
58
  zufall = (rand() % (max-min+1) +min);
59
  PORTD |= LED; 
60
  
61
  rueckwaerts();
62
  _delay_ms(1000);
63
  
64
  if ( zufall == 1 ) {
65
  links();
66
  _delay_ms(800);
67
  }
68
  
69
  else {
70
  rechts();
71
  _delay_ms(800);
72
  }
73

74
  }   
75
  else {
76
  PORTD &= ~LED;
77
  vorwaerts();  
78
  }
79
  }
80

81
return 0;
82
}

Ich steh irgendwie auf dem Schlauch. :o
Gast #3696023
Lesenswert?

Es gibt keine Screenshots der Code compiliert nur laueft das Programm 
nicht ab.
Sobald ich das in den Tiny Flashe tut sich nichts mehr.
Der "Falsche Code" geht astrein.

Nur laueft keine Funktion die ich erstelle.
Ausser sie sind in Main().
Dann gehen sie.
#3696024
Lesenswert?

Ich erwarte eine genaue Fehlerbeschreibung.
z.B. Er fährt nur vorwärts. Oder er ändert ständig die Richtung ohne an 
den Buzzer zu kommen.

Du gehts ja auch nicht zum Arzt und sagst nur "Mir gehts nicht gut".

Daher nicht wundern, dass bei solch einer nichtssagenden 
Fehlerbeschreibung nur die Codequalität diskutiert wird. Was soll man 
auch anderes machen, als nach einer falsch gesetzte Klammer zu suchen.
#3696049
Lesenswert?

Matthias I. schrieb:
> Sobald ich das in den Tiny Flashe tut sich nichts mehr.

Was sagt die LED (an, aus, flackern)?

Du kannst Das Programm auch erstmal nur auf "vorwärts" reduzieren. Und 
dann Stück für Stück weiter.

Wenn wirklich garnicht geht, prüfen, ob main überhaupt durchlaufen wird. 
Dafür kann man die LED nutzen, wenn man sonst nichts hat.

Wie siehst mit Compilerwarnings aus? Warnungen eingeschaltet? Die 
könnten einen Hinweis geben. Oder warnt der Linker?

Ich bezweifle momentan, dass das Problem am geposteten Code liegt.
#3696172
Lesenswert?

Also fuer Dumm verkaufen lasse ich mich sicher nicht.
Elf file flashen und so. Muss hier ja oft vorkommen.

Der Roboter macht einfach gar nichts, kein LED blinken nichts.
Wenn ich den Code mit den Funktionen in Main() als Hex brenne passt 
alles.
Wenn die Funktionen ausserhalb von Main() sind gehts nicht.
ist das so schwer zu verstehen ?
Geht nicht heisst, es geht nichts.
Da blinkt nichts, Kein Motor dreht, einfach nichts.
Der Controller zuckt kein Bisschen.

avr-gcc -mmcu=attiny2313 -Os -c motorun.c -o motorun.o
avr-gcc motorun.o -o motorun.elf
avr-objcopy -O ihex -j .text -j .data motorun.elf motorun.hex

avrdude  -p t2313 -c avrisp2 -P usb -U flash:w:motorun.hex

ich wuesste nicht was da falsch ist.

Mein Geraet funktioniert und tut auch was es soll.
Nur eben mit den unschoenen Funktionen in der Main()

Edit: wenn der Code minimal reduziert ist funktionierts auch nicht.
Also fehlt wohl irgendwas um Funktionen zu unterstuetzen.

Denn es geht auch keine simple Funktion wie:
(Ausgang natuerlich in main definiert..)

void led_an(){
PORTD |= LED;
}
Gast #3696182
Lesenswert?

Ahja der Compiler:
1
Es werden eingebaute Spezifikationen verwendet.
2
COLLECT_GCC=/usr/x86_64-pc-linux-gnu/avr/gcc-bin/4.8.2/avr-gcc
3
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/avr/4.8.2/lto-wrapper
4
Ziel: avr
5
Konfiguriert mit: /var/tmp/portage/cross-avr/gcc-4.8.2/work/gcc-4.8.2/configure --host=x86_64-pc-linux-gnu --target=avr --build=x86_64-pc-linux-gnu --prefix=/usr --bindir=/usr/x86_64-pc-linux-gnu/avr/gcc-bin/4.8.2 --includedir=/usr/lib/gcc/avr/4.8.2/include --datadir=/usr/share/gcc-data/avr/4.8.2 --mandir=/usr/share/gcc-data/avr/4.8.2/man --infodir=/usr/share/gcc-data/avr/4.8.2/info --with-gxx-include-dir=/usr/lib/gcc/avr/4.8.2/include/g++-v4 --with-python-dir=/share/gcc-data/avr/4.8.2/python --enable-languages=c,c++ --enable-obsolete --enable-secureplt --disable-werror --with-system-zlib --enable-nls --without-included-gettext --enable-checking=release --with-bugurl=https://bugs.gentoo.org/ --with-pkgversion='Gentoo 4.8.2 p1.3r1, pie-0.5.8r1' --enable-libstdcxx-time --enable-poison-system-directories --enable-shared --disable-threads --disable-bootstrap --enable-multilib --disable-altivec --disable-fixed-point --disable-libgcj --disable-libgomp --disable-libmudflap --disable-libssp --disable-libquadmath --enable-lto --without-cloog
6
Thread-Modell: single
7
gcc-Version 4.8.2 (Gentoo 4.8.2 p1.3r1, pie-0.5.8r1)

eventuell liegts ja am Compiler ?
Gast #3696229
Lesenswert?

Besten Dank,

tut mir leid das ich etwas ungehalten war, ich war schlichtweg entnervt.
Nun geht tatsaechlich alles wie es soll..

Gleichzeitig bin ich noch auf einen Bug im Gentoo avr-gcc gestossen
Die Linkerscripte waren nicht verlinkt.
ln -s /usr/lib/binutils/avr/2.24/ldscripts/ /usr/avr/lib/ldscripts
behebt das folgende Problem:
Cannot open linker script file ldscripts/avr25.xn: Datei oder 
Verzeichnis nicht gefunden

Und was ich nicht wusste war:
avr-gcc -mmcu=attiny2313 -O2 -c motorun.c -o motorun.o
avr-gcc -g -mmcu=attiny2313 motorun.o -o motorun.elf
avr-objcopy -O ihex -j .text -j .data motorun.elf motorun.hex

So gehts nun.
#3696557
Lesenswert?

@Johann L. (gjlayde) Benutzerseite

>> Konfiguriert mit: --disable-fixed-point

>Na prima.  Da wird mit viel Aufwand Assembler-optimerter Fixed-Point
>Support in avr-gcc eingebaut, und dann wird's einfach ausgeknipst...

Gefrickel 3.0

Wenn man schon mti Kommandozeile und selbstgestricktem Makefile arbeiten 
will, sollte man es wenigstens können. Da lob ich mir mein AVR-Studio!

F7!

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