So philipp, Versuche es damit. Bitte lese Dir die Komentare , die ich Dir in den Code eingefügt habe, besonders auch in bBezug auf den Refernzschalter, sehr aufmerksam durch, damit Du das System korrekt ans Laufen bekommst. Wichtig, erst lesen und erst wenn Du die hardwar angepasst hast, hochladen. Wenn der Referenzschalter nicht richtig positioniert oder angeschlossen ist, kann das System so nicht funktionieren.
```cpp
#include <SoftwareSerial.h>
#include <Stepper.h>
#include <EEPROM.h>
#define BT_RX_PIN 1
#define BT_TX_PIN 0
#define REF_SW_PIN 6 // Referenzschalter an Pin 6 vom Arduino, der Schalter MUSS , wenn die 0-Position erreicht ist,
// Pin & nach GND schalten !!!
#define IN1 8
#define IN2 10
#define IN3 9
#define IN4 11
SoftwareSerial bluetooth(BT_RX_PIN, BT_TX_PIN);
uint8_t blockNr = 0x00;
uint16_t blockAddr = 0x02;
uint16_t writeCount = 0x0000;
int16_t stepCount = 0;
uint16_t maxAngle = 50; // maximaler verfahr-Winkel jeweils in + und - Richtung vom Referenz-Punkt aus
const uint16_t stepsPerRevolution = 2048;
float angle = 0.0;
Stepper myStepper(stepsPerRevolution, IN1, IN2, IN3, IN4);
int8_t motorOn = 0;
int8_t lastDir = 0;
void getEEProm() {
if (EEPROM.read(0) == 0xC9) { // EEPROM ist initialisiert, lade Werte (lastDir, writeCount, blockNr) aus EEPROM
blockNr = EEPROM.read(1); // das eeprom wird in blöcke aufgeteilt um die lebensdauer des EEPROMS zu verlängern
blockAddr = (blockNr * 3) + 0x02; // berechnung der Startadresse des aktiven EEPROM-Blockes
EEPROM.get(blockAddr, writeCount); // dieser counter legt fest, wann der nächste Block aktiviert wird
lastDir = EEPROM.read(blockAddr + 2); /* hier wird die letzte bewegungsrichtung aus dem EEprom geholt, zur feststellung
in welche Richtung der Referenzschalter zu finden ist , dies ist bei nur einem,
in der Mitte des Weges angeordneten Referenzschalters notwendig, da der arduino
sonst nach dem Einschalten nicht feststellen kann in welche Richtung der Motor
laufen muss, um den Nullpunkt zu finden.
Wäre der Referenzschalter an einem Ende des Weges montiert kann die Nutzung des
EEPROMS entfallen, und da der motor, egal wo er steht, den referenzschalter immer
in die gleiche richtung suchen kann. Danach kann der Motor dann auch einfach in die
Mitte des Weges (halbe Strecke) fahren und diesen Punkt als Ausgangspunkt annehmen,
also als Nullposition setzten. MCit nur in der Mitte montiertem 1 Referenzschalter
geht es auch, ist halt Programmtechnisch etwas aufwändiger, jedoch positionirt er so
schneller, das heisst das Gerät ist nach dem Einschalten schneller betriebsbereit.
Nachteil ist jedoch, dass das gerät nach dem hochladen des sketches, also bei der
ersten Inbetriebname entweder direkt auf dem Referenzschalter stehen muss, oder ein
wenig in negativer Richtung kurz vor dem Referenzschalter.
UND ganz wichtig, im ausgerschalteten Zustand darf man nicht von Hand verstellen. eine andere Möglichkeit wäre, anstelle des Referenzschalters, ein Poti eizubauen,
dessen achse mit dem bebegten Teil des Gerätes mitläuft, dann könnte der arduino
jederzeit die Position feststellen und auch kontrolieren, das ergäbe dann eine
Art Servoantrieb , also ein antrieb mit aktiver Rückmeldung.
*/
return;
}
// EEPROM noch nicht initialisiert, jetzt initialisieren.
EEPROM.put(blockAddr, writeCount);
EEPROM.write(1, blockNr);
EEPROM.write(blockAddr + 2, (lastDir - 1));
EEPROM.write(0, 0xC9);
}
void writeLastDirection() {
if (lastDir == motorOn || motorOn == 0) return; // nur schreiben wenn motor drehen soll und Richtung wechselt
lastDir = motorOn; // drehrichtung in lastDir übernehmen
writeCount++; // schreibzähler erhöhen
if (writeCount == 0) { // Zähler überlauf? (>65535)
blockNr++; // ja, nächster EEPROM Block aktivieren.
EEPROM.write(1, blockNr); // neue BlockNr ins EEPROM
blockAddr = (blockNr * 3) + 0x02; // neue Blockadresse berechmem.
}
EEPROM.put(blockAddr, writeCount); // schreibzähler sichern
EEPROM.write(blockAddr + 2, lastDir); // Richtung im EEPROM sichern
}
void goToRefPoint() {
uint16_t maxSteps = ((maxAngle * stepsPerRevolution) / 360);
int8_t refDir = 0 - lastDir;
for (uint16_t steps = 0; steps < maxSteps; steps += 2) {
if (digitalRead(REF_SW_PIN) == 0) break; // Referenz Pos bereits gefunden?
myStepper.step(refDir * (stepsPerRevolution / 1024)); //
}
angle = 0.0;
}
void setup() {
Serial.begin(9600);
bluetooth.begin(9600);
myStepper.setSpeed(12);
myStepper.step(0);
pinMode(REF_SW_PIN, INPUT_PULLUP);
getEEProm();
goToRefPoint();
delay(1000);
}
void loop() {
if (Serial.available()) {
char dataToSend = Serial.read();
Serial.println(dataToSend);
bluetooth.write(dataToSend);
}
if (bluetooth.available()) {
char command = bluetooth.read();
if (command == '1' && angle < maxAngle) {
motorOn = 1;
writeLastDirection(); // Richtungswechsel sichern
} else if (command == '2' && angle > -maxAngle) {
motorOn = -1;
writeLastDirection(); // Richtungswechsel sichern
} else if (command == '0') {
motorOn = 0;
delay(5);
}
}
if (motorOn != 0) {
angle = stepCount * 360.0 / stepsPerRevolution; // Winkel berechnen
if (((angle <= -maxAngle) && motorOn < 0) || ((angle >= maxAngle) && motorOn > 0)) { // überwachen des gefahrenen Winkels
motorOn = 0; // bei erreichen einer der Endpos -> Motor aus
}
myStepper.step(motorOn * (stepsPerRevolution / 1024));
stepCount += (motorOn * 2); // Steps entsprechend Laufrichtung (Wert von motorOn) zählen.
// da der Motor immer 2 steps ausführt, müssen auch immer 2 steps addiert/subtrahiert werden, damit die Pos stimmt.
}
}