vorab, ich habe noch nicht die beste Erfahrung mit C++ deswegen bitte ich dies zu berücksichtigen.
Mein Ziel ist es aus einen Schrittmotor (Nema 17) und einen 270-Grad-Poti einen Servo-Motor zu bauen.
Ich habe ein Programm entworfen das ein PWM-Signal empfängt und auswertet.. Dabei findet ein Soll/Ist-Vergleich zwischen PWM und den aktuellen Standes des Potis statt, befindet sich der Analog-Wert (Ist) unter oder über dem PWM-Wert (Soll), Bekommt der Schrittmotorendriver(Easy-Driver) den Auftrag den Motor in die entsprechende Richtung zu bewegen, um auf das Soll zu kommen. Bis dahin funktioniert es eigentlich reibungslos. Nun habe ich das Problem das man das PWM und den Poti nie ganz sauber bekommt sodass sie immer so um ein paar Inkremente schwanken. Das bedeutet, dass der Motor an seinem Soll-Punkt anfängt zu sehr stark zu zittern.
Meine Idee wäre es ja gewesen an dem Soll-Punkt einen Bereich von so ca. +/- 10 Inkremente festzulegen, sodass wenn der Poti in diesen Bereich kommt der Step-Pin des Easy-Drivers auf LOW setzt... Wäre das möglich ? wenn ja wie ?
Ich wäre dankbar für jeden Lösungsansatz!
Grüße
Robert
int pwm_period;
volatile boolean done;
unsigned long start;
unsigned long currentMillis;
long previousMillis = 0;
long interval = 20;
#define poti A9
int potival;
// Servo PWM input pin
#define PWM_IN 7
const byte step_pin = 1;
const byte dir_pin = 3;
const byte MS1 = 4;
const byte MS2 = 5 ;
const byte SLEEP = 6;
int sollpot;
int istpot;
void setup() {
// stepper-Driver
pinMode(MS1,OUTPUT);
pinMode(MS2,OUTPUT);
pinMode(dir_pin,OUTPUT);
pinMode(step_pin,OUTPUT);
pinMode(SLEEP,OUTPUT);
digitalWrite(MS1,HIGH);
digitalWrite(MS2, HIGH);
/* Configure type of Steps on EasyDriver:
// MS1 MS2
//
// LOW LOW = Full Step //
// HIGH LOW = Half Step //
// LOW HIGH = A quarter of Step //
// HIGH HIGH = An eighth of Step //
*/
digitalWrite(SLEEP,HIGH);
delay(5);
pinMode(PWM_IN, INPUT);
attachInterrupt(digitalPinToInterrupt(PWM_IN), measurePulse, CHANGE);
SerialUSB.begin(9600);
}
void measurePulse() {
if (digitalRead(PWM_IN) == HIGH) {
// Beginning of pulse, mark time in start variable
start = micros();
}
else {
// End of pulse, determine pulse width
pwm_period = micros() - start;
done = true;
}
}
void loop() {
currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
// Reset current timestamp
previousMillis = currentMillis;
// Break if not finished measuring pulse width
if (!done)
return;
// Print pulse width measurement to serial monitor
SerialUSB.println (pwm_period);
// Reset done flag
done = false;
}
potival = analogRead(poti);
potival =map(potival, 0, 1023, 564,2401);
SerialUSB.println (potival);
potival = istpot;
pwm_period= sollpot;
// Soll/Ist-Vergleich
if (potival > pwm_period)
{
digitalWrite(dir_pin, HIGH); // (HIGH = anti-clockwise / LOW = clockwise)
digitalWrite(step_pin, HIGH);
delay(1);
digitalWrite(step_pin, LOW);
delay(1);
}
if (potival < pwm_period)
{
digitalWrite(dir_pin, LOW); // (HIGH = anti-clockwise / LOW = clockwise)
digitalWrite(step_pin, HIGH);
delay(1);
digitalWrite(step_pin, LOW);
delay(1);
}
}
gesteuert wird das ganze mit einem Seeeduiono Xiao , über einen Pegelwandler bekommt er die Signale.. aber es spielt ja erstmal keine Rolle meine Frage wahr wie man am besten diesen Bereich festlegen kann.. das Fein-Tuning kann ich dann machen.
ja das stimmt schon aber es hat zum einen einen baulichen Hintergrund und einen persönlichen Aspekt weil ich das ganze eigentlich sehr interessant finde : D
okay, aber das bedeutet ja, dass ich nur in (+) eine Toleranz von 10 habe wie kann ich das Gleichzeitig auch in (-) machen ?
if (potival > pwm_period + 10) & if (potival > pwm_period - 10) ?
Ok.
Ich bin nur aus Deinem Code nicht schlau geworden.
An dieser Stelle:
ist potival immer auf 0.
Das map soll doch sicher istPot werden.
Ich würde mehrere Werte einlesen und daraus eine Mittelwert bilden. Das klappt meist ganz gut.
int pwm_period;
volatile boolean done;
unsigned long start;
unsigned long currentMillis;
long previousMillis = 0;
long interval = 20;
#define poti A9
int potival;
// Servo PWM input pin
#define PWM_IN 7
const byte step_pin = 1;
const byte dir_pin = 3;
const byte MS1 = 4;
const byte MS2 = 5 ;
const byte SLEEP = 6;
int sollpot;
int istpot;
uint8_t zaehler;
const byte anzahl = 12;
uint16_t potiVal[anzahl];
void setup()
{
// stepper-Driver
pinMode(MS1, OUTPUT);
pinMode(MS2, OUTPUT);
pinMode(dir_pin, OUTPUT);
pinMode(step_pin, OUTPUT);
pinMode(SLEEP, OUTPUT);
digitalWrite(MS1, HIGH);
digitalWrite(MS2, HIGH);
/* Configure type of Steps on EasyDriver:
// MS1 MS2
//
// LOW LOW = Full Step //
// HIGH LOW = Half Step //
// LOW HIGH = A quarter of Step //
// HIGH HIGH = An eighth of Step //
*/
digitalWrite(SLEEP, HIGH);
delay(5);
pinMode(PWM_IN, INPUT);
attachInterrupt(digitalPinToInterrupt(PWM_IN), measurePulse, CHANGE);
SerialUSB.begin(9600);
}
void measurePulse()
{
if (digitalRead(PWM_IN) == HIGH)
{
// Beginning of pulse, mark time in start variable
start = micros();
}
else
{
// End of pulse, determine pulse width
pwm_period = micros() - start;
done = true;
}
}
uint16_t readAnalog()
{
static uint16_t returnWert = 564;
potiVal[zaehler] = analogRead(poti);
zaehler++;
if (zaehler == anzahl)
{
zaehler = 0;
uint16_t maxWert = 0;
uint16_t minWert = 1023;
uint32_t summeWert = 0;
for (byte b = 0; b < anzahlWerte; b++)
{
if (potiVal[b] > maxWert)
{
maxWert = potiVal[b];
}
if (potiVal[b] < minWert)
{
minWert = potiVal[b];
}
summeWert += potiVal[b];
}
summeWert -= maxWert;
summeWert -= minWert;
summeWert /= anzahl - 2;
{
returnWert = map(summeWert, 0, 1023, 564, 2401);
}
return returnwert;
}
}
void loop()
{
currentMillis = millis();
if (currentMillis - previousMillis >= interval)
{
// Reset current timestamp
previousMillis = currentMillis;
// Break if not finished measuring pulse width
if (!done)
{ return; }
// Print pulse width measurement to serial monitor
SerialUSB.println (pwm_period);
// Reset done flag
done = false;
}
istPot = readAnalog();
SerialUSB.println (istpot);
pwm_period = sollpot;
// Soll/Ist-Vergleich
if (istpot > pwm_period)
{
digitalWrite(dir_pin, HIGH); // (HIGH = anti-clockwise / LOW = clockwise)
digitalWrite(step_pin, HIGH);
delay(1);
digitalWrite(step_pin, LOW);
delay(1);
}
if (istpot < pwm_period)
{
digitalWrite(dir_pin, LOW); // (HIGH = anti-clockwise / LOW = clockwise)
digitalWrite(step_pin, HIGH);
delay(1);
digitalWrite(step_pin, LOW);
delay(1);
}
}
Du könntest aber auch auf den Istwert ganz verzichten und das Poti beim Start nur als Referenz einlesen. Wenn der Stepper richtig ausgelegt ist und mit einer Rampe betrieben wird geht dem normal nichts verloren. Dann kannst Du ihn mit einer Lib absolut verfahren.
Heinz
Abend,
vielen Dank für deine Idee aber leider bekomme ich deinen Code nicht kompiliert... ich bekomme es leider nicht raus. ich glaube er meckert die eckigen Klammern an.
Ok, ich hab das mal korrigiert - da Du mit dem serial.print anders umgehst, musste ich das auskommentieren.
Ich erklär mal kurz was passiert.
Es werden 12 Werte aufgenommen und wenn die alle aufgenommen sind, wird der höchste und der niedrigste Wert ermittelt und verworfen.
Es bleiben übrig 10 Werte, aus denen ein Mittelwert gebildet wird.
In dieser Version werden nach dem auswerten alle Werte verworfen und das Array mit 12 neuen Werten gefüllt.
Wenn Du das nicht willst, sondern die vorherigen Werte erhalten bleiben sollen "gleitend rechnen", dann musst Du die Klammer aus Zeile 96 deaktivieren und Zeile 74 setzen.
Ich habs kommentiert. (Dann kann auch das static vor dem returnwert entfallen)
Deine Warnung für Deine intervallgeschcihte auch bereinigt.
int pwm_period;
volatile boolean done;
unsigned long start;
unsigned long currentMillis;
uint32_t previousMillis = 0;
uint32_t interval = 20;
#define poti A9
int potival;
// Servo PWM input pin
#define PWM_IN 7
const byte step_pin = 1;
const byte dir_pin = 3;
const byte MS1 = 4;
const byte MS2 = 5 ;
const byte SLEEP = 6;
int sollpot;
int istpot;
uint8_t zaehler;
const byte anzahl = 12;
uint16_t potiVal[anzahl];
void setup()
{
// stepper-Driver
pinMode(MS1, OUTPUT);
pinMode(MS2, OUTPUT);
pinMode(dir_pin, OUTPUT);
pinMode(step_pin, OUTPUT);
pinMode(SLEEP, OUTPUT);
digitalWrite(MS1, HIGH);
digitalWrite(MS2, HIGH);
/* Configure type of Steps on EasyDriver:
// MS1 MS2
//
// LOW LOW = Full Step //
// HIGH LOW = Half Step //
// LOW HIGH = A quarter of Step //
// HIGH HIGH = An eighth of Step //
*/
digitalWrite(SLEEP, HIGH);
delay(5);
pinMode(PWM_IN, INPUT);
attachInterrupt(digitalPinToInterrupt(PWM_IN), measurePulse, CHANGE);
//SerialUSB.begin(9600);
}
void measurePulse()
{
if (digitalRead(PWM_IN) == HIGH)
{
// Beginning of pulse, mark time in start variable
start = micros();
}
else
{
// End of pulse, determine pulse width
pwm_period = micros() - start;
done = true;
}
}
uint16_t readAnalog()
{
static uint16_t returnWert = 564;
potiVal[zaehler] = analogRead(poti);
zaehler++;
if (zaehler == anzahl)
{
zaehler = 0;
// } Diese Klammer einkommentieren, damit gleitend gerechnet wird
uint16_t maxWert = 0;
uint16_t minWert = 1023;
uint32_t summeWert = 0;
for (byte b = 0; b < anzahl; b++)
{
if (potiVal[b] > maxWert)
{
maxWert = potiVal[b];
}
if (potiVal[b] < minWert)
{
minWert = potiVal[b];
}
summeWert += potiVal[b];
}
summeWert -= maxWert;
summeWert -= minWert;
summeWert /= anzahl - 2;
{
returnWert = map(summeWert, 0, 1023, 564, 2401);
}
} // Diese Klammer auskommentieren, wenn die Klammer in Zeile 74 aktiv ist
return returnWert;
}
void loop()
{
currentMillis = millis();
if (currentMillis - previousMillis >= interval)
{
// Reset current timestamp
previousMillis = currentMillis;
// Break if not finished measuring pulse width
if (!done)
{ return; }
// Print pulse width measurement to serial monitor
//SerialUSB.println (pwm_period);
// Reset done flag
done = false;
}
istpot = readAnalog();
//SerialUSB.println (istpot);
pwm_period = sollpot;
// Soll/Ist-Vergleich
if (istpot > pwm_period)
{
digitalWrite(dir_pin, HIGH); // (HIGH = anti-clockwise / LOW = clockwise)
digitalWrite(step_pin, HIGH);
delay(1);
digitalWrite(step_pin, LOW);
delay(1);
}
if (istpot < pwm_period)
{
digitalWrite(dir_pin, LOW); // (HIGH = anti-clockwise / LOW = clockwise)
digitalWrite(step_pin, HIGH);
delay(1);
digitalWrite(step_pin, LOW);
delay(1);
}
}