Hauptprojekt.ino 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. //Verfassser: Felix Stange 4056379 MET2016
  2. //Datum: 19.07.2017 erstellt, 20.10.2017 zuletzt geändert
  3. //Projekt: Der Zumo fährt automatisch zwischen 2 Linien ohne diese zu überfahren mithilfe der
  4. //Liniensensoren (3), ähnlich einer Spurhalteautomatik (dunkler Belag und helle Streifen).
  5. //Außerdem werden Kollisionen verhindert durch Nutzung der vorderen Abstandssensoren. Kommt es
  6. //dennoch zu einer Kollision, wird diese durch die Beschleunigungssensoren (LSM303) erkannt.
  7. //Für den Überholvorgang werden die seitlichen Abstandssensoren und der Drehbewegungssensor (L3G)
  8. //genutzt. Mithilfe der Quadraturencoder in den Motoren können Wegstrecken vermessen werden.
  9. //Der Zumo kommuniziert über ein Bluetooth-Modul (HC-05) mit anderen Geräten. Die
  10. //Kommunikation erfolgt seriell ('SERIAL' für USB, 'SERIAL1' für Bluetooth).
  11. //Das LCD kann bei Bluetoothnutzung nicht verwendet werden.
  12. #include <Wire.h>
  13. #include <Zumo32U4.h>
  14. Zumo32U4ProximitySensors proxSensors; //Abstandssensoren
  15. Zumo32U4LineSensors lineSensors; //Liniensensoren
  16. Zumo32U4Motors motors;
  17. Zumo32U4ButtonA buttonA;
  18. Zumo32U4Encoders encoders; //Motorencoder
  19. LSM303 compass; //Beschleunigungssensor x-Achse
  20. L3G gyro; //Drehbewegungssensor z-Achse
  21. uint16_t lineValue[3]; //von links (0) nach rechts (2)
  22. uint16_t lineOffset[3];
  23. uint16_t lineRaw[3];
  24. uint8_t proxValue[4]; //von links (0) nach rechts (3)
  25. int16_t encoderCounts[2]; //von links (0) nach rechts (1)
  26. int16_t driveRotation[2];
  27. int32_t rotationAngle = 0; //Drehwinkel
  28. int32_t turnAngle = 0;
  29. int16_t turnRate;
  30. int16_t gyroOffset;
  31. uint16_t gyroLastUpdate;
  32. int32_t moveDisplay = 0; //Beschleunigung
  33. int32_t moveDistance = 0;
  34. int16_t moveRate;
  35. int16_t compassOffset;
  36. uint16_t compassLastUpdate;
  37. uint8_t randy; //Richtungsauswahl Abbiegen geradeaus => 0
  38. bool leftCode; // links => 1
  39. bool rightCode; // rechts => 2
  40. int maxSpeed = 200; //Maximale Geschwindigkeit (möglich 400)
  41. char dir = '0'; //Fahrtrichtung, Ereignis
  42. char report[200]; //Ausgabe
  43. /*-----------------------------------------------------------------*/
  44. //Setup Liniensensoren
  45. void LineSetup()
  46. {
  47. ledYellow(1);
  48. lineSensors.initThreeSensors();
  49. //Kalibrierung
  50. uint32_t total[3] = {0, 0, 0};
  51. for(uint8_t i = 0; i < 120; i++)
  52. {
  53. if (i > 30 && i <= 90) motors.setSpeeds(maxSpeed, -maxSpeed);
  54. else motors.setSpeeds(-maxSpeed, maxSpeed);
  55. lineSensors.read(lineOffset);
  56. total[0] += lineOffset[0];
  57. total[1] += lineOffset[1];
  58. total[2] += lineOffset[2];
  59. lineSensors.calibrate();
  60. }
  61. ledYellow(0);
  62. motors.setSpeeds(0, 0);
  63. lineOffset[0] = total[0] / 120;
  64. lineOffset[1] = total[1] / 120;
  65. lineOffset[2] = total[2] / 120;
  66. }
  67. //Setup Abstandssensoren
  68. void ProxSetup()
  69. {
  70. proxSensors.initThreeSensors();
  71. }
  72. //Setup Drehbewegungssensor
  73. void GyroSetup()
  74. {
  75. ledYellow(1);
  76. gyro.init();
  77. gyro.writeReg(L3G::CTRL1, 0b11111111); //Ausgaberate 800Hz, Tiefpassfilter 100Hz
  78. gyro.writeReg(L3G::CTRL4, 0b00100000); //2000dps Auflösung
  79. gyro.writeReg(L3G::CTRL5, 0b00000000); //Hochpassfilter ausgeschaltet
  80. //Kalibrierung
  81. int32_t total = 0;
  82. for (uint16_t i = 0; i < 1024; i++)
  83. {
  84. while(!gyro.readReg(L3G::STATUS_REG) & 0x08);
  85. gyro.read();
  86. total += gyro.g.z;
  87. }
  88. gyroOffset = total / 1024;
  89. gyroLastUpdate = micros();
  90. ledYellow(0);
  91. }
  92. //Setup Beschleunigungssensor
  93. void CompassSetup()
  94. {
  95. ledYellow(1);
  96. compass.init();
  97. compass.enableDefault();
  98. //Kalibrierung
  99. int32_t total = 0;
  100. for (uint16_t i = 0; i < 1024; i++)
  101. {
  102. compass.read();
  103. total += compass.a.x;
  104. }
  105. compassOffset = total / 1024;
  106. compassLastUpdate = micros();
  107. ledYellow(0);
  108. }
  109. /*-----------------------------------------------------------------*/
  110. void setup()
  111. {
  112. //Initialisierung der Bluetoothverbindung
  113. Serial1.begin(9600);
  114. if(Serial1.available()) Serial1.println("bluetooth available");
  115. //Initialisierung und Kalibrierung der Sensoren
  116. Serial1.println("sensor calibration, dont touch");
  117. Wire.begin();
  118. delay(500);
  119. ProxSetup();
  120. LineSetup();
  121. GyroSetup();
  122. CompassSetup();
  123. //Zumo bereit zu starten
  124. Serial1.println("Zumo ready to start, press A");
  125. ledGreen(1);
  126. buttonA.waitForButton();
  127. randomSeed(millis());
  128. delay(500);
  129. }
  130. /*-----------------------------------------------------------------*/
  131. //Update Abstandssensoren
  132. void ProxUpdate()
  133. {
  134. proxSensors.read();
  135. proxValue[0] = proxSensors.countsLeftWithLeftLeds();
  136. proxValue[1] = proxSensors.countsFrontWithLeftLeds();
  137. proxValue[2] = proxSensors.countsFrontWithRightLeds();
  138. proxValue[3] = proxSensors.countsRightWithRightLeds();
  139. }
  140. //Updaten Liniensensoren
  141. void LineUpdate()
  142. {
  143. lineSensors.read(lineRaw);
  144. lineValue[0] = lineRaw[0] - lineOffset[0];
  145. lineValue[1] = lineRaw[1] - lineOffset[1];
  146. lineValue[2] = lineRaw[2] - lineOffset[2];
  147. }
  148. //Update Drehbewegungssensor
  149. void GyroUpdate()
  150. {
  151. gyro.read();
  152. turnRate = gyro.g.z - gyroOffset;
  153. uint16_t m = micros();
  154. uint16_t dt = m - gyroLastUpdate;
  155. gyroLastUpdate = m;
  156. int32_t d = (int32_t)turnRate * dt;
  157. turnAngle += (int64_t)d * 14680064 / 17578125;
  158. rotationAngle = (((int32_t)turnAngle >> 16) * 360) >> 16;
  159. }
  160. // Update Beschleunigungssensor
  161. void CompassUpdate()
  162. {
  163. compass.read();
  164. moveRate = compass.a.x - compassOffset;
  165. uint16_t m = micros();
  166. uint16_t dt = m - compassLastUpdate;
  167. compassLastUpdate = m;
  168. int32_t d = (int32_t)moveRate * dt;
  169. moveDistance += (int64_t)d * dt >> 14;
  170. moveDisplay = moveDistance * 1000 / 9,81;
  171. }
  172. //Update Encoder
  173. void EncoderUpdate()
  174. {
  175. encoderCounts[0] = encoders.getCountsLeft();
  176. driveRotation[0] = encoderCounts[0] / 910; //12cpr (Motorwelle) * 75,81:1 (Getriebe) = 909,7cpr (Antriebszahnrad)
  177. encoderCounts[1] = encoders.getCountsRight();
  178. driveRotation[1] = encoderCounts[1] / 910;
  179. }
  180. /*-----------------------------------------------------------------*/
  181. //Funktion Kollisionserkennung
  182. void CollisionDetection()
  183. {
  184. dir = 'X';
  185. Serial1.println("impact detected");
  186. ledRed(1);
  187. motors.setSpeeds(0, 0);
  188. delay(500);
  189. motors.setSpeeds(-maxSpeed/2, -maxSpeed/2);
  190. delay(1000);
  191. }
  192. //Funktion Hindernisumfahrung
  193. void ObstacleAvoidance()
  194. {
  195. dir = 'U';
  196. Serial1.println("obstacle avoidance");
  197. ledYellow(1);
  198. //Schritt 1: links bis über Mittellinie fahren
  199. rotationAngle = 0;
  200. GyroUpdate();
  201. while(lineValue[2] > 1000)
  202. {
  203. LineUpdate();
  204. motors.setSpeeds(maxSpeed/2, maxSpeed);
  205. }
  206. motors.setSpeeds(maxSpeed, maxSpeed);
  207. //Schritt 2: rechts fahren bis Fahrzeug gerade steht ohne dabei weitere Linien zu überfahren
  208. while(rotationAngle != 0)
  209. {
  210. GyroUpdate();
  211. motors.setSpeeds(maxSpeed, maxSpeed/2);
  212. }
  213. //Gegenverkehr beachten
  214. proxSensors.read();
  215. proxValue[1] = proxSensors.countsFrontWithLeftLeds();
  216. proxValue[2] = proxSensors.countsFrontWithRightLeds();
  217. if(proxValue[1] < 4 || proxValue[2] < 4)
  218. {
  219. //Schritt 3: geradeaus fahren bis Hindernis passiert
  220. maxSpeed = 400;
  221. motors.setSpeeds(maxSpeed, maxSpeed);
  222. delay(1000);
  223. proxSensors.read();
  224. proxValue[3] = proxSensors.countsRightWithRightLeds();
  225. while(proxValue[3] > 4)
  226. {
  227. motors.setSpeeds(maxSpeed, maxSpeed);
  228. proxSensors.read();
  229. proxValue[3] = proxSensors.countsRightWithRightLeds();
  230. TrackKeeper();
  231. }
  232. maxSpeed = 200;
  233. }
  234. //Schritt 4: rechts bis über Mittellinie fahren
  235. rotationAngle = 0;
  236. GyroUpdate();
  237. while(lineValue[0] > 1000)
  238. {
  239. LineUpdate();
  240. motors.setSpeeds(maxSpeed, maxSpeed/2);
  241. }
  242. motors.setSpeeds(maxSpeed, maxSpeed);
  243. //Schritt 5: links fahren bis Fahrzeug gerade steht ohne dabei weitere Linien zu überfahren
  244. motors.setSpeeds(maxSpeed/2, maxSpeed);
  245. while(rotationAngle != 0)
  246. {
  247. GyroUpdate();
  248. TrackKeeper();
  249. }
  250. }
  251. //Funktion Spurhalten
  252. void TrackKeeper()
  253. {
  254. //linke Linie erreicht, nach rechts fahren
  255. if(lineValue[0] < 1000)
  256. {
  257. motors.setSpeeds(maxSpeed, maxSpeed/2);
  258. ledYellow(1);
  259. delay(100);
  260. dir = 'R';
  261. }
  262. //rechte Linie erreicht, nach links fahren
  263. else if(lineValue[2] < 1000)
  264. {
  265. motors.setSpeeds(maxSpeed/2, maxSpeed);
  266. ledYellow(1);
  267. delay(100);
  268. dir = 'L';
  269. }
  270. //Linie überfahren, zurücksetzen
  271. else if(lineValue[1] < 1000)
  272. {
  273. ledRed(1);
  274. while(lineValue[0] > 1000 && lineValue[2] > 1000)
  275. {
  276. motors.setSpeeds(-maxSpeed/2, -maxSpeed/2);
  277. }
  278. delay(500);
  279. dir = 'B';
  280. }
  281. //Normale Fahrt
  282. else
  283. {
  284. motors.setSpeeds(maxSpeed, maxSpeed);
  285. ledGreen(1);
  286. dir = 'F';
  287. }
  288. }
  289. //Funktion Abbiegen
  290. void Crossroad()
  291. {
  292. ledYellow(1);
  293. dir = 'A';
  294. //Kodierung analysieren
  295. if(lineValue[0] > 500 && lineValue[0] < 1500) leftCode = true;
  296. else leftCode = false;
  297. if(lineValue[2] > 500 && lineValue[2] < 1500) rightCode = true;
  298. else rightCode = false;
  299. //Zufallszahl erzeugen
  300. if(leftCode == true && rightCode == true) randy = random(1, 3); //1, 2
  301. else if(leftCode == true && rightCode == false) randy = random(0, 2); //0, 1
  302. else if(leftCode == false && rightCode == true)
  303. {
  304. randy = random(3); //0, (1), 2
  305. while(randy == 1) randy = random(3); //!1 => 0, 2
  306. }
  307. //links Abbiegen
  308. if(randy == 1 && leftCode == true)
  309. {
  310. //zur Kreuzungsmitte fahren
  311. driveRotation[0] = 0;
  312. driveRotation[1] = 0;
  313. while(driveRotation[0] != 1 && driveRotation[1] != 1)
  314. {
  315. EncoderUpdate();
  316. motors.setSpeeds(maxSpeed/2, maxSpeed/2);
  317. }
  318. //links drehen
  319. rotationAngle = 0;
  320. GyroUpdate();
  321. while(rotationAngle != 90)
  322. {
  323. GyroUpdate();
  324. motors.setSpeeds(0, maxSpeed/2);
  325. }
  326. //geradeaus fahren
  327. motors.setSpeeds(maxSpeed/2, maxSpeed/2);
  328. }
  329. //rechts Abbiegen
  330. else if(randy == 2 && rightCode == true)
  331. {
  332. //rechts drehen
  333. rotationAngle = 0;
  334. GyroUpdate();
  335. while(rotationAngle != -90)
  336. {
  337. GyroUpdate();
  338. motors.setSpeeds(maxSpeed/2, 0);
  339. }
  340. //geradeaus fahren
  341. motors.setSpeeds(maxSpeed/2, maxSpeed/2);
  342. }
  343. //nicht Abbiegen, geradeaus fahren
  344. else motors.setSpeeds(maxSpeed/2, maxSpeed/2);
  345. }
  346. //Funktion Serielle Ausgabe
  347. void SerialOutput()
  348. {
  349. snprintf_P(report, sizeof(report),
  350. PSTR("Abstand: %3d %3d %3d %3d Linie: %6d %6d %6d Richtung: %3c Weg: %6d %6d Winkel: %6d"),
  351. proxValue[0], proxValue[1], proxValue[2], proxValue[3],
  352. lineValue[0], lineValue[1], lineValue[2],
  353. dir, driveRotation[0], driveRotation[1], rotationAngle);
  354. Serial1.println(report);
  355. }
  356. /*-----------------------------------------------------------------*/
  357. void loop()
  358. {
  359. ledGreen(0);
  360. ledYellow(0);
  361. ledRed(0);
  362. //Abfragen der Sensordaten
  363. LineUpdate();
  364. ProxUpdate();
  365. GyroUpdate();
  366. CompassUpdate();
  367. EncoderUpdate();
  368. //Funktionsauswahl
  369. if(moveRate > 1000) CollisionDetection();
  370. else if(proxValue[0] == 6 || proxValue[1] == 6) motors.setSpeeds(0, 0);
  371. else if(proxValue[0] > 4 || proxValue[1] > 4) ObstacleAvoidance();
  372. else if((lineValue[0] > 500 && lineValue[0] < 1500) || (lineValue[2] > 500 && lineValue[2] < 1500)) Crossroad();
  373. else TrackKeeper();
  374. //Ausgabe über Bluetoothverbindung
  375. SerialOutput();
  376. }