Encodermotoren mit dem Arduino auslesen

Alles rund um TX(T) und RoboPro, mit ft-Hard- und Software
Computing using original ft hard- and software
Forumsregeln
Bitte beachte die Forumsregeln!
Antworten
LM98
Beiträge: 10
Registriert: 15 Jul 2014, 17:32

Encodermotoren mit dem Arduino auslesen

Beitrag von LM98 » 02 Okt 2014, 19:23

Hallo zusammen,

Ich möchte mit dem Arduino den Encodermotor von Fischertechnik auslesen. Jedoch haben alle meine Versuche fehlgeschlagen. Vielleicht kennt sich jemand mit dem Thema schon ein bisschen aus und kann mir eventuell einen "Verdrahtungsplan" für den Arduino mit dem Encodermotor geben und dazu noch das passende und funktionierende Programm.

Gruß,
Ludwig

bummtschick
Beiträge: 60
Registriert: 12 Jan 2014, 13:14

Re: Encodermotoren mit dem Arduino auslesen

Beitrag von bummtschick » 02 Okt 2014, 20:15

Hallo Ludwig,

die Sache ist nicht ganz trivial, wenn man Mikrocontroller nicht mit der Muttermilch aufgesogen hat. Ich habe hilfreiche Hinweise in dem Artikel aus c't Hardware Hacks 2/2013, Seite 142 gefunden, wenn sich auch nicht alles aus dem Artikel als ganz zutreffend erwiesen hat.

Du brauchst natürlich einen Motortreiber wie zB den Adafruit Motor Shield V2, der in dem c't-Artikel empfohlen wird. Die Empfehlung würde ich voll unterstützen, weil der sehr leicht zu programmieren und sehr robust ist. Außerdem ist er stapbelbar und verbraucht keine Pins. Zwei Kabel gehen also zwischen Motor und dem Motorausgang des Motorshields hin und her.

Dann gibt es das spezielle dreipolige Kabel 137125 für den Encodermotor ( http://ft-datenbank.de/details.php?Arti ... 1d5aa6d661 ). Das grüne Kabel muss an Masse, das rote an +9V, und auf dem schwarzen liefert der Encodermotor das Encodersignal.

Dieses Signal schaltest Du am Arduino am besten an einen Pin, der "external interrupts" unterstützt. Die PIns sind hier aufgelistet. http://arduino.cc/en/Reference/attachInterrupt

Der c't-Artikel meint, man sollte einen Arduino Mega nehmen, weil er schneller sei. Ich hab die Befehlssätze jetzt nicht verglichen, aber der Uno und der Mega 2560 werden beide mit 16 MHz getaktet, so dass es da glaube ich keinen großen Unterschied gibt (hier können die µC-Experten vielleicht aus dem Stand noch etwas beitragen). Der Mega 2560 hat vor allem den Vorteil, viel mehr Pins zu haben und vier statt zwei externe Interrupts zu unterstützen. Wenn Dir aber die zwei Interrupts des Uno (bzw. des dort verbauten ATmega328) nicht ausreichen, gibt es auch eine auf den Arduino-Seiten nicht ausführlich erwähnte weitere Methode. Google mal nach "Arduino pin change interrupts", so kriegt man auch auf dem kleinen Arduino mehr als zwei Encoder-Motoren angeschlossen.

Dann musst Du einen Interrupt-Handler schreiben, der die Encoder-Signale zählt, und mit attachInterrupt() diese Routine einem Interrupt-Pin zuordnen.

Ich habe Stefan Falk schon versprochen, für die nächste ft:pedia über das ganze Thema "ft-Motoren mit Arduino" einen Artikel zu verfassen. Ich hoffe, dass ich das Versprechen halten kann, dann gibt's hoffentlich bald mehr Material dazu.

Meine Roboter, in denen ich das alles ausprobiert habe, findest Du hier: http://www.ftcommunity.de/categories.php?cat_id=2844 Die waren auch beide auf der Convention ausgestellt.

Die alte Version (Bertha V1) hatte einen Arduino Mega 2560, an den über zwei Flachbandkabel fast 40 Pins für diverse Taster und Encoder verbunden waren. Teilweise benutze ich Encodermotoren; wo deren Kraft nicht ausreicht, müssen Power-Motoren ran, dann benutze ich ft-Minitaster für das Encodersignal. Die neue Version V2 versucht die Flachbandkabel zu vermeiden und hat statt dessen mehrere kleine Arduinos, die untereinander mit I2C kommunizieren. Das Prinzip, die Encodermotoren wie oben beschrieben an Arduino-Interrupts zu hängen, ist aber immer dasselbe.

Herzliche Grüße
bummtschick

bummtschick
Beiträge: 60
Registriert: 12 Jan 2014, 13:14

Re: Encodermotoren mit dem Arduino auslesen

Beitrag von bummtschick » 02 Okt 2014, 20:32

Nachtrag, Code würde etwa wie folgt aussehen (das hab ich jetzt per copy/paste aus verschiedenen Routinen in meinem Code rausgenommen):

Interrupt-Handler für externe Interrupts (pin change ist komplizierter)

Code: Alles auswählen

// global variables
volatile int g_iPlusOrMinus = 0;    // set to +1 when motor is going forward, set to -1 when motor is going backward
volatile int g_iEncoderTicks = 0;

void fnInterruptMotor1()
{
    g_iEncoderTicks += g_iPlusOrMinus;    // add or subtract one per encoder tick
}
In setup():

Code: Alles auswählen

pinMode(pinInterrupt, INPUT_PULLUP);              // pin number, NOT interruptID 
attachInterrupt(interruptID,                     // NOT the pin number
                            fnInterruptMotor,
                            FALLING);
Interrupt-Pin und -ID entnimmst Du der besagten Tabelle bei http://arduino.cc/en/Reference/attachInterrupt .

Wenn Du den Motor anschaltest, setzt Du g_iPlusOrMinus auf entweder +1 oder -1, je nach Richtung. Mit den ft-Encodern kommen die Ticks "vorzeichenlos" rein, Du musst also selbst Buch führen, in welche Richtung der Motor läuft.

Für Testzwecke, ob die Interrupts überhaupt funktionieren, würde ich anfangs einfach nur die Ticks zählen ohne Richtung.

Bei meinem Roboter zählt der auf diese Weise pro Motor etwa bis 4000, so dass ein int (16 bits) also ausreicht. Evtl. musst Du statt dessen einen int32_t nehmen.

LM98
Beiträge: 10
Registriert: 15 Jul 2014, 17:32

Re: Encodermotoren mit dem Arduino auslesen

Beitrag von LM98 » 02 Okt 2014, 21:02

Hi,

danke schonmal für die Übersicht die du mir gegeben hast. Wir haben uns ja letzten Samstag mal über den Arduino unterhalten. Ich hab schon alles so verkabelt wie du es beschrieben hast.
Könntest du eventuell mir ein einfaches Programm schreiben, mit dem du einen Encodermotor einschaltest und einfach nur die Impulse zählst (und z.B. nach 75 Impulsen abschaltest).

Gruß,
Ludwig

PS: ich schreib gleich nochmal nen Artikel über das Eigenbauprojekt Arduino mit Motortriberchips etc.

LM98
Beiträge: 10
Registriert: 15 Jul 2014, 17:32

Re: Encodermotoren mit dem Arduino auslesen

Beitrag von LM98 » 03 Okt 2014, 12:00

Hallo nochmal,

soweit wie ich das Programm mir rekonstruieren kann müsste das dann so aussehen:

#include "TimerOne.h"

// global variables
volatile int g_iPlusOrMinus = 0; // set to +1 when motor is going forward, set to -1 when motor is going backward
volatile int g_iEncoderTicks = 0;

int pinInterrupt = 2;
int interruptID = ??;

void setup()
{
Serial.begin(9600);
pinMode(pinInterrupt, INPUT_PULLUP); // pin number, NOT interruptID
}


void loop()
{
attachInterrupt(interruptID, fnInterruptMotor, FALLING);


}

void fnInterruptMotor()
{
g_iEncoderTicks += g_iPlusOrMinus; // add or subtract one per encoder tick
Serial.println(g_iEncoderTicks);
}

Nur ich hab keine Ahnung was die interruptID sein soll.

Gruß,
Ludwig

bummtschick
Beiträge: 60
Registriert: 12 Jan 2014, 13:14

Re: Encodermotoren mit dem Arduino auslesen

Beitrag von bummtschick » 07 Okt 2014, 14:41

Lieber Ludwig,

ein Programm schreiben kann ich Dir nicht, aber ein paar Tips geben.

Aus Deinem Code schließe ich, dass Dir die Funktionen der Arduino-Routinen setup() und loop() noch nicht klar sind. Bevor Du Code laufen lässt, sollte Dir klar sein, was der Code eigentlich tun soll und was jede Funktion macht. Gerade bei µC kann man sonst echt Schaden anrichten. attachInterrupt() dient zB dazu, eine Routine in Deinem Code einem Interrupt zuzuordnen. Das macht man natürlich nur einmal, nämlich in setup(), und nicht viele hundertausend Mal in loop().

Wenn Du also mit einem Arduino noch gar nichts vorher gemacht hast, fang bitte nicht gleich mit Interrupts und Motorsteuerung an. Versuch erst mal eine LED (zB die eingebaute am Pin 13) ans Blinken zu bekommen, wie es jeder Arduino-Anfänger macht -- so habe ich es auch gemacht. Dann wird Dir der Unterschied zwischen setup() und loop() klar und Du weißt, ob Dein Arduino überhaupt funktioniert und Deinen Code ausführt.

Schritt 2 sollte dann sein, den Motor in beide Richtungen an- und ausschalten zu können. Das muss unabhängig von den Encoder-Impulsen und von den Interrupts funktioneren. Wenn das bei Dir noch nicht funktioniert, lass die Interrupts erst mal außen vor.

Wenn Du den Adafruit Motor Shield V2 benutzt, findest Du den nötigen Code bei Adafruit: https://learn.adafruit.com/adafruit-mot ... -dc-motors

Als Beispiel:

Code: Alles auswählen

#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_PWMServoDriver.h"

In setup():
AFMS.begin();

in loop():
{
Adafruit_DCMotor *myMotor = AFMS.getMotor(portno);   // portno ist 1 bis 4

// 1 Sekunde vorwärts laufen lassen
myMotor->setSpeed(100);   // 0-255)
myMotor->run(FORWARD);
delay(1000);

// // 1 Sekunde halten
myMotor->setSpeed(0);
myMotor->run(RELEASE);
delay(1000);

// 1 Sekunde rückwärts laufen lassen
myMotor->setSpeed(100);   // 0-255)
myMotor->run(BACKWARD);
delay(1000);

// // 1 Sekunde halten
myMotor->setSpeed(0);
myMotor->run(RELEASE);
delay(1000);

}
Ich hab den Code jetzt aus dem Gedächtnis hier reingeschrieben und nicht kompiliert, aber so was in der Art sollte laufen, bevor Du mit Interrupts anfängst.

Schritt 3 wäre dann erst, die Impulse zu zählen, die reinkommen, wenn der Motor läuft. Dafür ist mein ursprünglicher Code gedacht.

Was die Interrupt-ID ist, steht im übrigen in dem Link, den ich Dir schon gegeben habe: http://arduino.cc/en/Reference/attachInterrupt
Wenn Du also zB den Encoder bei einem Uno an Pin 2 anschließt, musst Du Interrupt-ID in attachInterrupt() angeben.

Beste Grüße
bummtschick

hamlet
Beiträge: 332
Registriert: 12 Jan 2011, 21:41

Re: Encodermotoren mit dem Arduino auslesen

Beitrag von hamlet » 07 Okt 2014, 19:23

Hallo Ludwig,
noch eine Anregung für Dich, wenn du die Anfangshürden überwunden hast: Der große Vorteil, den Encoder auf einen Interrupt zu legen ist, dass man in der Interrupt Service Routine nicht nur einen Zähler inkrementieren kann, was ja auch der TX tut, sondern, dass man die Zeit zwischen zwei Flanken messen kann. D.h. man kann mit jeder Flanke die Geschwindigkeit des Motors bestimmen. Damit könnte man dann einen schicken Regler für die Motordrehzahl implementieren. Das ist mit dem TX kaum möglich, da man dort nur milli-sekündlich auf den Zähler zugreifen kann.
Ich habe das irgendwann einmal für den mbed LPC1768 Controller implementiert: http://developer.mbed.org/users/humlet/ ... coder.html
Der Encoder funktioniert übrigens wunderbar mit 3.3V. Beim Arduino sind es glaub ich 5V, auch kein Problem. Versorg den Encoder nur nicht mit 9V. Du hättest dann die 9V auch auf der Signalleitung. Die würden den GPIOs Deines Arduinos vermutlich schlecht bekommen. Ich musste allerdings noch einen 10K pullup-Widerstand zwischen der schwarzen Signalleitung und der 3.3V Encoder-Versorgung für ein sauberes Encoder-Signal am Controller-Eingang einfügen. Der interne Pullup des mbed Controllers ist vermutlich nicht ausreichend.

Beste Grüße,
Helmut

thkais
Beiträge: 381
Registriert: 31 Okt 2010, 21:45

Re: Encodermotoren mit dem Arduino auslesen

Beitrag von thkais » 07 Okt 2014, 22:07

Moin,

der Encoder-Ausgang ist ein "Open Collector", d.h. eine Transistor-Ausgangsstufe, die nur Masse durchschaltet (deshalb braucht man auch den Pull-Up).
Ergo: Spannungsversorgung des Encoders mit 9V kein Problem, aber den Pull-Up nur mit der Versorgungsspannung des µC verbinden (oder einen internen Pull-Up verwenden). 3,3V als Versorgungsspannung für den Encoder sind grenzwertig.
Hamlet: Ich glaube eher, dass der interne Pull-up nicht eingeschaltet ist. Was sagt das Datenblatt denn über den Wert des Pull-Up aus?
Gruß
Thomas

hamlet
Beiträge: 332
Registriert: 12 Jan 2011, 21:41

Re: Encodermotoren mit dem Arduino auslesen

Beitrag von hamlet » 08 Okt 2014, 19:26

Hallo Thomas,
Du hast absolut recht. Dank Dir für den Hinweis. Hab mir gerade nochmal die Signale angeschaut. Egal ob 9V, 5V oder 3.3V Encoder-Versorgung mit oder ohne externen Pullup, das Signal am Eingang ist immer ein schönes Rechteck. Hab den internen Pullup eingeschaltet gehabt. Ich habe keine Ahnung mehr, was ich damals gemessen habe.
@Ludwig: Ich hoffe, dass ich dir keinen Schreck eingejagt habe (-:
Beste Grüße,
Helmut

LM98
Beiträge: 10
Registriert: 15 Jul 2014, 17:32

Re: Encodermotoren mit dem Arduino auslesen

Beitrag von LM98 » 12 Okt 2014, 19:01

Hallo,

vielen Dank erstmal für eure Rückmeldungen!
ich hab mich mit dem Arduino schon längere Zeit beschäftigt, nur mit Attachinterrupt noch nicht.

Mal ne ganz dumme Frage:
- wenn ich das Encoderrückmeldekabel (schwarz) auf einen digitalen Eingang setze, dann müsste ich doch mit einem ganz einfachen Programm das mir nur HIGH oder LOW ausgibt über Serial.println 1 und 0 sehen wenn sich der Encoder Motor dreht oder?

Gruß,
Ludwig

LM98
Beiträge: 10
Registriert: 15 Jul 2014, 17:32

Re: Encodermotoren mit dem Arduino auslesen

Beitrag von LM98 » 22 Okt 2014, 14:10

Hallo nochmal,

wenns jemand interessiert, man muss mit einem Pull-Up Widerstand +9V und den digitalen Messeingang verbinden.
Vielen Dank für die Information an Knobloch!

Gruß,
Ludwig

thkais
Beiträge: 381
Registriert: 31 Okt 2010, 21:45

Re: Encodermotoren mit dem Arduino auslesen

Beitrag von thkais » 22 Okt 2014, 14:58

LM98 hat geschrieben:Hallo nochmal,

wenns jemand interessiert, man muss mit einem Pull-Up Widerstand +9V und den digitalen Messeingang verbinden.
Vielen Dank für die Information an Knobloch!

Gruß,
Ludwig
Mpin,
wirklich sicher, dass der AVR des Arduino an den Eingängen 9V verträgt? Bei Anschluss des Pull-Up an 9V geht einiges an Strom über die Clamp-Dioden, und das machen die nicht unbedingt lange mit.
Der Anschluss des Pull-Up muss an die VERSORGUNGSSPANNUNG DER ELEKTRONIK = 5V
Gruß
Thomas

Majus
Beiträge: 129
Registriert: 30 Nov 2010, 15:35
Wohnort: Deutschland

Re: Encodermotoren mit dem Arduino auslesen

Beitrag von Majus » 27 Okt 2014, 19:27

Hallo,

mal davon abgesehen, dass unter Umständen der Widerstand oder eine Diode durchbrennt, steht in Kapitel 32 des 448 Seiten starken Handbuchs des Atmega327P dass maximal 5.5 Volt erlaubt sind. Ich würde das Experiment nicht wagen, mehr Spannung anzulegen...

Gruß

Majus

lemkajen
Beiträge: 123
Registriert: 05 Sep 2011, 12:58
Wohnort: Rhede (NRW)

Re: Encodermotoren mit dem Arduino auslesen

Beitrag von lemkajen » 31 Okt 2014, 06:40

Moin, auch die Eingänge des Arduino vertrgen DEFINITIV nicht mehr als 5v! - Totalzerstörung kann die Folge sein!
Gruß
Jens
----
Jens Lemkamp

Majus
Beiträge: 129
Registriert: 30 Nov 2010, 15:35
Wohnort: Deutschland

Re: Encodermotoren mit dem Arduino auslesen

Beitrag von Majus » 31 Okt 2014, 16:32

Hallo,

der Atmega 328 P ist der Microcontroller, der sich auf dem Arduino Board (=Platine) befindet. Ich dachte, das wäre klar. ;)

Gruß
Majus

Antworten