Schulprojekt

wenni

User
Hallo,

mache nebenher Technikerschule, da können wir nun im letzten Jahr eine Projektarbeit machen. Nun hatte ich zwar ein Jahr Grundlagen µC, hauptsächlich Assembler. Hab mich da durchgehangelt, aber der Programmierer vor dem Herrn wurd ich dadurch nicht. C hatten wir im Jahr davor, aber wenn man die Schule nebenher macht, ist das oft leider Bulimielernen, nur ein paar Grundlagen bleiben hängen.

Nun zu den beiden interessanten Projekten:

1. Eine Wippe, an jedem Ende ein Motor mit Propeller, eine Seite mit konstanter Drehzahl, die andere soll mittels Gyro nachgeregelt werden und die Wippe immer wieder in die Waage bringen.

Mein Gedankengang, zwei Brushless Motoren, einen an nem Servotester für die konstante Drehzahl, der andere an nen Arduino, mit Gyro.
MPU-6050 oder reicht der analoge einachsige GY-35-RC?

Auslegung der Motoren, denke meine vorhandenen beiden, mit denen ein Twinstar senkrecht aus der Hand ging, sind zu groß :) Was kann man da nehmen um eine 50cm Wippe zu bewegen? Kosten sollten auch recht niedrig bleiben, die Schule will da sicher keine Hacker oder Scorpion drin haben ;) Oder einfache brushed Motoren?

Variante B wäre, anstatt dem Gyro einfach ein Poti in die Achse und die Widerstandswerte auswerten (Vorschlag vom Lehrer)

2. Eine Art Gimbal, 2-Achsen, eine Platte soll sich unabhänig vom Untergrund immer wieder selbst gerade ausrichten.
Hier auch wieder, MPU-6050 oder zwei GY-35-RC? Servos, eher schnelle Digitale?

Zu 2. findet man ja schon recht viele fertige Projekte, keine Ahnung warum der Lehrer das so interessant findet. Wobei da aber meist Brushlessmotoren eingesetzt werden.

An die erfahrenen Bastler, welches ist das einfachere Projekt? Würde mal ins blaue aufs erste tippen. I²C haben wir nur mal angesprochen dass es das gibt, angewendet leider nicht.
 
Hallo,

ein paar Gedanken dazu:
Ich würde keinen Gyro nehmen (zumindest nicht nur), denn da bekommst Du leicht Probleme mit Drift.
Wenn der Lehrer das schon vorschlägt, würde ich es erstmal mit dem Poti versuchen. (Dann aber auf spielfreie Anlenkung des Potis achten!)
Alternativ würde ich einen 2-Achs Beschleunigungssensor verwenden, um herauszufinden, wo unten ist (möglichst direkt in der Drehachse angebracht)(wobei sogar 1-Achs reichen würde, wenn sichergestellt ist, dass sich die Konstruktion nie auf den Kopf stellt).
Wenn du das ganze ordentlich regeln willst, dann solltest du dafür einen PID-Regler programmieren. Für den D-Teil könntest du dann statt der Ableitung der g-Winkel-Werte (also der Richtung wo unten ist) auch direkt ein Gyro auslesen.
Ob Brushless oder Brushed dürfte relativ egal sein, solange du fertige ESCs verwenden darfst/sollst.
Einen Bürstenmotor könntest du natürlich einfach über einen FET ansteuern. Das senkt den Preis und erhöht die Eigenleistung.

Ganz wichtig: Sprich mit deinem Lehrer ab, was er erwartet.

Beste Grüße,

Lutz
 

wenni

User
Falls es irgendwen interessiert, oder auch nicht, egal :)

Motoren hab ich jetzt 1806 2300 bestellt, 18A Regler und halt das ganze außenrum, z.B. 12V 30A Schaltnetzteil und einen LM2596. Müsste da noch was zum sieben rein?

Bastle nebenher am Sketch, sieht schon recht passabel aus, nur fehlt mir grad eine Initialzündung bezüglich des geregelten Motors.
Werte ja den MPU-6050 aus, dieser gibt einen Wert aus (GyX oder GyY), bei den PID Beispielen finde ich immer analogRead, lese ich damit ein? Und was gebe ich aus damit dann die servo.h daraus ein PWM-Signal wurschteln kann?

Gebe ich dem Regler ein Grund-PWM vor oder macht das der PID Regler?
 
Hallo wenni
Ein paar Infos....
Was für ein CPU ?
Soll es Assembler, C oder was anderes werden ?
Sind das SimonK bzw BLHeli Regler ?


////edit
lese grad "servo.h", vermutlich Arduino ?

In der Main/Setup Routine die Regler Initialisierung nicht vergessen.

Mit der ServoLib funzen auch die BLheli und Simonk-Regler, die musst du dann aber in den Wegen einlernen (1-2Sek. Vollgas, dann 1-2Sek Leerlauf im Setup) normale Regler nur mit ca. 2Sek. Leerlauf initialisieren.

Werte schreiben mit https://www.arduino.cc/en/Reference/ServoWriteMicroseconds
Leerlauf 1100, Vollgas 1900



///
Hier ein Beispiel in C ohne die Servo-Lib mit einem 4MHz Atmega8 am TImer1: http://www.electronicsplanet.ch/mikrocontroller/source-code/ATmega8/ATmega8-Servo.htm
Dann aber aufpassen das keine Lib Timer1 ist den du für die PWM nutzt.
Damit kannst du BLHeli/SimonK mit 500Hz wesentlich schneller ansteuern.
Timer nach Datenblatt für deine CPU und Frequenz konfigurieren.
ICR-Top bestimmen.
50Hz 20ms PWM Signal für normale Regler
500Hz 2ms PWM Signal für BLheli/SimonK Regler
über zwei PWM Kanäle, z.B. OCR1A und OCR1B am Timer 1 kannst du dann die PWM an die Regler ausgeben.
"Leerlauf" ist dann immer 50% PWM, Vollgas 100% PWM (bzw vom ICR-Top, bei 100% besser 1 Bit drunter bleiben).
 

wenni

User
Ja, hab jetzt mal mit Arduino angefangen.

Da gibt es auch für alles mögliche Libraries, Problem ist nur irgendwie initialisiert der die nicht richtig.

Um eine Labrarie zu erstellen, kopiere ich doch das was man z.B. im Arduino Playground findet in Notepad++, speichert das als *.h in den Libraries-Ordner von Arduino IDE. Aufruf dann mit #include *.h

Habs auch mal mit CodeBlocks Arduino probiert, aber der findet die Libraries noch schwieriger und wenn, dann kommen zig Fehlermeldungen dass in denen irgendwas nicht passt.

z.B.
undefined reference to `PID::PID(double*, double*, double*, double, double, double, int)'

oder

C:\Users\RaBe\AppData\Local\Temp\cczX0N3O.ltrans0.ltrans.o: In function `setup':

F:\Schule\Arduino_Portable\portable\sketchbook\Projektarbeit_Wippe/Projektarbeit_Wippe.ino:96: undefined reference to `PID::SetMode(int)'

obwohl es richtig ausgefüllt ist... Verzweifle da grad etwas.

Ach ja, Regler hab ich mal einfache 18 Turnigy genommen, oder sind die untauglich? Das Projekt soll für nen Tag der offenen Tür herhalten können, aber auch kein Vermögen kosten.
 
In der Arduino IDE ist die Servo-Lib inkl zwei Beispiele schon mit drinn.

Das Beispiel "Knob" um den Regler am Pin9 erweitert (habe es nicht getestet, vorher ruhig mal mit einem Servo testen).
Dann solltest Du mit dem Poti den Motor regeln können. (1100-1900)
Code:
#include <Servo.h>
Servo myservo;          // create servo object to control a servo

int potpin = 0;           // analog pin used to connect the potentiometer
int val;                       // variable to read the value from the analog pin

void setup() {
  myservo.attach(9);                             // attaches the servo on pin 9 to the servo object 
  myservo.writeMicroseconds(1100);           // Regler initialisieren
  delay(3000);                                       // Regler initialisieren
}   

void loop() {
  val = analogRead(potpin);                 // reads the value of the potentiometer (value between 0 and 1023)
  val = map(val, 0, 1023, 1100, 1900);    // scale it to use it with the servo (value between 0 and 180)
  myservo.writeMicroseconds(val);         // sets the servo position according to the scaled value
  delay(15);                                      // waits for the servo to get there
}
 

wenni

User
Code:
#include<PID.h>  // PID Library
#include<MPU6050.h> // MPU-6050 Library 
#include<Servo.h>   // Servo Library zum erzeugen der PWM-Signale 
#include<Wire.h>    // Wire Library für I²C-Schnittstelle des Gyro


// Servobereich
Servo srvkonst;     // Erstellen der Konstante für PWM-Signal an Motor mit konstanter Drehzahl
int potpin = 0;     // Analog Pin 0 für Potischleifer
int val;            // Variable zum Lesen des Wertes von Analogpin 0

Servo srvgyro;      // Erstellen der Konstante für PWM-Signal an gyrogeregeltem Motor
int pwmg;           // Variable für PWM-Signal des Reglers der geregelt wird

// MPU-6050 Bereich
const int MPU_addr = 0x68;            // I²C Adresse des MPU-6050 (0x68 oder 0x69)
int16_t GyX, GyY;                     // Variablen der X- und Y-Achse

// PID Bereich
double Input, Output, Setpoint; // Variablen zum verbinden des PID
PID myPID(&Input, &Output, &Setpoint, 2, 5, 1, DIRECT); // PID-Links und Tuningparamater anlegen Zahlenwerte = Kp,Ki,Kd

//oder

//double Setpoint, Input, Output; //Define Variables we'll be connecting to
//double consKp=1, consKi=0.05, consKd=0.25; // PID-Einstellungswerte (Standardwerte 2,5,1)
//double aggKp=4, aggKi=0.2, aggKd=1; // für void loop wenn Umschaltung gewünscht
//PID myPID(&Input, &Output, &Setpoint, consKp, consKi, consKd, DIRECT); // PID-Links und Tuningparamater anlegen

void setup()

{
  // Servobereich
  srvkonst.attach(9);  // Ausgabe des konstanen PWM-Singals an Pin9
  srvgyro.attach(10);  // Ausgabe des geregelten PWM-Signals an Pin10

  // MPU-6050 Bereich
  Wire.begin();                       // Initialisieren der Wire Library und einbinden des I²C Bus
  Wire.beginTransmission(MPU_addr);   // Beginnen der Übertragung
  Wire.write(0x6B);                   // PWR_MGMT_1 Register, Nachfolgende Bytes puffern
  Wire.write(0);                      // 0 setzen weckt den MPU-6050 auf
  Wire.endTransmission(true);         // Übertragung zum Slave beenden und gepufferte Daten übertragen, Stopnachricht nach Übertragung, Verlassen des I²C Bus
  Serial.begin(9600);                 // Datenübetragunsrate in baud

  // PID-Bereich
  Input = GyX;            // Initialisieren der auszulesenden Variablen
  Setpoint = 100;                     // Wert um den herum geregelt wird
  myPID.SetMode(AUTOMATIC);           // PID einschalten
}

void loop()
{
    // PWM-Signal für Motor auf konstanter Drehzahl
  
    val = analogRead(potpin);            // Lesen der Potentiometerweres (0-1023)
    val = map(val, 0, 1023, 1000, 2000); // Potiwert in PWM skalieren
    srvkonst.write(val);                 // Servoposition entprechend des Wertes setzen
    delay(15);                           // Warten bis Servo den Wert erreicht hat
  

    // MPU-6050 Gyrowerte erfassen
  
    Wire.beginTransmission(MPU_addr);   // Begin der Übertragung
    Wire.write(0x43);                   // Starten im Register 0x43 (ACCEL_XOUT_H)
    Wire.endTransmission(false);        // Nach der Übertragung Restartbefehl senden
    Wire.requestFrom(MPU_addr, 4, true);// 4 Register anfordern

    GyX = Wire.read() << 8 | Wire.read(); // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
    GyY = Wire.read() << 8 | Wire.read(); // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)

    Serial.print(" | GyX = "); Serial.print(GyX);
    Serial.print(" | GyY = "); Serial.print(GyY);

    delay(333);

    // PID Regler
  
    Input = analogRead(GyX); // Eingang PID-Regler = Gyroausgabewert Gy...
    myPID.Compute();         // PID-Berechnungen ausführen
    analogWrite(3, Output); // Ausgang PID-Regler Variable noch zu definieren

  //oder
  /*
    Input = analogRead(0);

    double gap = abs(Setpoint-Input); //distance away from setpoint
    if(gap<10)
    {  //we're close to setpoint, use conservative tuning parameters
    myPID.SetTunings(consKp, consKi, consKd);
    }
    else
    {
    //we're far from setpoint, use aggressive tuning parameters
    myPID.SetTunings(aggKp, aggKi, aggKd);
    }

    myPID.Compute();
    analogWrite(3,Output);

  */

    // PWM-Signal für geregelten Motor
  
    pwmg = val + Output;                    // Lesen des PID Ausgangs
    //pwmg = map(pwmg, 1000, 2000, 0, 180); // Skalieren um den Wert mit einem Servo zu nutzen (0-180)
    srvgyro.write(pwmg);                    // Servoposition entprechend des Wertes setzen
    delay(15);                              // Warten bis Servo den Wert erreicht hat

}

So siehts derzeit aus, ja da sind noch Fehler drin, die wollte ich nach und nach ausmärzen. Gerade so Übergänge von z.B. dem MPU-6050 in den PID und von dem ins zweite "Servo".

Da ist Knob schon mit eingebaut :)
 
Moin Wenni

Du musst im Setup die Regler wie in meinem Beispiel erst noch initialisieren. Wenn die gleich höhere Werte bekommen laufen die nicht an, oder landen gar im Programmier-Mode (Stick-Mode), (und das passiert garantiert immer dann, wenn man es vorführen will ;))

Bei val mapst Du auf 1000-2000
Bei pwmg mapst Du auf 0-180
gibst beide mit xxx.write aus ;)

servo.write benötigt werte 0-180 (Grad Servowinkel, der Regler mag eher so 30-150)
servo writeMicroseconds benötigt werte 1100-1900 (ppm in ms)
Du solltest Dich für eine Variante entscheiden, die zweite lässt feineres Regeln zu.

Scheint mit alles irgendwie einfach nur zusammenkopiert zu sein ;)
Ich würde mal einen schlichten Sketch schreiben, mit den Du die beide Motoren mal testlaufen kannst, den Rest erst mal kmpl. weglassen, und erst da dann weiter drauf aufbauen, wenn das funktioniert. ich denke sonst verrennst Du Dich, und dem Lehrer wird es garantiert auch auffallen. Evtl mal schlüssige Bezeichnungen für beide Regler, man darf sie z.B. auch einfach Regler1 und Regler2, sowie pwm1 und pwm2 nennen o.Ä.

edit
Sollte es eigentlich nicht so sein; das Poti regelt global die Drehzahl beider Motoren, und der Sensor die Lage auch über beide Motoren ? (So ist es z.B. bei einem Copter)
 

wenni

User
Ähm ja, dem Kenner fällt es auf :) Ist dem Lehrer aber auch klar, wenn er Arduino zulässt dass es vieles fertig gibt. Aber man sieht ja, wirklich Copy&Paste funt schonmal in den seltensten Fällen :)

Wie gesagt die Feinheiten wollt ich eh noch ausbessern wie das PWM. Wundere mich nur gerade dass eben soviele Fehlermeldungen kommen die mit den Libraries zu tun haben. Codefehler würd ich ja akzeptieren und verstehen :)

Vorgabe ist vom Lehrer erst mal einen ausgleichenden und einen mit konstanter Drehzahl, wobei das schon im Hinterkopf ist und auch gemacht werden darf mit beiden. Wenn ich das gleich angehe, wäre auch ok. Vom Gedankengang her, beide hochregeln und beim einen die PID Werte invertiert aufschlagen.

Stimmt das mit dem Programmiermode hab ich ganz vergessen, so dachte ich eigentlich, dass man gezwungen ist das Poti runterzudrehen damit die überhaupt initialisieren und man nicht gleich nach dem einschalten z.b. Vollgas anliegen hat sondern selbst per Hand hochregelt.
 
Das ist das Problem an Arduino, manche Libs mögen sich nicht, und können nicht miteinander, meist sind das Konflikte mit den Timern, und sonstiges "unsauberes" aus dem Netz.

Darum, mit einer Sache anfangen, testen, was hinzufügen testen u.s.w. kommt der Fehler, weißt du was du als letztes hinzugefügt hast, und wo der Bock sitzt.
ServoLib mit Pin 9+10 nutzt z.B. Timer1... ;)
 

ruvy

User
Das ist das Problem an Arduino, manche Libs mögen sich nicht, und können nicht miteinander, meist sind das Konflikte mit den Timern, und sonstiges "unsauberes" aus dem Netz.

Darum, mit einer Sache anfangen, testen, was hinzufügen testen u.s.w. kommt der Fehler, weißt du was du als letztes hinzugefügt hast, und wo der Bock sitzt.
ServoLib mit Pin 9+10 nutzt z.B. Timer1... ;)

OT, aber interessiert mich trotzdem: warum genau ist das ein Arduino Problem?
Wenn ich für den Raspy oder einen anderen was "unsauberes" aus dem Netz verwende, ergeben sich die Problem doch dort auch?

lg, Rudi
 

wenni

User
Bin gerade dabei den Sketch neu zu machen, Schritt für Schritt, immer zwischendrin mal Prüfen/Kompilieren, bisher läufts gut mit Ansteuern der Regler und Einbinden des Gyro.

Bisher müsste er beide Regler ansteuern können und der Gyro misst zumindest etwas und schreibt in Register.

Erster Fehler kam sobald das void setup vom PID dazu kam.

PID myPID(&Input, &Output, &Setpoint, 2, 5, 1, DIRECT);

Diese Zeile kann er nicht leiden, nur warum?
 
Was kommt denn für eine Fehlermeldung? Schieb mal den Sketch rüber ;)

Die PID Lib ist aber korrekt eingebunden?
Funktioniert das Beispiel welches bei der Lib dabei ist?
 

wenni

User
Das kommt raus. Habe nach PID Librarie gesucht, den Inhalt in Notepad++ kopiert und das dann als PID.h gespeichert und in den Libraries-Ordner von Arduino, wo auch die anderen drin sind. Kann es sein dass da noch ne PID.cpp fehlt?

C:\Users\*****\AppData\Local\Temp\cc1wwtf3.ltrans0.ltrans.o: In function `__static_initialization_and_destruction_0':

F:\Schule\Arduino_Portable\portable\sketchbook\Projekt_Wippe_Step3/Projekt_Wippe_Step3.ino:26: undefined reference to `PID::PID(double*, double*, double*, double, double, double, int)'

collect2.exe: error: ld returned 1 exit status

exit status 1
Fehler beim Kompilieren für das Board Arduino Nano.

Edit:
die PID.cpp oder keywords.txt warens :)
 

wenni

User
Ähm, ja. Weil ich mich zum ersten mal überhaupt mit einem derartigen Projekt wirklich auseinandersetze und bisher nur bisschen Assembler und C rumgedrückt habe. Was man halt so in der Schule lernen kann. Fand das Projekt als Alternative zu HTML lernen dann doch interessanter. Muss dann eh erstmal auf bisschen Hardware warten, dann kann ichs real testen.

Bin mir z.B. noch unschlüssig ob der MPU-6050 so den GyX und GyY Wert in eine Variable schreibt (ob überhaupt) die der PID so auch lesen kann und das was der PID ausgibt auch so ohne weiteres auf das PWM der Regler dazu gerechnet oder abgezogen werden kann. Standardmäßig arbeitet er ja mit -250 bis 250 als Ausgabe um 0. Denke mal da muss das PWM noch eingegrenzt werden.

Edit: Da das ja ein Projekt mit Note werden soll, weiss nicht ob das so gut ist den gleich so zu veröffentlichen. Wenn jemand zu eventueller Fehlersuche beitragen möchte, kann ich den ja gern mal mailen.
 

wenni

User
So, Projekt ist vorangeschritten, jetz kommt der Zeitdruck :D Was man nicht gleichmäßig vorantreibt holt einen irgendwann ein.

Heute endlich fertig verkabelt und den Sketch aufgespielt.

Ernüchterung, meine Ideen hauen so überhaupt nicht hin. Ein Motor lässt sich sauber regeln, der zweite kommt erst ab 1/3 Potistellung dazu, vertauschen der Regler am Arduino lässt den Fehler wandern, also liegts am Sketch und der Gyro macht auch irgendwie nix...

Hat jemand Lust mal über den Sketch zu schauen, bin mir da in manchen Sachen nicht sicher.

Gruß
Rainer
 
Ansicht hell / dunkel umschalten
Oben Unten