Halloween - Spider Drop - Schaltung funktioniert nicht

OP #7390199
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.

Angehängte Dateien:
Moderator (Firma: Titel) Persönliche Seite #7390204
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.

OP #7390215
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ß

Moderator (Firma: Titel) Persönliche Seite #7390376
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?

und in Tinkercad den komplizierteren Pololu Motor controller.

Den da?

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. ...
  6. usf.
  7. Lass die Spider tanzen.
#7390698
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! :-)

#7390710
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.

OP #7395272
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ß

Moderator (Firma: Titel) Persönliche Seite #7395457
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
}
OP #7399191
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 ;-)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren