Ports manipulieren

Hallo zusammen

Ich habe eine Frage zur direkten Programierung über die DDR - PORT und PIN - Register

Ich benutze einen Mega 2560

Im Grunde geht es darum, 4 Relais möglichst synchron zu schalten (diese steuern dann über Schütze
jeweils 2 Motoren im Rechts- oder Linkslauf an (Drehrichtungsumkehr dur Phasentausch am Motor)).

Die Motoren ihrerseits verstellen mittels Gewindestangen und darauf laufenden Hubarmen die Höhe einer Bühne. Die aktuelle Höhe wird mittels Spindelpotis überwacht.

Gesteuert werden die Richtungen mittels Tastern, die gegeneinander verriegelt werden.

Mit den 'normalen' Befehlen zum lesen von oder schreiben auf die Analogen und Digitalen Anschlüsse funktioniert meine Steuerung soweit auch. Allerdings musste ich feststellen, daß die Hubhöhen der beiden Seiten recht schnell unterschiedlich werden, so daß die Hubarme neu Justiert werden müssen.

Da die Schaltverzögerung der Ausgänge bei Steuerung der Ausgänge mittels digitalWrite() sogar messbar ist, habe ich mir gedacht dies mittels Portzugriffen zu beschleunigen.

Ich habe jetzt einige kleinere Probleme

Zum besseren Verständnis einige Festlegungen aus meinem Programm

DDRF = B00000000;Port F komplet als Eingang
bei A4-A7 sind die Pullups eingeschalter

Als erstes ein eine Frage zu Analogports und dem PINx-Befehl

Hi

Dein Problem wird nicht die Verzögerung in den digitalWrite sein - Das sind unterste Millisekunden!
Messe Mal die Ansprechzeit der Schütze - dort wirst Du alleine schon Aufgrund des zurück zu legenden Weg mehr 'Zeit' finden.
Eine Verriegelung der Richtungen sollte ebenfalls nicht nur durch die Elektronik-Ausgänge gegeben sein - Schützverriegelung könnte Lesestoff bieten.

Auch werden Deine Motoren wohl mit unterschiedlich viel Schlupf zu kämpfen haben, was in einer differierenden Drehzahl und damit in unterschiedlicher Hubhöhe pro Zeit resultiert.

Du musst die Motoren entweder mechanisch koppeln - jeder 3D-Printer mit einstellbarem Bett macht Das mit einer umlaufenden Kette/Zahnriemen - hier vll. so nicht anwendbar, oder eben elektronisch, also die Motoren zu Servos machen - IST erfassen und auf SOLL bringen - der langsamste Motor bestimmt die Geschwindigkeit.

Sonst kannst Du per Bitmanipulation jedes beliebige Muster zusammen bekommen wie auch Bits unangetastet lassen.
Auslesen und Rückschreiben erlaubt der Arduino Dir ebenfalls.

MfG

PINx-Befehl

Das ist kein "Befehl". PINx mit dem Entsprechenden Port-Buchstaben ist das Pin-Eingangs-Register. Darin steht der Zustand der Pins

olaf2605:
Da die Schaltverzögerung der Ausgänge bei Steuerung der Ausgänge mittels digitalWrite() sogar messbar ist, habe ich mir gedacht dies mittels Portzugriffen zu beschleunigen.

messbar sicherlich. Aber ob das deine Asyncronität erklärt wage ich zu bezweiflen.
Zeig mal einen minimalen lauffähigen Code der das Problem zeigt.

olaf2605:
Die Motoren ihrerseits verstellen mittels Gewindestangen und darauf laufenden Hubarmen die Höhe einer Bühne. Die aktuelle Höhe wird mittels Spindelpotis überwacht.

Dann mußt Du doch nur die Spindelpotis abfragen und bei Abweichungen die zugehörigen Motoren schneller oder langsamer laufen lassen, bzw. kurzzeitig abschalten wenn Verlangsamen nicht geht.

Vermutlich handelt es sich ja um AC Motoren, deren Geschwindigkeit sich nicht so einfach beeinflussen läßt. DC oder BLDC Motoren erlabuen da eine weit bessere Steuerung.

Hallo zusammen

Danke für die schnellen Antworten
Ich bin neu in Foren und weiss noch nicht so wirklich, wie man sich hier bewegt
Anfang der 80'er Jahre habe ich programmieren gelernt, seit dem alerdings beruflich nicht mehr viel damit zu tun.
Seit bitte etwas nachsichtig mit mir, da es sich mit Mitte 50 nicht mehr so leicht lehrnt, wie mit 20 :slight_smile:

War gestern schon spät und mein Anliegen vielleicht etwas konfus beschrieben. Ausserdem fehlt meine eigentliche Frage komplett :frowning:

Ich will es mal anders versuchen:
Jeder von euch kennt eine Kfz - Hebebühne. Im Prinzip habe ich so etwas.
Jede Säule hat einen eigenen Drehstrommotor. Es gibt keine mechanischen Verbindungen zwischen den Säulen (Kette oder Synchronstange mit Tellerradgetriebe oder ähnlichem). dies ist auch nicht nachrüstbar.
Damit der Lastteil, an dem die Motoren hängen, erstmal im finanziellen Ramen bleibt, habe ich mich für Schütze entschieden (mit all ihren Nachteilen in Bezug auf Schaltzeiten.
Die Hilfsrelais fliegen demnächst raus und werden durch elektronische Schalter ersetzt (falen die Schaltverzögerungen schonmal zum großen Teil weg).
Eine Drehzahlregelung bei den Drehstrommotoren ist nicht vorgesehen (Phasenanschnitt oder ähnliches erscheint mir im Moment etwas übertrieben..
Was ich erreichen will, ist eigentlich eine Optimierung meines Programm's und das erlernen neuer Techniken.
Dabei bin ich über die Verwendung von Registern gestolpert.

Jetzt möchte ich eigentlich nur folgendes wissen:

kann ich über das direkte auslesen eines Registers mittels PINx einen Wert von 0 - 1023 erhalten
int poti1; // poti1 als Integer
DDRF = B00000000; // Register F als Eingänge

poti1 = (PINF & B00000001); // den Inhalt von Bit'0' (A0) der Variablen poti1 zuweisen

Serial.print(poti1); // auf der Console ausgeben

Bei mir wird in der Console lediglich der Wert '0' (Eingang auf Masse) korrekt ausgegeben.
Alle anderen Potistellungen ergeben Unsinn (Poti zwischen Masse und 5V).
Das Poti ist heil.
Habe auch schon den Port 'K' genommen - das selbe
Oder ist der Mega einfach defekt?

Ich versuche mal jedem einzeln zu antworten - möchte allerdings auch keine Wortklauberei lostreten :-))
Hoffentlich spreche ich alle korrekt an

#Senerifly Schande über mich - ich habe es umformuliert
Hast Du ev. noch einen Tip eine meiner neue Fragen?

#DrDiettrich Genau das habe ich gemacht und steuere dann abhängig von der Hubhöhe einen der
beiden Motoren nach -- und genau diese 'Nachsteuerung' will ich beschleunigen
Eine bestimte Differenz zwischen denn Potis ist erlaubt, wird diese überschritten, wird ein
Motor nachgesteuert

#Postmaster-INO Die Verriegelung gegen gleichzeitiges Drücken ist sogar doppelt in der Hardware.
Zum einen über Hilfskontakte an den Schützen und dann noch einmal an den Tastern.
Im Code frage ich, nachdem erkannt wurde welche Taste gedrückt wurde, nur noch diese
Taste in einer while-Schleife ab. Dadurch stelle ich zusätzlich sicher, daß das gleichzeitige
Drücken der 2.Taste ohne Einfluss auf die laufende Aktion bleibt

#noiasca der fragliche Schnipsel ist jetzt oben mit im Post - hatte heute Nacht gefehlt :-((

Danke an alle

int poti1 = (PINF & B00000001);

Serial.print(poti1);                        // auf der Console ausgeben




Bei mir wird in der Console lediglich der Wert '0' (Eingang auf Masse) korrekt ausgegeben.
Alle anderen Potistellungen ergeben Unsinn (Poti zwischen Masse und 5V).

Die Ausgabe kann nur 0 oder 1 sein, wobei ich eine 1 bei einer Poti-Stellung über ca. 60% erwarten würde. Zwischenstellungen (15% - 60%) würde ich bei digital I/O generell vermeiden.
Dass Port F beim atmega2560 auch für Analog-Messungen verwendet werden kann, spielt bei deiner Frage keine Rolle, hoffe ich ...
Dass Port F auch was mit JTAG (avr-debugging) zu tun hat, sagt mir jetzt nichts, aber ich würde an deiner Stelle probieren, ob ein anderes Register sich genauso verhält.


Ich sehe es so, dass du die zwei Fragen

  • große Motoren mit Schützen ansteuern
  • Arduino und direkte PORT Manipulation
    nun getrennt bearbeitest, da sie nichts miteinander zu tun haben.

Hallo michael

Es geht mir um das Auslesen eines 'Analogen' Wertes.

ich habe es noch einmal im kleinen aufgebaut
gebe ich auf a0 Masse /Port F Bit0), dann bekomme ich beim auslesen auch den Wert 0
lege ich ca. 2,5V an, bekomme ich eine 8 ausgegeben
und bei 5V ebenfalls eine 8

kann es sein, daß ich beim zugriff mit (PINF & B00000001) einen Binärwert zurück
bekomme, den ich erst in Dezimal umwandeln muss, damit das Ergebnis stimmt

Hi

In den Tiefen des Datenblatt des auf dem Arduino verbauten IC (MEGA256) wird sich finden lassen, wie Du ein AnalogRead ausführen kannst - ganz so einfach, wie Du Dir Das vorstellst, ist's dann nicht.

ABER:
Das wird Deine Probleme NICHT lösen.
Auch ein AnalogRead ist in Sekundenbruchteilen abgefrühstückt.

Eigentlich dürften Einschaltverzögerungen bei Dir gar keine Rolle spielen:
Wie denken uns, der ganze Kram geht nur sekündlich einen Schritt weiter!

  • HOCH wird gedrückt
  • Motor 1 fährt los
  • Motor 2 fährt los
  • Motor 3 fährt los
  • Motor 4 fährt los
  • Hoch wird los gelassen
  • Motor 1 stoppt
  • Motor 2 stoppt
  • Motor 3 stoppt
  • Motor 4 stoppt
    ... alle Motoren haben die gleiche Fahrzeit, trotz unterschiedlicher Start-Zeiten.
    Das Ganze kannst Du auch mit RUNTER oder erneutem HOCH-fahren weiter simulieren - da ändert sich NICHTS!!

Dein Problem sind verschieden schnell laufende Motoren - Du musst 'nur' zusehen, daß alle Motoren bei STOP auf der gleichen Höhe anhalten.
Also bei Stop alle Potis auslesen, das 'am weitesten gefahrene Poti' als SOLL nutzen, diesen Motor DIREKT stoppen.
Die anderen Motoren laufen weiter, die Poti-Position wird laufend eingelesen, jeder Motor, Der die Soll-Position erreicht (oder überschreitet) wird ausgeschaltet.

Klappt allerdings auch nur, wenn nicht schon beim 'von ganz Unten nach ganz Oben fahren' einer der Motoren drei Sekunden vor den Anderen fertig ist - Die stoppen dann zwar auch wieder auf gleicher Höhe, das Auto ist aber mittlerweile runter gefallen.

Anmerkung: Wenn mit der Hebebühne irgendetwas passiert, wird man Dich für seeehr lange Zeit nicht mehr in Ruhe lassen!!

MfG

kann es sein, daß ich beim zugriff mit (PINF & B00000001) einen Binärwert zurück bekomme

Es ist leider so, dass in PINF keine Analogwerte zu finden sind.
Das hat postmaster schon ausführlicher geschrieben.

PINF enthält die binären Zustande der 8 Digital I/O Pins von Port F. Und mit deinem & liest du nur einen davon aus.


analogRead braucht auf 16 MHz (Uno/Mega) ca. 0,1 ms. Das kann man bei Bedarf noch etwas optimieren, aber den Bedarf sehe ich nicht.

olaf2605:
kann es sein, daß ich beim zugriff mit (PINF & B00000001) einen Binärwert zurück
bekomme, den ich erst in Dezimal umwandeln muss, damit das Ergebnis stimmt

Mit & B00000001 kann eigentlich nichts anderes herauskommen als 0 oder 1. Andere Pins liefern natürlich andere Werte, der 4. Pin (B00001000) liefert dann 0 oder 8. Du mußt auf jeden Fall sicherstellen, daß Du für den Arduino Pin das jeweils zugehörige Bit im Portregister verwendest, offene Eingänge können jedesmal einen anderen Wert liefern.

olaf2605:
... Es gibt keine mechanischen Verbindungen zwischen den Säulen (Kette oder Synchronstange mit Tellerradgetriebe oder ähnlichem). dies ist auch nicht nachrüstbar.

Hast Du schon an eine „elektronische Achse“ gedacht? Dabei werden Umdrehungen synchronisiert, ohne eine mechanische Verbindung zwischen den zu drehenden Teilen herstellen zu müssen.

Gruß

Gregor

Hallo postmaster-ino

Dan habe ich mir wahrscheinlich falsche Vorstellungen von den Geschwindigkeitsunterschieden gemacht.
Die Datenblätter haben meistens einen großen Nachteil für mich - sie sind in englisch - und da hapert es doch etwas bei mir

Da die Hebebühne bei mir privat steht und bei einer Spindel länge von ca 3 m lediglich 1,5 m Hub ausführen soll, halten sich alle rechtlichen Bedenken in übersichtlichen Grenzen. Für jemanden anderen würde ich so was nicht aus der Hand geben. Wäre mir persönlich zu unsicher.

So wie Du es oben schreibst, ist es richtig. Und der Fehler war bei mir im Kopf. Klar die Zeiten sind gleich, wenn ich es in der selben Reihenfolge ein und ausschalte.

Aber ich habe eine andere und viel schlimmere Fehlerquelle gefunden - die Spindel wird mittels 20Jahre alten Keilriemen angetrieben - da kommen wohl 99% aller Fehler her. Habe gerade neue bestellt - sind dann Mi hier :-))

Also lasse ich das Poti auslesen so wie es ist. Habe mich wahrscheinlich von dem Unterschied bei der Ausführung blenden lassen. Die Digitalen E/A's werde ich trotzdem umstellen (reines Ego Ding ob ich es hin bekomme.)

Die oberen und unteren Stop-punkte werden für jede Säule separat eingestellt und abgespeichert. Beim Erreichen eines dieser Punkte wird alles abgeschaltet.
Beim normalen Hoch- oder Runterfahren habe ich bis jetzt immer nach dem loslassen des Tasters nachgeregelt, wenn ein Höhenunterschied größer eines erlaubten Wertes vorhanden war. - Sollte dann mit den neuen Riemen wieder funktionieren

Danke Dir für Deine ausführliche Antwort

#michael_x klar - hatte nicht gewußt, daß der AD-Wandler nicht permanent am Pin hängt, sondern erst
'zugeschaltet' wird. Damit sind dann auch alle anderen Überlegungen von mir in dieser Richtung
hinfällig

Danke auch allen anderen
Bin leider nicht ständig vor dem PC, sondern war gerade mehrmals an der Technik :slight_smile:

Tausche jetzt erst mal die Poti-Kabel gegen abgeschirmte
und dann geht es noch mal an das Programm

Habe wieder viel gelernt und einige Denkfehler sind gerade gerückt

Vielleicht bis zum nächsten Mal

Mfg Olaf

Du könntest die Motoren auch mit Frequenzumrichtern ansteuern. Dann brauchst du keine Schütze und die Geschwindigkeit lässt sich per pwm regeln.

Wieviel Leistung haben die Motore?

Hallo ElEspanol

die Leistung muss ich nachschauen - sie stammen aus einer 3t Hebebühne
An Frequenzumrichter habe ich noch gar nicht gedacht
Ist ne Überlegung wert

mfg

Wenn es echte 3-Phasen Drehstrommotore sind, gibt es vom FC bereits für unter 100€ brauchbare FUs. Anfahr- und Bremsrampe sind da ggf. auch schon integriert.

Hi

Bei maximal 3 Meter Spindellänge wird die Fahrt spätestens nach diesen 3 Metern beendet - egal wie!

Solange kein Motor ausfällt, werden Diese auch ungefähr die gleiche Geschwindigkeit erreichen.
Wie geschrieben: Wen nDa keine 3 Sekunden Differenz in der laufzeit drin sind - reicht Es, die Motoren auf Punkt anzuhalten.

Pro Motor einen FU - macht die Hebebühne ruck zuck arg uninteressant - auch ist es dem Auto egal, ob's mit Rampe beschleunigt wird ... Hauptsache, man kommt an Auspuff und Co.

Mein Vorgehen wäre:

  • IMMER die aktuelle Position aller Motoren auslesen
  • Bei zu großer Differenz NOTSTOP(p) - wenn z.B. ein Motor ausfällt, wird sich Dieser nicht weiter drehen - Das ist den anderen Motoren aber egal - und schon liegt das Auto bäuchlings oben im Dreck.

Wenn die Motoren doch zu schnell auseinander laufen, könnte man den schnellsten Motor auch einbremsen - wenn Differenz zu groß, den am weitesten gefahrenen Motor abschalten, Zuschalten wieder, wenn die anderen Motoren nachgerückt sind - somit wäre auch ein Motorausfall direkt abgedeckt - da sich heir die Differenz nicht selber verringert, fährt Da dann auch nix mehr weiter auseinander.

Das 2x schalten beim Aufwärtshub des Schütz für den schnellsten Motor - kann Das ab - klackert dann halt etwas mehr als unbedingt nötig.
Den Ablauf müsste man dann halt erarbeiten, sonst wäre es dicke ausreichend, bei zu großer Differenz einen Not-Stop auszulösen.

So hättest Du den Arduino zur REGELUNG der Motoren - denke, Das könnte smooth funktionieren.

MfG