PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Ansteuerung RC LED Scheinwerfer



StephanHD
06.03.2016, 18:22
Hallo RN-Gemeinde,

Ich bin neu hier und hoffe darauf, das ich hier ein bisschen Hilfe bei beinen Projekten bekomme.

Erst mal zu meiner Person, ich bin 33 Jahre, gelernter Elektriker und komme aus dem Rhein Neckar Kreis Rund um Heidelberg. Mein grosses Hobby ist der RC -Modellbau.
Ich möchte mich etwas mehr mit den ganzen AVR Mikropozessoren beschäftigen um damit die ein oder andere Funktion an meinen Modellen zu realisieren.

Ein konkretes erstes Projekt gibt es auch schon.

Zu meinem Vorhaben:

Ich habe ein Modell eines Polizeibootes (Robbe W3) gebaut, dies ist auch schon komplett fertig bis auf eine Funktion.

Auf dem Aufbau befindet sich ein Scheinwerfer, welchen ich auch schon mit einer LED (weiss 3V 20mA) bestückt habe. Dieser Scheinwerfer lässt sich über ein Modellbauservo drehen.

Aktuell habe ich aber keinen Schaltkanal mehr frei, um diesen Scheinwerfer einzuschalten. Hier soll nun ein Mikroprozessor ran.

Am liebsten würde ih es gerne mit einem Tiny13 realisieren aber ich befürchte der ist dafür schon fast zu klein.

Ich möchte gerne das Signal des Servos welches den Scheinwerfer dreht auswerten. Sprich Servo bewegt sich dann Scheinwerfer an, Servo steht für eine Zeit x still, Scheinwerfer geht wieder aus.
Am liebsten wäre mir auch, wenn die LED nicht einfach nur an und aus gehen würde sondern per PWM heller und dunkler wird.

Da der Tiny 13 ja nur einen Timer besitzt, denke ich mal ist hier das größte Problem.
Der Timer0 muss sofern das überhaupt gehen 3 Funktionen übernehmen.

- PWM vom Empfänger einlesen und auswerten
- PWM für die LED erzeugen
- Nachlaufzeit für LED nachdem keine Servobewegung mehr erkannt wurde zählen.

Meine konktrete Frage ist nun ist das mit dem Tiny 13 realisierbar ? oder doch eher ein 2313?

und welche Betriebsart für den Timer benutzen ? Verstehe ich das in dem Datenblatt richtig das er zwar nur einen Timer aber zwei unabhängig Compare register hat. Kann man dann das erste register nehmen um den Empfänger auszuwerten und das zweite für die LED PWM ? Und mit einem Überlauf kann ich mir dann ja evtl. die nachlaufzeit zusammen addieren oder?

Danke für eure Meinungen im Voraus.

Gruß

Stephan

021aet04
06.03.2016, 20:02
Willkommen im Forum,
Ich kenne den uC nicht, sollte aber, laut deinen Angaben, funktionieren.

Ansonsten könntest du noch den Attiny25, 45 bzw 85 oder Attiny44 nehmen.

Aber ein timer reicht eigentlich. Normale PWM Funktion für die LED (oder Soft PWM), die Interrupt zählen für die Stillstandserkennung. Für die Auswertung des Servosignals nimmst du einen normalen Int Eingang und liest bei einem Int den aktuellen Timerwert aus.

MfG Hannes

Sauerbruch
07.03.2016, 20:49
Hallo Stephan,

für so eine Aufgabe (Servo-Impulse überwachen, bei Änderungen eine LED einschalten, bei konstant bliebender Impulslänge die LED langsam abdimmen) ist ein Mikrocontroller geradezu ideal! Ich bin übrigens auch Modellbauer, auf dem Gebiet der Elektronik zwar nur Amateur, aber der Einstieg in die Materie der Mikrocontroller hat mir ganz neue Welten eröffnet.

Mit dem ATtiny13 habe ich gerade am letzten Wochenende eine kleine Schaltung für einen Modellbau-Kollegen realisiert, von daher habe ich seine Features gerade ganz gut auf dem Schirm. Wenn man einigermaßen sparsam mit dem Speicherplatz ummgeht, müsste Dein Projekt allemal mit diesem Chip zu realisieren sein. Der eine Timer reicht definitiv aus, wenn man ihn inteligent nutzt :-)

Der Timer an sich müsste zwei Dinge tun: Erstens die Länge der Servo-Impulse messen und zweitens bei Bedarf ein PWM-Signal erzeugen.
Für´s erste ist es oft sinnvoll, die einzelnen Teilfunktionen eines Programms zu programmieren, und ganz am Schluss alles zusammenzusetzen.

Wie viel weißt Du denn schon über Timer, Variable, Interrupts (ohne die wird´s nicht gehen!) usw.?

Gruß, Daniel

StephanHD
12.03.2016, 15:34
Hallo Daniel,

gut was weiß ich über Timer, Variablen und Interrupts.

Timer sind in wirklichkeit nichts anderes als Zähler.
Genau genommen erhöhen sich deren Zählwerte pro Programmdurchlauf um 1, was die Timergeschwindigkeit von der Taktrate des Mikroprozessors abhängig macht. Hab ne bissel was schon mit denen gemacht nur eben keine PWM.
Die Themen prescaler und das es eben nur ein 8 Bit Timer ist der nur bis 255 zählen kann sind mir klar.

Interrupts lößen meines wissens speziele Programmabschnitte / Routinen aus die möglichst kurz sein sollen. Die Routinen werden bei einem Flankenwechsel nur einmal durchlaufen soweit ich weiß
Variablen kenn ich die gängigsten Typen wie eben Bool Integer Word usw. Die sind mir von meiner Arbeit bekannt.

Mein Problem ist oftmals die Fehlersuche beim probieren.
Ich programmier auf Arbeit in Industriesteuerungen da hab ich aber immer die Möglichkeit online zuzuschauen was die CPU im Programm treibt.

Das fehlt mir leider bei den Mikroprozessoren ein wenig.

Ich bin leider noch nicht so wirklich weiter gekommen.

Bin immer noch am basteln.

Gruß Stephan

Sauerbruch
12.03.2016, 15:54
Mein Problem ist oftmals die Fehlersuche beim probieren.
Ich programmier auf Arbeit in Industriesteuerungen da hab ich aber immer die Möglichkeit online zuzuschauen was die CPU im Programm treibt.

Das fehlt mir leider bei den Mikroprozessoren ein wenig.

Ich bin leider noch nicht so wirklich weiter gekommen.

Bin immer noch am basteln.

Das stimmt - manchmal ist es schwierig herauszufinden, was in diesen kleinen Dingern wirklich gerade passiert. Aber es ist grundsätzlich möglich!
Wir wollen hier ja niemandem fertigen Code vorkauen, denn den meisten Spaß macht es ja, selber drauf gekommen zu sein!
Ich würde sagen, wir fangen mal mit was ganz einfachem an:

So ein Servo-Impuls bewegt sich zwischen 1 und 2 ms. Wenn man die Länge dieses Impulses mit dem (einzigen) Timer0 messen möchte, darf der Timer keinesfalls während des zu messenden Impulses "überlaufen", weil er danach ja wieder bei 0 anfängt und die Messung dann logischerweise total falsch wäre. Anders gesagt, um von 1 bis 255 hochzuzählen muss der Timer länger brauchen als 2 ms. Rechne doch mal aus wie viel Zeit der Timer0 is zum Überlauf braucht, wenn Du den Takt des Controllers auf 4,8 MHz und den Prescaler des Timers uf 64 einstellst - und dann sehen wir weiter!

StephanHD
12.03.2016, 22:42
Hi,
einen vorgekauten Code, will ich ja gar nicht haben :-)

Wenn ich mich jetzt nicht allzu dolle verrechnet habe, sollte bei 4,8 Mhz und einem Prescaler von 64 ein timerüberlauf nach 3,4 ms stattfinden, was ja aussreicht um die 2ms vom Empfänger zu erkennen.
Daher sollte der Timer bei 1ms einen Wert von ca. 75 haben und bei 2 ms einen Wert von 150.


Nur als Info, da nicht jeder Empfänger als High Pegel um die 5 V ausgibt sondern manchmal deutlich weniger, schalte ich mit der Impulsleitung einen kleinen NPN Transistor und ziehe mit diesem den Int0 auf GND. ansonsten benutze ich den Internen Pullup Widerstand.

Von der Theorie her dachte ich daran mit dem Int0 einen Interrupt auzulösen und in eine ISR zu springen. Dort Frage ich den Pin ab ob er 1 oder 0 ist und merke mir das. Nur müßte ich dann bei ausgelößter ISR und Gemerkter steigender Flanke den Timer starten und bei fallender Flanke auslesen und den Timer wieder stoppen.

Aber wie verwende ich den Timer dann noch für die anderen Funktionen?

021aet04
13.03.2016, 08:10
Was bedeutet deutlich weniger Spannung als 5V? Hast du das nachgemessen? Vielleicht benötigst du keinen Transistor. Und beim messen kein Multimeter sondern ein Oszilloskop verwenden.

Beim Timer darfst du nichts ändern, sonst funktioniert der Timer Interrupt und die PWM Funktion nicht richtig. Du liest nur den aktuellen Zählerstand aus. Du musst nur bedenken das es einen Überlauf geben kann. Bei einem Überlauf musst du die Berechnung etwas anpassen.

MfG Hannes

Sauerbruch
13.03.2016, 10:08
Genau so ist es, der Timer zählt zwischen 75 und 150 Schritte weiter. Und man darf ihn nicht starten und stoppen, wenn er gleichzeitig ein PWM-Signal generieren soll, auch das ist richtig. Und bei dieser Anzahl an Zählschritten ist es sogar sehr wahrscheinlich, dass der Timer regelmäßig während des Impulses überläuft. Aber das ist nicht schlimm:

Da Bytes ja keine negativen Werte haben können, gibt es sozusagen einen "Rückwärts-Überlauf", wenn Du von einem kleineren Byte ein größeres subtrahierst. Klingt jetzt vielleicht ein wenig abstrakt, aber an einem Beispiel wird es sicher verständlich:

Nehmen wir mal an der Impuls ist so lang, dass der Timer um 80 Schritte weiterzählt. In der ISR weist Du bei steigender Flanke einer Variablen (z.B. "Alt") den aktuellen Zählerstand zu, und bei fallender Flanke einer anderen (z.B. "Neu"). Anschließend subtrahierst Du Neu-Alt. Ist der Timer zwischen den Flanken nicht übergelaufen, ist alles klar: Neu ist grölßer als Alt, und die Differenz ist immer 80.

Aber was passiert wenn der Timer während des Impulses überläuft und Neu somit kleiner ist als Alt? Wenn Alt z.B. 200 ist, hätt Neu nach 80 Takten und einem Überlauf einen Wert von 24. Die Rechnung 24 - 200 ergibt auf Byte-Ebene aber nicht -176, sondern genau 80 (weil's nach der Null wieder bei 255 anfängt).

Der langen Rede kurzer Sinn: Lass den Timer ganz ungerührt durchlaufen, lese den Zählerstand bei steigender und fallender Flanke ab, subtrahiere die beiden Werte, und Du hast IMMER die Impulslänge :-)

StephanHD
13.03.2016, 17:06
Hallo Hannes,

es ist wirklich so, es gibt bei Empfängern große Unterschiede und das teilweise auch bei gleichen Herstellern.
Wenn man einen Empfänger mit den z. B. typichen 4,8V betreibt, gibt es keine Garantie das an einem Servoausgang auf der Impulsleitung auch 4,8V anliegen.
Ganz klar, das läßt sich nur mit dem Oszi messen.

Ich hatte schon Schaltungen aus dem Internet nachgebaut, an einem Servotester haben diese dann funktioniert und an einem Empfänger nicht.
Seit dem bau ich mir einen Tansistor davor, den bekommt man immer noch unter und es funktioniert zuverlässiger.

@Daniel

Ok das mit dem Überlauf hab ich verstanden :-) Ich bin es nur nicht gewohnt, ich programmier in 16 Bit Systemen da findet ein Byte nicht so die Verwendung und mit der Variable WORD läßt sich nur beschränkt rechnen. Und Integers sind vorzeichenbehaftet. :-) Manchmal kann die Lösung doch so einfach sein :-)

Ich habe bisher nur ganz kleine Sachen selbst gemacht. Wie ist das mit den Interrupts. Ich möchte den Int0 verwenden mehr hat der Tiny eh nicht. Das ist Pin B.1 ok wie genau funktioniert das? Springt der bei jedem Flankenwechsel in die ISR routine und bearbeitet diese genau einmal?
Also sowohl bei steigender als auch bei fallender Flanke?

Ich bin übersa Wochenende nicht zuhause und komme mal wieder nicht zum testen.

Aber könnte das so funktionieren? Wenn die Routine Zaehlung bei Int0 ausgelößt wird.

Zaehlung:
If Pinb.1 = 0 Then Signal_alt = Timer0 Else Signal_neu = Timer0
Return

Soweit ok den Timer Konfiguriere ich dann auch also nur als "Config Timer0 = Timer ; Prescaler 8"

Das heißt ich kann dann um ne PWM zu erzeugen einen vergleichswert nehmen, beim erreichen den Ausgang einschalten und wenn der Timer überläuft den Ausgang wieder auf null setzen. Das kommt dann im Endeffekt diesem Fast-PWM Mode ungefähr gleich.

Da hab ich jetzt ja mal ne paar anhaltspunkte.

Vielen Dank euch bis hierher schon mal

021aet04
13.03.2016, 21:05
Wie das in bascom funktioniert weiß ich nicht. Ich würde die normale PWM einstellen (egal welchen PWM Mode), also Prescaler, und die anderen Register für den PWM Mode, den du verwenden willst. Zusätzlich gibst du den Timer Interrupt frei. Dieser wird immer ausgelöst wenn der Timer überläuft (von Zähler max auf 0 springt).


Wie der Int 0 reagiert musst du einstellen (mit den Registern). Ich müsste nachschauen wie das bei dem uC ist, ich weiß ich nicht. Aber normalerweise kann ma wählen zwischen Flanke steigend, Flanke fallend, Flanke steigend und fallend bzw Pegel high bzw Pegel low.

MfG Hannes

Sauerbruch
14.03.2016, 18:18
Ich habe bisher nur ganz kleine Sachen selbst gemacht. Wie ist das mit den Interrupts. Ich möchte den Int0 verwenden mehr hat der Tiny eh nicht. Das ist Pin B.1 ok wie genau funktioniert das? Springt der bei jedem Flankenwechsel in die ISR routine und bearbeitet diese genau einmal?
Also sowohl bei steigender als auch bei fallender Flanke?


Es gibt ein paar Register mit denen man einstellen kann, ob der Interrupt bei steigender Flanke, fallender Flanke, bei jeder Flanke, einem High-Level oder einem Low-Level ausgelöst wird. Bascom erledigt das Setzen dieser Register, so dass man sie gar nicht im einzelnen kennen muss, sondern nur die richtige (und einfache!) Bascom-Syntax braucht. In der Bascom-Hilfe steht beim Befehl "Config INT0" alles wesentliche.

Dann muss man noch wissen, dass man Interrupts aus- und einschalten kann, denn mitunter kann es ja mal sein, dass das Hauptprogramm für eine Zeit eben nicht durch Interrupts gestört werden darf. Dieses Aus- und Einschalten geschieht auf zwei Ebenen:
Erstens muss man jeden einzelnen Interrupt aktiv freigeben, damit er ausgeführt werden kann. in diesem Falle wäre der Befehl Enable INT0.
Zweitens muss man eine "globale" Aktivierung aller Interrupts vornehmen, und zwar mit dem Befehl Enable Interrupts.
Nur wenn der einzelne Interrupt freigegeben ist UND die globale Freigabe erfolgt ist, werden Interrupts auch ausgeführt. Sinn dieser doppelten Freigabe-Ebene ist es, die Interrupts sowohl einzeln und gezielt ein- und ausschalten zu können, aber auch mit einem einzigen Befehl (disable Interrupts) global alle Interrupts zu deaktivieren, z.B. wenn der Controller gerade eine zeitkritische Aufgabe abarbeitet, bei der er nicht gestört werden darf.

Interrupt-Routinen (ISR) sollte so kurz wie möglich sein, um den Ablauf des Hauptprogramms nicht allzusehr aufzuhalten. In Deinem Fall könnte man das Subtrahieren der Werte aber auch gleich mit der fallenden Flanke mit erledigen und dem Hauptprogramm durch setzen eines Flag-Bits singalisieren, dass es eine neu gemessene Pulsdauer gibt. Dein Code war schon nahe dran:




...
Dim Signal_alt as Byte
Dim Signal_neu as Byte
Dim Flag as Bit
Dim Impulsdauer as Byte

Config INT0 = change
On INT0 Flanke
enable INT0
Enable Interrupts

Do
...
...

If Flag = 1 then
Flag = 0
...
(Schauen, ob der neue Impuls anders war als der zuletzt gemessene)
...
End if

Loop

ISR_Flanke:
If PINB.1 = 1 then
Signal_alt = Timer0
Else
Signal_neu = Timer0
Impulsdauer = Signal_neu - Signal_alt
Flag = 1
End if
Return




So könntest Du erstmal einen einfachen Code stricken der zunächst einmal nur überprüft, ob sich die Impulslänge nennenswert verändert hat. Wenn dieser Code läuft, könnte man den PWM-Teil dazubasteln!

StephanHD
19.03.2016, 23:39
Also irgendwie komme ich nicht weiter.

Habe den ganzen Tag rumexperimentiert mit bescheidenem Ergebnis.

Ich habe jetzt einen Servotester vom Conrad als Empfängerersatz genommen, dieser bringt einen 1 -2 ms Sekunden langen Impuls raus aber nur mit 3 V. Deswegen hab ich wie bereits erwähnt einen kleinen Transistor davor gebaut der mir den PinB.1 auf GND zieht und hab den internen Pullup aktivierten. An PortB.0 hängt eine LED gegen GND.

Ich habe jetzt folgendes Problem, die LED leuchtet immer schwach. Warum auch immer ist der Ausgang für 1ms an und dann 6ms aus wo das auch immer her kommt. Wenn ich den Servotester verstelle, gibt es irgendwo einen Punkt da wird die LED heller aber flackert manchmal und manchmal auch nicht. Ich kann es nicht nachvollziehen.

Das hier hab ich jetzt mal zusammen geschrieben:

$regfile = "attiny13a.dat" 'Attiny 13a
$crystal = 4800000 'Attiny @ 4,8 Mhz
$hwstack = 26 'HardwareStack
$swstack = 20 'SoftwareStack
$framesize = 10 'Framesize
'$baud = 4800

Config Portb.0 = Output 'Schaltausgang für LED an B.0

Config Pinb.1 = Input 'Anschluss am Empfänger B.2
Portb.1 = 1 'Pullupwiderstand einschalten

Config Timer0 = Timer , Prescale = 64 'Timer0 als Timer mit prescaler 64 laufen lassen

Config Int0 = Change

Enable Interrupts 'generell Interrupts Zulassen
Enable Int0 'Int0 freigeben

On Int0 Zaehlung 'Zaehlung Routine anspringen bei Signalwechsel an Int0

Dim Signal_alt As Byte 'Variable für die Empfänger Impulsbreite
Dim Signal_neu As Byte
Dim Signal As Byte


Wait 1 'einfach Mal Abwarten

Do 'Start Hauptschleife

Signal = Signal_alt - Signal_neu
If Signal >= 120 Then Portb.0 = 1 Else Portb.0 = 0


Loop



Zaehlung:

If Pinb.0 = 0 Then Signal_alt = Timer0 Else Signal_neu = Timer0

Return

Ziel soll erst mal sein die Impulslänge zu messen.

Eine PWM zu erzeugen hab ich geschafft ist aber hier nicht mehr mit drin, wollte vermeiden das es irgendwie daran liegt.

Wenn einer eine Idee hat, bin für alles Dankbar

Sauerbruch
20.03.2016, 07:56
Ich sehe einen kleinen "Schönheitsfehler":
Wenn der Impuls beginnt, wird die Variable Signal_alt zwar aktualisiert, aber die Subtraktion in der Hauptschleife wird noch mit dem alten Wert von Signal_neu ausgeführt. Auch wenn dieser Zustand nur 1-2ms lang dauert, kommt in dieser Zeit nichts sinnvolles heraus.
Mach die Subtraktion doch in der ISR nach dem Impulsende:



Zaehlung:
If Pinb.0 = 0 then
signal_alt = timer0
else
signal_neu = timer0
Signal = Signal_neu - Signal_alt
end if
Return



Dann hast Du schon mal immer einen "sauberen" Wert für die Variable Signal.

Und spannend ist natürlich auch die Frage, ob der Controller auch tatsächlich mit 4,8 MHz läuft! Hast Du das mit den Fusebits korrekt eingestellt?

oberallgeier
20.03.2016, 10:40
.. Scheinwerfer .. Servosignal auswerten .. LED-PWM .. Tiny 13 .. tiny2313 ..Mit nem tiny13 wird man das hinkriegen können. Ich würde trotzdem einen 2313 nehmen; bequem wie ich bin nehme ich die Controller meist zwei Nummern zu groß. Das hilft beim Debuggen per UART-Terminal-Ausgabe, beim Testen und so. Der 2313 hat auch gleich zwei Timer, einen 16bittigen und einen 8 bittigen. Da kann man den 8Bitter für die PWM nehmen und den 16Bitter fürs Dekodieren des Signals.

Aktuell dekodiere ich das Servosignal per Interrupt durch Pegelerkennung am Pinn; Controller ist bei mir ein mega1284er. Dazu gibts bei allen Atmelcontrollern den Externen Interrupt INTx oder den Pin Change Interrupt PCINTx. Den 16bittigen Timer nehme ich zur Messung des Servopulses: getriggert wird auf any edge, bei steigender Flanke wird der Timer in der ISR auf Null gesetzt (TCNTx = 0), bei fallender Flanke liest die ISR den Timerstand TCNTx aus. Das ergibt ohne Prescaler bei meinem 20Mhz-Takt eine maximal mögliche Messdauer (bis zum Timerüberlauf) von rund 3 ms in einer Auflösung von 0,05 µs !!! so genau/stabil ist das Servosignal garnicht. Bei einem niedrigeren Takt - für Deine Aufgabe wird der interne 8MHz-Takt ausreichend sein bzw. die 9,6 MHz des tiny13; damit ist dann auch die Auflösung eher an die Gegebenheiten Deines Servosignals angepasst. ABER wichtiger Vorteil für Dich wäre bei zwei Timern die Nutzungsmöglichkeit des Timer0 fürs Dimmen der LED.
Ohne den zweiten Timer könnte man Servopuls-Dekodierung und PWM mit einer etwas trickigen ISR lösen - vermute ich mal.
Anm.: Ich programmiere in C, kann Dir daher mit Codebeispielen allenfalls in C helfen.

Sauerbruch
20.03.2016, 13:17
Ohne den zweiten Timer könnte man Servopuls-Dekodierung und PWM mit einer etwas trickigen ISR lösen - vermute ich mal.

Sooo tricky ist das gar nicht - Timer einfach durchlaufen lassen, bei Impulsbeginn (steigende Flanke) Wert ablesen, bei Impulsende (fallende Flanke) nochmal Zählerstand ablesen, beide Stände voneinander subtrahieren - fertig! Und der durchlaufende Timer kann dann im Fast-PWM-Modus das PWM-Signal erzeugen.

StephanHD
20.03.2016, 15:51
Hallo zusammen,

hab mal ein paar Fotos gemacht. Zum einen Vom Ausgang des Servotesters, dann vom Eingang nach meinem Transistor am Int0 (PinB.1) Am Oszi waren je 2V/div und 2ms/div man sieht das am Servotester nur 3V rauskommen weiß halt nicht ob der Tiny das immer als High interpretiert. Deshalb der Transistor. Auf dem Bild vom Int0 sieht man das der Signalpegel 5 V hat aber logicherweise Invertiert ist. Auf dem letzten bild sieht man den Ausgang auf dem die LED angeklemmt ist, dort allerdings mit 5ms/div

Momentan ist es immer noch so, das ab einer bestimmten Position des Servotesters die LED leuchtet und bei der anderen Seite die LED blinkt wie im Bild zu sehen.

Das ist der aktuelle Programmcode

Do

If Flag = 1 Then Flag = 0
If Signal >= 160 Then Portb.0 = 1 Else Portb.0 = 0

Loop

Zaehlung:

If Pinb.1 = 1 Then
Signal_alt = Timer0
Else
Signal_neu = Timer0
Signal = Signal_neu - Signal_alt
Flag = 1
End If

Return

Bei der Frage ob deriny wirklich mit 4,8 MHz läuft bin ich mir nicht 100% sicher.

Ausgeliefert wird der Tiny 13 angeblich mit 9,6 und Ckdiv8 aktiv

CKSEL1..0 Nominal Frequency

10 = 9.6 MHz
01 = 4,8 MHz

so stehts im Handbuch habe die zwei Bits halt einfach getauscht und den Hacken bei Ckdiv8 entfernt.
Die Fuses sind :

HighFuse: FF
LowFuse: 79

Hoffe mal das stimmt so.

Gruß

oberallgeier
20.03.2016, 16:38
.. am Servotester nur 3V rauskommen weiß halt nicht ob der Tiny das immer als High interpretiert. Deshalb der Transistor ..Solche Fragen lassen sich anhand des Datenblattes bestens und relativ sicher beantworten. In meinem Datenblatt zum tiny13, 8126F–AVR–05/12, steht auf Seite 117 ne Tabelle 18.2 DC Characteristics, in der u.A. diese Werte genannt werden:

....
Min Max
Input High Voltage,
Any Pin as I/O
VCC = 1.8 - 2.4V 0.7VCC VCC + 0.5 V
VCC = 2.4 - 5.5V 0.6VCC VCC + 0.5 V
....
“Min” means the lowest value where the pin is guaranteed to be read as high.
SEHR empfehlenswerter Lesestoff.

Sauerbruch
20.03.2016, 16:39
Das ist ja putzig - das Eingangssignal ist ja vollkommen okay, aber woher kommt dieses Ausgangssignal, dessen Periodendauer ja noch nichtmal ein Vielfaches der Eingangs-Periodendauer ist...?
Die Fuses scheinen auch richtig zu sein; einen extrem nützlichen Fuse-Calculator gibt´s übrigens hier: http://www.engbedded.com/fusecalc/ (eines meiner meistgenutzten Lesezeichen!). Der gibt für Deine Einstellungen (4,8 MHz, CKDIV8 deaktiviert) genau FF und 79 an.
Im Zweifelsfall kann man einen ganz einfachen Test machen, ob die bei $crystal angegebene Taktfrequenz tatsächlich stimmt:


Do
Toggle PORTx.y
waitms 500
Loop


An PORTx.y schließt man ´ne LED an, und wenn $crystal und die tatsächliche Taktfrequenz übereinstimmen, blinkt sie im 1Hz-Takt.

Aber jetzt müssen wir Dein Problem glaube ich ein wenig einkreisen. Ich würde als erstes überprüfen, ob das Eingangssignal auch tatsächlich dazu führt, dass die ISR ausgeführt wird. Am einfachsten ginge das so:



Zaehlung:
PORTB.0 = PINB.1
Return


Wenn die ISR korrekt angesprungen wird, liegt am PORTB.0 genau Dein Eingangssignal an - das würde das Problem schon einkreisen... probier das doch mal aus und berichte!

Unregistriert
20.03.2016, 17:36
If Flag = 1 Then Flag = 0
If Signal >= 160 Then Portb.0 = 1 Else Portb.0 = 0


Was soll hier passieren? Änderung von PORTB.0 nur wenn Flag = 1 ist?

Dann muß es so sein:


If Flag = 1 Then
Flag = 0
If Signal >= 160 Then Portb.0 = 1 Else Portb.0 = 0
end if

Lesbarer und angenehmer für die Hilfeleistenden ist es, wenn du Code tags zum Einschließen des Codes nutzt.
[ CODE] zu Beginn und [ /CODE] zum Ende des Codes ohne die Leerzeichen nach der führenden eckigen Klammer.

StephanHD
20.03.2016, 20:13
Hi,

Also folgendes hab ich ausprobiert :



Do
Toggle PORTb.0
waitms 500
Loop


Die Led blinkt im Sekundentakt so wie se soll. Also sollte die Taktfrequenz ja mal stimmen, hätte mich auch gewundert, da ich mit den Vergleichswerten für die "Signal" Variable ja in dem Bereich liege den wir ganz am Anfang mal besprochen hatten.



Zaehlung:
PORTB.0 = PINB.1
Return


Hab ich auch ausprobiert mit dem Oszi gemessen, ist das Ausgangssignal genau gleich dem Eingangssignal an PinB.1

Sauerbruch
21.03.2016, 06:53
Manchmal sieht man den Wald vor lauter Bäumen nicht:
Du hast in der ISR nicht berücksichtigt, dass der Transistor das Signal invertiert! So wie die ISR jetzt ist, misst sie die Dauer des High-Impulses, und der ist mit seinen ca. 12ms so lang, dass der Timer mehrfach überläuft. Da kann also nix gutes bei rauskommen :-)

StephanHD
21.03.2016, 17:11
Mist verdammter :-) Hast ja recht des hätte ich auch selbst merken können.

Hab jetzt einfach in der ISR die Portabfrage gedreht.

Aber so richtig funktioniert es doch noch nicht.

Hab mal mit den Vergleichswerten gespielt ab einem Wert von >72 geht die LED dauerhaft a. Das ist klar weil das bei 1ms Impulslänge der kleinste Timerwert ist. Ab einem Wert von 150 geht se gar nicht mehr an. Das ist auch klar weil der Timer nicht so hoch zählt da die Impulslänge zu kurz ist. Alles kklar soweit das stimmt ja auch alles mit den Berechnungen von ganz am Anfang überein.

Ich hab den Wert jetzt mal auf 110 gestellt was so ungefähr der neutralstellung entspricht.
Es ist jetzt so ich dreh den Servotester auf die kleinste Impulslänge -> Die LED ist aus. Jetzt dreh ich die Impulslänge langsam hoch dann fängt so ab der Neutralstellung die LED wieder an zu blinken. Wieder mit dem 12ms Intervall. Erst wenn ich die Impulslänge noch etwas höher dreh dann leuchtet die LED dauerhaft.

Dafür noch irgend eine Idee woran das liegt.

Sauerbruch
21.03.2016, 18:47
Das ist ein ziemlich typisches Phänomen, was darauf zurückzuführen ist, dass die Anzahl der gemessenen Taktzyklen immer um den Wert 1 hin- und hergeht - und zwar auch dann, wenn der zu messende Impuls exakt auf die Nanosekunde konstant bleibt. Und das liegt letzten Endes daran, dass der Interrupt nicht dann ausgelöst wird, wenn sich der Pegel des zu messenden Signals ändert, sondern genau betrachtet erst mit der ersten steigende Flanke des Controller-Taktes nach dem Pegelwechsel des INT-Eingangs. Ich glaube ich male mal ein Bild und erkläre es damit:

Das Gemälde soll sieben Taktzyklen darstellen sowie einen Impuls, der die Länge von 4,5 Taktzyklen hat. Angenommen der Controller fragt seine Eingangspins immer bei der steigenden Taktflanke ab, wird er beim Impuls A eine Änderung zu Beginn der Taktimpulse 2 und 6 registrieren. Beginnt der gleiche Impuls einen halben Systemtakt später, wird der LH-Übergang zwar immer noch zu Beginn des Taktimpulses 2 erkannt, der HL-Übergang aber erst mit dem Taktimpuls 7 - er ist also scheinbar länger. Das ganze ist also darauf zurückzuführen, dass die Flanken des zu messenden Impulses und des Taktimpulses nicht synchronisiert sind. Bestimmt gibt´s in der Expertensprache auch einen schlagkräftigen Fachbegriff für dieses Phänomen - aber ich kann´s nur so erklären.

Wenn Du einen Controller mit ´ner UART-Schnittstelle hättest, könntest Du Dir nach jedem Servoimpuls die gemessene Länge ausdrucken lassen und würdest sehen, dass sie auch beim stabilsten Impuls immer um 1 variiert. Das macht sich natürlich nicht bemerkbar, wenn die gemessenen Werte weit weg von Deiner Entscheidungsgröße sind. Aber wenn sie genau auf der Grenze liegen, wird der Port halt im schnellen Wechsel ein- und ausgeschaltet.

Abhilfe kann hier eine Art "Software-Hysterese" schaffen: Wenn die gemessene Impulslänge den Grenzwert in eine bestimmte Richtung überschritten hat, wird der Grenzwert einmalig (!) um den Wert 1 oder 2 in die Gegenrichtung verschoben, und auf dem Rückweg wieder zurück. Das lässt sich relativ einfach programmieren :-)


Kleiner Nachtrag: Wenn er zu messende Impuls exakt ein ganzzahliges Vielfaches des Taktimpulses ist, tritt dieses Phänomen natürlich nicht auf - aber dann sind der zu messende Impuls und der Taktimpuls ja auch synchronisiert...
31447

StephanHD
22.03.2016, 18:52
Fachbegriff hin oder her, ich hab kapiert was du meinst.

Wieder was gelernt.

Ich hab mir trotzdem zum besseren Verständnis mein mini programm auf einen Tiny2313 umgeschrieben. Hab mir das ganze in der Terminal Konsole angesehen.
Nach deiner guten Erklärung, war es dann auch wenig wunderlich das es genau so aussieht.

Nichts desto trotz plan ich weiter alles auf dem kleinen Tiny 13 zu machen, obwohl ich durchaus den platz hätte ne Platine mi dem 2313 einzubauen. Will ich aber einfach nicht. :-)

Aber mit "einfach zu programmieren" ist das so ne sache :-)

Dann bastel ich mal an der Stelle weiter und versuch dieses gezappel mal abzustellen.

Sauerbruch
22.03.2016, 22:51
Aber mit "einfach zu programmieren" ist das so ne sache

Na ja, wenn der ATtiny13 Klartext verstehen würde, könnte man ihm dazu z.B. in etwa folgendes sagen:

"Wenn Impuls >= X ist, aber PORTB.0 noch 0 ist, dann reduziere X um 2.
Wenn Impuls < X ist, aber PORTB.0 noch 1 ist, dann erhöhe X um 2.
Wenn Impuls >= X ist, setzte PORTB.0 auf 1, ansonsten setzte PORTB.0 auf 0"

Das ganze bräuchtest Du jetzt nur noch in BASIC :-)