Forum: Mikrocontroller und Digitale Elektronik Halloween - Spider Drop - Schaltung funktioniert nicht


von Michael (discoverer81)


Angehängte Dateien:

Lesenswert?

Hallo,

ich Hobbybastler, habe seit längerer Zeit ein Projekt offen, bei dem ich 
nun nicht weiterkomme.

Ziel war es, über den Arduino mit Hilfe eines PIR einen Motor 
anzusteuern, welcher eine Spinne abseilt, wartet und wieder hochzieht, 
bis die Spinne einen Schalter betätigt und den Motor ausstellt.

Eigentlich simple.
Nun habe ich versucht dies über Tinkerpad zu simulieren, scheitere aber.
Eventuell liegt es an den fehlenden Bauteil in Tinkercad.
Ich nutze einen DC Motor Driver MX1508 und in Tinkercad den 
komplizierteren Pololu Motor controller.

Ich bitte hier um Betrachtung meiner Schaltung speziell auf diesem 
Bereich.
Code und Schaltplan, wie auch Link zu Tinkercad sind dabei.

https://www.tinkercad.com/things/g8yfKmDvUAT-spider-drop-not-working
1
// constants won't change. They're used here to set pin numbers:
2
const int PIRpin = 2;
3
//const int LEDpin =1;  //digispark
4
const int LEDpin =13; //UNO
5
const int limitPin = 7;     // the number of the pushbutton pin
6
//const int motorFWD = 0; //digispark
7
// const int motorREV = 4; //digispark
8
9
const int motorFWD = 5; //UNO
10
const int motorREV = 6; //UNO
11
const int frightDelay = 10000; //delay between actions
12
13
const int acceleration = 25; //how fast the motor starts to int acceleration delay in ms 
14
15
// variables will change:
16
int limitState = 1;         // variable for reading the pushbutton status
17
int PIRstate = 0;
18
int MOTdirection = 1;
19
int PWMValue = 200; // starting PWM value
20
21
void setup() {  // initialize the LED pin as an output:
22
  pinMode(LEDpin, OUTPUT);
23
  pinMode(PIRpin, INPUT);
24
  pinMode(motorFWD, OUTPUT);
25
  pinMode(motorREV, OUTPUT);
26
  pinMode(limitPin, INPUT_PULLUP);
27
}
28
29
void loop() {
30
31
PIRstate = digitalRead(PIRpin);
32
  if (PIRstate == HIGH ) {    PWMValue=200;    digitalWrite(LEDpin, HIGH);    do    {      limitState = digitalRead(limitPin);       driveMotor();    } while (limitState != 0); //state is 1 button is not activated
33
      if (MOTdirection ==0){MOTdirection = 1;} else { MOTdirection = 0;}
34
35
stopMotor();
36
delay(500);
37
lockMotor();
38
delay(1000);
39
stopMotor();
40
delay(frightDelay);  } digitalWrite(LEDpin, LOW);
41
}
42
43
void driveMotor(){
44
45
if (PWMValue < 255){++PWMValue;}  delay(acceleration);
46
if (MOTdirection ==1)
47
{ analogWrite(motorFWD, PWMValue);
48
analogWrite(motorREV, 0);
49
}
50
else
51
{
52
analogWrite(motorFWD, 0);
53
analogWrite(motorREV, PWMValue);
54
}
55
}
56
57
void stopMotor(){
58
analogWrite(motorFWD, 0);
59
analogWrite(motorREV, 0);
60
}
61
62
void lockMotor(){
63
digitalWrite(motorFWD, 1);
64
digitalWrite(motorREV, 1);

Ich liefere gerne mehr Infos dazu wenn nötig.

Danke vorab.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Michael schrieb:
> scheitere aber.
Was erwartest du und was passiert stattdessen?

> Eventuell liegt es an den fehlenden Bauteil in Tinkercad.
> Ich nutze einen DC Motor Driver MX1508 und in Tinkercad den
> komplizierteren Pololu Motor controller.
Wenn du andere Bauteile verwendest, dann musst du sie logischerweise 
natürlich entsprechend dem Datenblatt auch anders ansteuern.

> Ich bitte hier um Betrachtung meiner Schaltung speziell auf diesem
> Bereich.
Wie wäre es, wenn du diese einfache Schaltung genauso einfach Schritt 
für Schritt und Komponente für Komponente in Betrieb nimmst?

Denn aus langjähriger Erfahrung kann ich sicher sagen: eine 
Inbetriebnahme nach dem Motto "bau alles zusammen und schalte es ein" 
funktioniert in 99,9% der Fälle nicht.

Ich erwarte, dass man diesen einfachen Aufbau mit konsequentem 
schrittweisen Vorgehen leicht an 1 Abend zum Laufen bekommt.

von Michael (discoverer81)


Lesenswert?

Hallo Lothar!


Lothar M. schrieb:
> Was erwartest du und was passiert stattdessen?

Meine Erwartung wäre, dass wenn der PIR aktiviert wird, der Motor 
gestartet wird.
Es passiert aber nichts.


Lothar M. schrieb:
> Wenn du andere Bauteile verwendest, dann musst du sie logischerweise
> natürlich entsprechend dem Datenblatt auch anders ansteuern.

Daher erwähne ich ja ausdrücklich diesen Teil. Ich finde den Controlelr 
komplizierter als meinen und finde auch in verschiedenen Beispielen 
immer unterschiedliche Arten der Verwendung.
Also auch mit Nachbauten, habe ich keinen Erfolg verbuchen können.

Und der Schritt für Schritt Teil ist logisch. Bis zu diesem Punkt 
funktionierte auch alles. Wobei der Code entsprechend auch geändert 
werden musste (sollte aber passen).

Lothar M. schrieb:
> Ich erwarte, dass man diesen einfachen Aufbau mit konsequentem
> schrittweisen Vorgehen leicht an 1 Abend zum Laufen bekommt.

Als Hobbybasteler mit zwei Stunden pro Woche Zeit bin ich froh, dass ich 
überhaupt dazulernen möchte. Und Programmierung und Mikroelektronik 
standen vorher nicht auf meinem Stundenplan.
Aber ja, ich hätte auch erwartet, dass an einem Abend zu schaffen.
Ich finde den Fehler aber nicht, grenze ihn aber auf diesem Controller 
ein.

Wobei, ich habe aus Frust das Teil auch schon zusammengelötet, leider 
mit dem gleichen Ergebnis.

Deshalb wende ich mich jetzt an das Forum und Experten, welche im 
Gegensatz zu mir, vermutlich den Fehler innerhalb zwei Sekunden gefunden 
haben werden.

Danke und Gruß

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Michael schrieb:
> Meine Erwartung wäre, dass wenn der PIR aktiviert wird, der Motor
> gestartet wird.
> Es passiert aber nichts.
Also erste Frage: gibt der PIR überhaupt ein Signal aus?
Welche Pegel kannst du an dessen Ausgang mit einem Multimeter im 
"inaktiven" und "aktiven" Zustand messen?

> Es passiert aber nichts.
Kannst du den Motor mit einem kleinen Dreizeiler z.B. in einer 
Dauerschleife [2s links, 2s rechts] (ganz ohne besonderen Schnickschnack 
wie "Beschleunigung") zum Laufen bringen? Wenn nein: warum nicht? Läuft 
der Motor, wenn du die nötigen logischen Pegel ganz ohne µC direkt mit 
Drähten an den Controller anlegst?

Michael schrieb:
> Ich nutze einen DC Motor Driver MX1508
Den simplen urzeitigen L298-Verschnitt hier?
- https://www.pololu.com/product/1381

> und in Tinkercad den komplizierteren Pololu Motor controller.
Den da?
- 
https://www.roboter-bausatz.de/p/mx1508-dc-motor-treiber-modul-ln298n-1.5a

Das ist wie wenn du eigentlich nur Roller fahren willst, dafür aber zum 
Test schon mal das Raumschiff klar machst...

> Ich finde den Controlelr komplizierter als meinen
Dann interessiert der dich doch auch nicht. Du willst ja deine 
Schaltung zum Laufen bekommen, nicht irgendeine andere mit irgendwelchen 
anderen Bauteilen.

Aus diesem Grund: vergiss die nutzlose Simulation.
Verwende deine täglichen 2 Stunden besser darauf, deinen konkreten 
Aufbau Schritt für Schritt in Betrieb zu nehmen:
1. Lass mit einem Dreizeiler-Programm  eine LED an einem Ausgang 
blinken.
2. Zeige mit einem neuen Dreizeiler auf dieser LED an, ob du den PIR 
richtig eingelesen bekommst.
3. Steuere mit einem weiteren Dreizeiler den Motor so an, dass er das 
macht, was du willst.
4. usw.
5. ...
19. usf.
20. Lass die Spider tanzen.

: Bearbeitet durch Moderator
von S. L. (sldt)


Angehängte Dateien:

Lesenswert?

...

von Peter D. (peda)


Lesenswert?

Michael schrieb:
> Ich liefere gerne mehr Infos dazu wenn nötig.

Verlinke mal die real verwendeten Teile (Motor, Treiber, Sensor) oder 
nenne deren exakte Bezeichnung, damit man das Datenblatt suchen kann.

Ob ein 9V Block einen Motor versorgen kann?

von Elias K. (elik)


Lesenswert?

Hi Michael,

wie Lothar schon sagt, probier doch mal die Funktionen jede für sich 
allein. Wenn die sicher funktionieren, dann macht es Sinn, sich über den 
Ablauf Gedanken zu machen. (In dem Ablauf ist definitiv was falsch. Es 
sei denn, du hast für den Anschlag oben UND unten einen Taster. Aber das 
kommt aus deiner Beschreibung so nicht raus.)

Hier mal ein paar Beispiele, die bei dir funktionieren sollten:

LED leuchtet, wenn PIR was detektiert/PIR Ausgang high ist.
1
void loop() {
2
  PIRstate = digitalRead(PIRpin);
3
  if (PIRstate == HIGH )
4
    digitalWrite(LEDpin, HIGH);
5
  else
6
    digitalWrite(LEDpin, LOW);
7
}

LED leuchtet, wenn Taster gedrückt ist.
1
void loop() {
2
  limitState = digitalRead(limitPin);
3
  if (limitState == LOW )
4
    digitalWrite(LEDpin, HIGH); // LED 
5
  else
6
    digitalWrite(LEDpin, LOW);
7
}

Motor geht durch alle 4 Betriebsmodi durch.
1
void loop() {
2
  // --- 1s forward rotation
3
  // driveMotor();
4
  // driveMotor manually to use digitalWrite instead of analogWrite
5
  digitalWrite(motorFWD, HIGH);
6
  digitalWrite(motorREV, LOW);
7
  delay(1000);
8
9
  // --- 1s reverse rotation
10
  digitalWrite(motorFWD, LOW);
11
  digitalWrite(motorREV, HIGH);
12
  delay(1000);
13
14
  // --- 1s lock motor
15
  lockMotor();
16
  delay(1000);
17
18
  // --- 1s lock motor
19
  stopMotor();
20
  delay(1000);
21
}

Motor läuft in unterschiedlichen Leistungen.
1
void loop() {
2
  // --- drive motor at 0% power
3
  PWMValue = 0;
4
  driveMotor();
5
  delay(1000);
6
  // --- drive motor at 25% power
7
  PWMValue = 63;
8
  driveMotor();
9
  delay(1000);
10
  // --- drive motor at 50% power
11
  PWMValue = 127;
12
  driveMotor();
13
  delay(1000);
14
  // --- drive motor at 75% power
15
  PWMValue = 191;
16
  driveMotor();
17
  delay(1000);
18
  // --- drive motor at 100% power
19
  PWMValue = 254;
20
  driveMotor();
21
  delay(1000);
22
}

Wenn irgendeins von den Beispielen nicht funktioniert, dann wäre das ein 
guter Ansatzpunkt für weitere Unterstützung. Happy Debugging! :-)

: Bearbeitet durch User
von Manfred P. (pruckelfred)


Lesenswert?

Lothar M. schrieb:
> Denn aus langjähriger Erfahrung kann ich sicher sagen: eine
> Inbetriebnahme nach dem Motto "bau alles zusammen und schalte es ein"
> funktioniert in 99,9% der Fälle nicht.

Über die Nachkommastelle können wir streiten, aber ich unterschreibe das 
gerne, geht überwiegend schief.

Elias K. schrieb:
> wie Lothar schon sagt, probier doch mal die Funktionen jede für sich
> allein. Wenn die sicher funktionieren, dann macht es Sinn, ...

Das füttert wieder meine Vorurteile: Anstatt selbst logisch zu agieren, 
lieber im Internet schreiben. Ich weiß garnicht, wie viele Stunden ich 
schon auf eigenen Fehlern gekaut habe, gerne Kleinigkeiten, die man 
einfach übersieht.

Elias K. schrieb:
> LED leuchtet, wenn PIR was detektiert/PIR Ausgang high ist.
1
void loop() {
2
  limitState = digitalRead(limitPin);
3
  if (limitState == LOW )
4
    digitalWrite(LEDpin, HIGH); // LED 
5
  else
6
    digitalWrite(LEDpin, LOW);
7
}

Das bekomme ich sogar in eine Zeile:
1
void loop() {
2
digitalWrite(LEDpin, digitalRead(limitPin));
3
}

Nachtrag : Bei Arduino hat man USB dran und den seriellen Monitor - da 
setze ich meist serial.print und gucke mir am Bildschirm an, was los 
ist.

: Bearbeitet durch User
von Michael (discoverer81)


Lesenswert?

Hallo und danke.

Ich habe das Ding inzwischen zusammengebastelt und diverse Codes 
versucht.

Die Komponenten funktionieren alle, Schaltung ist auch richtig (Hatte in 
Tinkercad den falschen Motor Driver).

Mittlerweile habe ich den Code umgeschrieben und unnötiges rausgenommen:
1
// constants won't change. They're used here to set pin numbers:
2
const int PIRpin = 2;
3
const int limitPin = 7;
4
const int motorFWD = 5;
5
const int motorREV = 6;
6
const int frightDelay = 10000;
7
const int acceleration = 25;
8
9
// variables will change:
10
int limitState = 1;
11
int PIRstate = 0;
12
int MOTdirection = 1;
13
int PWMValue = 200;
14
15
void setup() {
16
  pinMode(PIRpin, INPUT);
17
  pinMode(motorFWD, OUTPUT);
18
  pinMode(motorREV, OUTPUT);
19
  pinMode(limitPin, INPUT_PULLUP);
20
}
21
22
void loop() {
23
  PIRstate = digitalRead(PIRpin);
24
  if (PIRstate == HIGH ) {
25
    PWMValue=200;
26
    do {
27
      limitState = digitalRead(limitPin);
28
      driveMotor();
29
    } while (limitState != 0);
30
31
    if (MOTdirection ==0){
32
      MOTdirection = 1;
33
    } else {
34
      MOTdirection = 0;
35
    }
36
37
    stopMotor();
38
    delay(500);
39
    lockMotor();
40
    delay(1000);
41
    stopMotor();
42
    delay(frightDelay);
43
  }
44
}
45
46
void driveMotor(){
47
  if (PWMValue < 255){
48
    ++PWMValue;
49
  }  
50
  delay(acceleration);
51
52
  if (MOTdirection ==1){
53
    analogWrite(motorFWD, PWMValue);
54
    analogWrite(motorREV, 0);
55
  } else {
56
    analogWrite(motorFWD, 0);
57
    analogWrite(motorREV, PWMValue);
58
  }
59
}
60
61
void stopMotor(){
62
  analogWrite(motorFWD, 0);
63
  analogWrite(motorREV, 0);
64
}
65
66
void lockMotor(){
67
  digitalWrite(motorFWD, 1);
68
  digitalWrite(motorREV, 1);
69
}
Der Motor fährt vorwärts, bis der Knopf gedrückt wird.
Eigentlich sollte er aber erst vorwärts fahren, pausieren und nach einer 
kurzen Zeit rückwärts fahren, bis der Knopf gedrückt wird.
Der Motor selbst ist dazu in der Lage (bereits getestet durch umgekehrte 
Batteriekabel).

Was mir auch auffällt ist, dass die Geschwindigkeit des 
rückwärtsdrehenden Motors leider nicht langsamer ist.
Das langsame Drehen des Motors habe ich noch gar nicht hinbekommen (z.B. 
PBW auf 50).

Seht ihr den Fehler?

Danke und lieben Gruß

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Michael schrieb:
> Mittlerweile habe ich den Code umgeschrieben und unnötiges rausgenommen
Ich hatte nicht umsonst gesagt: nimm jede Komponente einzeln für sich in 
Betrieb. Lies einfach nochmal meinen Post und melde dich, wenn du darin 
etwas nicht verstanden hast.

> Der Motor selbst ist dazu in der Lage (bereits getestet durch umgekehrte
> Batteriekabel).
Dann steuere den Motorcontroller erst mal ganz ohne µC mit 
Drahtverbindungen nach high und low so an, dass der Motor mal in die 
eine und in die andere Richtung fährt.

Dann ersetzt du diese Drahtverbindungen durch µC-Pins und steuerst den 
µC mit einem Dreizeiler lass so an, dass er statische high und low Pegel 
ausgibt und der Motor in die Richtung läuft, die du erwartest.

Und dann schreib einen Dreizeiler, mit dem du per PWM-Wert die 
Motorgeschwindigkeit einstellen kannst.

Und dann schreib einen weiteren Dreizeiler, mit dem der Motor mit 
unterschiedlichen Geschwindigkeiten periodisch vor und zurück läuft.

Und dann kläre noch, was denn der Unterschied zwischen stopMotor() und 
lockMotor() ist. Und vor allem: ob du diesen Unterschied überhaupt 
brauchst.

> Eigentlich sollte er aber ...
Mein Vorschlag: lies dich mal zum Thema FSM (Zustandsautomaten) ein. Das 
ist wesentlich weniger wild als es sich anhört, aber du bekommst damit 
die blockierenden delay() raus. Denn im Grunde ist ein delay() einfach 
nur aktive Rechenzeitverschwendung, weil der Prozessor da "nebenher" 
nichts anderes machen kann.
Kurz gesagt: wenn ich irgendwo im Ablauf ein delay() sehe, dann sehe ich 
einen Programmfehler.

Und wie gesagt:
1
  delay(acceleration);
lass den Käse mit der Beschleunigung erst mal weg. Besonders, wenn da 
schon wieder ein delay() im Spiel ist!

Ich würde daher sowas ansetzen:
1
:
2
int Schritt = 0; // Ablaufschritte / 0 = warte auf PIR
3
int Startzeit, Jetzt;
4
:
5
:
6
void loop() {
7
  Jetzt = millis();
8
  switch (Schritt )
9
     case 0: // warte auf PIR und fahre dann vorwärts
10
             if (digitalRead(PIRpin)) {
11
                PWMValue=200;
12
                driveMotor(1);  // vorwärts
13
                Startzeit = Jetzt;
14
                Schritt = 1;
15
             }
16
             break;
17
18
     case 1: // fahre 500 ms und halte dann an
19
             if (Jetzt-Startzeit > 500) {
20
                stopMotor();
21
                Startzeit = Jetzt;
22
                Schritt = 2;
23
             }
24
             break;
25
26
     case 2: // warte 500 ms und fahre dann rückwärts
27
             if (Jetzt-Startzeit > 500) {
28
                PWMValue=50;
29
                driveMotor(0);  // rückwärts
30
                Startzeit = Jetzt;
31
                Schritt = 3;
32
             }
33
             break;
34
35
     case 3: // rückwärts bis Endschalter belegt, dann anhalten und von vorn
36
             if (digitalRead(limitPin)) {
37
                stopMotor();
38
                Schritt = 0;
39
             }
40
             break;
41
42
     default:  Schritt = 0;
43
             break;
44
  }
45
}
46
47
void driveMotor(richtung){
48
  if (richtung){
49
    analogWrite(motorFWD, PWMValue);
50
    analogWrite(motorREV, 0);
51
  } else {
52
    analogWrite(motorFWD, 0);
53
    analogWrite(motorREV, PWMValue);
54
  }
55
}

: Bearbeitet durch Moderator
von Michael (discoverer81)


Lesenswert?

Hallo.

Danke für die Hilfe.
Leider haben mich die Code-Erweiterungen eher neuen Problemen ausgesetzt 
oder generell überfordert ;-) .

Habe nochmal neu angefangen (versucht "delay" zu vermeiden) und es 
funktioniert auch fast wie gewünscht.
1
const int pirPin = 2;     // PIR sensor pin
2
const int switchPin = 7;  // Switch pin
3
const int motorPin1 = 5;  // Motor driver pin 1
4
const int motorPin2 = 6;  // Motor driver pin 2
5
const int forwardSpeed = 255;  // Motor speed during forward movement (range: 0-255)
6
const int reverseSpeed = 30;   // Motor speed during reverse movement (range: 0-255)
7
const int stopDelay = 3000;    // Delay in ms after motor stops
8
9
void setup() {
10
  pinMode(pirPin, INPUT);
11
  pinMode(switchPin, INPUT_PULLUP);
12
  pinMode(motorPin1, OUTPUT);
13
  pinMode(motorPin2, OUTPUT);
14
  Serial.begin(9600);
15
}
16
17
void loop() {
18
  // Wait for PIR sensor to detect movement
19
  while (digitalRead(pirPin) == LOW) {
20
    delay(1000);
21
  }
22
  
23
  // Wait 30 seconds before detecting movement again
24
  delay(30000);
25
26
  // Start moving motor forward at full speed
27
  analogWrite(motorPin1, forwardSpeed);
28
  analogWrite(motorPin2, 0);
29
  delay(3000);
30
31
  // Stop motor and wait for 3 seconds
32
  analogWrite(motorPin1, 0);
33
  analogWrite(motorPin2, 0);
34
  delay(stopDelay);
35
36
  // Start moving motor backwards slowly
37
  analogWrite(motorPin1, 0);
38
  analogWrite(motorPin2, reverseSpeed);
39
40
  // Wait for switch to be pressed or 3 seconds to elapse
41
  unsigned long startTime = millis();
42
  while (digitalRead(switchPin) == HIGH && (millis() - startTime < 3000)) {
43
    delay(100);
44
  }
45
46
  // Stop motor
47
  analogWrite(motorPin1, 0);
48
  analogWrite(motorPin2, 0);
49
}

ABER, die Geschwindigkeit beim Rückwärtsfahren ist zu schnell und 
jegliche Änderungen unter 50 bringen den Motor dazu hohe Töne abzugeben 
oder sich gar nicht mehr zu bewegen.

Meine Frage also nun:
Wie lasse ich den Motor langsam rückwärts fahren ohne diese hohen Töne?

Danke und Gruß

Und bitte keine neuen Code-Teile mehr besser komplett.
ich blicke schon bald echt nicht mehr durch ;-)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.