Drehimpulsgeber: Sketch in größeren Sketch integrieren - wie?

Ich habe diesen Drehimpulsgeber: http://www.reichelt.de/Drehimpulsgeber/STEC11B13/3/index.html?;ACTION=3;LA=2;ARTICLE=73916;GROUPID=3714;artnr=STEC11B13

In den Tiefen des Forums habe ich einen passeden Sketch gefunden. Dieser wurde etwas modifiziert. Nun kann ich auf einem Uno (zum Testen) mit dem Drehimpulsgeber das PWM-Signal am Pin11 zwischen 0 und 5 Volt regeln. Das funktioniert einwandfrei.

int val; 
 int encoder0PinA = 4;
 int encoder0PinB = 5;
 int encoder0Pos = 0;
 int encoder0PinALast = LOW;
 uint32_t encoder0PinALastChange = 0;
 int n = LOW;

 void setup() { 
   pinMode (encoder0PinA,INPUT);
   pinMode (encoder0PinB,INPUT);
   Serial.begin (57600);
 } 

 void loop() { 
   n = digitalRead(encoder0PinA);
   if ((encoder0PinALast == LOW) && (n == HIGH) && (millis() - encoder0PinALastChange > 2)) {
     if (digitalRead(encoder0PinB) == LOW) {
       if (encoder0Pos > 0)
         encoder0Pos--;
     } else {
       if (encoder0Pos < 255)
          encoder0Pos++;
     }
     Serial.print (encoder0Pos);
     Serial.print ("/");
     analogWrite (11, encoder0Pos);
     encoder0PinALastChange = millis();
   } 
   encoder0PinALast = n;
 }

Jetzt soll dieser kleine Sketch aber in einen inzwischen 16 KB großen Sketch integriert werden. Für einen Durchlauf der loop-Schleife benötigt der aber rund eine Sekunde. Man könnte den Drehimpulsgeber wahrscheinlich gar nicht vernünftig nutzen.

Wie könnte man dieses Problem lösen? Die Kombination von millis() und Interrupt funktioniert wohl nicht, wie ich im anderen Faden eben gelesen habe. Aber was könnte man dann machen, damit man den Drehimpulsgeber in “Echtzeit” nutzen kann?

Frank

Hier ist allgemeiner C-Code für den Atmega. Lässt sich vielleicht für den Arduino anpassen: http://www.mikrocontroller.net/articles/Drehgeber

Das verwendet auch einen Timer, aber es werden sowie ich das sehe nicht direkt die Millisekunden ausgewertet, sondern nur jede ms etwas gemacht. Dieses Delay könnte man beim Arduino auch einfach in der loop machen ohne einen Timer manuell zu programmieren. Es denn du machst bei dir in der loop schon sehr viel, dann bietet sich natürlich ein Timer an: http://playground.arduino.cc/Main/MsTimer2

Auch ein 16kB großer Sketch braucht keine Sekunde, wenn man's richtig macht ;) Nur mal als Größenordnung 1 byte/clock angenommen: Selbst wenn jeder Befehl in jedem loop-Durchlauf dran käme ( einmal ), dauert das ca. 1 ms

Die Kombination von millis() und Interrupt funktioniert wohl nicht, wie ich im anderen Faden eben gelesen habe.

Das kann man so nicht sagen, aber schön wäre es schon, wenn nicht nur im Sekundentakt auf encoder-Änderungen reagiert werden würde.

Die Kombination von millis() und Interrupt funktioniert schon wenn auch mit Einschränkungen. Innerhalb der Interrupt-Funktion wird millis() und micros() nicht weitergezählt. Man kann keine Verzögerung innerhalb einer Interruptfunktion mit millis() oder micros() machen. Man kann aber ohne Probleme millis() in eine Variable abspeichern und beim nächsten Interruptaufruf die Zeitdifferenz errechnen oder außerhalb der Interruptfunktion die abgespeicherte Zeit benutzen.

Grüße Uwe

Ich habe noch ein weiteres Problem gefunden. An dieser Stelle muss ich aussteigen und auf die Hilfe eines Profis hier im Forum hoffen.

Ich beschreibe zuerst einmal, was ich machen möchte:

Die Funktion, die im Moment ein 10-Gang Poti (R7 - siehe Link in Signatur) hat, soll künftig über einen Drehimpulsgeber erfüllt werden. Dieser soll einen PWM-Ausgang steuern. Der PWM-Ausgang des Arduino soll einen Transistor (evtl. BUZ11) ansteuern, der dann die Spannung von 0 bis 12 Volt regelt.

Nun kommt das erste Problem: Die Stromsenke soll (angenommen) max. 80 A "vernichten". Wenn ich das über die vorhandenen 255 PWM-Schritte mache, bedeutet das, dass ich gut 300 mA pro Raste am Drehimpulsgeber einstelle. Also sehr sehr grob. Das ist nicht optimal. Wenn es möglich wäre, die Auflösung auf 1024 zu erhöhen, wären es nur noch knapp 80 mA pro Raste. Das wäre schon besser. Aber noch etwas feiner wäre noch besser. Aber nun kommt das praktische Problem. Bei 80 mA müsste ich den Knopf pro Ampere 12,5 mal drehen. Das ist nicht machbar, wenn man "mal schnell" von 20 auf 10 Ampere runterregeln möchte = 125 Umdrehungen.

Meine Idee (als nicht Nichtprogrammierer und Nichtelektroniker) wäre, einen Drehimpulsgeber für die Grobeinstellung zu nehmen ein einen für die Feineinstellung. So habe ich es auch an einem meiner Labornetzteile mit zwei Potis gemacht.

Dann kommt noch das zweite Problem, dass oben schon beschrieben wurde. Ich habe einen inzwischen recht umfangreichen Sketch, der ein Nutzen des Drehimpulsgebers in "Echtzeit" wahrscheinlich so nicht möglicht macht. Daher müsste eine Lösung gefunden werden, bei der die/der Drehimpulsgeber in "Echtzeit" genutzt werden können.

Bisher habe ich mein Projekt in viele Einzelaufgaben aufgeteilt, die ich nacheinander abgearbeitet habe. Die Hardwarelösungen sind meist trivial, mussten von mir aber trotzdem erst angelesen und erfragt werden (Spannungsteiler, OpAmp, Mosfet, etc.) Die Sketches dazu habe ich mir in den Weiten des Netzes und des Forums zusammen gesucht und entsprechend meinen Anforderungen angepasst. Die für mich nicht zu lösenden Stellen (Erweiterung des Sketches um zwei PWM-Pins) wurden netter Weise von pylon ergänzt.

Soweit zur Funktion und meiner bisherigen Herangehensweise. Bevor ich mit dem Erlernen der Programmierung soweit bin, dass ich das alleine lösen könnte, bin ich alt und grau(er). Aus diesem Grund frage ich mal in die Runde, ob sich jemand meinem Problem annimmt und es für mich programmiert? Ein Obulus für die Kaffeekasse ist selbstverständlich. Oder ist das zu umfangreich?

Frank

Bei der Suche nach weiteren Informationen bin ich auf die folgenden beiden Seiten gestoßen:

http://playground.arduino.cc/Main/MsTimer2 http://forum.arduino.cc/index.php?topic=55505.0

Hast du dir das mal angeschaut: http://www.mikrocontroller.net/articles/Drehgeber

Das verwendet einen Timer-Interrupt, der den Wert des Drehgebers alle 1ms updatet. Dann kann man den aktuellen Wert an einer beliebigen Stelle per Hand abfragen und der sollte korrekt sein auch wenn du zwischendurch viel anderen Code abgearbeitet hast.

Den puren AVR/C Code für den Arduino anzupassen ist keine große Sache. Der Timer in dem Programm ist nur dazu da den Drehgeber alle 1ms einzulesen. Das kannst du durch durch MsTimer2 ersetzen. Aber abgesehen von cli()/sei() funktioniert das auch mehr oder weniger so (statt dessen noInterrupts()/interrupts()). Der Arduino ist schließlich auch ein AVR.

Man könnte vielleicht einen zweiten Timer nehmen der den aktuellen Wert des Drehgebers (der durch den ersten Timer ständig aktualisiert wird) alle 20-50ms (oder was gute Ansprechzeiten bringt) ausließt und verarbeitet. Dann sollte er direkt reagieren, egal was sonst läuft.

Hi,

wegen der Wertigkeit des Drehimpulses kann ich mit vorstellen, dass du mit dem Taster des Drehgebers die Wertigkeit einstellt, und mit dem Drehgeber dann mit den Wertigkeiten de-/ inkrementierst.

Also entweder 1/ 10 fach togglen, dann hat mit 1-fach ein Klick 80 mA, mit 10 fach ein Klick dann 800mA, oder mit der 1-2-5 Skalierung die Wertigkeiten entsprechend umschalten.

Ich hoffe, das ist verständlich..

Greetz, Linpo

Hallo,

das ist witzig, exakt die gleiche Idee hatte ich heute Nachmittag auch schon. Als erstes muss aber geklärt werden, wie ich eine feinere Abstufung hin bekomme. 255 Stufen sind definitiv zu wenig. 1023 sind Minimum nötig.

  • Kein KIick 500 mA
  • Ein Klick ein Zehntel davon
  • Doppelklick Wechsel ins Menü (das kommt noch)

Ob ein weiterer Schritt sinnvoll ist, wird die Praxis zeigen. Trotzdem danke für die Idee.

Frank

Oder: Statt 1Puls = 1 Schritt auch die Pulsgeschwindigkeit zu berücksichtigen: Langsames Ändern = fein, Schnell = grössere Schritte / Puls

Das ist intuitiver, finde ich, da nicht die gerade gewählte Geschwindigkeit gemerkt/angezeigt werden muss. Bei mehreren Schritten muss man oft klicken, wenn man die Schrittweite zu groß hatte und wieder kleinere Schritte haben will.

Ich würde die Werte beim Drehimpulsgeber einfach logarithmisch verteilen. Die Idee ist, daß Du bei hohen Stromwerten ja gar keine hohe Auflösung brauchst. D.h. wenn Du 80A versenken willst, dann ist 79.9A wahrscheinlich gar nicht interessant. Wohingegen der Sprung von 10mA auf 100mA eher groß ist. D.h. meine Rasten wären:

1mA, 2mA, 5mA, 10mA, 20mA, 50mA, 100mA, 200mA, 500mA, 1A, 2A, 5A, 10A, 20A, 50A, 100A oder 1mA, 1.5mA, 2mA, 3mA, 5mA, 7mA, 10mA, 15mA, 20mA, 30mA, 50mA, 70mA, 100mA, ...

(Ich runde einfach die Werte aus den Widerstandsreihen: http://www.infoseite.at/daten/technik/widerstaende_reihen.htm) E24 hat 24 Werte pro Dekade und Du hast 5 Dekaden --> 120 Schritte und die Auflösung ist super. Wenn das nicht reicht --> E48 und 240 Schritte.

Mir würde sowas reichen. Damit löst sich das Problem der vielen Stufen und der komplizierten Bedienung in Luft auf.

Was die Auflösung der PWM angeht: Timer1 hat 16 Bit Auflösung. Zur Not mußt Du den direkt programmieren. Damit kommst Du auf 1.2mA Auflösung.

Hi,

das war mit der 1-2-5 Teilung gemeint. Wenn Du aber 73.25A einstellen musst, dann ist ein log-Poti imho nicht ausreichend. Dort wäre dann die zwei Knopf Lösung oder das Wertigkeit umschalten geeignet.

Ich sehe, wir haben zusammen schon eine Menge guter Ideen...

Greetz, Linpo

Eure Ideen sind spitze und mein "Projekt" immer umfangreicher ;)

Also sollte das so zu machen sein, dass ich durch die Drehgeschwindigkeit die Dekade bestimme, in der der Wert springt, dann sollte das ausreichend sein, um auch krumme Werte wie 73.25A einzustellen. Diese krummen Werte kommen wahrscheinlich sowieso nur im unteren Bereich (etwa bis 10 A) zum tragen. Zumindest für die bisher ins Auge gefassten Anwendungen. Im oberen Bereich machen sie schon alleine wegen der fehlenden Messgenauigkeit keinen Sinn.

Ein OpAmp holt sich vom Shunt den Spannungsabfall und multipliziert ihn so auf, dass ich etwa 50 mV pro Ampere habe. Das zumindest war meine Idee. Blöderweise ist das nicht linear. Je höher die ausgegebene Spannung am OpAmp ansteigt, desto höher ist die Spannung pro Volt. Ich muss mir noch ein Zangenamperemeter besorgen, um die Ströme jenseits von 20 A zu messen. Ich bin mir auch nicht sicher, ob es nicht vielleicht am Multimeter liegt. Ein zweites Messgerät wird Klarheit bringen. Die Abweichung werde ich wohl irgendwie in Software bereinigen müssen. Dazu muss ich aber erst mal alle Werte haben.

Ich wollte damit nur sagen, dass alleine dadurch die Abweichung im Bereich über, sagen wir mal, 20 A eh größer ist und eine Einstellung auf feinere Werte als 200-300 mA wenig Sinn macht.

Frank