Forum: Mikrocontroller und Digitale Elektronik Anfänger benötigt hilfe beim Fehler im Programm


von Thomas (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
ich habe ein kleines Programm geschrieben, aber irgendwie funktioniert 
es nicht wirklich wie es soll.
Ich möchte das ganze auf einen Attiny45 machen. Wenn am Pin4 ein Signal 
anliegt, soll an Pin0 ein PWM-Signal erzeugt werden und an Pin1 eine LED 
angehen.

das überspielen läuft. Allerdings leuchtet die LED sofort, sobald der 
kontroller power bekommt.
Den Schrittmotor habe ich noch nicht getestet, da aber schon die LED 
nicht das macht, was die soll, befürchte ich, dass der Schrittmotor auch 
nicht richtig arbeitet.


zum Aufbau:
an Pin1 folgt ein Widerstand und eine LED, welches mit GND verbunden 
ist. vor Pin4 habe ich einen Taster, welcher von mit VCC verbunden ist. 
Also solange ich den Taster Drücke, soll der arbeiten und danach wieder 
aufhören.
1
#define F_CPU 1000000UL
2
#include <stdlib.h>
3
#include <stdio.h>
4
#include <stdint.h>
5
#include <avr/io.h>
6
#include <util/delay.h>
7
8
void timer(){
9
  TCCR0A |= (1<<WGM00) | (1<<WGM01); // Set Fast PWM mode.
10
  TCCR0A |= (1<<COM0A1);  // Clear 0C0A on compare.
11
  TCCR0B |= (1<<CS00) | (1<<CS01);  // Start timer, no prescaling. 
12
  OCR0A = 0;
13
}
14
15
void pins(){
16
  DDRB |= (1<<PB0);  //PB0 -> Ausgang  
17
  PORTB &= ~(1<<PB0);  // PB0 -> low 
18
  DDRB |= (1<<PB1);  //PB1 -> Ausgang 
19
  PORTB &= ~(1<<PB1);  // PB1 -> low 
20
  DDRB &= ~(1<<PB4);  // PB4 -> Eingang 
21
  PORTB |= (1<<PB4);  // Interner Pull-Up einschalten
22
}
23
24
25
26
27
int main(){
28
  int i=5;
29
  PORTB &= ~(1<<PB1);
30
  pins();
31
  timer();
32
  while(1){
33
    if(PINB&(1<<PINB4)){  // Pin4 -> High
34
    PORTB |= (1<<PB1);  // LED an Pin1 -> an
35
    while(PINB&(1<<PINB4)){
36
      PORTB |= (1<<PB1);  // LED an Pin1 -> an
37
      i++;      // PWM +1
38
    if(i>=180) i=180;
39
    OCR0A = i;    // setze PWM
40
    _delay_ms(15);
41
    }
42
  }
43
  else{
44
    PORTB &= ~(1<<PB1);  // LED an Pin1 -> aus
45
    while(i>=5){
46
      PORTB &= ~(1<<PB1);  // LED an Pin1 -> aus
47
      i--;      // PWM -1
48
    OCR0A = i;    // setze PWM
49
    _delay_ms(15);
50
    if(PINB&(1<<PINB4)) break;
51
    }          
52
  }
53
  }
54
  return 0;
55
}

Ob das mit dem Timer richtig ist, habe ich absolut keine Ahnung. Dies 
habe ich so fertig gefunden und so benutzt.

Wäre aber über jeden Hinweis, wie ich das Programm richtig machen kann 
dankbar.

von berliner (Gast)


Lesenswert?

Ich vermute dein Schalter soll den Pin4 nach VCC ziehen?
Sobald der PullUp an ist, wird der Pin4 ohnehin "high".
Abhilfe wäre den Pin4 durch einen Schalter nach GND zu ziehen und im 
Programm ein "false" (Null) abzufragen.

von berliner (Gast)


Lesenswert?

oder den Pin4 als PullDown konfigurieren soll angeblich stromfressend 
sein, was in deinem Fall vermutlich egal ist.

von ich (Gast)


Lesenswert?

berliner schrieb:
> als PullDown konfigurieren

Wie meinst du das? Hat der Tiny etwa eingebaute Pulldowns?

Ich denke, als Eingang konfigurieren und extern einen Pulldown 
anschließen ist vermutlich das, was du eigentlich meinst...

von Thomas (Gast)


Angehängte Dateien:

Lesenswert?

Wäre das so richtig?
1
...
2
int main(){
3
  int i=5;
4
  PORTB &= ~(1<<PB1);
5
  init_servo();
6
  init_timer();
7
  TCCR0B = (1<<CS01); // Prescaler 8
8
  while(1){
9
    if(!(PINB&(1<<PINB4))){  // Pin4 -> High
10
    PORTB |= (1<<PB1);  // LED an Pin1 -> an
11
    while(!(PINB&(1<<PINB4))){
12
      PORTB |= (1<<PB1);  // LED an Pin1 -> an
13
      i++;      // PWM +1
14
    if(i>=180) i=180;
15
    OCR0A = i;    // setze PWM
16
    _delay_ms(15);
17
    }
18
  }
19
  else{
20
    PORTB &= ~(1<<PB1);  // LED an Pin1 -> aus
21
    while(i>=5){
22
      PORTB &= ~(1<<PB1);  // LED an Pin1 -> aus
23
      i--;      // PWM -1
24
    OCR0A = i;    // setze PWM
25
    _delay_ms(15);
26
    if(PINB&(1<<PINB4)) break;
27
    }          
28
  }
29
  }
30
  return 0;
31
}

Also funktionieren tut es, aber ich weiss jetzt nicht, ob es einfach nur 
Glück ist, oder ob es so richtig ist (was mich natürlich mehr freuen 
würde)

Allerdings läuft der Schrittmotor noch nicht so richtig.
manchmal höre ich ein summen, manchmal fährt er ein bisschen in einer 
richtung und manchmal springt er hin und her.
wüsstest du auch woran das liegen könnte?

mfg

von Thomas (Gast)


Lesenswert?

Ähm,
das Programm ist
1
int main(){
2
  int i=5;
3
  PORTB &= ~(1<<PB1);
4
  pins();
5
  timer();
6
  while(1){
7
    if(!(PINB&(1<<PINB4))){  // Pin4 -> High
8
    PORTB |= (1<<PB1);  // LED an Pin1 -> an
9
    while(!(PINB&(1<<PINB4))){
10
      PORTB |= (1<<PB1);  // LED an Pin1 -> an
11
      i++;      // PWM +1
12
    if(i>=180) i=180;
13
    OCR0A = i;    // setze PWM
14
    _delay_ms(15);
15
    }
16
  }
17
  else{
18
    PORTB &= ~(1<<PB1);  // LED an Pin1 -> aus
19
    while(i>=5){
20
      PORTB &= ~(1<<PB1);  // LED an Pin1 -> aus
21
      i--;      // PWM -1
22
    OCR0A = i;    // setze PWM
23
    _delay_ms(15);
24
    if(PINB&(1<<PINB4)) break;
25
    }          
26
  }
27
  }
28
  return 0;
29
}

von Marvin (Gast)


Lesenswert?

Hi,

Meinst Du Servo oder Schrittmotor ?

Wenn Schrittmotor -> falsche Ansteuerung

Wenn Servo -> Check mal die CPU Frequenz....


Gruß

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

ich schrieb:
> berliner schrieb:
>> als PullDown konfigurieren
> Ich denke, als Eingang konfigurieren und extern einen Pulldown
> anschließen ist vermutlich das, was du eigentlich meinst...
Ich denke, als Eingang mit Pullup kofigurieren und dann mit einem 
Pulldown einen anständigen Low-Pegel zu erzeugen, der anschließend mit 
einem Taster wieder auf 5V gezogen werden kann, das wird es sein, was 
gemeint war...

@ Thomas
> schaltplan_neu.png
Sieh dir mal andere Schaltpläne an. Erkennst du den Unterschied?
Richtig: in einem richtigen Schaltplan ist kein Gehäuse abgebildet, 
sondern Funktionen und Pinnummern.

von Thomas (Gast)


Angehängte Dateien:

Lesenswert?

Hi,
für mich waren Schrittmotoren und Servos immer das gleiche. Dies ist 
aber nicht so. Also, es ist kein SChrittmotor, sondern ein Servo. Dieser 
bewegt sich jetzt aber überhaupt nicht mehr.
habe mir das Beispiel "Signalerzeugung für 1 Servo mittels Timer (C)"
von
http://www.mikrocontroller.net/articles/Modellbauservo_Ansteuerung
zur hilfe genommen, aber er rührt sich kein Stück. Den Servo habe ich 
angelschlossen mit:
Braun -> GND
Rot -> VCC
Orange -> PB0
1
#define F_CPU 1000000UL
2
#include <stdlib.h>
3
#include <stdio.h>
4
#include <stdint.h>
5
#include <avr/io.h>
6
#include <avr/interrupt.h>
7
#include <util/delay.h>
8
9
10
11
void init_timer(){
12
  // Set Fast PWM mode.
13
  TCCR0A |= (1<<WGM00) | (1<<WGM01);
14
  // Clear 0C0A on compare.
15
  TCCR0A |= (1<<COM0A1);
16
  // Start timer, no prescaling.
17
  TCCR0B |= (1<<CS00) | (1<<CS01);
18
  // Duty cycle 0% 
19
  OCR0A = 2250;
20
21
  sei();
22
23
}
24
25
void init_pins(){
26
  DDRB |= (1<<PB0);  //PB0 -> Ausgang  
27
  PORTB &= ~(1<<PB0);  // PB0 -> low 
28
  DDRB |= (1<<PB1);  //PB1 -> Ausgang 
29
  PORTB &= ~(1<<PB1);  // PB1 -> low 
30
  DDRB &= ~(1<<PB4);  // PB4 -> Eingang 
31
  PORTB |= (1<<PB4);  // Interner Pull-Up einschalten
32
}
33
34
ISR(TIMER1_COMPA_vect){                // Interruptbehandlungsroutine
35
  OCR0A = 2500-OCR0A;      // Das Servosignal wird aus der Differenz von
36
                                        // Periodenlänge (2500*0,008ms=20ms) und letztem
37
                                        // Vergleichswert (OCR0A) gebildet 
38
}
39
40
41
int main(){
42
  int i = 2250; // Rechte Ausgangsstellung Servo (2500-2250)*0,008 = 2   (1->Links; 1,5->Mitte;  2->Rechts)
43
             // 2375->Links
44
  PORTB &= ~(1<<PB1);
45
  init_timer();
46
  init_pins();
47
  _delay_ms(1000);
48
  while(1){
49
    if(!(PINB&(1<<PINB4))){  // Pin4 -> High
50
    PORTB |= (1<<PB1);  // LED an Pin1 -> an
51
    while(!(PINB&(1<<PINB4))){
52
      PORTB |= (1<<PB1);  // LED an Pin1 -> an
53
    cli();
54
      i++;      // PWM +1
55
    if(i>=2375) i=2375;
56
    OCR0A = i;    // setze PWM
57
    sei();
58
    _delay_ms(15);
59
    }
60
  }
61
  else{
62
    PORTB &= ~(1<<PB1);  // LED an Pin1 -> aus
63
    while(i>=2250){
64
      PORTB &= ~(1<<PB1);  // LED an Pin1 -> aus
65
    cli();
66
      i--;      // PWM -1
67
    OCR0A = i;    // setze PWM
68
    sei();
69
    _delay_ms(15);
70
    if(!(PINB&(1<<PINB4))) break;
71
    }          
72
  }
73
  }
74
  return 0;
75
}


Ich hoffe, dass dieser Schaltplan ein bisschen besser ist. Habe die 
Pinbelegung jetzt rangeschrieben. Leider weiss ich nicht, wie ich es 
anders  aufzeichnen soll.

mfg

von Uwe (de0508)


Lesenswert?

Hallo,

was passiert wohl, wenn i<2375 ?
Alle Interrupts sind gesperrt - soll das so sein ?
1
cli();
2
      i++;      // PWM +1
3
    if(i>=2375) i=2375;
4
    OCR0A = i;    // setze PWM
5
    sei();
6
    _delay_ms(15);
7
    }

von Bitflüsterer (Gast)


Lesenswert?

Uwe S. schrieb:
> Hallo,
>
> was passiert wohl, wenn i<2375 ?
Die nachfolgenden Aufrufe und Zuweisungen werden unabhängig davon 
ausgeführt ob oder ob nicht i <2375.

> Alle Interrupts sind gesperrt - soll das so sein ?
>
>
1
cli();
2
>  i++;      // PWM +1
3
>  if(i>=2375)
4
>    i=2375;
5
>  OCR0A = i;    // setze PWM
6
>  sei();
7
>  _delay_ms(15);
8
>}

von Thomas (Gast)


Lesenswert?

Wenn i<2375 ist, soll i einfach weiter hochzählen und somit den Servo 
weiter drehen.
1
if(i>=2375) i=2375;
habe ich nur reingemacht, damit der Servomotr stehen bleibt.
2375 laut meiner Berechnung einen Impuls von 2 ms bringen und somit 
Sollte der Servomotor an der grenze sein.
oder habe ich dich falsch verstanden?

von Bitflüsterer (Gast)


Lesenswert?

Was mich aber darauf bringt, das man mal die Formattierung korrigieren 
könnte.
Meine Brille beschlägt schon, der Hund jault seit der Code auf dem 
Bildschirm ist und die Ratten verlassen das Haus. :-)

von Thomas (Gast)


Lesenswert?

1
  cli();
2
  i++;      // PWM +1
3
  if(i>=2375) i=2375;
4
  OCR0A = i;    // setze PWM
5
  sei();
6
  _delay_ms(15);
7
}

ist das so besser?
aber trotzdem bleibt noch das Problem, dass sich mein Servomotor 
überhaupt nicht bewegt.

gruß

von Bitflüsterer (Gast)


Lesenswert?

>ist das so besser?
Entschuldige, aber ist das Naivität oder willst Du mich verarschen? :-)
Die Formatierung sollte für den gesamten Code korrekt sein. Dann sieht 
man auch Fehler besser.

Die vom if abhängige Anweisung, kannst Du natürlich so auf der selben 
Zeile lassen. Das steht Dir frei. Aber Du siehst ja, zu welchem 
Mißverständnis das führt.

von Thomas (Gast)


Lesenswert?

1
#define F_CPU 1000000UL
2
#include <stdlib.h>
3
#include <stdio.h>
4
#include <stdint.h>
5
#include <avr/io.h>
6
#include <avr/interrupt.h>
7
#include <util/delay.h>
8
9
10
11
void init_timer(){
12
  // Set Fast PWM mode.
13
  TCCR0A |= (1<<WGM00) | (1<<WGM01);
14
  // Clear 0C0A on compare.
15
  TCCR0A |= (1<<COM0A1);
16
  // Start timer, no prescaling.
17
  TCCR0B |= (1<<CS00) | (1<<CS01);
18
  // Duty cycle 0% 
19
  OCR0A = 2250;
20
21
  sei();
22
}
23
24
void init_pins(){
25
  DDRB |= (1<<PB0);  //PB0 -> Ausgang  
26
  PORTB &= ~(1<<PB0);  // PB0 -> low 
27
  DDRB |= (1<<PB1);  //PB1 -> Ausgang 
28
  PORTB &= ~(1<<PB1);  // PB1 -> low 
29
  DDRB &= ~(1<<PB4);  // PB4 -> Eingang 
30
  PORTB |= (1<<PB4);  // Interner Pull-Up einschalten
31
}
32
33
ISR(TIMER1_COMPA_vect){                // Interruptbehandlungsroutine
34
  OCR0A = 2500-OCR0A;      // Das Servosignal wird aus der Differenz von
35
                                        // Periodenlänge (2500*0,008ms=20ms) und letztem
36
                                        // Vergleichswert (OCR0A) gebildet 
37
}
38
39
40
int main(){
41
  int i = 2250; // Rechte Ausgangsstellung Servo (2500-2250)*0,008 = 2   (1->Links; 1,5->Mitte;  2->Rechts)
42
             // 2375->Links
43
  PORTB &= ~(1<<PB1);
44
  init_timer();
45
  init_pins();
46
  _delay_ms(1000);
47
  while(1){
48
    if(!(PINB&(1<<PINB4))){  // Pin4 -> High
49
      PORTB |= (1<<PB1);  // LED an Pin1 -> an
50
      while(!(PINB&(1<<PINB4))){
51
        PORTB |= (1<<PB1);  // LED an Pin1 -> an
52
        cli();
53
        i++;      // PWM +1
54
        if(i>=2375) i=2375;
55
        OCR0A = i;    // setze PWM
56
        sei();
57
        _delay_ms(15);
58
      }
59
    }
60
    else{
61
      PORTB &= ~(1<<PB1);  // LED an Pin1 -> aus
62
      while(i>=2250){
63
        PORTB &= ~(1<<PB1);  // LED an Pin1 -> aus
64
        cli();
65
        i--;      // PWM -1
66
        OCR0A = i;    // setze PWM
67
        sei();
68
        _delay_ms(15);
69
        if(!(PINB&(1<<PINB4))) break;
70
      }          
71
    }
72
  }
73
  return 0;
74
}

so, nun noch einmal alles ausgerichtet und hoffe, dass man es jetzt 
besser lesen kann. Die verschiebungen kamen aber erst, als ich es hier 
herein kopiert habe.


mfg

Ps.: Verarschen möchte ich hier gar keinen. Ich möchte ja schließlich 
was lernen und hilfe zu meinen Problemen bekommen. Da fände ich so etwas 
nicht angebracht.

von Karl H. (kbuchegg)


Lesenswert?

Thomas schrieb:

>   // Set Fast PWM mode.
>   TCCR0A |= (1<<WGM00) | (1<<WGM01);


Das ist aber nicht das, was im von dir genannten Artikel steht.
Dort ist ein CTC Modus benutzt worden.

Generell: Diesen Code muss ich mal aus dem Artikel rauswerfen. Der ist 
nicht besonders gut und er hat ein potentielles Problem.


Also:
#Zurück an den Anfang. Hol dir den Originalcode vom Artikel.

Und dann machst du eines NICHT!
Du fängst nicht an, diesen Code an allen Ecken und Enden zu verändern, 
sondern du bringst ihn jetzt erst mal auf deinem µC zum laufen. 
Veränderungen, die du machen musst, weil du einen anderen µC benutzt, 
die musst du natürlich machen. Aber an der grundsätzlichen 
Funktionsweise, wie zb das da eine fixe Servoposition vorgegeben wurde 
änderst du erst mal nichts.

Wenn der Code dann soweit auf deinem µC läuft, dann machst du KLEINE 
Veränderungen, wobei du nach jeder Veränderung testest, ob noch alles 
funktioniert. Sonst landest du wieder bei einem Programm, dass 300 
Veränderungen zum Original hat, die nie einzeln getestet wurden, das 
nicht funktioniert und du hast keine Ahnung, wo du mit der Suche 
anfangen sollst.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:

> Generell: Diesen Code muss ich mal aus dem Artikel rauswerfen. Der ist
> nicht besonders gut und er hat ein potentielles Problem.

Wenn ich es mir recht überlege:
Nein, der hat nicht nur ein potentielles Problem, der hat sogar ein 
recht handfestes Problem, das gar nicht so leicht zu lösen ist. Der Code 
funktioniert zwar, so wie er gepostet ist (wenn man Glück hat), aber er 
ist in der Praxis zu nichts zu gebrauchen. Den werd ich demnächst 
rauswerfen bzw. umbauen. Den Pin vom Timer toggeln zu lassen und naiv in 
der Hauptschleife OCR0A einen neuen Wert zu verpassen, das funktioniert 
nur deswegen leidlich, weil der Puls wesentlich kürzer als die Pulspause 
ist und so die Chance in der Hauptschleife abwechselnd einmal den Puls 
und dann wieder die Pause mit einem OCR0A+=3 zu verlängern bei rund 1:19 
zu Gunsten der Pause steht.

: Bearbeitet durch User
von Thomas (Gast)


Lesenswert?

Das werde ich dann doch wohl mal machen, da habe ich aber direkt ein 
paar fragen.
So wie es da steht funktioniert es bei mir nicht. Da bekomme ich die 
Fehlermeldung:
../useless452.c:20:3: error: 'TCCR1A' undeclared (first use in this 
function)
Das selbe für TCCR1B und WGM12 und andere fehler
das liegt denke ich mal am Kontroller und das werde ihc mit dem 
Datenblatt versuchen hearuszufinden.

Aber meine wäre eigentlich zur While Schleife. Eigentlich Bekomme ich 
das PWM-Signal ja von PB0.
jetzt habe ich in der while-Schleife die abfrage
1
if( !(PINB & (1<<PINB0)) )
und
1
if( !(PINB & (1<<PINB1)) )

das erste bedeutet doch, dass PB0 auf GND gezogen werden muss und beim 
zweiten PB1 oder?
Wenn das so ist, an welchem Pin ist mein PWM-Signal?

mfg

von Thomas (Gast)


Lesenswert?

Ah nein, mit PB0 und PB1 kann ich den Servo hin und her fahren lassen 
oder? aber an welchem Pin bekomme ich mein PWM-Signal? im welchen Teil 
vom Code steht das?

von Thomas (Gast)


Lesenswert?

Habe das jetzt mal so geändert, dass es meiner meinung nach 
Funktionieren müsste. Aber natürlich bewegt scih gar nichts.

Eigentlich habe ich vieles so gelassen, bis auf

TCCR1A = (1<<COM1A0); -> TCCR1 = (1<<COM1A0);
TCCR1B = (1<<WGM12) | (1<<CS11); -> TCCR1 = (1<<CS12);
DDRB = 0b11111100; -> DDRB = 0b11100111;
PORTB = (1<<PB1) | (1<<PB0); -> PORTB = (1<<PB3) | (1<<PB4);

1
#define F_CPU 1000000UL
2
 
3
#include <avr/io.h>
4
#include <avr/interrupt.h>
5
#include <util/delay.h>
6
 
7
ISR( TIMER1_COMPA_vect )                // Interruptbehandlungsroutine
8
{
9
  OCR1A = 2500-OCR1A;      // Das Servosignal wird aus der Differenz von
10
                                        // Periodenlänge (2500*0,008ms=20ms) und letztem
11
                                        // Vergleichswert (OCR1A) gebildet 
12
}
13
 
14
 
15
int main (void)
16
{
17
  DDRB = 0b11100111;
18
  PORTB = (1<<PB3) | (1<<PB4);          // Pullup für PB3 und PB4
19
 
20
  TCCR1 = (1<<COM1A0);                 // Togglen bei Compare Match
21
  TCCR1 = (1<<CS12);                   // Prescaler  
22
  TIMSK  = (1<<OCIE1A);                 // Timer-Compare Interrupt an
23
24
 
25
26
  OCR1A = 2312;                         // Neutralposition ((2500-2312)*0.008ms)=1,5ms)
27
 
28
  sei();                                // Interrupts global an
29
 
30
  while( 1 ) {
31
 
32
    if( !(PINB & (1<<PINB3)) ) {       // Impuls-Zeit verlängern
33
      cli();
34
      OCR1A = OCR1A + 3;
35
      sei();
36
      _delay_ms(50);
37
    }
38
 
39
    if ( !(PINB & (1<<PINB4)) ) {       // Impuls-Zeit verkürzen
40
      cli();
41
      OCR1A = OCR1A - 3;
42
      sei();
43
      _delay_ms(50);
44
    }
45
  }
46
 
47
  return 0;
48
}

was ist jetzt noch falsch? Ich habe wirklich keine Ahnung mehr. Wäre 
über jeden Hinweis sehr dankbar.

Thomas

von spess53 (Gast)


Lesenswert?

Hi

>Ich möchte das ganze auf einen Attiny45 machen.

>OCR1A = 2312;

Der Timer1 vom ATTiny45 ist ein 8-Bit Timer. Der ganze Code kann nicht 
funktionieren.

MfG Spess

von Thomas (Gast)


Lesenswert?

Aber was kann daran nicht funktionieren?
Ich habe es so wie aus dem Beispel gemacht.
Prozessortakt = 1MHz
Prescalar = 8

1MHz/8 = 125kHz -> 0,008ms

(2500-2312)*0,008ms=1,504ms

Was muss ich anders einstellen?

von spess53 (Gast)


Lesenswert?

Hi

>Aber was kann daran nicht funktionieren?

Beim ATTiny45 kann OCR1A nur Werte von 0...255 annehmen. Als notorischer 
Assemblerprogrammierer wundert es mich echt, warum bei einem

OCR1A = 2312;

der Compiler nicht eine Fehlermeldung oder zumindest eine Warnung 
ausgibt. Den richtigen Controller hast du für den GCC eingestellt?

Der ATTiny45 hat eine Reihe von Eigenheiten, die ihn von 'normalen' AVRs 
unterscheiden. Deshalb werden eine ganze Reihe von hier veröffentlichten 
Beispielprogrammen nicht funktionieren.

Besorge dir z.B. einen ATTiny2313 dann läuft auch das Programm.

MfG Spess

von Thomas (Gast)


Lesenswert?

So habe es jetzt geändert.
Die Frequenz habe ich auf 100000Hz gesetzt und OCR1A=250-OCR1A. Damit 
beträgt mein T 20ms. das t_ein kann zwischen 1ms (OCR1A=237) und 2ms 
(OCR1A=225) geändert werden.
Allerdings rührt sich gar nichts bei mir. Der Fährt am Anfang noch nciht 
mal in seine Ausgangsposition.
1
#define F_CPU 100000UL
2
 
3
#include <avr/io.h>
4
#include <avr/interrupt.h>
5
#include <util/delay.h>
6
 
7
ISR( TIMER1_COMPA_vect )                // Interruptbehandlungsroutine
8
{
9
  OCR1A = 250-OCR1A;      // Das Servosignal wird aus der Differenz von
10
                                        // Periodenlänge (2500*0,008ms=20ms) und letztem
11
                                        // Vergleichswert (OCR1A) gebildet 
12
}
13
 
14
 
15
int main (void)
16
{
17
  DDRB = 0b100111;
18
  PORTB = (1<<PB3) | (1<<PB4);          // Pullup für PB3 und PB4
19
 
20
  TCCR1 = (1<<COM1A0);                 // Togglen bei Compare Match
21
  TCCR1 = (1<<CS12);          // Prescalar 8  
22
  TIMSK  = (1<<OCIE1A);                 // Timer-Compare Interrupt an
23
24
25
  OCR1A = 250;                         // Neutralposition ((2500-2312)*0.008ms)=1,5ms)
26
 
27
  sei();                                // Interrupts global an
28
 
29
  while( 1 ) {
30
 
31
    if( !(PINB & (1<<PINB3)) ) {       // Impuls-Zeit verlängern
32
      cli();
33
      OCR1A = OCR1A + 1;
34
      if(OCR1A>=237) OCR1A=237;
35
      sei();
36
      _delay_ms(50);
37
    }
38
 
39
    if ( !(PINB & (1<<PINB4)) ) {       // Impuls-Zeit verkürzen
40
      cli();
41
      OCR1A = OCR1A - 1;
42
      if(OCR1A<=225) OCR1A=225;
43
      sei();
44
      _delay_ms(50);
45
    }
46
  }
47
 
48
  return 0;
49
}

von Walter (Gast)


Lesenswert?

um ein Servosignal zu erzeugen braucht man keinen Interrupt

von Thomas (Gast)


Lesenswert?

Das heisst, ich nehme
1
TIMSK  = (1<<OCIE1A);
wieder raus?
Das hat leider auch nichts geändert.

von 金的龙 (Gast)


Lesenswert?

Thomas schrieb:
> Das heisst, ich nehmeTIMSK  = (1<<OCIE1A);wieder raus?
> Das hat leider auch nichts geändert.

Ist das jetzt die Erfindung der evolutionären Programmierung?

Warum nimmst du nicht gleich ein neuronales Netzwerk und turnst dem das 
richtige Verhalten 10000-mal vor?

von Thomas (Gast)


Lesenswert?

Das soll keine Erfindung sein, ich habe einfach nur keine Ahnung warum 
das nicht funktioniert. Wenn mir dann gesagt wird, dass das überflüssig 
ist, dann glaube ich das, da ich denke, dass hier Leute mit mehr Ahnung 
als ich antworten.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Thomas schrieb:
> Das soll keine Erfindung sein, ich habe einfach nur keine Ahnung warum
> das nicht funktioniert.
Nein, du hast nicht keine Ahnung, warum das nicht funktioniert, du hast 
offenbar nich den geringsten Plan, was du machen willst. Das einzige, 
was du bisher tust, ist einen x-beliebigen Code irgendwo herzukopieren 
und dann daran rumzubasteln.

Warum versuchst du nicht einfach erst mal deinen Modellbauservo 
überhaupt anzusteuern? Und zwar einfach mit einem Delay? Hier mal 
Pseudocode dazu:
1
   Pin=high;
2
   delay_us(1500);
3
   Pin=low;
4
   dely_ms(20);
Und dann spielst du mal an den 1500 rum und guckst, was dein Servo 
macht.

Es ist übrigens unglaublich beschwerlich, solche Sachen in Betrieb zu 
nehmen, wenn man kein Oszi hat. Man rät dauernd herum, was da jetzt 
gerade erzeugt wird. Mein Tipp: pumpe deine Eltern um 50€ an und kauf 
ein Oszi in der Bucht. Für solche PWM-Geschichten tut es jedes Oszi. Und 
du wirst sehen, es tut sich ein neuer Horizont für dich auf...

Wenn du allerdings schon ein Oszi hast, dann stimmt mich das 
nachdenklich...

von tommy (Gast)


Lesenswert?

Hallo Namensvetter ;-)

Thomas schrieb:
> #define F_CPU 100000UL

Was bezweckst Du mit dem oben zitierten define?

von Amateur (Gast)


Lesenswert?

>Was bezweckst Du mit dem oben zitierten define?

Das liegt an den mangelhaften, hellseherischen Fähigkeiten der heutigen 
Compiler.

Eine Bibliothek wie:

#include <util/delay.h>

tut sich schwer mit der Verzögerung, wenn sie nicht weis wie Du tickst.

Viele Teiler werden von diesem Takt abgeleitet. Im normalen tut man sich 
ganz gut diesen auch für verschidene Brechnungen zur Verfügung zu haben.

Manche Entwicklungsumgebungen erfragen diesen Takt auch bei der 
Einrichtung und fügen ihn selbstständig in die Compileraufrufe ein. Dann 
erscheint diese Zeile zwar nicht explizit im Code, ist aber trotzdem 
definiert.

F_CPU ist eine Vereinbarung, die praktisch offiziell ist.

von Thomas (Gast)


Lesenswert?

So, jetzt habe ich es noch einmal so gemacht wie Lothar Miller es gesagt 
hat. Noch einmal ganz von vorne
1
#define F_CPU 1000000UL
2
 
3
#include <avr/io.h>
4
#include <util/delay.h>
5
6
7
void init_pins(){
8
  DDRB |= (1<<PB0);  //PB0 -> Ausgang  
9
  PORTB &= ~(1<<PB0);  // PB0 -> low 
10
  DDRB &= ~(1<<PB3);  // PB3 -> Eingang 
11
  PORTB |= (1<<PB3);  // Interner Pull-Up einschalten
12
  DDRB &= ~(1<<PB4);  // PB4 -> Eingang 
13
  PORTB |= (1<<PB4);  // Interner Pull-Up einschalten
14
}
15
16
int main (void)
17
{
18
  init_pins();
19
20
  while( 1 ) {
21
 
22
    if( !(PINB & (1<<PINB3)) ) {
23
      PORTB |= (1<<PB0);
24
      _delay_us(1000);
25
       PORTB &= ~(1<<PB0);
26
      _delay_ms(19);
27
    }
28
 
29
    else if ( !(PINB & (1<<PINB4)) ) {
30
      PORTB |= (1<<PB0);
31
      _delay_us(2000);
32
       PORTB &= ~(1<<PB0);
33
      _delay_ms(18);
34
    }
35
    else{
36
      PORTB |= (1<<PB0);
37
      _delay_us(1500);
38
       PORTB &= ~(1<<PB0);
39
      _delay_ms(18);
40
    }
41
  }
42
  return 0;
43
}

ABer mein Servomotor bewegt sich immer noch kein Stück.
Ist der Kaputt? Nein, da wenn ich das ganze mit meinem Arduino mache, 
bewegt der sich.

Einen Plan was ich machen möchte habe ich sehr wohl. Allerdings bin ich 
kein Profi in Programmieren oder von mir aus auch ein totaler Anfänger. 
Ich habe mich aber an den Tutorials auf dieser Seite orientiert. Daher 
habe ich gedacht, dass es nicht so kompliziert ist.

gruß

von Bitflüsterer (Gast)


Lesenswert?

Ich denke Lothar meinte das anders. Noch einfacher. Erstmal sollst Du 
überhaupt nur das Prinzip der PWM-Ansteuerung verwenden.

Es geht darum, dass Du nicht sofort die endgültige Funktionalität 
anstrebst sondern erstmal ganz kleine Schritte machst (im Sinne des 
Projektfortschrittes). Ich empfehle Dir dringend, begleitend dazu 
Material (wenigstens das Datenblatt) über den uC (die Timer) zu lesen.

Die Beispiele beschränken sich in ähnlicher Weise in vielerlei Hinsicht. 
Auf bestimmte uCs. Auf bestimmte Voraussetzungen. Erwarte nicht mehr von 
Ihnen, als der Zusammenhang, in dem sie erscheinen, verspricht. Sonst 
wirst Du, wie hier, frustriert.

Was ist eigentlich mit dem Oszilloskop? Hast Du eines?

1
#define F_CPU 1000000UL
2
 
3
#include <avr/io.h>
4
#include <util/delay.h>
5
6
7
void init_pins(){
8
  DDRB |= (1<<PB0);  //PB0 -> Ausgang  
9
  PORTB &= ~(1<<PB0);  // PB0 -> low
10
}
11
12
int main (void)
13
{
14
  init_pins();
15
16
  while( 1 ) {
17
    PORTB |= (1<<PB0);
18
    _delay_us(1000);
19
    PORTB &= ~(1<<PB0);
20
    _delay_ms(19);
21
  }
22
}

Jetzt müsste der Motor irgendeine Position halten. Macht er das?

Ich bin übrigends furchtbar neugierig auf Deinen Schaltplan und ein Foto 
Deines Aufbaus. Irgendwie habe ich mehrfach den Gedanken gehabt: Ob Du 
wohl die Versorgungsspannung mit 100nF gepuffert hast?

von tommy (Gast)


Lesenswert?

Amateur schrieb:
>>Was bezweckst Du mit dem oben zitierten define?
>
> Das liegt an den mangelhaften, hellseherischen Fähigkeiten der heutigen
> Compiler.
>
> Eine Bibliothek wie:
>
> #include <util/delay.h>
>
> tut sich schwer mit der Verzögerung, wenn sie nicht weis wie Du tickst.
>
> Viele Teiler werden von diesem Takt abgeleitet. Im normalen tut man sich
> ganz gut diesen auch für verschidene Brechnungen zur Verfügung zu haben.
>
> Manche Entwicklungsumgebungen erfragen diesen Takt auch bei der
> Einrichtung und fügen ihn selbstständig in die Compileraufrufe ein. Dann
> erscheint diese Zeile zwar nicht explizit im Code, ist aber trotzdem
> definiert.
>
> F_CPU ist eine Vereinbarung, die praktisch offiziell ist.

Vielen Dank für diese gute Erklärung.
Ich muss aber gestehen, dass ich das schon wusste.
Ausser mir schien es aber niemand aufgefallen zu sein,dass
F_CPU mit 100kHz definiert wurde ;-)

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.