Robot Car Project

Hauptprojekt.ino.cpp 27KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811
  1. #include <Arduino.h>
  2. #line 1 "c:\\Users\\Carolin\\Downloads\\VSCode\\Zumo32U4\\Zumo32U4\\Hauptprojekt\\Hauptprojekt.ino"
  3. #line 1 "c:\\Users\\Carolin\\Downloads\\VSCode\\Zumo32U4\\Zumo32U4\\Hauptprojekt\\Hauptprojekt.ino"
  4. //Verfassser: Felix Stange, 4056379, MET2016
  5. //Datum: erstellt am 19.07.2017, zuletzt geändert am 14.05.2018
  6. //Projektthema: Untersuchungen und Implementierung eines automatisierten Fahrens mittels Pololu Zumo
  7. /*Kurzbeschreibung: Der Zumo fährt automatisch zwischen 2 Linien ohne diese zu überfahren mithilfe
  8. der Liniensensoren (3), ähnlich einer Spurhalteautomatik (heller Belag und dunkle Streifen).
  9. Außerdem werden Kollisionen verhindert durch Nutzung der vorderen Abstandssensoren. Kommt es
  10. dennoch zu einer Kollision, wird diese durch den Beschleunigungssensor (LSM303) erkannt.
  11. Für den Überholvorgang werden die seitlichen Abstandssensoren und der Drehbewegungssensor (L3G)
  12. genutzt. Mithilfe der Quadraturencoder in den Motoren können Wegstrecken vermessen werden.
  13. Für die Filterung der Messwerte werden Medianfilter genutzt. Der Zumo kommuniziert über ein
  14. Bluetooth-Modul (HC-05) mit anderen Geräten. Die Kommunikation erfolgt seriell ('SERIAL' für USB,
  15. 'SERIAL1' für Bluetooth). Das LCD kann bei Bluetoothnutzung nicht verwendet werden.*/
  16. #include <Wire.h>
  17. #include <Zumo32U4.h>
  18. #include <MedianFilter.h>
  19. Zumo32U4ProximitySensors proxSensors; //Abstandssensoren
  20. Zumo32U4LineSensors lineSensors; //Liniensensoren
  21. Zumo32U4Motors motors; //Motoren
  22. Zumo32U4ButtonA buttonA; //Taste A
  23. Zumo32U4Encoders encoders; //Motorencoder
  24. LSM303 compass; //Beschleunigungssensor x-Achse
  25. L3G gyro; //Drehbewegungssensor z-Achse
  26. MedianFilter LineFilter0(3, 0); //erstellen der Filter für Liniensensoren
  27. MedianFilter LineFilter1(3, 0); //Medianfilter geben mittleren Wert einer Reihe aus
  28. MedianFilter LineFilter2(3, 0); //Fenstergröße: 3, Basiswerte: 0 0 0
  29. MedianFilter ProxFilter0(5, 0); //erstellen der Filter für Abstandssensoren
  30. MedianFilter ProxFilter1(5, 0);
  31. MedianFilter ProxFilter2(5, 0);
  32. MedianFilter ProxFilter3(5, 0);
  33. #define MARKLINE0 150
  34. #define MARKLINE1 100
  35. #define MARKLINE2 120
  36. #define SIGN0 500
  37. #define SIGN1 300
  38. #define SIGN2 500
  39. #define MAXSPEED 400
  40. #define FULLSPEEDLEFT 104
  41. #define HALFSPEEDLEFT 52
  42. #define SLOWSPEEDLEFT 26
  43. #define FULLSPEEDRIGHT 100
  44. #define HALFSPEEDRIGHT 50
  45. #define SLOWSPEEDRIGHT 25
  46. int16_t lineValue[3]; //Liniensensoren
  47. uint16_t lineOffset[3]; //von links (0) nach rechts (2)
  48. uint8_t proxValue[4]; //Abstandssensoren v.l. (0) n.r. (3)
  49. int16_t encoderCounts[2]; //Anzahl der Umdrehungen
  50. int16_t driveRotation[2]; //von links (0) nach rechts (1)
  51. int32_t rotationAngle = 0; //Drehwinkel
  52. int32_t turnAngle = 0;
  53. int16_t turnRate;
  54. int16_t gyroOffset;
  55. uint16_t gyroLastUpdate;
  56. //int32_t moveDisplay = 0; //Beschleunigung
  57. //int32_t moveDistance = 0;
  58. int16_t moveRate;
  59. int16_t compassOffset;
  60. //uint16_t compassLastUpdate;
  61. uint16_t lastUpdate = 0; //Systemzeit
  62. uint16_t eventTime = 0; //Zeit seit letzter Geschwindigkeitsänderung
  63. char report[200]; //Ausgabe
  64. float eventSpeed = 1; //vermindert die Geschwindigkeit bei Manövern
  65. int btData = 0; //Gelesene Daten aus Bluetooth
  66. bool alarm = false; //zeigt Manöver abhängig von btData
  67. /*-----------------------------------------------------------------*/
  68. //Setup Bluetoothverbindung
  69. #line 78 "c:\\Users\\Carolin\\Downloads\\VSCode\\Zumo32U4\\Zumo32U4\\Hauptprojekt\\Hauptprojekt.ino"
  70. void BlueSetup();
  71. #line 88 "c:\\Users\\Carolin\\Downloads\\VSCode\\Zumo32U4\\Zumo32U4\\Hauptprojekt\\Hauptprojekt.ino"
  72. void LineSetup();
  73. #line 117 "c:\\Users\\Carolin\\Downloads\\VSCode\\Zumo32U4\\Zumo32U4\\Hauptprojekt\\Hauptprojekt.ino"
  74. void ProxSetup();
  75. #line 123 "c:\\Users\\Carolin\\Downloads\\VSCode\\Zumo32U4\\Zumo32U4\\Hauptprojekt\\Hauptprojekt.ino"
  76. void GyroSetup();
  77. #line 156 "c:\\Users\\Carolin\\Downloads\\VSCode\\Zumo32U4\\Zumo32U4\\Hauptprojekt\\Hauptprojekt.ino"
  78. void CompassSetup();
  79. #line 187 "c:\\Users\\Carolin\\Downloads\\VSCode\\Zumo32U4\\Zumo32U4\\Hauptprojekt\\Hauptprojekt.ino"
  80. void setup();
  81. #line 213 "c:\\Users\\Carolin\\Downloads\\VSCode\\Zumo32U4\\Zumo32U4\\Hauptprojekt\\Hauptprojekt.ino"
  82. void TimeUpdate();
  83. #line 219 "c:\\Users\\Carolin\\Downloads\\VSCode\\Zumo32U4\\Zumo32U4\\Hauptprojekt\\Hauptprojekt.ino"
  84. void LoopTiming();
  85. #line 263 "c:\\Users\\Carolin\\Downloads\\VSCode\\Zumo32U4\\Zumo32U4\\Hauptprojekt\\Hauptprojekt.ino"
  86. void ProxUpdate();
  87. #line 294 "c:\\Users\\Carolin\\Downloads\\VSCode\\Zumo32U4\\Zumo32U4\\Hauptprojekt\\Hauptprojekt.ino"
  88. void LineUpdate();
  89. #line 304 "c:\\Users\\Carolin\\Downloads\\VSCode\\Zumo32U4\\Zumo32U4\\Hauptprojekt\\Hauptprojekt.ino"
  90. void GyroUpdate();
  91. #line 317 "c:\\Users\\Carolin\\Downloads\\VSCode\\Zumo32U4\\Zumo32U4\\Hauptprojekt\\Hauptprojekt.ino"
  92. void CompassUpdate();
  93. #line 330 "c:\\Users\\Carolin\\Downloads\\VSCode\\Zumo32U4\\Zumo32U4\\Hauptprojekt\\Hauptprojekt.ino"
  94. void EncoderUpdate();
  95. #line 341 "c:\\Users\\Carolin\\Downloads\\VSCode\\Zumo32U4\\Zumo32U4\\Hauptprojekt\\Hauptprojekt.ino"
  96. void Kontaktvermeiden();
  97. #line 360 "c:\\Users\\Carolin\\Downloads\\VSCode\\Zumo32U4\\Zumo32U4\\Hauptprojekt\\Hauptprojekt.ino"
  98. void Hindernisumfahren();
  99. #line 486 "c:\\Users\\Carolin\\Downloads\\VSCode\\Zumo32U4\\Zumo32U4\\Hauptprojekt\\Hauptprojekt.ino"
  100. void Abbiegen();
  101. #line 647 "c:\\Users\\Carolin\\Downloads\\VSCode\\Zumo32U4\\Zumo32U4\\Hauptprojekt\\Hauptprojekt.ino"
  102. void Spurhalten();
  103. #line 692 "c:\\Users\\Carolin\\Downloads\\VSCode\\Zumo32U4\\Zumo32U4\\Hauptprojekt\\Hauptprojekt.ino"
  104. void Spurfinden();
  105. #line 710 "c:\\Users\\Carolin\\Downloads\\VSCode\\Zumo32U4\\Zumo32U4\\Hauptprojekt\\Hauptprojekt.ino"
  106. void SerielleAusgabe();
  107. #line 725 "c:\\Users\\Carolin\\Downloads\\VSCode\\Zumo32U4\\Zumo32U4\\Hauptprojekt\\Hauptprojekt.ino"
  108. void loop();
  109. #line 78 "c:\\Users\\Carolin\\Downloads\\VSCode\\Zumo32U4\\Zumo32U4\\Hauptprojekt\\Hauptprojekt.ino"
  110. void BlueSetup()
  111. {
  112. Serial1.begin(9600); //Initialisierung mit Datengeschwindigkeit(Baud)
  113. Serial1.setTimeout(10); //verkürzt Serial(1).read auf 10 ms statt 1000 ms
  114. if(Serial1.available()) Serial.println("Bluetoothverbindung hergestellt");
  115. if(Serial1.available() > 0) Serial1.read(); //Verwerfen der alten Informationen aus dem Puffer
  116. Serial1.print(0);
  117. }
  118. //Setup Liniensensoren
  119. void LineSetup()
  120. {
  121. ledYellow(1);
  122. lineSensors.initThreeSensors(); //Initialisierung von 3 Sensoren (max 5)
  123. //Kalibrierung
  124. uint32_t total[3] = {0, 0, 0};
  125. for(uint8_t i = 0; i < 120; i++)
  126. {
  127. if (i > 30 && i <= 90) motors.setSpeeds(FULLSPEEDLEFT, -FULLSPEEDRIGHT);
  128. else motors.setSpeeds(-FULLSPEEDLEFT, FULLSPEEDRIGHT);
  129. lineSensors.read(lineOffset);
  130. total[0] += lineOffset[0];
  131. total[1] += lineOffset[1];
  132. total[2] += lineOffset[2];
  133. lineSensors.calibrate();
  134. }
  135. motors.setSpeeds(0, 0);
  136. lineOffset[0] = total[0] / 120;
  137. lineOffset[1] = total[1] / 120;
  138. lineOffset[2] = total[2] / 120;
  139. ledYellow(0);
  140. // lineOffset[0] = 240;
  141. // lineOffset[1] = 120;
  142. // lineOffset[2] = 220;
  143. }
  144. //Setup Abstandssensoren
  145. void ProxSetup()
  146. {
  147. proxSensors.initThreeSensors();
  148. }
  149. //Setup Drehbewegungssensor
  150. void GyroSetup()
  151. {
  152. ledYellow(1);
  153. gyro.init(); //Initialisierung
  154. if(!gyro.init()) //Fehlerabfrage
  155. {
  156. //Fehler beim Initialisieren des Drehbewegungssensors
  157. ledRed(1);
  158. while(1)
  159. {
  160. Serial.println("Fehler Drehbewegungssensors");
  161. delay(5000);
  162. }
  163. }
  164. gyro.writeReg(L3G::CTRL1, 0b11111111); //Ausgaberate 800Hz, Tiefpassfilter 100Hz
  165. gyro.writeReg(L3G::CTRL4, 0b00100000); //2000dps Auflösung
  166. gyro.writeReg(L3G::CTRL5, 0b00000000); //Hochpassfilter ausgeschaltet
  167. //Kalibrierung
  168. int32_t total = 0;
  169. for(uint16_t i = 0; i < 1024; i++)
  170. {
  171. while(!gyro.readReg(L3G::STATUS_REG) & 0x08); //Fehlerabfrage
  172. gyro.read();
  173. total += gyro.g.z;
  174. }
  175. gyroOffset = total / 1024;
  176. gyroLastUpdate = micros();
  177. ledYellow(0);
  178. }
  179. //Setup Beschleunigungssensor
  180. void CompassSetup()
  181. {
  182. ledYellow(1);
  183. compass.init(); //Initialisierung
  184. if(!compass.init()) //Fehlerabfrage
  185. {
  186. //Fehler beim Initialisieren des Beschleunigungssensors
  187. ledRed(1);
  188. while(1)
  189. {
  190. Serial.println("Fehler Beschleunigungssensors");
  191. delay(5000);
  192. }
  193. }
  194. compass.enableDefault();
  195. //Kalibrierung
  196. int32_t total = 0;
  197. for (uint16_t i = 0; i < 1024; i++)
  198. {
  199. compass.read();
  200. total += compass.a.x;
  201. }
  202. compassOffset = total / 1024;
  203. //compassLastUpdate = micros();
  204. ledYellow(0);
  205. }
  206. /*-----------------------------------------------------------------*/
  207. void setup()
  208. {
  209. //Initialisierung der Bluetoothverbindung
  210. BlueSetup();
  211. //Initialisierung und Kalibrierung der Sensoren
  212. //Serial1.println("Sensorkalibrierung");
  213. Wire.begin();
  214. delay(500);
  215. ProxSetup();
  216. LineSetup();
  217. GyroSetup();
  218. CompassSetup();
  219. //Zumo bereit zu starten
  220. //Serial1.println("Zumo bereit, starte mit A");
  221. ledGreen(1);
  222. buttonA.waitForButton();
  223. randomSeed(millis());
  224. delay(500);
  225. //Serial1.println("Start");
  226. }
  227. /*-----------------------------------------------------------------*/
  228. //Update Durchlaufzeit
  229. void TimeUpdate()
  230. {
  231. uint16_t m = millis();
  232. eventTime = m - lastUpdate;
  233. }
  234. void LoopTiming()
  235. {
  236. const int AL = 100; // Arraylänge, NUR GERADE Zahlen verwenden!
  237. static unsigned long LoopTime[AL];
  238. static unsigned int Index=0, Messung=0, Min=0xFFFF, Max, Avg;
  239. if (Messung % 2 == 0) // wenn Messung X gerade (0,2,4,6 usw.), entspricht immer Anfang der Loop
  240. {
  241. LoopTime[Index] = millis();
  242. Messung++;
  243. Index++;
  244. return; // Funktion sofort beenden, spart etwas Zeit
  245. }
  246. if (Messung % 2 == 1) // wenn Messung X ungerade (1,3,5,7 usw.), entspricht immer Ende der Loop
  247. {
  248. LoopTime[Index] = millis();
  249. LoopTime[Index-1] = LoopTime[Index] - LoopTime[Index-1]; // Loopdauer einen Index niedriger einspeichern wie aktuell
  250. Messung++;
  251. }
  252. if (Index >= AL) // Array voll, Daten auswerten
  253. {
  254. for (int i = 0; i<AL; i++)
  255. {
  256. Min = min(Min, LoopTime[i]);
  257. Max = max(Max, LoopTime[i]);
  258. Avg += LoopTime[i];
  259. }
  260. Avg = Avg / AL;
  261. Serial1.print(F("Minimal "));Serial1.print(Min);Serial1.println(" ms ");
  262. Serial1.print(F("Durchschnitt "));Serial1.print(Avg);Serial1.println(" ms ");
  263. Serial1.print(F("Maximal "));Serial1.print(Max);Serial1.println(" ms ");
  264. SerielleAusgabe();
  265. Min = 0xFFFF;
  266. Max = 0;
  267. Avg = 0;
  268. Messung = 0;
  269. Index = 0;
  270. }
  271. }
  272. //Update Abstandssensoren
  273. void ProxUpdate()
  274. {
  275. bool done = false;
  276. int state = LOW;
  277. while(done == false)
  278. {
  279. //wiederholt abfragen, ob bereits gesendet wird (Dauer je 1000 us bzw. 1 ms)
  280. if(pulseIn(20, state, 1000) == 0 && pulseIn(22, state, 1000) == 0 && pulseIn(4, state, 1000) == 0)
  281. //if(pulseIn(22, state, 1000) > 0)
  282. {
  283. //wenn nichts gesendet wird, selbst Messung durchführen
  284. proxSensors.read();
  285. proxValue[0] = ProxFilter0.in(proxSensors.countsLeftWithLeftLeds());
  286. proxValue[1] = ProxFilter1.in(proxSensors.countsFrontWithLeftLeds());
  287. proxValue[2] = ProxFilter2.in(proxSensors.countsFrontWithRightLeds());
  288. proxValue[3] = ProxFilter3.in(proxSensors.countsRightWithRightLeds());
  289. // Serial.println(proxValue[0]);
  290. // Serial.println(proxValue[1]);
  291. // Serial.println(proxValue[2]);
  292. // Serial.println(proxValue[3]);
  293. done = true;
  294. }
  295. else
  296. {
  297. //solange fremde Signale empfangen werden, Fehler ausgeben
  298. Serial.println("Fremdmessung erkannt");
  299. }
  300. }
  301. }
  302. //Update Liniensensoren
  303. void LineUpdate()
  304. {
  305. uint16_t lineRaw[3];
  306. lineSensors.read(lineRaw); //lese Messwerte der Liniensensoren aus
  307. lineValue[0] = LineFilter0.in(lineRaw[0] - lineOffset[0]); //ziehe Offsetwerte von Messwerten ab und gib diese in Filter ein
  308. lineValue[1] = LineFilter1.in(lineRaw[1] - lineOffset[1]); //erhält neue mittlere Werte der Filter
  309. lineValue[2] = LineFilter2.in(lineRaw[2] - lineOffset[2]); //"LineFilter.out" um gefilterte Werte auszugeben ohne neue Werte einzugeben
  310. }
  311. //Update Drehbewegungssensor
  312. void GyroUpdate()
  313. {
  314. gyro.read(); //Rohwert 10285 entspricht 90° bzw.
  315. turnRate = gyro.g.z - gyroOffset; //8,75mdps/LSB
  316. uint16_t m = micros();
  317. uint16_t dt = m - gyroLastUpdate;
  318. gyroLastUpdate = m;
  319. int32_t d = (int32_t)turnRate * dt;
  320. turnAngle += (int64_t)d * 14680064 / 17578125;
  321. rotationAngle = (((int32_t)turnAngle >> 16) * 360) >> 16;
  322. }
  323. //Update Beschleunigungssensor
  324. void CompassUpdate()
  325. {
  326. compass.read(); //Rohwert 16384 entspricht 1g (9,81m/s²) bzw.
  327. moveRate = compass.a.x - compassOffset; //bei +/-2g Messbereich 0,61mg/LSB
  328. // uint16_t m = micros();
  329. // uint16_t dt = m - compassLastUpdate;
  330. // compassLastUpdate = m;
  331. // int32_t d = (int32_t)moveRate * dt;
  332. // moveDistance += (int64_t)d * dt >> 14;
  333. // moveDisplay = moveDistance * 9,81 / 1000;
  334. }
  335. //Update Encoder
  336. void EncoderUpdate()
  337. {
  338. encoderCounts[0] = encoders.getCountsLeft();
  339. driveRotation[0] = encoderCounts[0] / 910; //12cpr (Motorwelle) * 75,81:1 (Getriebe) = 909,7cpr (Antriebszahnrad)
  340. encoderCounts[1] = encoders.getCountsRight();
  341. driveRotation[1] = encoderCounts[1] / 910;
  342. }
  343. /*-----------------------------------------------------------------*/
  344. //Funktion Kontaktvermeiden
  345. void Kontaktvermeiden()
  346. {
  347. //Serial1.println("Kontaktvermeiden");
  348. Serial1.print(1);
  349. ledRed(1);
  350. motors.setSpeeds(0, 0);
  351. delay(1000);
  352. while(proxValue[1] == 0 || proxValue[2] == 0)
  353. {
  354. ProxUpdate();
  355. motors.setSpeeds(-HALFSPEEDLEFT, -HALFSPEEDRIGHT);
  356. if(lineValue[0] > MARKLINE0 || lineValue[2] > MARKLINE2) break;
  357. }
  358. motors.setSpeeds(0, 0);
  359. //Serial1.println("Vermeiden beendet");
  360. Serial1.print(0);
  361. }
  362. //Funktion Hindernisumfahrung
  363. void Hindernisumfahren()
  364. {
  365. //Serial1.println("Hindernisumfahren");
  366. Serial1.print(1);
  367. ledYellow(1);
  368. //Schritt 1: Spurwechsel links
  369. //links drehen
  370. turnAngle = 0;
  371. rotationAngle = 0;
  372. GyroUpdate();
  373. while(rotationAngle < 20)
  374. {
  375. GyroUpdate();
  376. LineUpdate();
  377. motors.setSpeeds(SLOWSPEEDLEFT, FULLSPEEDRIGHT);
  378. }
  379. GyroUpdate();
  380. while(rotationAngle < 45)
  381. {
  382. GyroUpdate();
  383. LineUpdate();
  384. motors.setSpeeds(SLOWSPEEDLEFT, FULLSPEEDRIGHT);
  385. if(lineValue[2] > MARKLINE2 && lineValue[2] < SIGN2) break;
  386. }
  387. //geradeaus über Mittellinie fahren
  388. LineUpdate();
  389. while(lineValue[2] < MARKLINE2)
  390. {
  391. LineUpdate();
  392. motors.setSpeeds(FULLSPEEDLEFT, FULLSPEEDRIGHT);
  393. //if(lineValue[0] > MARKLINE0) break;
  394. }
  395. //rechts drehen
  396. GyroUpdate();
  397. while(rotationAngle > 10)
  398. {
  399. GyroUpdate();
  400. LineUpdate();
  401. if(lineValue[0] > MARKLINE0 && lineValue[0] < SIGN0) motors.setSpeeds(FULLSPEEDLEFT, 0);
  402. else if(lineValue[2] > MARKLINE2 && lineValue[2] < SIGN2) motors.setSpeeds(FULLSPEEDLEFT, FULLSPEEDRIGHT);
  403. else motors.setSpeeds(FULLSPEEDLEFT, SLOWSPEEDRIGHT);
  404. }
  405. //geradeaus fahren
  406. motors.setSpeeds(FULLSPEEDLEFT, FULLSPEEDRIGHT);
  407. //Gegenverkehr beachten
  408. ProxUpdate();
  409. //if(proxValue[1] < 5 || proxValue[2] < 5)
  410. //{
  411. //Schritt 2: Hindernis passieren
  412. //Serial1.println("Aufholen");
  413. lastUpdate = millis();
  414. while(proxValue[3] < 6)
  415. {
  416. ProxUpdate();
  417. LineUpdate();
  418. Spurhalten();
  419. TimeUpdate();
  420. //Serial1.println(eventTime);
  421. if(eventTime > 3000) break;
  422. }
  423. //Serial1.println("Vorbeifahren");
  424. ProxUpdate();
  425. while(proxValue[3] == 6)
  426. {
  427. ProxUpdate();
  428. LineUpdate();
  429. Spurhalten();
  430. }
  431. //Serial1.println("Abstand gewinnen");
  432. lastUpdate = millis();
  433. TimeUpdate();
  434. while(eventTime < 3000)
  435. {
  436. LineUpdate();
  437. Spurhalten();
  438. TimeUpdate();
  439. //Serial1.println(eventTime);
  440. }
  441. //}
  442. //Schritt 3: Spurwechsel rechts
  443. //rechts drehen
  444. turnAngle = 0;
  445. rotationAngle = 0;
  446. GyroUpdate();
  447. while(rotationAngle > -20)
  448. {
  449. GyroUpdate();
  450. LineUpdate();
  451. motors.setSpeeds(FULLSPEEDLEFT, SLOWSPEEDRIGHT);
  452. }
  453. GyroUpdate();
  454. while(rotationAngle > -45)
  455. {
  456. GyroUpdate();
  457. LineUpdate();
  458. motors.setSpeeds(FULLSPEEDLEFT, SLOWSPEEDRIGHT);
  459. if(lineValue[0] > MARKLINE0 && lineValue[0] < SIGN0) break;
  460. }
  461. //geradeaus über Mittellinie fahren
  462. LineUpdate();
  463. while(lineValue[0] < MARKLINE0)
  464. {
  465. LineUpdate();
  466. motors.setSpeeds(FULLSPEEDLEFT, FULLSPEEDRIGHT);
  467. //if(lineValue[0] > MARKLINE0) break;
  468. }
  469. //links drehen
  470. GyroUpdate();
  471. while(rotationAngle < -10)
  472. {
  473. GyroUpdate();
  474. LineUpdate();
  475. if(lineValue[2] > MARKLINE2 && lineValue[2] < SIGN2) motors.setSpeeds(0, FULLSPEEDRIGHT);
  476. else if(lineValue[0] > MARKLINE0 && lineValue[0] < SIGN0) motors.setSpeeds(FULLSPEEDLEFT, FULLSPEEDRIGHT);
  477. else motors.setSpeeds(SLOWSPEEDLEFT, FULLSPEEDRIGHT);
  478. }
  479. //geradeaus fahren
  480. //Serial1.println("Umfahren beendet");
  481. Serial1.print(0);
  482. motors.setSpeeds(FULLSPEEDLEFT, FULLSPEEDRIGHT);
  483. }
  484. //Funktion Abbiegen
  485. void Abbiegen()
  486. {
  487. ledYellow(1);
  488. //Serial1.println("Abbiegen");
  489. Serial1.print(1);
  490. //Markierung analysieren
  491. LineUpdate();
  492. bool leftCode; //links => 1
  493. bool rightCode; //rechts => 2
  494. if((lineValue[0] > SIGN0 && lineValue[0] < 1600) && (lineValue[1] > SIGN1 && lineValue[1] < 800)) leftCode = true;
  495. else leftCode = false;
  496. if((lineValue[2] > SIGN2 && lineValue[2] < 1600) && (lineValue[1] > SIGN1 && lineValue[1] < 800)) rightCode = true;
  497. else rightCode = false;
  498. //Zufallszahl erzeugen
  499. uint8_t randy; //geradeaus => 0
  500. if(leftCode == true && rightCode == true) randy = random(1, 3); //1, 2
  501. else if(leftCode == true && rightCode == false) //randy = 1;
  502. {
  503. randy = random(0, 2); //0, 1
  504. //if(randy == 0) randy = random(0, 2); //erhöht Wahrscheinlickeit abzubiegen
  505. }
  506. else if(leftCode == false && rightCode == true) //randy = 2;
  507. {
  508. randy = random(0, 2); //0, 1
  509. //if(randy == 0) randy = random(0, 2); //erhöht Wahrscheinlickeit abzubiegen
  510. if(randy == 1) randy = 2; //!1 => 2
  511. }
  512. //links Abbiegen (von der Verbindungsstrecke)
  513. if(randy == 1 && rightCode == true)
  514. {
  515. //Serial1.println("links Abbiegen von der Verbindungsstrecke");
  516. //geradeaus zur Mittellinie fahren
  517. motors.setSpeeds(FULLSPEEDLEFT, FULLSPEEDRIGHT+10);
  518. lastUpdate = millis();
  519. TimeUpdate();
  520. while(eventTime < 1000)
  521. {
  522. TimeUpdate();
  523. motors.setSpeeds(FULLSPEEDLEFT, FULLSPEEDRIGHT+10);
  524. }
  525. LineUpdate();
  526. while(lineValue[0] < MARKLINE0 && lineValue[2] < MARKLINE2)
  527. {
  528. LineUpdate();
  529. motors.setSpeeds(FULLSPEEDLEFT, FULLSPEEDRIGHT);
  530. }
  531. //links drehen
  532. turnAngle = 0;
  533. rotationAngle = 0;
  534. GyroUpdate();
  535. while(rotationAngle < 90)
  536. {
  537. GyroUpdate();
  538. LineUpdate();
  539. if(lineValue[2] > MARKLINE2 && lineValue[2] < SIGN2) motors.setSpeeds(0, FULLSPEEDRIGHT);
  540. else if(lineValue[0] > MARKLINE0 && lineValue[0] < SIGN0) motors.setSpeeds(HALFSPEEDLEFT, FULLSPEEDRIGHT);
  541. else motors.setSpeeds(SLOWSPEEDLEFT, FULLSPEEDRIGHT);
  542. }
  543. //geradeaus fahren
  544. motors.setSpeeds(FULLSPEEDLEFT, FULLSPEEDRIGHT);
  545. }
  546. //links Abbiegen (vom Rundkurs)
  547. else if(randy == 1 && leftCode == true)
  548. {
  549. //Serial1.println("links Abbiegen vom Rundkurs");
  550. //links drehen
  551. turnAngle = 0;
  552. rotationAngle = 0;
  553. driveRotation[1] = 0;
  554. GyroUpdate();
  555. while(rotationAngle < 40)
  556. {
  557. GyroUpdate();
  558. EncoderUpdate();
  559. motors.setSpeeds(SLOWSPEEDLEFT, FULLSPEEDRIGHT);
  560. //if(driveRotation[1] > 1) break;
  561. }
  562. driveRotation[1] = 0;
  563. GyroUpdate();
  564. while(rotationAngle < 85)
  565. {
  566. GyroUpdate();
  567. EncoderUpdate();
  568. motors.setSpeeds(SLOWSPEEDLEFT, FULLSPEEDRIGHT);
  569. //if(driveRotation[1] > 1) break;
  570. }
  571. //geradeaus fahren
  572. motors.setSpeeds(FULLSPEEDLEFT, FULLSPEEDRIGHT);
  573. lastUpdate = millis();
  574. TimeUpdate();
  575. while(eventTime < 1000)
  576. {
  577. TimeUpdate();
  578. LineUpdate();
  579. if(lineValue[2] > MARKLINE2 && lineValue[2] < SIGN2) break;
  580. }
  581. lastUpdate = millis();
  582. TimeUpdate();
  583. while(eventTime < 1000)
  584. {
  585. TimeUpdate();
  586. LineUpdate();
  587. Spurhalten();
  588. }
  589. }
  590. //rechts Abbiegen
  591. else if(randy == 2 && rightCode == true)
  592. {
  593. //Serial1.println("rechts Abbiegen");
  594. //rechts drehen
  595. turnAngle = 0;
  596. rotationAngle = 0;
  597. driveRotation[0] = 0;
  598. GyroUpdate();
  599. while(rotationAngle > -40)
  600. {
  601. GyroUpdate();
  602. EncoderUpdate();
  603. LineUpdate();
  604. motors.setSpeeds(FULLSPEEDLEFT, SLOWSPEEDRIGHT);
  605. if(lineValue[0] > MARKLINE0 && lineValue[0] < SIGN0) break;
  606. }
  607. GyroUpdate();
  608. lastUpdate = millis();
  609. while(rotationAngle > -85)
  610. {
  611. TimeUpdate();
  612. GyroUpdate();
  613. LineUpdate();
  614. if(eventTime > 3000) break;
  615. if(lineValue[0] > MARKLINE0 && lineValue[0] < SIGN0) motors.setSpeeds(FULLSPEEDLEFT, 0);
  616. //else if(lineValue[1] > MARKLINE1 && lineValue[1] < SIGN1) motors.setSpeeds(-SLOWSPEEDLEFT, -SLOWSPEEDRIGHT);
  617. else if(lineValue[2] > MARKLINE2 && lineValue[2] < SIGN2) motors.setSpeeds(FULLSPEEDLEFT, HALFSPEEDRIGHT);
  618. else motors.setSpeeds(FULLSPEEDLEFT, SLOWSPEEDRIGHT);
  619. }
  620. }
  621. //nicht Abbiegen, geradeaus fahren
  622. else
  623. {
  624. //Serial1.println("nicht Abbiegen");
  625. motors.setSpeeds(FULLSPEEDLEFT, FULLSPEEDRIGHT);
  626. lastUpdate = millis();
  627. TimeUpdate();
  628. while(eventTime < 1000)
  629. {
  630. TimeUpdate();
  631. LineUpdate();
  632. Spurhalten();
  633. }
  634. }
  635. //Serial1.println("Abbiegen beendet");
  636. Serial1.print(0);
  637. }
  638. //Funktion Spurhalten
  639. void Spurhalten()
  640. {
  641. uint16_t StartTime = millis();
  642. uint16_t Update = millis();
  643. uint16_t Time = Update - StartTime;
  644. //linke Linie erreicht, nach rechts fahren
  645. if(lineValue[0] > MARKLINE0 && lineValue[0] < SIGN0)
  646. {
  647. ledYellow(1);
  648. //Serial1.println("Spur nach rechts korrigieren");
  649. motors.setSpeeds(FULLSPEEDLEFT/eventSpeed, SLOWSPEEDRIGHT/eventSpeed);
  650. while(Time < 100)
  651. {
  652. Update = millis();
  653. Time = Update - StartTime;
  654. LineUpdate();
  655. if(lineValue[2] > MARKLINE2) break;
  656. }
  657. }
  658. //rechte Linie erreicht, nach links fahren
  659. else if(lineValue[2] > MARKLINE2 && lineValue[2] < SIGN2)
  660. {
  661. ledYellow(1);
  662. //Serial1.println("Spur nach links korrigieren");
  663. motors.setSpeeds(SLOWSPEEDLEFT/eventSpeed, FULLSPEEDRIGHT/eventSpeed);
  664. while(Time < 100)
  665. {
  666. Update = millis();
  667. Time = Update - StartTime;
  668. LineUpdate();
  669. if(lineValue[0] > MARKLINE0) break;
  670. }
  671. }
  672. //normale Fahrt
  673. else
  674. {
  675. ledGreen(1);
  676. motors.setSpeeds(FULLSPEEDLEFT/eventSpeed, FULLSPEEDRIGHT/eventSpeed);
  677. }
  678. }
  679. //Funktion Spurfinden
  680. void Spurfinden()
  681. {
  682. ledRed(1);
  683. //Serial1.println("Spurfinden");
  684. Serial1.print(1);
  685. lastUpdate = millis();
  686. while(lineValue[0] < MARKLINE0 && lineValue[2] < MARKLINE2) //Zumo fährt solange rückwärst bis er wieder auf der Spur steht
  687. {
  688. TimeUpdate();
  689. LineUpdate();
  690. motors.setSpeeds(-FULLSPEEDLEFT, -FULLSPEEDRIGHT);
  691. if(eventTime > 3000) break;
  692. }
  693. //Serial1.println("Spur gefunden");
  694. Serial1.print(0);
  695. }
  696. //Funktion Serielle Ausgabe
  697. void SerielleAusgabe()
  698. {
  699. snprintf_P(report, sizeof(report),
  700. PSTR("Abstand: %d %d %d %d Linie: %d %d %d"),
  701. proxValue[0], proxValue[1], proxValue[2], proxValue[3],
  702. lineValue[0], lineValue[1], lineValue[2]);
  703. Serial1.println(report);
  704. snprintf_P(report, sizeof(report),
  705. PSTR("Weg: %d %d Winkel: %d Beschleunigung: %d"),
  706. driveRotation[0], driveRotation[1], rotationAngle, moveRate);
  707. Serial1.println(report);
  708. }
  709. /*-----------------------------------------------------------------*/
  710. void loop()
  711. {
  712. //LoopTiming(); //Zykluszeit beträgt max. 20ms im Idle
  713. ledGreen(0);
  714. ledYellow(0);
  715. ledRed(0);
  716. //Abfragen der Sensordaten
  717. ProxUpdate();
  718. EncoderUpdate();
  719. GyroUpdate();
  720. CompassUpdate();
  721. LineUpdate();
  722. TimeUpdate();
  723. //Funktionsauswahl
  724. //btData = Serial1.readString();
  725. if(Serial1.available() > 0) btData = Serial1.read();
  726. if(btData == '1') alarm = true;
  727. else if(btData == '0') alarm = false;
  728. //verfügbare Funktionen bei laufenden Manövern
  729. //if(btData == "Abbiegen" || btData == "Hindernisumfahren" || btData == "Kontaktvermeiden"|| btData == "Spurfinden")
  730. if(alarm == true)
  731. {
  732. //Serial1.println("Verstanden");
  733. eventSpeed = 1.4;
  734. if(moveRate > 1500 || (proxValue[1] == 6 && proxValue[2] == 6) || lineValue[0] > SIGN0 || lineValue[2] > SIGN2 || lineValue[1] > MARKLINE1) motors.setSpeeds(0, 0);
  735. else Spurhalten();
  736. }
  737. //verfügbare Funktionen im Normalfall
  738. else
  739. {
  740. eventSpeed = 1.0;
  741. //if(abs(moveRate) > 1500 && eventTime > 1000) Kontaktvermeiden();
  742. if(proxValue[1] == 6 && proxValue[2] == 6) Hindernisumfahren();
  743. else if((lineValue[0] > SIGN0 && lineValue[0] < 1600) && (lineValue[1] > SIGN1 && lineValue[1] < 800)) Abbiegen();
  744. else if((lineValue[2] > SIGN2 && lineValue[2] < 1600) && (lineValue[1] > SIGN1 && lineValue[1] < 800)) Abbiegen();
  745. else if(lineValue[1] > MARKLINE1 && lineValue[1] < SIGN1) Spurfinden();
  746. else Spurhalten();
  747. }
  748. //LoopTiming();
  749. }