Problem: Steuerung eines Schrittmotors mit Lichtsensor + Taster

Hallo Zusammen,
ich bin grade dabei einen Schrittmotor mit Hilfe eines Lichtsensors und eines Tasters anzusteuern.
Nachdem ich das Internet auf den Kopf gestellt habe bin ich jetzt an meine Grenzen gekommen und hoffe dass ihr mir weiter helfen könnt.

Mein Ziel ist es die unten im Code beschriebenen Aktionen durchzuführen. Leider dreht der Schrittmotor momentan fröhlich vor sich hin und reagiert weder auf den Taster noch auf Schwellwert des Potis. Während der Schrittmotor dreht reagiert außerdem die LCD Anzeige nicht mehr…

Wäre cool wenn mir jmd. helfen könnte, habe grad ein paar Knoten zu viel im Hirn! :confused:

Gruß, Fabian

int Lichtstaerke;
int Lichtstaerkestore;
int LEDPin = 13;
int Potiwert;
int Potistore;

int Pin1 = 7;
int Pin2 = 8;
int Pin3 = 9;
int Pin4 = 10;

const int Taster1 = 5;
int Taster1State = 0; // Variable zum Erkennen des TasterStatus

#include <LiquidCrystal.h>
const int rs = 12, en = 11, d4 = 6, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

#include <Stepper.h>
const int SPR = 2048;
Stepper Motor(SPR, 7, 8, 9, 10);

/////////////////////////////////////////////////
void setup() {
Serial.begin(9600);

// LED
pinMode(LEDPin,OUTPUT);
 
// Motor
pinMode(Pin1, OUTPUT);
pinMode(Pin2, OUTPUT);
pinMode(Pin3, OUTPUT);
pinMode(Pin4, OUTPUT);

Motor.setSpeed(10); 

// LCD
lcd.begin(16, 2);
lcd.print("Lichtstaerke");
lcd.setCursor(0,1);
lcd.print("Schwellwert");

// Taster
pinMode(Taster1,INPUT);
}

/////////////////////////////////////////////////
void loop() {
  
  Potiwert = analogRead(1) / 10;
  Serial.println(Potiwert);

  Lichtstaerke = analogRead(0) / 20;  
  Serial.println(Lichtstaerke);

  Taster1State = digitalRead(Taster1);

////// DARSTELLUNG LCD //////////////////////// 
  lcd.setCursor(13,0);
  lcd.leftToRight();
  lcd.print(Lichtstaerke,DEC);
  
  if (Lichtstaerkestore != Lichtstaerke) 
  {
    lcd.setCursor(13,0); lcd.print(Lichtstaerke); // Variable ausgeben
    if (Lichtstaerke < 10) lcd.print("  ");      // 2 Leerzeichen
    else if (Lichtstaerke < 100) lcd.print(" "); // 1 Leerzeichen
  }
  Lichtstaerkestore = Lichtstaerke;
  
  delay(300);
  lcd.setCursor(13,1);
  lcd.leftToRight();
  lcd.print(Potiwert,DEC);

  if (Potistore != Potiwert) 
  {
    lcd.setCursor(13,1); lcd.print(Potiwert); // Variable ausgeben
    if (Potiwert < 10) lcd.print("  ");      // 2 Leerzeichen
    else if (Potiwert < 100) lcd.print(" "); // 1 Leerzeichen
  }
  Potistore = Potiwert;
////// Ende DARSTELLUNG LCD /////////////////////// 

/// Ab hier fangen meine Probleme an:
/// Steuerung des Motors / LED in Abhängikeit zu dem Lichtsensor + Taster

  if (Lichtstaerke <= Potiwert) /// Sobald der Wert der Lichtstärke kleiner/gleich des Potiwertes ist...
  {
  digitalWrite(LEDPin,HIGH);    /// ...geht die LED an
  Motor.step(2048);             /// ... & der Motor beginnt an zu drehen. (Umdrehungen in vorerst in Steps angegeben)
    if (Taster1State = HIGH)    /// Wenn der Taster gedrückt wird...
    { 
    Motor.step(0);              /// ... soll der Motor stoppen.(LED bleibt an)
    }
  }

  if (Lichtstaerke >= Potiwert) /// Sobald der Wert der Lichtstärke größer/gleich des Potiwertes ist...
  {
  digitalWrite(LEDPin,LOW);     /// ...geht die LED aus
  Motor.step(2048);             /// ... & der Motor beginnt an zu drehen. (Umdrehungen in vorerst in Steps angegeben)
    if (Taster1State = HIGH)    /// Wenn der Taster gedrückt wird...
    { 
    Motor.step(0);              /// ... soll der Motor stoppen.(LED bleibt aus)
    }  
  }
}

Vlt. trägt es zu Verständnis bei, wenn ich kurz die Anwendung beschreibe:

Tür Steuerung eines Hühnerstalls.

Wenn es dunkel wird soll sich die Klappe schließen.
(Die Klappe ist angetrieben durch den Schrittmotor, sobald die Klappe zu ist wird ein Taster aktiviert und der Schrittmotor ausgeschaltet.)

Wenn es hell wird soll sich die Klappe öffnen.
(Sobald die Klappe offen ist wird ein Taster aktiviert und der Schrittmotor ausgeschaltet.)

Der Schwellwert soll über einen Poti eingestellt werden.

Die Stepper-Lib blockiert das Programm solange, wie der Motor läuft. In der Zeit werden keine anderen Aktionen ausgeführt. Während delay() übrigens auch nicht.
Während dieser Zeit wird auch kein Taster gelesen.

Probiere mal lieber die Lib AccelStepper, die blockiert nicht.

Gruß Tommy

Danke! Werde ich jetzt ausprobieren...

Gruß, Fabian

Habe jetzt die AccelStepper Lib in Gebrauch. Das LCD Display ist nicht mehr eingefroren und der Sensor arbeitet auch wieder so wie er soll. :slight_smile:
Leider bewegt sich der Motor nicht mehr… :disappointed_relieved:

int Lichtstaerke;
int Lichtstaerkestore;
int LEDPin = 13;
int Potiwert;
int Potistore;

int Pin1 = 7;
int Pin2 = 8;
int Pin3 = 9;
int Pin4 = 10;

const int Taster1 = 5;
int Taster1State = 0; // Variable zum Erkennen des TasterStatus

#include <LiquidCrystal.h>
const int rs = 12, en = 11, d4 = 6, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

#include <AccelStepper.h>
AccelStepper Motor(AccelStepper::FULL4WIRE, 7, 8, 9, 10);

/////////////////////////////////////////////////
void setup() {
Serial.begin(9600);

// LED
pinMode(LEDPin,OUTPUT);
 
// Motor
pinMode(Pin1, OUTPUT);
pinMode(Pin2, OUTPUT);
pinMode(Pin3, OUTPUT);
pinMode(Pin4, OUTPUT);



Motor.setSpeed(15);

// LCD
lcd.begin(16, 2);
lcd.print("Lichtstaerke");
lcd.setCursor(0,1);
lcd.print("Schwellwert");

// Taster
pinMode(Taster1,INPUT);
}

/////////////////////////////////////////////////
void loop() {
  
  Potiwert = analogRead(1) / 10;
  Serial.println(Potiwert);

  Lichtstaerke = analogRead(0) / 20;  
  Serial.println(Lichtstaerke);

  Taster1State = digitalRead(Taster1);

////// DARSTELLUNG LCD //////////////////////// 
  lcd.setCursor(13,0);
  lcd.leftToRight();
  lcd.print(Lichtstaerke,DEC);
  
  if (Lichtstaerkestore != Lichtstaerke) 
  {
    lcd.setCursor(13,0); lcd.print(Lichtstaerke); // Variable ausgeben
    if (Lichtstaerke < 10) lcd.print("  ");      // 2 Leerzeichen
    else if (Lichtstaerke < 100) lcd.print(" "); // 1 Leerzeichen
  }
  Lichtstaerkestore = Lichtstaerke;
  
  delay(300);
  lcd.setCursor(13,1);
  lcd.leftToRight();
  lcd.print(Potiwert,DEC);

  if (Potistore != Potiwert) 
  {
    lcd.setCursor(13,1); lcd.print(Potiwert); // Variable ausgeben
    if (Potiwert < 10) lcd.print("  ");      // 2 Leerzeichen
    else if (Potiwert < 100) lcd.print(" "); // 1 Leerzeichen
  }
  Potistore = Potiwert;
////// Ende DARSTELLUNG LCD /////////////////////// 

/// Ab hier fangen meine Probleme an:
/// Steuerung des Motors / LED in Abhängikeit zu dem Lichtsensor + Taster

  if (Lichtstaerke <= Potiwert) /// Sobald der Wert der Lichtstärke kleiner/gleich des Potiwertes ist...
  {
  digitalWrite(LEDPin,HIGH);    /// ...geht die LED an
  Motor.run();             /// ... & der Motor beginnt an zu drehen. (Umdrehungen in vorerst in Steps angegeben)
    if (Taster1State = HIGH)    /// Wenn der Taster gedrückt wird...
    { 
    Motor.stop();              /// ... soll der Motor stoppen.(LED bleibt an)
    }
  }

  if (Lichtstaerke >= Potiwert) /// Sobald der Wert der Lichtstärke größer/gleich des Potiwertes ist...
  {
  digitalWrite(LEDPin,LOW);     /// ...geht die LED aus
  Motor.run();             /// ... & der Motor beginnt an zu drehen. (Umdrehungen in vorerst in Steps angegeben)
    if (Taster1State = HIGH)    /// Wenn der Taster gedrückt wird...
    { 
    Motor.stop();              /// ... soll der Motor stoppen.(LED bleibt aus)
    }  
  }
}

Da könnten evtl. Infos zum Motor weiter helfen. Evtl. braucht der was anderes als FULL4WIRE.

Übrigens: Diskussionen zu Hühnerklappensteuerungen gib es hier im Forum schon.

Gruß Tommy

Ich versuche mir mit diesem Projekt Arduino beizubringen, daher habe ich mir die bereits erarbeiteten Lösungen für Hühnerklappen noch nicht näher angeschaut. Ich versuche das ganze Schritt für Schritt zu verstehen und nicht einfach nach zu basteln...

Auf dem Motor steht Step Motor 28BY-48 5V DC 61018209 (Der soll aber später ausgetauscht werden, da zu schwach)

FabianW:
Auf dem Motor steht Step Motor 28BY-48

Das ist ein unipolarer Motor, vertausche mal die Anschlüsse an Pin 8 und 9.

agmue:
Das ist ein unipolarer, vertausche mal die Anschlüsse an Pin 8 und 9.

leider keine Veränderung...

Was tut der Motor zusammen mit einem Testsketch der Bibliothek, beispielsweise Random?

agmue:
Was tut der Motor zusammen mit einem Testsketch der Bibliothek, beispielsweise Random?

Er dreht minimal sobald die Impulse schnell hintereinander kommen. Die LED des Treibers leuchten immer in der Reihenfolge ACBD

Tausche ich die Pins 8 und 9, so wie du vorgeschlagen hast, dreht der Motor vor und zurück (zwar minimal aber er macht es) Eine Reihenfolge der LED's kann ich nicht erkennen, es wechseln zumindest immer 2 auf einmal.

Mir erscheint diese Variante richtiger als die zuvor...
in meinem Haupt sketch klappt es leider dennoch nicht... Hab ich vlt einen Fehler in der If Funktion?

Hi

Der unipolare Schrittmotor möchte, wenn ich mich recht entsinne, in folgender Reihenfolge haben:
0101
0110
1010
1001

Entspricht aber halbwegs Deinem oben genanntem ACBD.
Die linken zwei Bits sind für das eine Spulenpaar, somit die Anderen für das andere Paar.

Würde Das ganz ohne Lib im 100ms-Takt ausgeben und erst Mal schauen, daß der Stepper zum Drehen kommt.
Dir sollte aber jetzt schon klar sein, daß ein 'richtiger' Stepper mit diesem Code nicht laufen wird.
Vll. kannst Du den Stepper ja noch weiter untersetzen - dann braucht die Hühnerklappe halt etwas länger, bis Diese oben oder unten angekommen ist - wobei diese Motörchen eben keine Kraftprotze sind (habe davon auch ein halbes Dutzend hier rumfliegen, aber auch erst zwei Mal mit 'gespielt' - mindestens einen Motor 'gehackt', also rote Draht raus und die Leiterbahn-Verbindung zwischen den Mittelanzapfungen aufgetrennt)

MfG

FabianW:
(zwar minimal aber er macht es)

Das ist gut! Du hast einen Motor, der wegen des Getriebes etwas andere Werte benötigt. Versuche mal dies:

#include <AccelStepper.h>

// Define a stepper and the pins it will use
AccelStepper stepper(AccelStepper::FULL4WIRE, 7, 8, 9, 10);

void setup()
{
    stepper.setMaxSpeed(1000);
    stepper.setAcceleration(1000);
}

void loop()
{
  if (stepper.distanceToGo() == 0)
  {
    // Random change to speed, position and acceleration
    // Make sure we dont get 0 speed or accelerations
    delay(1000);
    stepper.move(2048);
  }
  stepper.run();
}

run() muß durchlaufen werden, wenn eine Bewegung erfolgen soll
move (long relative) Relative Bewegung ab der aktuellen Position
moveTo (long absolute) Bewegung zu einer absoluten Position.

Nun sollte der Motor eine Umdreheung machen, dann Pause, dann wieder eine Umdreheung usw.

Tut er das?

Danke für euer Feedback! Für heute ist Schluss. Ich werde es morgen Abend mal testen.

Wenn das Testprogramm aus #13 läuft, kannst Du mit dem hier weitermachen:

const byte LEDPin = 13;
const int HYSTERESE = 5;
int Lichtstaerke;
int Potiwert;
const uint32_t anzeigeIntervall = 200;
uint32_t aktMillis, anzeigeMillis;

#include <AccelStepper.h>
//                      Steuerplatine    IN 1  3  2  4
AccelStepper Motor(AccelStepper::FULL4WIRE, 7, 8, 9, 10);

void setup() {
  Serial.begin(9600);

  pinMode(LEDPin, OUTPUT);

  Motor.setMaxSpeed(1000);
  Motor.setAcceleration(1000);
}

void loop() {
  aktMillis = millis();
  if (Motor.distanceToGo() == 0)
  {
    if (aktMillis - anzeigeMillis >= anzeigeIntervall)
    {
      anzeigeMillis = aktMillis;
      //Potiwert = analogRead(A1) / 10;
      Potiwert = 50;
      Serial.println(Potiwert);

      Lichtstaerke = analogRead(A0) / 10;
      Serial.println(Lichtstaerke);
    }
    /// Steuerung des Motors / LED in Abhängikeit zu dem Lichtsensor + Taster

    if (Lichtstaerke <= Potiwert - HYSTERESE) /// Sobald der Wert der Lichtstärke kleiner/gleich des Potiwertes ist...
    {
      digitalWrite(LEDPin, HIGH);   /// ...geht die LED an
      Motor.moveTo(0);              // Motor dreht auf Position 0 Schritte
    }

    if (Lichtstaerke >= Potiwert + HYSTERESE) /// Sobald der Wert der Lichtstärke größer/gleich des Potiwertes ist...
    {
      digitalWrite(LEDPin, LOW);    /// ...geht die LED aus
      Motor.moveTo(1024);           // Motor dreht auf Position 1024 Schritte
    }
    Motor.disableOutputs ();
  } else {
    Motor.run();                    // Motorsteuerung
  }
}

Nabend! Ich hatte die Tage viel zu tun, daher erst jetzt meine Rückmeldung. Die Testprogramme laufen soweit! Jedoch habe ich mich in der Zwischenzeit auf Empfehlung dazu entschlossen doch einen DC Motor zu verwenden. Dennoch war der Lerneffekt da :slight_smile: Ich warte jetzt auf ein paar Bauteile, die ich mir bestellt habe und dann kanns weiter gehen :slight_smile:
Danke für eure Hilfe!