Totale Testversion
Dependencies: mbed
Fork of DrehungMitStopp by
main.cpp
- Committer:
- freunjor
- Date:
- 2017-05-21
- Revision:
- 5:24350e6fc9d7
- Parent:
- 4:2ebbd24aa610
File content as of revision 5:24350e6fc9d7:
#include "mbed.h" #include "IRSensor.h" #include "MotorEncoder.h" #include "LowpassFilter.h" #include "Servo.h" #include <cmath> DigitalOut led(LED1); //Zustands-LED: Grüne LED für Benutzer //--------------------IRSensoren------------------------------------------------ AnalogIn distance(PB_1); //Input der Distanzsensoren DigitalOut enableSensor(PC_1); //Aktivierung der IRSensoren DigitalOut bit0(PH_1); //Ansteuerung der Sensoren 0-5 mit 3 Bits DigitalOut bit1(PC_2); DigitalOut bit2(PC_3); IRSensor sensors[6]; //Erstellt 6 IRSensor-Objekte als Array DigitalOut leds[] = { PC_8, PC_6, PB_12, PA_7, PC_0, PC_9 }; //LED-Outputs der Sensoren float sensorMittelwert[6]; //Array der 6 Sensorenwerte float sensorTiefbass[6]; float sensorZentimeter[6]; int printfZaehler = 0; //Titel printf() void title() { printf("\f"); //"\f" Setzt den Cursor an den Anfang der nächsten Seite } void sensorWerte() //Rechnet Sensorwerte aus und speichert sie unter sensorZentimeter[] { for(int j = 0; j < 25; j++) { //Zählt 25 Sensorwerten pro Sensor zusammen for(int i = 0; i < 6; i++) { sensorMittelwert[i] += sensors[i].read(); } } for(int i = 0; i < 6; i++) { sensorTiefbass[i] = sensorTiefbass[i]*0.75f + sensorMittelwert[i]*0.25f; //Verrechnet den neuen Wert mit dem alten sensorMittelwert[i] = 0.0f; //Setzt die Sensorwerte auf NULL switch(i) { //Rechnet die Werte in Zentimeter case 0: //Mitte if(sensorTiefbass[i] < 2.97f) sensorZentimeter[i] = 80.0f; //Grenzwert else sensorZentimeter[i] = 110.0f/pow((sensorTiefbass[i]-1.9f),0.41f)-27.0f; break; case 1: //UntenRechts if(sensorTiefbass[i] < 3.2f) sensorZentimeter[i] = 69.0f; //Grenzwert else sensorZentimeter[i] = 87.0f/pow((sensorTiefbass[i]-2.2f),0.41f)-18.0f; break; case 3: //Links if(sensorTiefbass[i] < 3.67f) sensorZentimeter[i] = 80.0f; //Grenzwert sensorZentimeter[i] = 80.0f/pow((sensorTiefbass[i]-3.1f),0.38f)-19.0f; break; case 4: //Rechts if(sensorTiefbass[i] < 3.53f) sensorZentimeter[i] = 80.0f; //Grenzwert else sensorZentimeter[i] = 90.0f/pow((sensorTiefbass[i]-2.8f),0.4f)-22.0f; break; case 5: //UntenLinks if(sensorTiefbass[i] < 4.4f) sensorZentimeter[i] = 59.0f; //Grenzwert else sensorZentimeter[i] = 115.0f/pow((sensorTiefbass[i]-2.5f),0.4f)-30.0f; break; } } printf("%f\t%f\n\r", sensorZentimeter[5], sensorZentimeter[0]); //Plottet die unteren Sensoren + Mitte-Oben } //--------------------Motor&Encoder--------------------------------------------- const float PERIOD = 0.002f; // period of control task, given in [s] const float COUNTS_PER_TURN = 1200.0f; // resolution of encoder counter const float LOWPASS_FILTER_FREQUENCY = 300.0f; // frequency of lowpass filter for actual speed values, given in [rad/s] const float KN = 40.0f; // speed constant of motor, given in [rpm/V] const float KP = 0.2f; // speed controller gain, given in [V/rpm] const float MAX_VOLTAGE = 12.0f; // supply voltage for power stage in [V] const float MIN_DUTY_CYCLE = 0.02f; // minimum allowed value for duty cycle (2%) const float MAX_DUTY_CYCLE = 0.98f; // maximum allowed value for duty cycle (98%) MotorEncoder counterLeft(PB_6, PB_7); MotorEncoder counterRight(PA_6, PC_7); LowpassFilter speedLeftFilter; LowpassFilter speedRightFilter; DigitalOut enableMotorDriver(PB_2); PwmOut pwmLeft(PA_8); PwmOut pwmRight(PA_9); short previousValueCounterRight = 0; short previousValueCounterLeft = 0; float desiredSpeedLeft; //Ansteuerung des linken Motors float desiredSpeedRight; //Ansteuerung des rechten Motors float actualSpeedLeft; float actualSpeedRight; void speedCtrl() { // Berechnen die effektiven Drehzahlen der Motoren in [rpm] short valueCounterLeft = counterLeft.read(); short valueCounterRight = counterRight.read(); short countsInPastPeriodLeft = valueCounterLeft-previousValueCounterLeft; short countsInPastPeriodRight = valueCounterRight-previousValueCounterRight; previousValueCounterLeft = valueCounterLeft; previousValueCounterRight = valueCounterRight; actualSpeedLeft = speedLeftFilter.filter((float)countsInPastPeriodLeft /COUNTS_PER_TURN/PERIOD*60.0f); actualSpeedRight = speedRightFilter.filter((float)countsInPastPeriodRight /COUNTS_PER_TURN/PERIOD*60.0f); // Berechnen der Motorspannungen Uout float voltageLeft = KP*(desiredSpeedLeft-actualSpeedLeft)+desiredSpeedLeft/KN; float voltageRight = KP*(desiredSpeedRight-actualSpeedRight)+desiredSpeedRight/KN; // Berechnen, Limitieren und Setzen der Duty-Cycle float dutyCycleLeft = 0.5f+0.5f*voltageLeft/MAX_VOLTAGE; if (dutyCycleLeft < MIN_DUTY_CYCLE) dutyCycleLeft = MIN_DUTY_CYCLE; else if (dutyCycleLeft > MAX_DUTY_CYCLE) dutyCycleLeft = MAX_DUTY_CYCLE; pwmLeft = dutyCycleLeft; float dutyCycleRight = 0.5f+0.5f*voltageRight/MAX_VOLTAGE; if (dutyCycleRight < MIN_DUTY_CYCLE) dutyCycleRight = MIN_DUTY_CYCLE; else if (dutyCycleRight > MAX_DUTY_CYCLE) dutyCycleRight = MAX_DUTY_CYCLE; pwmRight = dutyCycleRight; } int active = 0; float distanceStatic; int geradeaus_langsam(float distance) // Rückgabewert 1 -> distance erreicht { if(active == 0) { active = 1; distanceStatic = distance; counterLeft.reset(); counterRight.reset(); } if((counterLeft.read() - counterRight.read()) / 100.0f < distanceStatic) { desiredSpeedLeft = 1.5 + 30; desiredSpeedRight = 1.5 - 30; } else { desiredSpeedLeft = 0.0; desiredSpeedRight = 0.0; active = 0; return 1; } return 0; } int zurueck_langsam(float distance) // Rückgabewert 1 -> distance erreicht { if(active == 0) { active = 1; distanceStatic = distance; counterLeft.reset(); counterRight.reset(); } if((counterRight.read() - counterLeft.read()) / 100.0f < distanceStatic) { desiredSpeedLeft = 1.5 - 50; desiredSpeedRight = 1.5 + 50; } else { desiredSpeedLeft = 0.0; desiredSpeedRight = 0.0; active = 0; return 1; } return 0; } int geradeaus_schnell(float distance) // RRückgabewert 1 -> distance erreicht { if(active == 0) { active = 1; distanceStatic = distance; counterLeft.reset(); counterRight.reset(); } if((counterLeft.read() - counterRight.read()) / 100.0f < distanceStatic) { desiredSpeedLeft = 1.5 + 90; desiredSpeedRight = 1.5 - 90; } else { desiredSpeedLeft = 0.0; desiredSpeedRight = 0.0; active = 0; return 1; } return 0; } //--------------------Ausweichen------------------------------------------------ int a = 0; int statusAusweichen = 0; int zaehlerAusweichen = 0; int ausweichen() { if(statusAusweichen == 0) { if(sensorZentimeter[0] < 10) statusAusweichen = 1; //statusAusweichen 1 -> Wand vorne -> 90° rechts else if(sensorZentimeter[0] + sensorZentimeter[3] + sensorZentimeter[4] < 70) statusAusweichen = 2; //statusAusweichen 2 -> Ecke -> 90° rechts else if(sensorZentimeter[3] < 10) { if(a > 0) statusAusweichen = 9; //Spezial else statusAusweichen = 3; //statusAusweichen 3 -> Wand links -> 30° rechts } else if(sensorZentimeter[4] < 10) { if(a > 0) statusAusweichen = 9; //Spezial else statusAusweichen = 4; //statusAusweichen 4 -> Wand rechts -> 30° links } } switch(statusAusweichen) { case 0: //kein Hindernis a = 0; return 1; //Ausgewichen case 1: //Hindernis vorne case 2: //Ecke if(zaehlerAusweichen > 12) { statusAusweichen = 0; zaehlerAusweichen = 0; desiredSpeedLeft = 0; desiredSpeedRight = 0; } else { desiredSpeedLeft = 60; desiredSpeedRight = 60; zaehlerAusweichen++; } break; case 3: //Hindernis links if(zaehlerAusweichen > 4) { a++; statusAusweichen = 0; zaehlerAusweichen = 0; desiredSpeedLeft = 0; desiredSpeedRight = 0; } else { desiredSpeedLeft = 60; desiredSpeedRight = 60; zaehlerAusweichen++; } break; case 4: //Hindernis rechts if(zaehlerAusweichen > 4) { a++; statusAusweichen = 0; zaehlerAusweichen = 0; desiredSpeedLeft = 0; desiredSpeedRight = 0; } else { desiredSpeedLeft = -60; desiredSpeedRight = -60; zaehlerAusweichen++; } break; case 9: //Spezial 120° if(zaehlerAusweichen > 16) { a = 0; statusAusweichen = 0; zaehlerAusweichen = 0; desiredSpeedLeft = 0; desiredSpeedRight = 0; } else { desiredSpeedLeft = 60; desiredSpeedRight = 60; zaehlerAusweichen++; } break; } return 0; //Am ausweichen... } //--------------------Servos---------------------------------------------------- Servo Arm(PA_10); Servo Greifer(PC_4); Servo Deckel(PB_8); AnalogIn Red (PB_0); //Farbauswertung Rot AnalogIn Green (PA_4); //Farbauswertung Grün void aufheben() { enableSensor = 0; desiredSpeedLeft = 0.0f; desiredSpeedRight = 0.0f; for (int pos = 800; pos < 1400; pos += 25) { //Greifer öffnen Greifer.SetPosition(pos); wait_ms(7); } for (int pos = 440; pos < 2300; pos += 25) { //Arm Runter Arm.SetPosition(pos); wait_ms(7); } desiredSpeedLeft = 65.0f; desiredSpeedRight = -60.0f; wait_ms(400); for (int pos = 1400; pos > 800; pos -= 25) { //Greifer Schliessen Greifer.SetPosition(pos); wait_ms(80); } desiredSpeedLeft = 0.0f; desiredSpeedRight = 0.0f; if (Green>Red) { desiredSpeedLeft = -35.0f; desiredSpeedRight = 30.0f; wait(1.0f); desiredSpeedLeft = 0.0f; desiredSpeedRight = 00.0f; for (int pos = 2300; pos > 440; pos -= 30) { //Arm heben Arm.SetPosition(pos); wait_ms(5); } wait(0.1f); for (int pos = 800; pos < 1400; pos += 25) { //Greifer öffnen Greifer.SetPosition(pos); wait_ms(3); } } else if(Red>Green) { for (int pos = 1300; pos < 2250; pos += 25) { //Deckel schliessen Deckel.SetPosition(pos); wait_ms(2); } desiredSpeedLeft = -35.0f; desiredSpeedRight = 30.0f; wait(1.0f); desiredSpeedLeft = 0.0f; desiredSpeedRight = 00.0f; for (int pos = 2300; pos > 440; pos -= 25) { //Arm heben Arm.SetPosition(pos); wait_ms(9); } for (int pos = 800; pos < 1400; pos += 25) { //Greifer öffnen Greifer.SetPosition(pos); wait_ms(4); } for (int pos = 440; pos < 700; pos += 25) { //Arm Runter Arm.SetPosition(pos); wait_ms(5); } for (int pos = 2250; pos > 1300; pos -= 30) { //Deckel öffnen Deckel.SetPosition(pos); wait_ms(5); } for (int pos = 700; pos > 440; pos -= 25) { //Arm heben Arm.SetPosition(pos); wait_ms(5); } } else { for (int pos = 2300; pos > 1600; pos -= 25) { //Arm heben um alfällig eingeklemmte Klötze von den Sensoren zu entfernen Arm.SetPosition(pos); wait_ms(5); } desiredSpeedLeft = -40.0f; desiredSpeedRight = 30.0f; wait(1.0f); desiredSpeedLeft = 0.0f; desiredSpeedRight = 0.0f; for (int pos = 800; pos < 1400; pos += 25) { //Greifer öffnen Greifer.SetPosition(pos); wait_ms(2); } for (int pos = 1600; pos > 440; pos -= 25) { //Arm heben Arm.SetPosition(pos); wait_ms(5); } } enableSensor = 1; } //--------------------Status&Main----------------------------------------------- enum RobotState { // START = 0, FAHREN = 0, AUSWEICHEN, VORSUCHEN, SUCHEN, DREHUNGBACK, ANFAHREN, LADEN }; int main() { // Initialisieren der PWM Ausgaenge pwmLeft.period(0.00005f); // PWM Periode von 50 us pwmLeft.period(0.00005f); // Setzt die Periode auf 50 μs pwmRight.period(0.00005f); pwmLeft = 0.5f; // Duty-Cycle von 50% pwmRight.period(0.00005f); // PWM Periode von 50 us pwmRight = 0.5f; // Duty-Cycle von 50% // Initialisieren von lokalen Variabeln previousValueCounterLeft = counterLeft.read(); previousValueCounterRight = counterRight.read(); speedLeftFilter.setPeriod(PERIOD); speedLeftFilter.setFrequency(LOWPASS_FILTER_FREQUENCY); speedRightFilter.setPeriod(PERIOD); speedRightFilter.setFrequency(LOWPASS_FILTER_FREQUENCY); desiredSpeedLeft = 0.0f; //Initialisiere Geschwindigkeit auf 0 desiredSpeedRight = 0.0f; //Initialisiere Geschwindigkeit auf 0 actualSpeedLeft = 0.0f; actualSpeedRight = 0.0f; Ticker t1; t1.attach( &speedCtrl, PERIOD); int status = 0; //status definiert aktuellen Programmcode (0: Startprogramm, 1: Suchen, 2: Ausrichten, 3: Anfahren, 4: Aufnehmen) //Servos Greifer.Enable(1500,20000); Arm.Enable (440,20000); Deckel.Enable(1500,20000); //SensorArrays int z = 0; //Zähler int y = 0; float sensorLinks[500]; float sensorOben[500]; enableMotorDriver = 1; //Initialisiert Distanzsensoren und setzt sensorValue und sensorTiefbass auf NULL for( int i = 0; i < 6; i++) { sensors[i].init(&distance, &bit0, &bit1, &bit2, i); sensorMittelwert[i] = 0.0f; sensorTiefbass[i] = 0.0f; } enableSensor = 1; //Aktiviert die IRSensoren status = FAHREN; int timer = 0; led = 0; while(1) { //Lese Sensorwerte, Tiefpass Initialisierung sensorWerte(); timer++; wait(0.0125f); switch(status) { /* case START: //Start Sequenz status = FAHREN; break; */ case FAHREN: status = AUSWEICHEN; if(geradeaus_schnell(100)) { status = VORSUCHEN; } break; case AUSWEICHEN: if(ausweichen()) status = FAHREN; //Wenn fertig ausgewichen -> FAHREN break; case VORSUCHEN: led = 1; desiredSpeedLeft = 15.0f; //Drehung desiredSpeedRight = 15.0f; if(z<12) { //Schreibt die Sensorwerte in ein Array if(sensorZentimeter[0] > 60) sensorOben[z] = 60; else sensorOben[z] = sensorZentimeter[0]; sensorLinks[z] = sensorZentimeter[5]; z++; } else status = SUCHEN; break; case SUCHEN: //for(int i = 0; i < 10; i++) desiredSpeedLeft = 20.0f; //Drehung desiredSpeedRight = 20.0f; if(z < 500) { if(sensorZentimeter[0] > 60) sensorOben[z] = 60; //ACHTUUUUNG Z <500 und sensorOben = 60 else sensorOben[z] = sensorZentimeter[0]; sensorLinks[z] = sensorZentimeter[5]; //Prüft Ausschlag && vergleicht ersten mit letztem Wert && prüft Zwischenwerte if(3.0f * sensorLinks[z] > sensorLinks[z-7] + sensorLinks[z-6] + sensorLinks[z-5] + 13.5f && sensorLinks[z] + 1 > sensorLinks[z-12] && sensorLinks[z] >= sensorLinks[z-2] && sensorLinks[z] >= sensorLinks[z-3] && sensorLinks[z] >= sensorLinks[z-4] && sensorLinks[z-12] >= sensorLinks[z-10] && sensorLinks[z-12] >= sensorLinks[z-9] && sensorLinks[z-12] >= sensorLinks[z-8]) { // if(sensorLinks[z-7] + sensorLinks[z-6] + sensorLinks[z-5] > 3 * 33.5f) { //Prüft Hindernis if(sensorLinks[z-5] + 3.5f < sensorOben[z-5] && sensorLinks[z-6] + 3.5f < sensorOben[z-6] && sensorLinks[z-7] + 3.5f < sensorOben[z-7]) { status = DREHUNGBACK; z--; printf("\n\r"); // } } } z++; } else { z = 0; status = FAHREN; } break; case DREHUNGBACK: if(y < 5) { desiredSpeedLeft = -25.0f; //Drehung rückwärts desiredSpeedRight = -25.0f; y++; /* } else if {y < 30){ desiredSpeedLeft = 0.0f; //Stillstand für genauen Sensorwert desiredSpeedRight = 0.0f; y++; */ } else { y = 0; status = ANFAHREN; } break; case ANFAHREN: if(sensorLinks[z-6] < 15.0f) { if(zurueck_langsam(15.0f - sensorLinks[z-6])) { z = 0; status = LADEN; } } else if(geradeaus_langsam(sensorLinks[z-6] - 15.0f)) { //-15cm Roboterarm-Offset z = 0; status = LADEN; } break; case LADEN: aufheben(); desiredSpeedLeft = -50.0f; //Drehung rückwärts desiredSpeedRight = -50.0f; wait(0.1f); desiredSpeedLeft = 0.0f; //Stopp desiredSpeedRight = 0.0f; status = VORSUCHEN; break; } } }