Hallo,
das ist mein erster Beitrag, deshalb Gnade, falls er nicht den Richtlinien entspricht.
Ich versuche eine Modellseilbahnsteuererung mit Arduino Nano zu erstellen:
- In der Talstation befinden sich 2 Ultraschallsensoren, die die Entfernung der Gondeln messen.
- Beim Einschalten läuft sie mit voller Geschwindigkeit los.
- Nähert sich eine Gondel der Talstation, wird die Geschwindigkeit langsam reduziert.
- Ist sie in der Talstation, bleibt die Seilbahn stehen, wartet 15 Sekunden und dann läuft der Motor in die andere Richtung langsam an, bis er die volle Geschwindigkeit erreicht hat.
Das funktioniert alles,wenn ich den Arduino über USB an den PC anschließe. Wenn ich ihn über ein Netzteil mit 12 V, über das auch der Motor läuft, anschließe, läuft der Motor immer mit voller Geschwindigkeit und wechselt dann irgendwann - nicht nachvollziehbar - die Richtung - wieder mit voller Geschwindigkeit.
Hier ist mein Schaltplan (etwas unprofessionell; wenn USB angeschlossen ist sind die beiden 12V Verbindungen VIN und GND am Arduino nicht verbunden):

Und mein Sketch:
/* Steuerung der Seilbahn
* - Für jede Kabine der Seilbahn gibt es einen Ultraschall-Sensor, der den
* Abstand der Kabine zum Sensor misst. Nähert sich eine Kabine bis auf
* SLOW_DISTANCE wird die Geschwindigkeit verringert bis die Kabine
* STOP_DISTANCE erreicht und dann steht.
* - Dann bleibt die Seilbahn STOP_TIME lang stehen.
* - Anschließend fährt die Seilbahn langsam an, bis sie SLOW_DISTANCE ereicht
* und fährt dann mit voller Geschwindigkeit weiter.
*
* Für die Abstandsmessung wird die Bibliothek "NewPing" verwendet, da
* sie einige Vorteile gegenüber der Standardbibliothek hat.
*
* Belegung Arduino:
* D1
* D2
* D3
* D4
* D5 Trigger-Pin linker Ultraschallsensor
* D6 Echo-Pin linker Ultraschallsensor
* D7 Trigger-Pin rechter Ultraschallsensor
* D8 Echo-Pin rechter Ultraschallsensor
* D9 Motortreiber Pin 4
* D10 Motortreiber Pin 5
* D11 Motortreiber Pin 6
* D12
* D13
* Belegung Motortreiber:
* ___
* | |
* ---
* ___ Motor
* | |
* ---
* _______
* |1|2|3| |4|5|6|
* -------
*
* 1 +12V (in)
* 2 GND
* 3 +5V (out)
* 4 Arduino D9
* 5 Arduino D10
* 6 Arduino D11
*/
#include <NewPing.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Defines
#define DEBUG // Steuerung der Debug-Ausgabe
#define MAX_DISTANCE 70 // Maximaler Abstand in cm, der gemessen werden
// soll; größere Abstände werden nicht gemessen
#define SLOW_DISTANCE 50 // Abstand in cm, bei dem die Geschwindigkeit
// reduziert wird
#define STOP_DISTANCE 10 // Abstand in cm, bei dem gestoppt wird
#define STOP_TIME 15000 // Stopzeit in ms in der Station
#define MOTOR_RECHTS false // Variable für die Motorrichtung
#define MOTOR_LINKS true // Variable für die Motorrichtung
#define NEXT_PING 100 // Delay in ms nächste distanzabfrage (>= 30!)
// Vereinbarungen für den Motor
#define MIN_MOTOR_SPEED 50
#define MAX_MOTOR_SPANNUNG 10.0
#define MAX_ARD_SPANNUNG 10.0
#define MAX_ARD_SPEED 255
// Vereinbarungen für den Motortreiber
// Pin am Motortreiber | Pin am Arduino
// 6 | 11
// 5 | 10
// 4 | 9
#define MOTOR_PWM 9
#define MOTOR_IN1 10
#define MOTOR_IN2 11
// Die aktuellen Modi, in der sich die Seilbahn befinden kann
#define MODE_STOP 0
#define MODE_SLOWDOWN 1
#define MODE_ACCELERATE 2
#define MODE_MAX 3
// Linker Ultraschallsensor (in Fahrtrichtung)
#define TRIGGER_PIN_1 5
#define ECHO_PIN_1 6
NewPing sensor1 (TRIGGER_PIN_1, ECHO_PIN_1, MAX_DISTANCE);
// Rechter Ultraschallsensor (in Fahrtrichtung)
#define TRIGGER_PIN_2 7
#define ECHO_PIN_2 8
NewPing sensor2 (TRIGGER_PIN_2, ECHO_PIN_2, MAX_DISTANCE);
// Globale Variable
float distanceLinks, // Gemessener Abstand links
distanceRechts, // Gemessener Abstand rechts
currentDistance, // Aktueller Abstand
currentMotorSpeed; // Aktuelle Motorgeschwindigkeit
boolean currentMotorDirection; // Aktuelle Motordrehrichtung
unsigned long myTimer = 0; // Timer-Variable (nicht mit delay)
int speed,
maxMotorSpeed,
currentMode;
// --------------------------------------------
void setup()
{
#ifdef DEBUG
Serial.begin(9600);
#endif
// Verbindung Motor
pinMode (MOTOR_IN1, OUTPUT);
pinMode (MOTOR_IN2, OUTPUT);
pinMode (MOTOR_PWM, OUTPUT);
// Motorspannung <= MAX_MOTOR_SPANNUNG, aber Arduino Maximalspannung = ARD_MAX_SPANNUNG5
maxMotorSpeed = MAX_ARD_SPEED * MAX_MOTOR_SPANNUNG / MAX_ARD_SPANNUNG;
// Seilbahn fährt am Anfang immer mit maximaler Geschwindigkeit los
// Drehrichtung ist links
currentMode = MODE_MAX;
currentMotorSpeed = maxMotorSpeed;
currentMotorDirection = MOTOR_LINKS;
}
// --------------------------------------------
void loop()
{
// Abstände messen
distanceLinks = sensor1.ping_cm();
distanceRechts = sensor2.ping_cm();
#ifdef DEBUG
if (currentMode != MODE_STOP)
{
Serial.print("distanceLinks: ");
Serial.print(distanceLinks);
Serial.print("cm, distanceRechts: ");
Serial.print(distanceRechts);
Serial.println("cm");
}
#endif
// Aktion abhängig vom Modus
switch (currentMode)
{
case MODE_STOP:
modeStop ();
break;
case MODE_SLOWDOWN:
modeSlowDown ();
break;
case MODE_ACCELERATE:
modeAccelerate ();
break;
case MODE_MAX:
modeMax ();
break;
}
// Warte bis zur nächsten Distanzabfrage
delay (NEXT_PING);
}
// --------------------------------------------
void setRotationDirection ()
{
if ( currentMotorDirection )
{
// Drehrichtung links
digitalWrite (MOTOR_IN1, HIGH);
digitalWrite (MOTOR_IN2, LOW);
}
else
{
// Drehrichtung rechts
digitalWrite (MOTOR_IN1, LOW);
digitalWrite (MOTOR_IN2, HIGH);
}
}
//---------------------------------------------
int calculateSpeed ()
{
speed = MIN_MOTOR_SPEED + (maxMotorSpeed - MIN_MOTOR_SPEED) *
(currentDistance - STOP_DISTANCE) /
(SLOW_DISTANCE - STOP_DISTANCE);
speed = max (speed, MIN_MOTOR_SPEED);
return speed;
}
//---------------------------------------------
void modeStop ()
{
#ifdef DEBUG
Serial.println("modeStop ");
#endif
// Seilbahn wird gestoppt
currentMotorSpeed = 0;
analogWrite (MOTOR_PWM, currentMotorSpeed);
// Seilbahn wartet die vorgegebene Zeit.
// Aber die Motorgeschwindigkeit = 0 muss gesetzt werden. Deshalb
// funktioniert "delay" nicht und ein Timer wird verwendet.
if ( millis() > (myTimer + STOP_TIME ) )
{
// Stopzeit ist erreicht
myTimer = millis();
// Dann wird beschleunigt
currentMode = MODE_ACCELERATE;
setRotationDirection ();
currentMotorSpeed = MIN_MOTOR_SPEED;
analogWrite (MOTOR_PWM, maxMotorSpeed);
}
}
//---------------------------------------------
void modeSlowDown ()
{
// Prüfe, ob die STOP_DISTANCE erreicht ist
if ( ( currentMotorDirection && (distanceLinks > 0) &&
(distanceLinks <= STOP_DISTANCE )) ||
( !currentMotorDirection && (distanceRechts > 0) &&
(distanceRechts <= STOP_DISTANCE )) )
{
// Seilbahn wird gestoppt
currentMode = MODE_STOP;
// Timeranfangszeit wird gesetzt
myTimer = millis ();
// Motor-Drehrichtung wird umgekehrt
if ( currentMotorDirection == MOTOR_RECHTS )
{
currentMotorDirection = MOTOR_LINKS;
}
else
{
currentMotorDirection = MOTOR_RECHTS;
}
}
else
{
// Seilbahn wird verlangsamt
// Aktueller Abstand
if ( currentMotorDirection == MOTOR_RECHTS )
{
currentDistance = distanceRechts;
}
else
{
currentDistance = distanceLinks;
}
// Fehlmessungen werden nicht berücksichtigt
if ( currentDistance == 0 )
{
return;
}
// Berechne die neue Geschwindigkeit
speed = calculateSpeed ();
currentMotorSpeed = min (currentMotorSpeed, speed);
#ifdef DEBUG
Serial.print("modeSlowDown ");
Serial.print(" currentMotorDirection: ");
Serial.print(currentMotorDirection);
Serial.print(" currentMotorSpeed: ");
Serial.print(currentMotorSpeed);
Serial.print(" currentDistance: ");
Serial.println(currentDistance);
#endif
// Setze Drehrichtung und Geschwindigkeit
setRotationDirection ();
analogWrite (MOTOR_PWM, currentMotorSpeed);
}
}
//---------------------------------------------
void modeAccelerate ()
{
// Prüfe, ob die SLOW_DISTANCE erreicht ist
if ( ( currentMotorDirection && (distanceRechts > 0) &&
(distanceRechts >= SLOW_DISTANCE )) ||
( !currentMotorDirection && (distanceLinks > 0) &&
(distanceLinks >= SLOW_DISTANCE )) )
{
// Seilbahn fährt mit Maximal-Geschwindigkeit weiter
currentMode = MODE_MAX;
currentMotorSpeed = maxMotorSpeed;
}
else
{
// Seilbahn wird beschleunigt
// Aktueller Abstand
if ( currentMotorDirection == MOTOR_LINKS )
{
currentDistance = distanceRechts;
}
else
{
currentDistance = distanceLinks;
}
// Berechne die neue Geschwindigkeit
speed = calculateSpeed ();
currentMotorSpeed = max (currentMotorSpeed, speed);
#ifdef DEBUG
Serial.print("modeAccelerate ");
Serial.print(" currentMotorDirection: ");
Serial.print(currentMotorDirection);
Serial.print(" currentMotorSpeed: ");
Serial.print(currentMotorSpeed);
Serial.print(" currentDistance: ");
Serial.println(currentDistance);
#endif
// Setze Drehrichtung und Geschwindikeit
setRotationDirection ();
analogWrite (MOTOR_PWM, currentMotorSpeed);
}
}
//---------------------------------------------
void modeMax ()
{
#ifdef DEBUG
Serial.print("modeMax: ");
Serial.println(currentMotorSpeed);
#endif
// Setze Drehrichtung und Geschwindigkeit
setRotationDirection ();
analogWrite (MOTOR_PWM, currentMotorSpeed);
// Prüfe, ob ein Grenzabstand schon erreicht ist
if ( ( currentMotorDirection && (distanceLinks > 0) &&
(distanceLinks <= SLOW_DISTANCE )) ||
( !currentMotorDirection && (distanceRechts > 0) &&
(distanceRechts <= SLOW_DISTANCE )) )
{
currentMode = MODE_SLOWDOWN;
}
}
Wo liegt mein Fehler?
