Hallo,
ups klammer zu viel sorry
ziel = constrain((90 + along / 50 - across / 50 - vertical / 50), 45, 135); // 45 - 135° (front left)
Hallo,
ups klammer zu viel sorry
ziel = constrain((90 + along / 50 - across / 50 - vertical / 50), 45, 135); // 45 - 135° (front left)
Ich würde sagen, dass war schon richtig so. Habe nochmal geschaut. Im Original Code aus dem Link, steht es auch so. Vor Constrain ist eine Klammer und hinter 135 noch eine.:
void writeServos() {
servoFL.write(constrain((90 + along / 20 - across / 20 - vertical / 20), 45, 135)); // 45 - 135° (front left) servoFR.write(constrain((90 - along / 20 - across / 20 + vertical / 20), 45, 135));; // 45 - 135° (front right) servoRL.write(constrain((90 - along / 20 - across / 20 - vertical / 20), 45, 135)); // 45 - 135° (rear left) servoRR.write(constrain((90 + along / 20 - across / 20 + vertical / 20), 45, 135)); // 45 - 135° (rear right) }
Habe es mit dem Code von dir ohne Klammer versucht. Leider bei keiner Version Bewegungen der Servos festzustellen.
Was ist nicht verstehe: Wo wird dem Servo ein Wert zugeordnet, damit er hier gelesen wird:
akt = servoFL.read();
Hallo,
akt = servoFL.read();
das ist nicht die reale ist Position des servos sondern die aus der lib, eigendlich ist das immer die letzte angefahrene Sollposition. Wenn man den Servo langsam fahren lassen würde, mittes eines Konstrukts aus millis() , also immer nur kleine Schrittchen, würde sich die der der Wert servo.read() auch langsam ändern.
die Klammer muss schon weg siehe Arduino referenz link
bekommst Du den unterschiedliche Werte für ziel angezeigt wenn der Senso bewegt wird ?
ich muss mal suchen irgedwo hab ich noch so einen Sensor rumfliegen dann muss ich das mal aufbauen morgen und mit dem original sketch und dann mit dem geänderten testen
Heinz
Hallo Heinz,
das ist ja interessant mit der Klammer. Im Original Sketch war die Klammer ich da und es hat funktioniert.
Den Serial Teil hatte ich noch nicht eingebaut. Das mache ich morgen ( heute ) mal. Falls du keinen Sensor hast, kann ich dir auch gerne einen schicken. Du hast mir schon so viel geholfen.
Viele Grüße
Sven
Hast Du denn einen Sensor gefunden. Bin heute leider noch nicht dazu gekommen, mal den Serial Teil einzubauen. Hoffe ich schaffe das noch.
Hallo,
ich habe mir heute mal den original Sketch zusammen mit einem Sensor aufgebaut. Grundsätzlich klappt der Sketche ja, allerdings misst der Sensor sehr schnell. Wenn man jetzt eine Peek hat, bekommt der Servo das eventuell gar nicht mit.
ich hab dann mal einen delay(10) eingebaut damit war das dann besser. Darauf hab ich dann meinen Sketch verwendet , den mit der Classe Feder, und das noch ein bischen angepasst. Ich denke mehr kann man da nicht rausholen.
Bei der Ausgabe für den Servo hab ich jetzt mal einen mit Feder und die 3 anderen sind ohne. Damit kann man den Unterschied besser sehen. Es gibt noch eine serielle Ausgabe dazu die auch im Plotter läuft , da kann man dann was mehr sehen.
Es besteht noch ein Grundsätzliches Problem. Der Vorgang an sich ist ja ein kontinuierlicher, wenn nun dazwischen die Feder mit den Schritten zum nachfedern ablaufen soll dann kann das zu einem verfahren des Servos in Stufen führen. Langsame Bewegungen des Sensors klappen , schnelle auch , dazwischen kanns Probleme geben. Bei starken Bremsvorgänge des Modells wid das Ding schon nachfedern, das muss man mal probieren am Modell. Eventuell ist eine Lösung mit zu spitzem PI Regler noch eine Variante die einen Versuch wert wäre.
// 4 Channel "Micro RC" Receiver with 4 standard RC Servo Outputs (used as active suspension)
// ATMEL Mega 328P TQFP 32 soldered directly to the board, 8MHz external resonator, (tested on a Pro Micro 8MHz)
// MPU-6050 gyro / accelerometer
/* This code is still very quick and dirty!
MPU-6050 code based on the work of Joop Brokking, no library required!
8MHz is a bit on the weak side, servo lag may occure
This simulation shows an active truck cabin suspension, using 4 servos
*/
const float codeVersion = 0.1; // Software revision (see)
//
// =======================================================================================================
// BUILD OPTIONS (comment out unneeded options)
// =======================================================================================================
//
//#define DEBUG // if not commented out, Serial.print() is active! For debugging only!!
//
// =======================================================================================================
// INCLUDE LIRBARIES
// =======================================================================================================
//
// Libraries
#include <Wire.h> // I2C library (for the MPU-6050 gyro /accelerometer)
#include <Servo.h>
// Tabs (header files in sketch directory)
#include "MPU6050.h"
#include "helper.h"
// ========================================================
// Classe Federn
// ======================================================
class Federn {
private:
byte schritt;
uint32_t altzeit;
uint32_t intervall;
float faktor;
int neuepos, aktuelleps;
public:
// Konstruktor
Federn( uint32_t intervall, float faktor): intervall{intervall}, faktor{faktor} {}
int nachfedern(int zielpos, int aktuellepos) { //Methode
if ( millis() - altzeit >= intervall || schritt==0) {
altzeit = millis();
if (schritt < 5) {
// Position berechnen
neuepos = aktuellepos + (zielpos - aktuellepos) * faktor;
}
else {
neuepos = zielpos;
}
// Serial.print(schritt); Serial.print('\t');
// Serial.print(neuepos); Serial.print('\t');
// Serial.print(aktuellepos); Serial.println();
if (neuepos !=zielpos)schritt++; // schritt hochzählen
else schritt = 0; // oder fertig
}
return (neuepos);
}
};
//
// =======================================================================================================
// PIN ASSIGNMENTS & GLOBAL VARIABLES
// =======================================================================================================
//
// Create Servo objects
Servo servoFL;
Servo servoFR;
Servo servoRL;
Servo servoRR;
// Create feder Objeke
Federn federFL(300, 1.6);
Federn federFR(300, 1.6);
Federn federRL(200, 1.6);
Federn federRR(200, 1.6);
// Pin assignment
#define SERVO_FL_PIN 4 // Front left servo pin
#define SERVO_FR_PIN 5 // Front right servo pin
#define SERVO_RL_PIN 6 // Rear left servo pin
#define SERVO_RR_PIN 7 // Rear right servo pin
//
// =======================================================================================================
// MAIN ARDUINO SETUP (1x during startup)
// =======================================================================================================
//
void setup() {
//#ifdef DEBUG
Serial.begin(115200);
//#endif
// Servo pins
servoFL.attach(SERVO_FL_PIN);
servoFR.attach(SERVO_FR_PIN);
servoRL.attach(SERVO_RL_PIN);
servoRR.attach(SERVO_RR_PIN);
// MPU 6050 accelerometer / gyro setup
setupMpu6050();
}
//
// =======================================================================================================
// WRITE SERVO POSITIONS
// =======================================================================================================
//
void writeServos() {
int ziel, akt, pos;
delay(10);
ziel = constrain((90 + along / 50 - across / 50 - vertical / 50), 45, 135); // 45 - 135° (front left)
akt = servoFL.read();
pos = federFL.nachfedern(ziel, akt);
servoFL.write(constrain(pos,45,135));
Serial.print(ziel); Serial.print('\t');
Serial.print(akt); Serial.print('\t');
Serial.print(pos); Serial.println();
ziel = constrain((90 - along / 50 - across / 50 + vertical / 50), 45, 135); // 45 - 135° (front right
akt = servoFR.read();
pos = federFR.nachfedern(ziel, akt);
servoFR.write(constrain(ziel,45,135));
ziel = constrain((90 - along / 50 - across / 50 - vertical / 50), 45, 135); // 45 - 135° (rear left)
akt = servoRL.read();
pos = federRL.nachfedern(ziel, akt);
servoRL.write(constrain(ziel,45,135));
ziel = constrain((90 + along / 50 - across / 50 + vertical / 50), 45, 135); // 45 - 135° (rear right)
akt = servoRR.read();
pos = federRR.nachfedern(ziel, akt);
servoRR.write(constrain(ziel,45,135));
}
// =======================================================================================================
// SUSPENSION CALCULATIONS
// =======================================================================================================
//
void calculateSuspension() {
// Read sensor data
readMpu6050Data();
}
//
// =======================================================================================================
// MAIN LOOP
// =======================================================================================================
//
void loop() {
// Calculate suspension
calculateSuspension();
// Write the servo positions
writeServos();
}
Das Servo darfst du max. 50x die Sekunde mit einer neuen Position füttern, sonst macht's komische Sachen.
Hallo,
ich hole den Post noch mal nach vorne. Wer mich ein bischen kennt der weis das wenn ich mich in was verbissen habe dann will ich das auch lösen.
Die Idee eine PI Regler zu verwenden und den zu spitz einzustellen um den Servo nachfedern zu lassen hat mir keine Ruhe gelassen. Nu hat ein Servo ja eine ziemlich straffen Regelkreis intern um die Postiton anzufahren. Ein zusätzlicher Regler ist damit also eigendlich völlig Banane. Um eine abklingende Schwingung zu erzeugen baucht man erst mal eine odere mehrere zeitliche Komponente, am besten und einfachsten als PT1 Glied . Ein gleitender Mittelwert macht genau das.
Ich habe mir also eine Classe erstellt mit eine PI Regler und einem Istwerfilter in Form eines gleitenden Mittelwertes. Istwertfilter werden ja auch in realen Regelkreisen oft benötigt, ist also naheliegend das als Methode in die PI Classe zu packen. Natürlich hätte ich auch den standard PID regler nehmen können, aber mal einen selber machen kann ja auch Spass machen. ![]()
Also hier das Ergebniss
/* Servo mit PI Regler (Nachbildung einer Federbewegung)
* als Sollwertprung werden zwei Positionen angefahren
* Mit den Parametern kann die Federnachbilung verändert werden
* Ziel ist eine Reglereistellung die stark überchwingt
* Dämpfung Zeitverhalten ( Masse)
*
*/
#include <Servo.h>
int pos1 = 80; // Sollwert positionen
int pos2 = 120;
bool posstate;
int ziel;
uint32_t altzeit, altdisp; // letzte Sollwertumschaltng und Anzeige Zeit
// Regler Parameter
#define PI_cycle 20 // ms
#define KP 0.3
#define KI 20.0
#define daempfung 20
class PiRegler {
private:
float soll, ist, y , yi, yp, dif, lastyi;
float Kp, Ki;
float buff, av; // Mittelwert bilden
uint32_t altzeit, cycletime, av_time;
public:
// Konstruktor
PiRegler(uint32_t cycletime, float Kp, float Ki): cycletime{cycletime}, Kp{Kp}, Ki{Ki} {};
float control(float soll, float ist) {
if (millis() - altzeit >= cycletime) {
altzeit = millis();
dif = (soll - ist); // Regeldifferenz
yp = constrain (dif * Kp, -200, 200); // P-Anteil
yi = constrain (lastyi + dif * Ki * cycletime / 1000.0 , -200, 200); //I-Anteil
lastyi = yi;
y = yp + yi; // Stellgrösse bilden
}
return (y);
}
float mittel(float in, int f) { // gleitender Mittelwert
if (millis() - av_time > 10) {
av_time = millis();
buff = buff - buff / f;
buff = buff + in;
av = buff / f;
}
return (av);
}
};
// Objekte erstellen
Servo servo1;
PiRegler regler1(PI_cycle, KP, KI);
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
servo1.attach(4);
servo1.write(pos1);
}
void loop() {
int akt, pos;
// Sollwert Umschaltung zum testen
// letztlich kommen die Sollwerte ja vom Sensor.
if (millis() - altzeit >= 3000) {
altzeit = millis();
posstate = !posstate;
if ( posstate ) ziel = pos1;
else ziel = pos2;
}
akt = servo1.read(); // Istwert lesen
akt = regler1.mittel(akt, daempfung); // dämpfen Mittelwert
pos = regler1.control(ziel, akt); // PI Regler bearbeiten
pos = constrain(pos, 0, 180); // Auf servo begrenzen
servo1.write(pos); // Wert an Servo geben
if (millis() - altdisp >= 20) { // Werte anzeigen
altdisp = millis();
Serial.print(ziel); Serial.print('\t');
Serial.print(akt); Serial.print('\t');
Serial.println();
}
}// =====loop ende


This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.