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
voidtimer(){
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
voidpins(){
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
intmain(){
28
inti=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
return0;
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.
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.
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...
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
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.
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
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
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 ?>>
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?
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. :-)
>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.
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.
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.
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.
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
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?
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
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?
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
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.
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?
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.
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...
>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.
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
voidinit_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
intmain(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
elseif(!(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
return0;
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ß
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
voidinit_pins(){
8
DDRB|=(1<<PB0);//PB0 -> Ausgang
9
PORTB&=~(1<<PB0);// PB0 -> low
10
}
11
12
intmain(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?
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 ;-)