Forum: Mikrocontroller und Digitale Elektronik ATTiny2313 - Probleme C-Code Useless Machine


von Sebastian K. (Firma: none) (bastel-basti)


Lesenswert?

Hallo liebes Forum

Wie man dem Titel schon entnehmen kann, versuche ich mir gerade als 
erstes AVR-Projekt (erstes ohne Arduino) die Useless Machine nach zu 
bauen.

Den Code habe ich der Übersichtlichkeit halber mal bei Pastebin 
hochgeladen:

http://pastebin.com/w9RkGT06


Der Gedanke hinter dem Code ist:

1. Nach Reset/Stromanschluss: Initialisierung des Servo (Software-PWM an 
PB1) auf Anfangsposition, wenn der Schalter (PD2) auf GND steht.

2. Nach erfolgreicher Initialisierung -> Interrupt auf INT0 (PD2) 
einschalten

3. Einschlafen nach Interrupt- Aktivierung um Strom zu sparen

4. Sobald Interrupt kommt, diesen Sperren und mit Servo Schalter 
ausschalten

5. Wenn Schalter auf "Aus", Interrupt wieder an

6. Servo zurück und wieder einschlafen


Im Simulator (AVRStudio 4 mit SP3) läuft die Sache (soweit ich als 
Anfänger verifizieren kann) eigentlich rund.
Nach Flashen und setzen der passenden Flags (interner 8MHz-Oszi ohne 
Clockdiv) läuft in der Realität aber garnichts.
Der Servo zuckt nur kurz in eine Richtung bis zum Anschlag wenn man den 
uC mehrmals resetted. Und auf Interrupt (Flanke von LOW auf HIGH an 
INT0) reagiert er leider auch nicht :(

Mit nem einfachen Sweep-Test für den Servo, reailisiert mit 
for-Schleifen und der gleichen Software-PWN tut meine Schaltung was sie 
bei nem Sweep soll.

Ich wär echt dankbar für jeden Hinweis. Versuch schon 4 Tage das Problem 
in den Griff zu kriegen.

Schöne Grüße,
Basti

von Düsendieb (Gast)


Lesenswert?

für eine Antwort, hänge den C-Code lieber an den Thread. Auf so einen 
ominösen Link klickt keiner gerne.

Axel

von Sebastian K. (Firma: none) (bastel-basti)


Angehängte Dateien:

Lesenswert?

Hallo

wie gewünscht gibts hier meinen Code als Datei im Anhang.

Ich kann den Code auch gerne nochmal direkt in einen Post schreiben, 
aber ich befürchte ich verstoße damit gegen die Foren-Etikette, da er 
(auch aufgrund meiner Kommentierung und Formatierung) wohl recht lang 
ist :/


Danke schonmal im Voraus für alle Hinweise und Tips.

Gruß,
Basti

von Karl H. (kbuchegg)


Lesenswert?

No.
So

        //setze Pin PB1 auf LOW
        PORTB &= ( 0 << PB1  );

wird kein Pin gelöscht


> Ich kann den Code auch gerne nochmal direkt in einen Post
> schreiben, aber ich befürchte ich verstoße damit gegen die
> Foren-Etikette

Mach dir deswegen keine Sorgen.
Langer Code ist nur dann ein Problem, wenn du ihn direkt ins Posting 
reinschreibst. Als ANhang ist das kein Problem.

> Im Simulator (AVRStudio 4 mit SP3) läuft die Sache
> (soweit ich als Anfänger verifizieren kann) eigentlich rund.
> Nach Flashen und setzen der passenden Flags (interner 8MHz-Oszi
> ohne Clockdiv) läuft in der Realität aber garnichts.

Schwerer Fehler:
Man entwickelt niemals Code nur mit dem Simulator.
Du willst immer so schnell wie möglich auf den realen Prozessor und das 
Programm, bzw. die Teile die du bereits hast testen.
Du willst immer so schnell wie möglich testen und immer so wenig wie 
möglich an neuem Code testen. Sonst geht es dir nämlich genau so wie es 
dir jetzt geht: Du stehst mit einem Haufen Code da, der nicht 
funktioniert und weißt nicht wo du anfangen sollst. Daher willst du 
immer mit so wenig Code wie möglich anfangen und den bereits testen. 
Dann kommt wieder Code dazu und dann wird der getestet. Dadurch hast du 
immer Programmteile, die schon getestet sind und von denen du ausgehen 
kannst, dass sie zumindest einigermasen richtig sind. Kommt eine 
Erweiterung dazu und nichts geht mehr, dann wird der Fehler höchst 
wahrscheinlich im neu hinzugekommenen Code sein. Und da der nicht 
umfangreich sondern klein ist, hast du auch weniger Möglichkeiten, wo du 
den Fehler seuchen musst. Läuft dann die Erweiterung, dann kommt die 
nächste Erweiterung dazu.

In diesem Sinne werden Programme stufenweise entwickelt. Aber davon 
auszugehen, dass du ein Programm komplett runtertippen kannst und alles 
läuft auf Anhieb - das ist ein schwerer Fehler von 
Selbstüberheblichkeit. Da hilft dir auch ein Simulator nichts, denn was 
du im Simulator nicht testen kannst, dass ist die Hardware.

von Sebastian K. (Firma: none) (bastel-basti)


Lesenswert?

Hallo

Danke erstmal für den Hinweis zum LOW setzen von Pins.
Ich werds dann mal damit
1
PORTB &= ~(1<<PB2);
probieren.

Der Hinweis mit dem Testen von Code-Abschnitten ist wohl auch ein guter 
Gedanke. Ich werd meinen Code mal in Häppchen zerlegen und einzeln 
testen.

Ich wollte mit meinen Posts auf keinen Fall überheblich erscheinen. 
Sorry falls das so rüberkam.

Und Danke nochmal für die Hinweise. Melde mich wieder wenn ich Erfolg 
vorweisen kann (oder wenn nicht).

Gruß

von Karl H. (kbuchegg)


Lesenswert?

Sebastian K. schrieb:

> Ich wollte mit meinen Posts auf keinen Fall überheblich erscheinen.
> Sorry falls das so rüberkam.


Ich muss mich entschuldigen. Da hab ich mich wohl nicht gut genug 
ausgedrückt.
Worum es geht, ist das Anfänger gerne glauben man tippt ein Programm 
runter, bessert ein oder zwei Tippfehler aus und dann funktioniert 
alles. Die 'Selbstüberheblichkeit' (das Wort passt nicht ganz) besteht 
in genau diesem Glauben, dass man das könne.
Das genaue Gegenteil ist der Fall. Auch Profis arbeiten stufenweise, 
wenn auch ihre Stufen etwas größer sind.

von Sebastian K. (Firma: none) (bastel-basti)


Lesenswert?

Hallo

Dann hab ich den Hinweis auch selbst ein wenig falsch aufgefasst.
Ich bin ja sehr dankbar, dass solche Möglichkeiten wie dieses Forum und 
die Tutorials hier existieren.

Um zurück zum Projekt zu kommen:

Ich habe jetzt vom Projekt erstmal die Initialisierungphase abgespalten 
und wollte testen was der Tiny2313 damit macht.

Hier der Code:
1
//includes
2
#ifndef F_CPU
3
#define F_CPU 8000000UL
4
#endif
5
#include <avr/io.h>
6
#include <inttypes.h>
7
#include <util/delay.h>
8
#include <avr/sleep.h>
9
#include <avr/interrupt.h>
10
11
12
13
//Methoden:
14
15
//Methode zur Schalterabfrage
16
uint8_t CallSwitchState(const volatile uint8_t *inputreg, uint8_t inputbit)
17
{
18
  return ( *inputreg & (1<<inputbit) );
19
}
20
21
// lange, variable Wartezeit, Einheit in Millisekunden 
22
void long_delay(uint8_t ms) 
23
{
24
    for (; ms>0; ms--) _delay_ms(1);
25
}  
26
27
28
//main-Methode
29
int main(void)
30
{
31
  //variables
32
  uint8_t switch_state = 0;
33
  uint8_t count = 0;
34
  
35
  //Set pins of Port D as input
36
  DDRD = 0b00000000;
37
  //Disable internal pull ups of Port D
38
  PORTD = 0b00000000;
39
  //Set PORT B pins as output
40
  DDRB = 0b11111111;
41
42
  //Hauptschleife (läuft dauerhaft...)
43
  while(1)
44
  {
45
    //frage schalterstatus ab
46
    switch_state = CallSwitchState( &PIND, PD2 );
47
    
48
    //'Servo-Aus'-Schleife beginnen, wenn PD2 = LOW
49
    while (switch_state == 0)
50
    {
51
      //wenn noch keine Sekunde vorbei (Einstellphase für Servo)
52
      if (count < 75)
53
      {
54
        //counter hochzählen    
55
        count +=1;
56
        
57
        //setze Pin PB1 auf LOW
58
        PORTB &= ~( 1 << PB2 );
59
60
        //warte 13 ms (duty-cycle des Servo)
61
        long_delay(13);
62
      
63
        //setze Pin PB1 HIGH
64
        PORTB |= ( 1 << PB1 );
65
      
66
        //warte 1,3 ms (Pulslänge für "Servo eingefahren"-Ausschlag)
67
        _delay_us(1300);
68
      }
69
      //wenn servo sicher nach initialisierung auf "Eingefahren"
70
      else
71
      {
72
        //setze counter auf 0
73
        count = 0;
74
        
75
        //verlasse Servo-while-schleife, wenn Zeit um
76
        break;  
77
      }      
78
    }
79
  }
80
81
  return(0);
82
}

Leicht ernüchtert musste ich feststellen, dass der uC nicht mal 
Ansatzweise daran denkt den Servo zu bewegen. Der Aktor zuckt nur einmal 
kurz beim Reset, was sich aber vermutlich auf 
"Initialisierungs-Glitches" zurück führen lässt.

Ich habe gerade selbst die Vermutung, dass ich vielleicht den Pin nicht 
korrekt abfrage, oder ich noch eine falsche Vorstellung vom Rückgabewert 
der "switch_state"-Methode habe.
Könnte da was dran sein, oder bin ich da total auf dem Holzweg?

Gruß,
Basti

von Sebastian K. (Firma: none) (bastel-basti)


Angehängte Dateien:

Lesenswert?

Hallo mal wieder

Mittlerweile habe ich meinen Code lauffähig bekommen.
Er ist vielleicht nicht ganz so professionell und elegant, aber immerhin 
tut er was er soll :)
(Steuern des Servos und den Schlafmodus nutzen um Strom zu sparen)

Der entsprechende C-Code findet sich (recht ausführlich kommentiert) im 
Anhang an diesen Post.

Zusätzlich sind dort die Schaltpläne für eine Steuerplatine der 
Useless-Machine zu finden (Eagle-Files).
Habe die Platine aber dank kleiner Größe mit Lochraster aufgebaut.

Danke nochmal an alle Hinweise und die Tutorials zu AVR-GCC auf dieser 
Seite.

Beste Grüße,

Basti

von Wegstaben V. (wegstabenverbuchsler)


Lesenswert?

wo ist jetzt der Vorteil, anstelle von

_delay_ms(15)

zu schreiben

long_delay(15)

?????

das erste scheint mir besser lesbar zu sein, und spar auch noch code 
(-Speicherplatz)

von Sebastian K. (Firma: none) (bastel-basti)


Lesenswert?

Guten Morgen,

Wegstaben Verbuchsler schrieb:
> wo ist jetzt der Vorteil, anstelle von
>
> _delay_ms(15)
>zu schreiben
>
>long_delay(15)
>

Das ist ne gute Frage denk ich...
Ich meinte irgendwo gelesen zu haben, das lange Warteschleifen manchmal 
Probleme verursachen können. Und gleich darunter fand ich dann den Tip 
mit der "long_delay()"-Methode.
Als Anfänger hab ich das dann gleich mal aufgegriffen und wollte auf 
Nummer sicher gehen. Ich lasse mich aber gerne eines Besseren belehren, 
wenn mein Vorgehen da unsinnig ist :)


Ein kleiner Nachtrag noch zum Code/zu externen Interrupts:
Ich hatte anfangs sehr lange rumprobiert, bis ich den ATTiny2313 mit 
externem Interrupt aus dem Schlafmodus holen konnte.
Falls jemand Anderes bei ersten Gehversuchen auch auf dieses Problem 
trifft:
Im Datenblatt des uC steht (auf Seite 31 glaub ich, bei den 
Sleep-Modes), dass sich der 2313 nur durch anhaltenden Low-Level an INT0 
und INT1, oder aber durch die PCINTX-Eingänge aus dem Power-Down-Modus 
aufwecken lässt (Bitte korrigiert, falls falsch).
Leider hatte ich sehr lange rumprobiert den uC mit einer steigender 
Flanke an INT0 und INT1 zu wecken, was aber nicht sehr fruchtbar war.


Gruß,
Basti

von Sebastian K. (Firma: none) (bastel-basti)


Angehängte Dateien:

Lesenswert?

Sorry für den Doppelpost.

Mir ist heute Nachmittag noch ein Fehler in den Eagle-Files aufgefallen.
PB4 hing bei offenem Schalter in der Luft. Der Pull-Down Widerstand war 
leider falsch gesetzt.
Korrigierte Files sind im Anhang, für die die es nachbauen wollen.

Gruß,
Basti

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.