-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhardware.cpp
More file actions
287 lines (240 loc) · 8.68 KB
/
Copy pathhardware.cpp
File metadata and controls
287 lines (240 loc) · 8.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
#include "hardware.h"
/*
Diese Funktion muss im Setup() teil des Arduino Programms aufgerufen werden, um die Hardware zu initialisieren
*/
void hardware_setup(void)
{
motor_right.setSpeed(255);
motor_left.setSpeed(255);
motor_right.run(RELEASE);
motor_left.run(RELEASE);
sensor1.trig_pin = FRONT_RIGHT_TRIG;
sensor1.echo_pin = FRONT_RIGHT_ECHO;
sensor2.trig_pin = BACK_RIGHT_TRIG;
sensor2.echo_pin = BACK_RIGHT_ECHO;
sensor3.trig_pin = FRONT_FRONT_TRIG;
sensor3.echo_pin = FRONT_FRONT_ECHO;
pinMode(sensor1.trig_pin, OUTPUT);
pinMode(sensor1.echo_pin, INPUT);
pinMode(sensor2.trig_pin, OUTPUT);
pinMode(sensor2.echo_pin, INPUT);
pinMode(sensor3.echo_pin, INPUT);
pinMode(sensor3.trig_pin, OUTPUT);
}
/*
Diese Funktion ist aequivalent zur geradeaus_fahren Funktion, nur mit der Unterschied, dass ich hier versuche, keine Mischung von Englischen und Deutschen woertern zu verwenden
distance_from_middle bezeichnet die Abweichung nach LINKS vom Mittellinie
use_side beschreibt, auf welche Seite die Sensoren verwendet werden sollen
0 ist links, 1 ist rechts (LEFT_SIDE und RIGHT_SIDE benutzen)
*/
void drive_straight(int distance_from_middle, char use_side, char wanted_speed)
{
char motorA_speed = wanted_speed;
char motorB_speed = wanted_speed;
int tolerance_left;
int tolerance_right;
int target_distance;
struct side_info side = get_side_info(use_side); /*Abhaengig, welche Seite beruecksichtigt werden soll, lese die entsprechende Seite aus*/
if (use_side) /*falls die Sensoren auf der rechten Seite beruecksichtigt werden sollen*/
{
//target_distance = (TRACK_WIDTH / 2) - (ROBOT_WIDTH) + distance_from_middle; /*bestimme soll-entfernung vom Wand, basierend auf den Roboter- sowie Fahrbahnbreite und der gewünschten Abweichung vom Mittellinie*/
target_distance = distance_from_middle; /*anscheinend will der arduino sich nur schlecht auf diese weise steuern lassen weil die angaben ein bissl unpraezise sind
/*Toleranz beruecksichtigen*/
tolerance_left = target_distance + TOLERANCE;
tolerance_right = target_distance - TOLERANCE;
/*pruefen, ob roboter ausserhalb der Toleranzen ist und Motorengeschiwndigkeiten ggf. anpassen*/
if (tolerance_right > side.average_distance)
{
motorA_speed = regulate_speed(motorA_speed, target_distance, side.average_distance); /*Regelalgorithmus fuer Motorengeschwindigkeit ist in ein separates Funktion damit man verschiedene Regelalgorithmen testen kann*/
}
else if (tolerance_left < side.average_distance)
{
motorB_speed = regulate_speed(motorB_speed, target_distance, side.average_distance);
}
/*Winkel zur Wand Pruefen und ggf. gegensteuern*/
if (side.angle > 0)
{
motorB_speed = regulate_angle(motorB_speed, side.angle);
}
else if (side.angle < 0)
{
motorA_speed = regulate_angle(motorA_speed, side.angle);
}
}
else /*falls die Sensoren auf der linken Seite beruecksichtigt werden sollen*/
{
//target_distance = (TRACK_WIDTH / 2) - (ROBOT_WIDTH) - distance_from_middle; /*bestimme soll-entfernung vom Wand, basierend auf den Roboter- sowie Fahrbahnbreite und der gewünschten Abweichung vom Mittellinie*/
target_distance = distance_from_middle;
/*Toleranz beruecksichtigen*/
tolerance_left = target_distance - TOLERANCE;
tolerance_right = target_distance + TOLERANCE;
/*pruefen, ob roboter ausserhalb der Toleranzen ist und Motorengeschiwndigkeiten ggf. anpassen*/
if (tolerance_right < side.average_distance)
{
motorB_speed = regulate_speed(motorB_speed, target_distance, side.average_distance);
}
else if (tolerance_left > side.average_distance)
{
motorA_speed = regulate_speed(motorA_speed, target_distance, side.average_distance);
}
/*Winkel zur Wand Pruefen und ggf. gegensteuern*/
if (side.angle > 0)
{
motorA_speed = regulate_angle(motorA_speed, side.angle);
}
else if (side.angle < 0)
{
motorB_speed = regulate_angle(motorB_speed, side.angle);
}
}
drive(1, motorA_speed, motorB_speed);
}
/*
Diese Funktion bestimmt die Motorengeschwindigkeit anhand der Winkel in dem der Roboter auf den Wand steht.
Die quadratische Korrektur ist nötig da wir im Moment nur eine Sehr vage Winkelmessung hinbekommen
*/
int regulate_angle(char motor_speed, int angle)
{
motor_speed -= pow(angle, 2) / HARDNESS;
if (motor_speed < 50)
{
motor_speed = 50;
}
return motor_speed;
}
/*
diese Funktion bestimmt die Motorgeschwindigkeit anhand der Abweichung vom vorgegebenen Mittelwert
hier koennen verschiedene Regelalgorithmen implementiert werden
*/
int regulate_speed(char motor_speed, int target_distance, int distance)
{
motor_speed -= (distance - target_distance) * HARDNESS;
if (motor_speed < 50)
{
motor_speed = 50;
}
return motor_speed;
}
/*
Diese Funktion ist da, um das Roboter fahren lassen zu koennen
direction steht fuer Richtung, 1 ist vorwaerts, 0 fuer rueckwaerts
*/
void drive(char direction, char motorA_speed, char motorB_speed)
{
motor_right.setSpeed(motorA_speed);
motor_left.setSpeed(motorB_speed);
if (direction) /*Richtung setzen*/
{
motor_right.run(FORWARD);
motor_left.run(FORWARD);
}
else
{
motor_right.run(BACKWARD);
motor_left.run(BACKWARD);
}
}
/*
Diese Funktion dreht den Motor in die angegebene Richtung (1 fuer Rechtsdreh) um ungefaehr den angegebenen winkel in Grad
*/
void turn(char direction, short degree)
{
int duration = (int)(MILLIS_PER_DEGREE * (float)degree);
motor_right.setSpeed(255);
motor_left.setSpeed(255);
if (direction)
{
motor_right.run(BACKWARD);
motor_left.run(FORWARD);
}
else
{
motor_right.run(FORWARD);
motor_left.run(BACKWARD);
}
delay(duration);
stop_motors();
}
/*
Motoren stoppen. Geschwindigkeit wird einfach auf 0 gesetzt. Wegen der Getriebe muss nicht aktiv gebremst werden
*/
void stop_motors(void)
{
motor_right.run(RELEASE);
motor_left.run(RELEASE);
}
/*
Liefert Abstand- und Winkelinformationen zu eine Seite in ein "side_info" struct zurueck
aufpassen, kann sein, dass hier malloc und pointern benötigt werden! -> zumindest waere es von der Speicherverbrauch her besser
*/
struct side_info get_side_info(char side)
{
struct side_info result; /*struct in dem das Ergebnis gespeichert wird*/
struct sensor sensors[2]; /*array zum speichern der Sensorpins auf der benoetigten Seite*/
int sensorDist[2]; /*array zum speichern der gemessenen Sensorwerte*/
if (side) /*falls rechte Seite benutzt werden soll*/
{
sensors[0] = sensor1;
sensors[1] = sensor2;
}
else
{
/*Muss dringend geändert werden!!!!!!*/
sensors[0] = sensor1;
sensors[1] = sensor2;
}
int i = 0;
for (i = 0; i < 2; i++) /*auslesen der sensoren und werte in array speichern*/
{
sensorDist[i] = get_dist(sensors[i]);
}
result.average_distance = calc_average(sensorDist, 2); /*Durchschnittlicher Entfernung vom Wand wird berechnet und im Ergebnis gespeichert*/
result.angle = calc_angle(sensorDist); /*Berechne winkel zwischen Roboter und den Wand*/
return result;
}
/*
Diese Funktion berechnet den Mittelwert aus drei integern und gibt es als integer zurück
*/
int calc_average(int values[], int size_of_array)
{
int sum = 0;
int i = 0;
for (i = 0; i < size_of_array; i++)
{
sum += values[i];
}
return (sum / size_of_array);
}
/*
Diese funktion berechnet den Winkel zwischen Roboter und Wand und liefert einen Wert in Grad zurück
Falls Winkel positiv ist, bedeutet das, dass Roboter in Richtung Wand steht
Falls Winkel negaitv ist, Roboter steht in Richtung weg von der Wand
Berechnung erfolg entweder Basierend auf Situation 1 oder 2 (Bilder im Ordner) abhaengig davon, wie Sensoren Distanz messen, hier muss der Eine auskommentiert werden
Die Verwendung von Pointern verschwendet weniger RAM
*/
int calc_angle(int values[])
{
int opposite = values[0] - values[1]; /*Wegunterschied zwischen den hinten und vorne gemessenen Entfernung*/
/*Situation 1*/
//double angle = atan2((double)opposite, (double)DIST_IR_FRONT_BACK);
/*da atan2 winkel in radian liefert, muessen die noh in grad konvertiert werden*/
// angle = angle / (2.0 * PI) * 360.0 * 10;
// return (int)angle;
return opposite;
}
/*
Diese Funktion liest analoge Werte der IR Sensoren aus und berechnet davon die Entfernung
Die zurueckgelieferte Werte muessen in Millimetern erfolgen!
*/
int get_dist(struct sensor Sensor)
{
long duration = 0;
digitalWrite(Sensor.trig_pin, LOW);
delayMicroseconds(2);
digitalWrite(Sensor.trig_pin, HIGH);
delayMicroseconds(10);
digitalWrite(Sensor.trig_pin, LOW);
duration = pulseIn(Sensor.echo_pin, HIGH);
duration = (duration / 2.0) / 2.91;
return (int)duration;
}