PPM Signale auswerten, bzw. 6-Kanal Empfänger ?

AVR-Billy

Mitglied
19. Juni 2017
40
0
6
Remscheid
Sprachen
  1. BascomAVR
Hallo liebe Gemeinde !

Ich hoffe dies ist die Richtige Themen-Kategorie ?

Ich bin relativ neu bei der BASCOM-AVR Geschichte, bzw. in der Atmel-Umgebung.
Nachdem ich ein paar kleinere Spielereien ausprobiert habe, bzw. einen Dimmer für
24VAC gebaut/programmiert habe möchte ich mich einem Komplexeren Problem widmen.

Ich habe eine etwas ältere Schaltung (ohne µC) , die ein 6-Kanal PPM-Signal generiert und
dieses in das Gleis einer Modellbahn einspeist. Die Schaltung erzeug 6-Signale (Kanäle) ,
die jeweils unabhängig voneinander mit Potis gesteuert werden. Auf der Gegenseite (Lok) wird
dies über ein IC ausgewertet und mittels einem NE544 Servoverstärker für die Lok aufbereitet.
Da der NE544 mittlererweile nicht mehr oder nur für über 20€ zu bekommen ist, habe ich mich gefragt,
ob die Funktion der gesamten Schaltung nicht auch ein Atmel übernehmen könnte ? Generell habe ich
schon ein paar Besipiele gefunden, wo PPM-Signale ausgewertet werden (Youtube Videos), leider jedoch
keine Programme dazu. Ich habe auch bereits die "PULSEIN" - Funktion gesehen, aber bin mir insgesamt
nicht darüber im Klaren, wie man die 6 einzelnen Signale auswerten müsste, um jeweils einen Kanal
zu differenzieren.Sicherlich müsste man mit Timer arbeiten ?
Soll ich hier einmal die Schaltung zeigen, damit man sich ein Bild machen kann, oder genügt es, die
allgemeine Erläuterung/Beschreibung zu posten ?

Hier kurz die Beschreibung :

PPM-Steuerung, 6 Kanäle innerhalb eines 20ms - Zeitraumes. Jedes Signal max. 2ms lang,
1,0ms = Fahrt in die eine Richtung , 1,5ms = Stillstand , 2ms = Fahrt in die andere Richtung.
Ein 7. Impuls kündigt die Synchronisationspause an. Das ganze läuft mit 50Hz.
Signalform : 15VDC -mit aufgesetzten Impulsen 20VDC max.

Vieleicht kann man ein solches Projekt hier gemeinsam eroieren, damit auch andere dabei evtl.
etwas lernen oder dies nachbauen können, falls das Thema von allgem. Interesse ist ?

Ich würde mich sehr freuen.

Viele Güsse Billy !
 
Zuletzt bearbeitet:
Hallo, und willkommen im Forum.

Wenn ich Dich richtig verstanden habe, soll die Empfängerseite "nachgebaut" werden.
Grundsätzlich sollte beides machbar sein.
Inwiefern BASCOM dafür was fertiges bietet (sechs Kanäle), müßte mal ein BASCOM-Spezialist sagen.
In ASM sollte das kein Thema sein, aber in BASCOM wirst Du (ggf mit Hilfe) sicher auch selbst was hinbekommen.

Ich kenne das ähnlich von Funkfernsteuerungen - da gabs aber mMn noch'ne Trägerfrequenz drüber.

Existiert immer eine Lücke zwischen den einzelnen Impulsen, oder können die bei "alle max=2ms" zusammenwachsen?
Der Controller würde also permanent (alle?) sechs Impulslängen digitalisieren - was soll mit diesen "Zahlen" weiterhin geschehen?
(In der beschreibung werden nur deri diskrete Zustände (vorwärts/rückwärts/stop) genannt - keine variablen Geschwindigkeiten?)
((daran anknüpfend: welche zeitliche Auflösung wäre erforderlich?)

Zur Lösung braucht man (wie Du selbst schon sagtest) 'n Timer, möglicherweise wäre die Verwendung eines Input Capture Units von Vorteil (Timer stoppen und auslesen), ggf koppelt man den außerdem an'nen externen IRQ bzw Pin Change IRQ (Timer Starten).

Grüße und'n schönen Sonntag,
LotadaC
 
Hallo,zunächst vielen Dank für Deine Antwort...!

Ich muss mich leider absolut auf Bascom beschränken, da ich von früher her aus dem Basic des Commodore komme
und mit dem Bascom sehr gut zurecht komme. Ich finde die Möglichkeiten super.

Zur Thematik :

das ganze läuft mit 50Hz (vermutlich Trägerfrequenz, bzw, Referenzimpulse ?) und es kommt eigentlich sogar von den
Funksendern/-empfängern (der NE 544 wurde dafür konzipiert). Der Unterschied ist lediglich, dass das Signal nicht
über Funk oder IR versendet, sondern direkt ins Gleis eingespeist wird, wo die Loks es über die Schienen direkt aufnehmen
und verarbeiten. Die Impulsbreite wird im steuergerät mittels Poti für jeden Kanal verändert, und die Zustände von 1-1,5ms bzw.
1,5-2ms sind die variable Geschwindigkeit.
Also 1ms ist max. (vorwärts) alles in Richtung 1,5ms heisst es wird langsamer. 2ms ist auch wieder max. (rückwärts) und alles
in Richtung 1,5ms wird wieder langsamer.
Zum Abstand der Signale der Kanäle und weiteren Verständnis zitiere ich mal aus einem alten Buch mittels Bild :

Impuls.jpg

(Quelle : Franzis Verlag, Dr. Christoffer, Modellbahn digitalisieren)

Was mir in Bascom nicht so richtig aufgeht ist, wie ich die Kanäle erkenne und die Impulsbreite in die
entsprechende Information umsetze, die dann der Leistungsteil in der Lok bekommt. Jedenfalls wäre der Bauteil-
aufwand mit einem Atmel - selbst in der ATiny 2313-Grösse - wesentlich geringer, als momentan mit dem Decoder
und Servoverstärker IC+ Leistungsteil auf einer Platine (14 und 16-pol) . Ausserdem wäre ich flexibler und anpassungs-
fähiger um andere Funktionen mit unter zu bringen.

Ja - ich weiss - es gibt auch fertige Digitallösungen im Handel für Modellbahnen, aber die kommen nicht in Frage,
da mein Vater auch noch mit im Boot ist und der ist 77 und möchte nicht auf diese Lösungen umsteigen.
Ausserdem haben wir 2 PPM-Steuergeräte fertig aufgebaut. Wenn es mit den Atmel klappt wäre das ein guter
Kompromiss...


Gruss Billy
 
Zuletzt bearbeitet:
Was mich in BASCOM immer ein wenig stört ist, daß man (gerade als Anfänger) nicht viel von der eigentlichen Controller-Hardware mitbekommt - bzw es halt zu einfach ist, fertige Softwarelösungen zu verwenden, WEIL man sich nicht mit der Hardware beschäftigt hat, und es vielleicht 'ne möglichkeit gibt, die Hardware des Controllers zu nutzen. Auch mit BASCOM - DU siehst diesen Lösungsweg nur gar nicht erst. Das ist natürlich sicher auch auf andere Hochsprachen übertragbar.
Abgesehen davon kannst Du Assembler einbetten, wenn nötig, und auch vieles umsetzen. Gewisse Tricks, insbesondere die Interruptvektoren betreffend gehen nicht. Bei mehreren Returns aus einer IVT gibts wohl auch Probleme. Und dann erzeugt BASCOM einen gewissen Code-Overhead, mit dem man ebe leben muß. Dafür erscheinen die Programme kürzer und ggf einfacher lesbar, was das menschliche Auge betrifft.

Zum Thema:
Wie oben bereits angedeutet, mußt Du nur die Zeit (Anzahl der Timertakte) zwischen zwei fallenden Flanken messen (zählen lassen). Da die mir bekannten Tiny-Timer keinen automatischen Reset bei einem Event wie dem Pegelwechsel bieten, muß das in Software geschehen.
Kann man davon ausgehen, daß immer alle sieben SynchroImpulse kommen?
Ich würde also einen Timer mittels Prescaler auf eine sinnige(*) Reichweite einstellen. Das Signal soll bei jeder Flanke einen IRQ triggern, entweder einen Pinchangeinterrupt, oder den Inputcapture des verwendeten Timers.
In der ISR wird der nach einer steigenden Flanke der Zählerstand des Timers ausgelesen. Bei der Capture-Variante aus dem Input-Capture-Register. Bei der anderen sollte der Timer erstmal angehalten werden, danach das Timer/Counter Register gelesen werden. Damit hast Du die "Zeit", und mußt sie nur noch dem Kanal zuordnen (**). Nach der fallenden Flanke wird der Timer zurückgesetzt, und ggf neu gestartet.

(*)sinnig: Der Timer darf in den 2ms (genau genommen verschiebt sich das durch den Synchroimpuls jetzt auf 1,1..1,6ms) nicht überlaufen, soll aber 'ne möglichst gute Auflösung bieten. Bei angenommenen 8MHz Systemtakt hätte ein 16bit-Timer mit Prescaler=1 'ne Reichweite von gut 8ms und 'ne Auflösung von 125ns. Paßt doch ganz gut.
(**)Wenn die sieben Kanäle alle max. sind, vergehen bis zum siebten Impuls 14ms, verbleiben von den 20ms ca. 6ms. Wenn man den Timer also zusätzlich auf 5ms Reichweite (mittels OutputCompare) begrenzt, würde das entsprechende Flag jedesmal die SynchroLücke signalisieren.
Nehmen wir mal an, die Werte sollen in einem Array abgelegt werden. Bei jeder steigenden Signalflanke inkrementierst Du den Index. Außerdem prüfst Du das Überlauf- (genauer: das Compare-Flag) des Timers. Ist es gesetzt (=SynchroLücke), wird der Index wieder auf den Anfang des Arrays gesetzt. (anschließend wäre das Flag zurückzusetzen).

Idee soweit klar? Nach der ersten Synchrolücke landen die Ergebnisse an den richtigen Stellen im Array.
Im Hauptprogramm (außerhalb der ISR) kannst Du die digitalisierten Ergebnisse dann aus dem Array weiterverarbeiten...
 
Hi !

Vorweg : es muss nicht unbedingt ein Tiny sein (wäre schon gut , weil z.B. der 45er oder 12/13er sehr klein ist) Ich würde auch mit einem Mega8 im 32A package
zurecht kommen , der ist ja gerade mal 1qcm gross...

So, ich versuche mal alles zu verstehen. leider bin ich da etwas langsam, bzw. nicht tief in der Materie drin und habe oft noch Schwierigkeiten,
die Fachbegriffe direkt um zu setzen. Ich benötige das meist bildlich/beispielhaft - sorry. Aber so kann ich mich da gut herantasten.

Bei meinem Dimmer-Projekt war es so , dass ich mit einem externen Nulldurchgangsdetektor (Transistoren) einen Interrupt am INT0 genutzt habe,der dann
einen entsprechend gescalten Timer laufen lies. Wenn ich es richtig verstanden habe, muss ich hier auch ähnlich vorgehen, allerdings ist mir noch nicht klar,
wie ich zum Einen das Ereignis auslöse und zum Anderen die Impulse zähle, bzw, dann deren Länge feststelle. Fangen wir mal mit dem "Erkennen" eines
Impulses an - muss ich den hardwaremässig erfassen (Zusatzhardware) oder kann der Atmel, bzw. Bascom einen/mehrere Impuls/e detektieren ? Ich hatte
gesehen, dass es ja die "PULSEIN" Routine gibt, die einen Impuls erfassen kann. Könnte ich damit etwas erreichen ?

Syntax

PULSEIN var , PINX , PIN , STATE

var = a word variable that is assigned with the result.

PINX = a PIN register like PIND

PIN = the pin number(0-7) to get the pulse time of.

STATE = May be 0 or 1. 0 means sample 0 to 1 transition.1 means sample 1 to 0 transition.


Es gibt dieses Video im Netz, genau das benötige ich quasi auch - aber leider gibt es kein CodeBeispiel...


Gruss Billy
 
Was mich in BASCOM immer ein wenig stört ist, daß man (gerade als Anfänger) nicht viel von der eigentlichen Controller-Hardware mitbekommt - ...
Ich kenne Bascom nicht (das letzte mal ein Netzwerksimulationsprogramm in Basic auf PET 2001 programmiert), aber ich gehe mal davon aus, daß man alle Bascom-AVR-spezifischen Befehle weglassen kann und mit peek und poke direkt auf die Hardwareregister der AVRs zugreifen kann. Damit wäre man dann fast genauso hardwarenah, wie mit C bzw. asm.
 
Damit wäre man dann fast genauso hardwarenah, wie mit C bzw. asm.
BASCOM kennt auch die Register-Bits und erlaubt deren direkte Manipulation, insofern bist Du mMn sogar dichter an der Hardware als bei C.
Dichter als Assembler geht nicht, da das ja eins zu eins der Hardware entspricht.
Allerdings kannst Du weder bei Bascom (noch bei C ? ) direkt festlegen, in welche Flashadressen bestimmter Code geschrieben wird (insbesondere innerhalb der IVT.
mit peek und poke direkt auf die Hardwareregister der AVRs zugreifen
Bascom kennt wie gesagt die Register. Du kannst also zB TCCR0A=0x42 oder so.
Auf die Bits kannst Du zB auch so zugreifen: PortB.1=0
aber ich gehe mal davon aus, daß man alle Bascom-AVR-spezifischen Befehle
Natürlich (wobei dann trotzdem der ganze Overhead erzeugt wird (RETI in alle ungenutzten Interruptvektoren, der gesamte SRAM wird gelöscht, Stackpointer (auch wenns nicht nötig ist, ... weiß nicht mehr - hatte das irgendwo mal aufgeschlüsselt...
egal...
Worauf ich da hinauswollte war, daß man als Anfänger gar nichts vom eigentlichen Potential des Controllers (insbesondere der periphären Hardware) mitbekommt. Du kannst völlig problemlos 'n Software-UART auf'nem kleinen Tiny ... verwenden. Bascom macht das für Dich. Du kannst dasselbe auch auf 'nem Controller mit drei Hardware-UARTs machen. Teilweise ist das nicht mal einfach nachzuvollziehen, ob Bascom das als Hard- oder Software macht. (Irgendwo in der IDE gibts Voreinstellungen dazu, die genutzt werden, wenn Du gar nichts weiter festlegst, und im Programm dann nur "Print" benutzt). Ähnliches gilt bei SPI, TWI,... (der Anfänger sucht halt nach Codeschnipseln, und ist glücklich über einen gefundenen lauffähigen Soft-TWI - der Controller bietet aber eigentlich auch 'ne Hard-TWI... und dann ist der Controller irgendwann zu"schwach" für das restliche zu implementierende Programm...)
Natürlich KANNST Du unter Bascom (und anderen Hochsprachen) das Potential der Controller-/Hardware nutzen, aber dazu mußt Du sie selbst auch erstmal kennen...
Beim PTC (Peripheral Touch Controller) bist Du in allen Sprachen (selbst Assembler) aufgeschmissen - der wird nur von C unterstützt.
So, genug OT. Werde den Rest mal in'nem neuen Beitrag anfangen...
 
es muss nicht unbedingt ein Tiny sein (wäre schon gut , weil z.B. der 45er oder 12/13er sehr klein ist)
Du kannst solchen Impulse auch von'nem Tiny4/5/9/10 erfassen lassen. Das wäre ein SOT23-6.
Mir ist aber noch nicht ganz klar, wie es mit den empfangenen digitalisierten "Zahlen" dann weitergehen soll. Der Tiny hätte insgesamt drei nutzbare Beine (wenn eines normaler Reset bleiben soll). Also ein Bein für das Eingangssignal, und zwei für irgendwelche Aktoren.

Der Tiny25/45/85 hätte nur 8bit-Timer ohne InputCapture-Unit (geht ja auch ohne, wie ich oben sagte).
Ein 8bit-Timer hätte bei 8MHz Systemtakt und 64er Prescaler 'ne Reichweite von ziemlich genau 2ms, und 'ne Auflösung von 8µs. Sollte auch passen.
Dimmer-Projekt war es so , dass ich mit einem externen Nulldurchgangsdetektor (Transistoren) einen Interrupt am INT0 genutzt habe,der dann einen entsprechend gescalten Timer laufen lies.
Teilweise ähnlich.
Beim Anschnittsdimmer (?) synchronisierst Du den Timerstart auf den Nulldurchgang, und löst nach einer bestimmten Zeit (Timer) die Zündung aus (Ich hatte das bei meinem sogar als PWM gemacht - der Timer selbst setzt und löscht den Zündimpuls des TRIAC ohne weitere Softwareeingriffe, Nulldurchgang (via Komperator->Optokoppler->Cintroller) synchronisiert den Timerstart).
Hier willst Du aber die Pulslänge erfassen. Bzw die Länge der low-Phase (Länge in Systemtakten bzw in prescalten Timertakten). Du könntest also auch einfach nur durch die Flanken einen Interrupt auslösen lassen, und die Differenz der verstrichenen Timer-Takte ermitteln (also jedesmal das Timer-Register lesen, und die Differenz bilden. Da dabei der Timer übergelaufen sein kann, mußt Du den Überlauf miteinbeziehen.
Deswegen der Vorschlag, den Timer auf die fallende Flanke zu synchronisieren. Bei der steigenden Flanke wird der Timer gestoppt, der Zählerstand ausgelesen, und überprüft, ob der Timer übergelaufen war (Synchrolücke) dann das Flag zurückgesetzt, sonst das Ergebnis ggf im Array abgespeichert.
Das geschieht in der ISR des externen Interruptes/PCINT, wo das eingehende Signal anliegt. Du hättest in der ISR dann 'ne Fallunterscheidung und die beiden gennanten Aktionen.
Bei jedem Flankenwechsel wird Dein restliches Programm kurz für die Aktionen in der ISR unterbrochen, die Erfassung der Impulse erfolgt für Dein restliches Programm quasi(!!) im Hintergrund.
Ob Pulsein hingegen nicht einfach nur auf beide Flanken wartet, und ggf irgendwas hochzählt - und den Controller ansonsten ausbremst, weiß ich nicht.

Ist Dir mein Vorschlag jetzt halbwegs klar?
(Dann versuch das mal unter Bascom umzusetzen.)
 
Hallo !

Langer Tag - sorry.
Ehrliche Antwort : Jein ;-)

Ich versuche das ganze mal in meine Worte zu fassen , um dann ein Konzept daraus zu machen.

Ich müsste ertmal die Impulse aus der Fahrspannung abkoppeln, da diese ja um 20VDC liegt (mit Tastimpulsen).
Dazu kann ich mich selbiger Hardware bedienen , wie bei den Decodern, die ohne µC laufen. Wenn ich die Impulse sauber
vorliegen habe dann

muss ich ersteinmal den Synchronisationsimpuls, bzw. die Synchropause detektieren , richtig ? Dieser unterscheidet sich darin,
dass die er Abstand ungefähr 7,6ms ist, gegenüber den anderen Impulsen. Also würde ich so vorgehen, dass ich durch die eingehenden
Impulse mit der steigenden Flanke einen Interrupt z.B. an INT0 auslöse und dann einen vorkonfigurierten Timer laufen lasse. Jeder Impuls löst
ja wieder einen Interrupt aus und ich lese den Timer jedesmal aus. Dieser hat bei der 7,6ms Pause ja dann einen bestimmten Wert, also erkenne
ich daran den Sync-Impuls, richtig ?

Erst dann kann ich beginnen,mit ähnlichem Schema, die einzelnen Impulse zu zählen um den Kanal zu differenzieren, bzw. die Impulslängen
zu unterscheiden/messen...?!

Ist das soweit richtig erfasst von mir ?

Gruss Billy
 
PS: ich glaube ich habe das in das falsche Forum gestellt (?) - ich sehe gerade, dass es ein Bascom Forum gibt...!
Sorry - ich war etwas verpeilt und stelle es somit dort auch nochmal ein.

Gruss Billy !
 
Ich müsste ertmal die Impulse aus der Fahrspannung abkoppeln, da diese ja um 20VDC liegt (mit Tastimpulsen).
Dazu kann ich mich selbiger Hardware bedienen , wie bei den Decodern, die ohne µC laufen. Wenn ich die Impulse sauber
vorliegen habe dann
Ja, davon war ich ausgegangen...
muss ich ersteinmal den Synchronisationsimpuls, bzw. die Synchropause detektieren , richtig ?
nicht "erstmal", das geschieht nebenbei...
Wenn der Timer mit Prescaler=64 an den Systemtakt gekoppelt wird (genau das soll bei jeder fallenden Flanke mittels externem-/PinChange-Interrupt geschehen), inkrementiert er mit jedem 64sten Taktzyklus. Ein 8bit-Timer würde so bei 8MHz nach 2,084 ms überlaufen.
Allerdings kommt vorher (nach spätestens 1,6ms - der Timer wäre bei 200) die Steigende Flanke, wo Du den Timer stoppen (und zurücksetzen läßt).
Nur in der Synchronisationslücke kann und wird der Timer überlaufen (sogar mehrmals). Dabei wird automatisch das Timer-Überlaufs-Interrupt-Flag gesetzt, und da der dazugehörige Interrupt nicht aktiviert wurde, löst es keinen Interrupt aus, und wird auch nicht zurückgesetzt.
Du kannst das Flag also bei jeder steigenden Flanke überprüfen - ist es gesetzt (=Lücke), interessiert Dich der Timerstand nicht, dafür weißt Du, daß der nächste Impuls Kanal1 ist.

Also:
  • Du definierst Array mit sechs Bytes für die sechs Kanäle
  • Du definierst ein Byte als Indexzähler
  • Du machst für den Pin mit dem Signal den Interrupt scharf (beide Flanken), und natürlich die Interrupts global
  • Du implementierst die ISR dazu (Verankerung in der Interruptvektortabelle nicht vergessen -> "On interruptname Sprungziel")
    • Fallunterscheidung fallende Flanke
      • Timer auf null setzen und mittels Prescaler starten
    • Fallunterscheidung steigende Flanke
      • Timer mittels Prescaler stoppen
      • wenn Überlaufflag gesetzt
        • Überlaufflag zurücksetzen
        • Indexzähler auf null
      • sonst
        • Indexzähler inkrementieren
        • Timer(wert) in Array(index) ablegen
In deiner noch leeren Hauptprogrammschleife kannst Du die Werte aus dem Array lesen und weiterverarbeiten, nach der ersten Lücke landen die Kanäle in den richtige Feldern.
In der Fallunterscheidung-> Lücke erkannt kannst Du außerdem 'n Flag für Dein Hauptprogramm setzen lassen, sozusagen 'ne 20ms-Zeitbasis.

P.S.:
in das falsche Forum gestellt (?) - ich sehe gerade, dass es ein Bascom Forum gibt...!
Sorry - ich war etwas verpeilt und stelle es somit dort auch nochmal ein.
Wäre einfacher gewesen, wenn ein Moderator das Topic einfach rüberschiebt. (und jetzt das zweite löscht - oder hattest Du da noch was neues/zusätzliches?)

Nachtrag: genau genommen sollte auch das starten/stoppen des Timers unnötig sein, allerdings ist die Timerreichweite mit 2,048ms sehr knapp an den 2ms (=max)... also Prescaler erhöhen und ggf die Reichweite mittels CTC begrenzen. Mindert aber die Auflösung der Ergebnisse.
 
Zuletzt bearbeitet:
Hallo & Danke erstmal.

Sorry - da komme ich nicht so richtig mit. Ich werde ersteinmal ein bisschen experimentieren , um alles nachvollziehen zu können.
Parallel dazu werde ich mir den geschilderten Ablauf vornehmen und versuchen dies Schritt für Schritt in Bascom Zeilen zu fassen.
Wie gesagt - für mich noch relativ neu alles und nur mit Hilfe komme ich ans Ziel...
Da ich momentan immer von der Arbeit komme und dann total platt bin wird es etwas dauern.

Gruss Billy !
 
Ich nochmal ...

Ich muss noch 1-2 dinge besser erläutern, da ich es glaube ich nicht richtig dargestellt habe.

Ich muss nicht in jedem Empfänger alle 6-Kanäle auswerten, sondern immer explizit einen davon.
D.h. ich hätte nachher 6 Empfänger, wovon jedem eine Adresse von 1-6 zugeordnet ist. Das widerum
heisst, ich muss mir in der Software einen Kanalimpuls raussuchen und dessen Impulsdauer (Pausendauer)
messen und weiter verwerten. Zur Verwertung möchte ich erst später kommen.

Dann habe ich festgestellt, dass das Bild recht ungeschickt ist (?) - Was der, mit den Logik-IC aufgebaute
Empfänger macht ist, dass jeweils die Dauer zwischen der steigenden Flanke 2er Impulse gemessen wird.
Die Impulse selbst dauern alle immer nur 0,4ms. D.h, die eigentliche Kanal/Fahrbefehlinformation steckt in
der Dauer des Abstandes zwischen den beiden steigenden Flanken und diese ist zwischen 1ms und 2ms lang
(1,5ms als Mittelstellung= 0 Geschwindigkeit). Der empfänger wandelt diese Pause noch in einen weiteren Impuls
um, den er dann im Servoverstärker auswertet. In der Logikvariante d. Empfängers ist weiterhin die Pause zwischen
der steigenden Flanke des 7. Impulses und der des 1. Impulses (eines neuen Zyklus) innerhalb 20ms, so gross
(min. 7,6ms), dass sich über die Dauer ein Kondensator auflädt, der den Reset des Zählers auslöst , was als
Sync -Signal genutzt wird. Die Normalen Impulse/pausen reichen nicht aus um dies zu bewirken.

Vieleicht ist jetzt alles etwas genauer.
Ich versuche später mal Bascom Zeilen hier zu posten und wäre über Hilfe dankbar.
Mir ist noch manches nicht so klar, wie ich das umsetze.was mir noch nicht klar ist, auf was ich den Timer
Prescalen/einstellen/abfragen muss, bzw. wie genau (Bascom Befehlsreihenfolge/ISR) ich die Impulsflanken
auswerten muss. Das Prinzip ist relativ klar - "Config INT0 = Rising" usw.

Gruss Billy
 
Hi Billy,

ich empfehle Dir dringend, Dir so'n (vollständiges, nicht nur das summary) Controller-Datenblatt mal durchzulesen. Reicht ja erstmal eins von'nem Tiny (wegen dem Umfang bietet sich der Tiny13 oder der 85 an). Das ist bei allen AVR im wesentlichen ähnlich. Kurz gesagt besitzen die AVR eine gewisse Anzahl Register, und die gesammte Hardware wird über diese Register eingestellt. Unter Bascom kannst Du zB einen Timer mit "Config Timer Blablub" konfigurieren, Du kannst aber ebenso die entsprechenden Register beschreiben ("TCCR1A=0x42" oder so). Damit lassen sich auch Einstellungen vornehmen, die die Config-Instruktion nicht kennt (oder die Dir nicht bekannt ist).

Ok, dann vereinfachen wir das mal etwas. Annahmen/Vorraussetzungen:
Die Differenz zwischen zwei steigenden (oder fallenden) Flanken ist entweder 1..2ms (Kanal) oder 8..14ms (Lücke)
Dabei spielt es keinen Unterschied, ob man fallende oder steigende Flanken nutzt.
Der Timer darf also in den zwei ms definitv nicht überlaufen.
Der Timer muß in acht ms sicher überlaufen.
Dafür stehen Dir je nach verwendetem Controller, Systemtakt, vorhandenen Vorteilern, verwendetem Timer usw vershiedene konkrete Möglichkeiten zur Verfügung.
Timer0 des Tiny85 zB bei 8MHz Systemtakt und Prescaler = 64 'ne Reichweite von 2,048ms und 'ne Auflösung von 8µs. wär mir zu knapp. (die 48µs wären zwar für den Controller viiiieeeel Zeit (384 Taktzyklen), aber wie sauber kommt das Signal rein?)
der nächstmögliche Prescaler wäre 256 (also 8,192ms aber nur noch 32µs Auflösung (1ms entspräche 'nem Zählerstand von 31, 2ms 62) wenn das hinreichend präzise ist mit 31 unterscheidbaren Zuständen...)
Timer1 hätte auch noch einen 128er Prescaler (also Reichweite und Auflösung genau dazwischen).

Man würde also wieder einen Indexzähler und ein Array für sechs Bytes dimensionieren, den Timer starten, den externen IRQ auf eine (!) Flanke einstellen, die ISR müßte dann:
Das Überlaufflag des Timers prüfen.
Ist es gesetzt, wird es zurückgesetzt, und der Indexzähler auf 0 gesetzt. (*)
Sonst wird der Indexzähler inkrementiert und Array(Index)=Timervalue.
Anschließend wird der Timer auf null gesetzt.
Im Hauptprogramm kannst(!) du jeden beliebigen Eintrag aus dem Array auswerten.
An (*) könntest Du außerdem eine 20ms-Zeitbasis für Dein Hauptprogramm koppeln (natürlich nur so genau, wie das Eingangssignal).
(Die ISR sollte sich mit Inline-Assembler sehr flott und schlank gestalten lassen)
 
Hallo, guten Abend !

Noch eine wichtige Frage vorweg :

wenn ich die Timer nutze, um die Impulse zu zählen/detektieren , dann kann ich
DIESE Timer nicht mehr für PWM später nutzen , oder wie muss ich mir das vorstellen ?

Gruss Billy
 
Hallo !

Also, ich versuche das jetzt mal für mich zu verstehen und bitte um Korrektur/Schützenhilfe.
Wie gesagt muss ich mich auf den Bascom Befehlssatz beschränken, da ich Assembler leider nicht beherrsche.

Nachdem ich nun alle Voraussetzungen erfüllt habe, die Impulse am µC korrekt ein zu lesen würde ich mal bitte von
folgenden Dingen ausgehen wollen

-der µC läuft mit 8MHz
-Impulse kommen mit 50Hz rein
-ich möchte gerne den Kanal 3 auswerten (Impulspausendauer feststellen)

ich gebe also mein Signal auf den Pin , der INT0 auf steigende Flanken auswertet und konfiguriere mir den TIMER0 entsprechend
mit prescaler so, wie beschrieben, dass er bei den Kanal-Impulsen nicht überläuft und bei der langen Pause (Sync) sicher
überläuft. Wenn der Timer also überläuft, löst er auch widerum einen Interrupt aus und das ist dann das sichere Zeichen, mit dem
Zählen der Impulse zu starten (wie es dann weiter geht, habe ich noch nicht verstanden) ?

also

...
Config TIMER0 = Timer, Prescale = xy
Config INT0 = Rising
Enable INT0
Enable TIMER0
Enable Interrupts
...
On INT0 ISR_Timer_starten
On TIMER0 ISR_Impulse_zaehlen
...
ISR_Timer_starten
start TIMER0
Return

ISR_Impulse_zaehlen
... (mit PULSEIN ? )
Return

weiter weis ich noch nicht?
Ist das denn soweit schon richtig ?

Gruss Billy
 
wenn ich die Timer nutze, um die Impulse zu zählen/detektieren , dann kann ich
DIESE Timer nicht mehr für PWM später nutzen , oder wie muss ich mir das vorstellen ?
Das kommt darauf an, wie Du den Timer benutzt (und auf dessen Ausstattung). Wenn Dein Timer nur ein Output-Compare-Unit besitzt, und Du dieses zur Begrenzung der Reichweite verwenden willst, kann das Output-Compare-Unit kein PWM mehr generieren.
Wenn Du den Timer mal zurücksetzt, und mal nicht (Lücke), kann der Timer zwar mit seinen OC-Units grundsätzlich PWM generieren, aber ob das Ergebnis für Dich sinnig ist, mußt Du wissen. Du würdest ja ständig unterschiedliche PWM-Frequenzen haben - wenn dabei der OC-Vorgabewert nicht angepaßt wird, verändert sich dabei auch das (relative) PWM-Verhältnis.
Wenn man den Timer also unbedingt als PWM braucht und unbehindert durchlaufen lassen will, kann man entweder bei jeder fallenden oder(!) steigenden Flanke den Zählerstnd erfassen, und unter Beachtung des Überlaufflags die Differenz zur letzten Flanke in Software ermitteln - oder man läßt den Timer im Überlauf 'ne Zeitbasis erzeugen, die man als Software-Zähler benutzt.
Du solltest also erstmal festlegen, wieviele PWMs Du konkret brauchst. Mit welchen PWM-Frequenzen.

Der Tiny25/45/85 bietet zwei 8bit-Timer mit je zwei PWM-Kanälen. Timer0 ist recht "normal", das Register von Kanal A kann auch zur Frequenzkorrektur verwendet werden (CTC-Mode), dann steht Kanal A natürlich nicht mehr als PWM zur Verfügung. KanalA kann dann aber immer noch bei jedem (frequenzkorrigiertem) Überlauf gesetzt oder gelöscht werden.
Timer1 ist schon spezieller - der bietet ein drittes CompareUnit ohne PWM für die Frequenzkorrektur, außerdem können Kanal A und B an zwei weiteren Beinen invertiert ausgegeben werden. Überlappungsfrei zu den ersten. Damit kann man dann zB H-Brücken oder sowas kurzschlußfrei ansteuern. Timer1 kann außerdem nnicht nur über den Systemtakt (und Prescaler dazwischen) angetrieben werden, sondern auch über die PLL (also 64 oder 32 MHz-> Prescaler-> Timer). Wenn Du jetzt Schaltnetzteile im Kopf hast, liegst Du richtig.
Zu Bedenken ist, daß einige PWMs der beiden Timer um dieselben Beine konkurrieren.

Du solltest also erstmal festlegen, was der Controller außer der Impulslängenerfassung noch alles machen soll, bevor Du (oder wir) Dir konkretere Gedanken um das wie und welche Hardwaremodule (und ggf welchen Controller) machen kannst.
Mit dem Tiny25/45/85 solltest Du generell (in Hardware) drei PWM gleichzeitig und die Impulslängenerfassung hinbekommen und behältst (außer dem Reset) sogar noch ein Bein für irgendwas anderes frei...
 
Hallo, guten Morgen ! Bin wieder da - kämpfe gerade mit einem Infekt, an Stellen ,
die für den Mann echt super sind :-( Daher dauerts momentan etwas...

Ja klar, das habe ich vergessen zu sagen, wie ich das Signal verarbeiten möchte.
Bei der Logic-IC-Variante nimmt das Signal, was vom Kanal-Dekodierer kommt
dann der NE 544 auf. Dieser vergleicht es mit einem Referenzimpuls, um fest zu
stellen, ob es 1-1,5ms, 1,5ms, oder 1,5-2ms gross ist - also Richtung/Geschwindigkeit
oder Stillstand und dann wird das Signal über einen Impulsdehner an eine Verstärker-
schaltung (Brückenverstärker mit Transistoren) abgegeben, damit der Motor damit
betrieben werden kann.

Also im Grunde muss ich auch feststellen, wie gross der Impuls ist und diesen einfach
nur (per PWM?) wieder ausgeben. Ich kann ja einfach mal mit PWM im Vorfeld etwas
experimentieren (Auf dem Steckbrett) und schauen, ob der Schaltverstärker ein PWM
Signal vom µC verarbeiten kann. Das sollte aber so sein, denn im Buch zur Schaltung
wird gesagt, das der Motor mit "gepulstem Strom" angesteuert wird.

Ist denn mein Gedankengang zum Bascom-Code oben soweit schon richtig ?

Gruss Billy
 
Zuletzt bearbeitet:
Du hast da dann einen H-Brücken-IC, oder wie? Sowas kannst Du generell mit zwei Kanälen von einem Timer ansteuern. Einer für rückwärts, einer für vorwärts. Wenn nötig, kannst Du dabei sogar die komplementären Beine mitbenutzen. Je nach Fahrtrichtung wird der eine oder(!) der ander PWM-Kanal des Timers auf Output geschaltet. Die Geschwindigkeit wird dann über den entsprechenden Output Comparewert festgelegt.
Wenn Du also mit einem Timer und maximal zwei PWM-Kanälen beim Aktor auskommst, kannst Du den anderen Timer vollständig zur Impulslängenerfassung nutzen.

Zum Code: ich hatte den Weg in Beitrag 14 deutlich vereinfacht...
Es wird nur noch der externe Interrupt an einer Flanke verwendet, der Timer liefert keine IRQs.
die ISR müßte dann:
Das Überlaufflag des Timers prüfen.
Ist es gesetzt, wird es zurückgesetzt, und der Indexzähler auf 0 gesetzt.
Sonst wird der Indexzähler inkrementiert und Array(Index)=Timervalue.
Anschließend wird der Timer auf null gesetzt.
Die ISR füllt Dir so im Hintergrund ununterbrochen das sechs-Byte-Array mit den Impulslängen (genauer: mit den dabei verstrichenen Timertakten).
Im Hauptprogramm kannst Du dann zB Array(3) auswerten, und den PWM-Timer für die H-Brücke einstellen. Und in Abhängigkeit von Array(5) die Zugbeleuchtung/Pfeife/whatever schalten.

Wenn Du meinen Lösungsvorschlag, die Idee dahinter, verstanden hast, können wir uns um die Umsetzung kümmern. Sind in Bascom ja nur wenige Zeilen...

Als ersten Test könnte man dann vier Kontrollerbeine in Abhängigkeit von vier Signal-Kanälen an-/ausschalten lassen. Also bei einer diskreten Schwelle pro Kanal.

Alternativ kann man sich auch erstmal um die Aktorseite kümmern, statt dem Eingangssignal nur'n Potentiometer an PB2, welcher als ADC-Eingang verwendet wird. Wenn Du so den Motor im Griff hast, kannst Du hinterher das Signal auf PB2 legen (ohne Poti), und die Impulsweitenerfassung angehen...
 
Salut !

Wenn Du also mit einem Timer und maximal zwei PWM-Kanälen beim Aktor auskommst, kannst Du den anderen Timer vollständig zur Impulslängenerfassung nutzen.

Dann passt das ja :)
Ja , es ist eine Brückenschaltung aus 4 Transistoren, als Motortreiber - entweder für Wechselstrommotoren oder Gleichstrommotoren.

Die ISR füllt Dir so im Hintergrund ununterbrochen das sechs-Byte-Array mit den Impulslängen (genauer: mit den dabei verstrichenen Timertakten).
Im Hauptprogramm kannst Du dann zB Array(3) auswerten, und den PWM-Timer für die H-Brücke einstellen. Und in Abhängigkeit von Array(5) die Zugbeleuchtung/Pfeife/whatever schalten.

Wenn Du meinen Lösungsvorschlag, die Idee dahinter, verstanden hast, können wir uns um die Umsetzung kümmern. Sind in Bascom ja nur wenige Zeilen...

Ich versuche es ... bin aber noch nicht ganz dahinter gekommen.
Ich denke vieleicht zu "ablaufartig" seriell...? Und ich bin in Gedanken immer dabei, dass ich ja nur einen Kanal benötige,
den ich auslese. Natürlich ist es aber egal, wenn ich den entsprechenden Kanal aus dem Array auslese, klar.

Aber generell war der Ansatz auch nicht verkehrt, vom Prinzip her ?

Alternativ kann man sich auch erstmal um die Aktorseite kümmern, statt dem Eingangssignal nur'n Potentiometer an PB2, welcher als ADC-Eingang verwendet wird. Wenn Du so den Motor im Griff hast, kannst Du hinterher das Signal auf PB2 legen (ohne Poti), und die Impulsweitenerfassung angehen...

Ich versuche gleich mal mit PWM den Motortreiber anzusteuern. Ich habe ein Beispiel PRG welches per PWM LEDs dimmt ...
Das habe ich so umgestrickt, dass man den Duty-Cycle eingeben kann über UART und dann schaue ich mal, was der Treiber und der Motor dazu sagen...

Gruss Billy
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)