Renate de Boer / Mbed 2 deprecated script_voor_project_copy

Dependencies:   Servoaansturing mbed QEI HIDScope biquadFilter MODSERIAL FastPWM

Committer:
Renate
Date:
Thu Oct 24 11:46:17 2019 +0000
Revision:
20:a6a5bdd7d118
Parent:
19:1fd39a2afc30
Child:
21:456acc79726c
Versie 24-10

Who changed what in which revision?

UserRevisionLine numberNew contents of line
RobertoO 0:67c50348f842 1 #include "mbed.h"
Rosalie 3:6ee0b20c23b0 2 #include "HIDScope.h"
Rosalie 3:6ee0b20c23b0 3 #include "QEI.h"
RobertoO 1:b862262a9d14 4 #include "MODSERIAL.h"
Rosalie 3:6ee0b20c23b0 5 #include "BiQuad.h"
Rosalie 3:6ee0b20c23b0 6 #include "FastPWM.h"
WiesjeRoskamp 2:aee655d11b6d 7 #include <math.h>
Rosalie 5:9f1260408ef2 8 #include "Servo.h"
RobertoO 0:67c50348f842 9
Renate 11:4bc0304978e2 10 // Definieer objecten
WiesjeRoskamp 2:aee655d11b6d 11 Serial pc(USBTX, USBRX);
Rosalie 3:6ee0b20c23b0 12
Renate 14:54343b9fd708 13 PwmOut motor1(D6); // Misschien moeten we hiervoor DigitalOut gebruiken, moet
Renate 14:54343b9fd708 14 PwmOut motor2(D5); // samen kunnen gaan met de servo motor
Renate 15:ad065ab92d11 15
Renate 15:ad065ab92d11 16 DigitalOut motor1_dir(D7);
Renate 15:ad065ab92d11 17 DigitalOut motor2_dir(D4);
Renate 14:54343b9fd708 18
Renate 14:54343b9fd708 19 DigitalIn Power_button_pressed(D1); // Geen InterruptIn gebruiken!
Renate 9:4de589636f50 20 DigitalIn Emergency_button_pressed(D2);
WiesjeRoskamp 2:aee655d11b6d 21
Renate 15:ad065ab92d11 22 AnalogIn EMG_biceps_right_raw (A0);
Renate 15:ad065ab92d11 23 AnalogIn EMG_biceps_left_raw (A1);
Renate 19:1fd39a2afc30 24 AnalogIn EMG_calf_raw (A2);
Renate 15:ad065ab92d11 25
Renate 8:c7d3b67346db 26 Ticker loop_ticker;
Renate 19:1fd39a2afc30 27 Ticker HIDScope_ticker;
Renate 19:1fd39a2afc30 28 Ticker emgSampleTicker;
Renate 19:1fd39a2afc30 29
Renate 19:1fd39a2afc30 30 bool calib = false; // MOGELIJK GAAT HET HIER FOUT
Renate 19:1fd39a2afc30 31 int i_calib = 0;
Renate 19:1fd39a2afc30 32
Renate 20:a6a5bdd7d118 33 HIDScope scope(3);
Renate 20:a6a5bdd7d118 34
Renate 20:a6a5bdd7d118 35 float mean_EMG_biceps_right;
Renate 20:a6a5bdd7d118 36 float mean_EMG_biceps_left;
Renate 20:a6a5bdd7d118 37 float mean_EMG_calf;
Renate 20:a6a5bdd7d118 38 float normalized_EMG_biceps_right;
Renate 20:a6a5bdd7d118 39 float filtered_EMG_biceps_right;
Renate 20:a6a5bdd7d118 40 float normalized_EMG_biceps_left;
Renate 20:a6a5bdd7d118 41 float filtered_EMG_biceps_left;
Renate 20:a6a5bdd7d118 42 float normalized_EMG_calf;
Renate 20:a6a5bdd7d118 43 float filtered_EMG_calf;
Renate 20:a6a5bdd7d118 44
Renate 20:a6a5bdd7d118 45 // Definities voor eerste BiQuadChain (High-pass en Notch)
Renate 20:a6a5bdd7d118 46 BiQuadChain bqc;
Renate 20:a6a5bdd7d118 47 BiQuad bq1(0.8006, -1.6012, 0.8006, -1.5610, 0.6414); // High-pass
Renate 20:a6a5bdd7d118 48 BiQuad bq2(1, -1.6180, 1, -1.6019, 0.9801); // Notch
Renate 20:a6a5bdd7d118 49
Renate 20:a6a5bdd7d118 50 // Na het nemen van de absolute waarde moet de tweede BiQuadChain worden toegepast.
Renate 20:a6a5bdd7d118 51 // Definieer (twee Low-pass -> vierde orde verkrijgen):
Renate 20:a6a5bdd7d118 52 BiQuadChain bqc2;
Renate 20:a6a5bdd7d118 53 BiQuad bq3(1.5515e-4, 3.1030e-4, 1.5515e-4, -1.9645, 0.9651); // Low-pass
Renate 20:a6a5bdd7d118 54 BiQuad bq4(1.5515e-4, 3.1030e-4, 1.5515e-4, -1.9645, 0.9651); // Low-pass
Renate 20:a6a5bdd7d118 55
Renate 19:1fd39a2afc30 56 void emgSampleFilter() // Deze functie wordt aangeroepen dmv een ticker. Het sampled
Renate 20:a6a5bdd7d118 57 // hierdoor het EMG signaal en het haalt er een filter overheen.
Renate 20:a6a5bdd7d118 58 // Het signaal kan tevens via de HIDScope worden gevolgd.
Renate 20:a6a5bdd7d118 59 // Tenslotte wordt er een stuk script gerund, wanneer de robot
Renate 20:a6a5bdd7d118 60 // zich in de kalibratie toestand bevindt.
Renate 19:1fd39a2afc30 61 {
Renate 20:a6a5bdd7d118 62 float filtered_EMG_biceps_right_1=bqc.step(EMG_biceps_right_raw.read());
Renate 20:a6a5bdd7d118 63 float filtered_EMG_biceps_left_1=bqc.step(EMG_biceps_left_raw.read());
Renate 20:a6a5bdd7d118 64 float filtered_EMG_calf_1=bqc.step(EMG_calf_raw.read());
Renate 20:a6a5bdd7d118 65
Renate 20:a6a5bdd7d118 66 float filtered_EMG_biceps_right_abs=abs(filtered_EMG_biceps_right_1);
Renate 20:a6a5bdd7d118 67 float filtered_EMG_biceps_left_abs=abs(filtered_EMG_biceps_left_1);
Renate 20:a6a5bdd7d118 68 float filtered_EMG_calf_abs=abs(filtered_EMG_calf_1);
Renate 20:a6a5bdd7d118 69
Renate 20:a6a5bdd7d118 70 float filtered_EMG_biceps_right=bqc2.step(filtered_EMG_biceps_right_abs);
Renate 20:a6a5bdd7d118 71 float filtered_EMG_biceps_left=bqc2.step(filtered_EMG_biceps_left_abs);
Renate 20:a6a5bdd7d118 72 float filtered_EMG_calf=bqc2.step(filtered_EMG_calf_abs);
Renate 19:1fd39a2afc30 73
Renate 19:1fd39a2afc30 74 float filtered_EMG_biceps_right_total=filtered_EMG_biceps_right;
Renate 19:1fd39a2afc30 75 float filtered_EMG_biceps_left_total=filtered_EMG_biceps_left;
Renate 19:1fd39a2afc30 76 float filtered_EMG_calf_total=filtered_EMG_calf;
Renate 19:1fd39a2afc30 77
Renate 20:a6a5bdd7d118 78 //void sendHIDScope() // Deze functie geeft de gefilterde EMG-signalen weer in de HIDScope
Renate 20:a6a5bdd7d118 79 // Wordt eveneens gerund dmv een ticker
Renate 20:a6a5bdd7d118 80 //{
Renate 20:a6a5bdd7d118 81 /* Set the sampled emg values in channel 0 (the first channel) and 1 (the second channel) in the 'HIDScope' instance named 'scope' */
Renate 20:a6a5bdd7d118 82 scope.set(0, filtered_EMG_biceps_right); // Werkt dit zo? Of nog met .read?
Renate 20:a6a5bdd7d118 83 scope.set(1, filtered_EMG_biceps_left);
Renate 20:a6a5bdd7d118 84 scope.set(2, filtered_EMG_calf);
Renate 20:a6a5bdd7d118 85 /* Repeat the step above if required for more channels of required (channel 0 up to 5 = 6 channels)
Renate 20:a6a5bdd7d118 86 * Ensure that enough channels are available (HIDScope scope( 2 ))
Renate 20:a6a5bdd7d118 87 * Finally, send all channels to the PC at once */
Renate 20:a6a5bdd7d118 88 scope.send();
Renate 20:a6a5bdd7d118 89 // Eventueel nog een ledje laten branden
Renate 20:a6a5bdd7d118 90 //}
Renate 20:a6a5bdd7d118 91
Renate 20:a6a5bdd7d118 92 if (calib) // In de kalibratie staat treedt deze loop in werking. De spier wordt
Renate 20:a6a5bdd7d118 93 // dan maximaal aangespannen (gedurende 5 seconden). De EMG waarden
Renate 20:a6a5bdd7d118 94 // worden bij elkaar opgeteld, waarna het gemiddelde wordt bepaald.
Renate 19:1fd39a2afc30 95 {
Renate 19:1fd39a2afc30 96 if (i_calib < 500)
Renate 19:1fd39a2afc30 97 {
Renate 19:1fd39a2afc30 98 filtered_EMG_biceps_right_total=filtered_EMG_biceps_right+filtered_EMG_biceps_right_total;
Renate 19:1fd39a2afc30 99 filtered_EMG_biceps_left_total=filtered_EMG_biceps_left+filtered_EMG_biceps_left_total;
Renate 19:1fd39a2afc30 100 filtered_EMG_calf_total=filtered_EMG_calf+filtered_EMG_calf_total;
Renate 19:1fd39a2afc30 101 i_calib++;
Renate 19:1fd39a2afc30 102 }
Renate 19:1fd39a2afc30 103 if (i_calib >= 500)
Renate 19:1fd39a2afc30 104 {
Renate 20:a6a5bdd7d118 105 float mean_EMG_biceps_right=filtered_EMG_biceps_right_total/500;
Renate 20:a6a5bdd7d118 106 float mean_EMG_biceps_left=filtered_EMG_biceps_left_total/500;
Renate 20:a6a5bdd7d118 107 float mean_EMG_calf=filtered_EMG_calf_total/500;
Renate 19:1fd39a2afc30 108 calib = false;
Renate 19:1fd39a2afc30 109 }
Renate 19:1fd39a2afc30 110 }
Renate 19:1fd39a2afc30 111 }
Renate 19:1fd39a2afc30 112
Renate 11:4bc0304978e2 113 // Emergency
Renate 8:c7d3b67346db 114 void emergency()
Rosalie 3:6ee0b20c23b0 115 {
Renate 11:4bc0304978e2 116 loop_ticker.detach();
Renate 8:c7d3b67346db 117 motor1.write(0);
Renate 8:c7d3b67346db 118 motor2.write(0);
Renate 11:4bc0304978e2 119 pc.printf("Ik ga exploderen!!!\r\n");
Renate 11:4bc0304978e2 120 // Alles moet uitgaan (evt. een rood LEDje laten branden), moet
Renate 14:54343b9fd708 121 // opnieuw worden opgestart. Mogelijk kan dit door de ticker te
Renate 11:4bc0304978e2 122 // detachen
Renate 8:c7d3b67346db 123 }
Renate 11:4bc0304978e2 124
Renate 11:4bc0304978e2 125 // Motoren uitzetten
Renate 8:c7d3b67346db 126 void motors_off()
Renate 8:c7d3b67346db 127 {
Renate 8:c7d3b67346db 128 motor1.write(0);
Renate 8:c7d3b67346db 129 motor2.write(0);
Renate 9:4de589636f50 130 pc.printf("Motoren uit functie\r\n");
Renate 8:c7d3b67346db 131 }
Renate 8:c7d3b67346db 132
Renate 14:54343b9fd708 133 // Motoren aanzetten
Renate 15:ad065ab92d11 134 void motors_on()
Renate 15:ad065ab92d11 135 {
Renate 15:ad065ab92d11 136 motor1.write(0.9);
Renate 15:ad065ab92d11 137 motor1_dir.write(1);
Renate 15:ad065ab92d11 138 motor2.write(0.1);
Renate 15:ad065ab92d11 139 motor1_dir.write(1);
Renate 15:ad065ab92d11 140 pc.printf("Motoren aan functie\r\n");
Renate 15:ad065ab92d11 141 }
Renate 19:1fd39a2afc30 142
Renate 19:1fd39a2afc30 143 // EMG kalibreren
Renate 19:1fd39a2afc30 144 void emg_calibration()
Renate 19:1fd39a2afc30 145 {
Renate 19:1fd39a2afc30 146 // Gedurende bijv. 5 seconden EMG meten, wanneer de spieren maximaal
Renate 19:1fd39a2afc30 147 // worden aangespannen -> maximaal potentiaal verkrijgen. Een fractie
Renate 19:1fd39a2afc30 148 // hiervan kan als drempel worden gebruikt voor beweging
Renate 19:1fd39a2afc30 149
Renate 19:1fd39a2afc30 150 // *Tijd instellen*
Renate 19:1fd39a2afc30 151 // Iets met DOUBLE_MAX? https://docs.microsoft.com/en-us/cpp/c-language/cpp-integer-limits?view=vs-2019
Renate 19:1fd39a2afc30 152
Renate 19:1fd39a2afc30 153 // Ledje van kleur laten veranderen
Renate 19:1fd39a2afc30 154
Renate 19:1fd39a2afc30 155 // MOGELIJK NIET MEER NODIG???
Renate 19:1fd39a2afc30 156
Renate 19:1fd39a2afc30 157 }
Rosalie 3:6ee0b20c23b0 158
Renate 6:64146e16e10c 159 // Finite state machine programming (calibration servo motor?)
Renate 12:93ad9781eeef 160 enum states {Motors_off, Calib_motor, Calib_EMG, Homing, Operation_mode};
Renate 6:64146e16e10c 161
Renate 6:64146e16e10c 162 states currentState = Motors_off;
Renate 6:64146e16e10c 163 bool stateChanged = true; // Make sure the initialization of first state is executed
Renate 6:64146e16e10c 164
Renate 6:64146e16e10c 165 void ProcessStateMachine(void)
Renate 9:4de589636f50 166 {
Renate 6:64146e16e10c 167 switch (currentState)
Renate 6:64146e16e10c 168 {
Renate 6:64146e16e10c 169 case Motors_off:
Renate 6:64146e16e10c 170
Renate 9:4de589636f50 171 if (stateChanged)
Renate 6:64146e16e10c 172 {
Renate 8:c7d3b67346db 173 motors_off(); // functie waarbij motoren uitgaan
Renate 11:4bc0304978e2 174 stateChanged = false;
Renate 9:4de589636f50 175 pc.printf("Motors off state\r\n");
Renate 9:4de589636f50 176 }
Renate 11:4bc0304978e2 177 if (Power_button_pressed.read() == false) // Normaal waarde 1 bij indrukken, nu nul -> false
Renate 6:64146e16e10c 178 {
Renate 15:ad065ab92d11 179 motors_on();
Renate 9:4de589636f50 180 currentState = Calib_motor;
Renate 11:4bc0304978e2 181 stateChanged = true;
Renate 11:4bc0304978e2 182 pc.printf("Moving to Calib_motor state\r\n");
Renate 6:64146e16e10c 183 }
Renate 11:4bc0304978e2 184 if (Emergency_button_pressed.read() == false) // Normaal waarde 1 bij indrukken, nu nul -> false
Renate 8:c7d3b67346db 185 {
Renate 10:83f3cec8dd1c 186 emergency();
Renate 9:4de589636f50 187 }
Renate 6:64146e16e10c 188 break;
Renate 6:64146e16e10c 189
Renate 9:4de589636f50 190 case Calib_motor:
Renate 9:4de589636f50 191
Renate 9:4de589636f50 192 if (stateChanged)
Renate 9:4de589636f50 193 {
Renate 9:4de589636f50 194 // Hier wordt een kalibratie uitgevoerd, waarbij de motorhoeken worden bepaald
Renate 11:4bc0304978e2 195 currentState = Calib_EMG;
Renate 11:4bc0304978e2 196 stateChanged = true;
Renate 9:4de589636f50 197 pc.printf("Moving to Calib_EMG state\r\n");
Renate 9:4de589636f50 198 }
Renate 11:4bc0304978e2 199 if (Emergency_button_pressed.read() == false)
Renate 11:4bc0304978e2 200 {
Renate 11:4bc0304978e2 201 emergency();
Renate 11:4bc0304978e2 202 }
Renate 11:4bc0304978e2 203 break;
Renate 11:4bc0304978e2 204
Renate 15:ad065ab92d11 205 case Calib_EMG:
Renate 11:4bc0304978e2 206
Renate 14:54343b9fd708 207 motors_off();
Renate 11:4bc0304978e2 208 if (stateChanged)
Renate 11:4bc0304978e2 209 {
Renate 11:4bc0304978e2 210 // Hierbij wordt een een kalibratie uitgevoerd, waarbij de maximale EMG-amplitude waarde wordt bepaald
Renate 20:a6a5bdd7d118 211
Renate 19:1fd39a2afc30 212 calib = true;
Renate 20:a6a5bdd7d118 213 emgSampleFilter(); // Gaat dit nu goed? -> moet sws worden toegevoegd bij relevante onderdelen?
Renate 19:1fd39a2afc30 214 if (i_calib >= 500) // of wait(10);?
Renate 19:1fd39a2afc30 215 {
Renate 19:1fd39a2afc30 216 currentState = Homing;
Renate 19:1fd39a2afc30 217 stateChanged = true;
Renate 19:1fd39a2afc30 218 pc.printf("Moving to Homing state\r\n");
Renate 19:1fd39a2afc30 219 }
Renate 20:a6a5bdd7d118 220
Renate 11:4bc0304978e2 221 currentState = Homing;
Renate 11:4bc0304978e2 222 stateChanged = true;
Renate 11:4bc0304978e2 223 pc.printf("Moving to Homing state\r\n");
Renate 11:4bc0304978e2 224 }
Renate 20:a6a5bdd7d118 225
Renate 10:83f3cec8dd1c 226 if (Emergency_button_pressed.read() == false)
Renate 10:83f3cec8dd1c 227 {
Renate 11:4bc0304978e2 228 emergency();
Renate 11:4bc0304978e2 229 }
Renate 11:4bc0304978e2 230 break;
Renate 11:4bc0304978e2 231
Renate 11:4bc0304978e2 232 case Homing:
Renate 11:4bc0304978e2 233
Renate 15:ad065ab92d11 234 motors_on();
Renate 11:4bc0304978e2 235 if (stateChanged)
Renate 11:4bc0304978e2 236 {
Renate 11:4bc0304978e2 237 // Ervoor zorgen dat de motoren zo bewegen dat de robotarm
Renate 11:4bc0304978e2 238 // (inclusief de end-effector) in de juiste home positie wordt gezet
Renate 11:4bc0304978e2 239 currentState = Operation_mode;
Renate 11:4bc0304978e2 240 stateChanged = true;
Renate 12:93ad9781eeef 241 pc.printf("Moving to operation mode \r\n");
Renate 11:4bc0304978e2 242 }
Renate 11:4bc0304978e2 243 if (Emergency_button_pressed.read() == false)
Renate 11:4bc0304978e2 244 {
Renate 10:83f3cec8dd1c 245 emergency();
Renate 10:83f3cec8dd1c 246 }
Renate 11:4bc0304978e2 247 break;
Renate 11:4bc0304978e2 248
Renate 14:54343b9fd708 249 case Operation_mode: // Overgaan tot emergency wanneer referentie niet
Renate 14:54343b9fd708 250 // overeenkomt met werkelijkheid
Renate 11:4bc0304978e2 251
Renate 11:4bc0304978e2 252 if (stateChanged)
Renate 12:93ad9781eeef 253
Renate 11:4bc0304978e2 254 // Hier moet een functie worden aangeroepen die ervoor zorgt dat
Renate 11:4bc0304978e2 255 // aan de hand van EMG-signalen de motoren kunnen worden aangestuurd,
Renate 11:4bc0304978e2 256 // zodat de robotarm kan bewegen
Renate 11:4bc0304978e2 257
Renate 11:4bc0304978e2 258 {
Renate 20:a6a5bdd7d118 259 float normalized_EMG_biceps_right=filtered_EMG_biceps_right/mean_EMG_biceps_right;
Renate 20:a6a5bdd7d118 260 float normalized_EMG_biceps_left=filtered_EMG_biceps_left/mean_EMG_biceps_left;
Renate 20:a6a5bdd7d118 261 float normalized_EMG_calf=filtered_EMG_calf/mean_EMG_calf;
Renate 20:a6a5bdd7d118 262
Renate 20:a6a5bdd7d118 263 if (normalized_EMG_biceps_right >= 0.3)
Renate 20:a6a5bdd7d118 264 {
Renate 20:a6a5bdd7d118 265 motor1.write(0.5);
Renate 20:a6a5bdd7d118 266 motor2.write(0);
Renate 20:a6a5bdd7d118 267 }
Renate 20:a6a5bdd7d118 268 if (normalized_EMG_biceps_right < 0.3)
Renate 20:a6a5bdd7d118 269 {
Renate 20:a6a5bdd7d118 270 motor1.write(0);
Renate 20:a6a5bdd7d118 271 motor2.write(0);
Renate 20:a6a5bdd7d118 272 }
Renate 20:a6a5bdd7d118 273 if (normalized_EMG_biceps_left >= 0.3)
Renate 20:a6a5bdd7d118 274 {
Renate 20:a6a5bdd7d118 275 motor2.write(0.9);
Renate 20:a6a5bdd7d118 276 motor1.write(0);
Renate 20:a6a5bdd7d118 277 }
Renate 20:a6a5bdd7d118 278 if (normalized_EMG_biceps_left < 0.3)
Renate 20:a6a5bdd7d118 279 {
Renate 20:a6a5bdd7d118 280 motor2.write(0);
Renate 20:a6a5bdd7d118 281 motor1.write(0);
Renate 20:a6a5bdd7d118 282 }
Renate 20:a6a5bdd7d118 283
Renate 20:a6a5bdd7d118 284 if (Power_button_pressed.read() == false) // Normaal waarde 1 bij indrukken, nu nul -> false
Renate 20:a6a5bdd7d118 285 {
Renate 20:a6a5bdd7d118 286 motors_off();
Renate 20:a6a5bdd7d118 287 currentState = Motors_off;
Renate 20:a6a5bdd7d118 288 stateChanged = true;
Renate 20:a6a5bdd7d118 289 pc.printf("Terug naar de state Motors_off\r\n");
Renate 20:a6a5bdd7d118 290 }
Renate 20:a6a5bdd7d118 291 if (Emergency_button_pressed.read() == false)
Renate 20:a6a5bdd7d118 292 {
Renate 20:a6a5bdd7d118 293 emergency();
Renate 20:a6a5bdd7d118 294 }
Renate 20:a6a5bdd7d118 295 // wait(5);
Renate 20:a6a5bdd7d118 296 else
Renate 20:a6a5bdd7d118 297 {
Renate 20:a6a5bdd7d118 298 currentState = Homing;
Renate 20:a6a5bdd7d118 299 stateChanged = true;
Renate 20:a6a5bdd7d118 300 pc.printf("Terug naar de state Homing\r\n");
Renate 20:a6a5bdd7d118 301 }
Renate 20:a6a5bdd7d118 302 break;
Renate 20:a6a5bdd7d118 303
Renate 20:a6a5bdd7d118 304 }
Renate 20:a6a5bdd7d118 305
Renate 7:1d57463393c6 306 default:
Renate 7:1d57463393c6 307 // Zelfde functie als die eerder is toegepast om motoren uit te schakelen -> safety!
Renate 14:54343b9fd708 308 motors_off();
Renate 9:4de589636f50 309 pc.printf("Unknown or uninplemented state reached!\r\n");
Renate 8:c7d3b67346db 310
WiesjeRoskamp 2:aee655d11b6d 311 }
Renate 11:4bc0304978e2 312 }
WiesjeRoskamp 2:aee655d11b6d 313
Renate 8:c7d3b67346db 314 int main(void)
Renate 8:c7d3b67346db 315 {
Renate 9:4de589636f50 316 pc.printf("Opstarten\r\n");
Renate 20:a6a5bdd7d118 317 bqc.add(&bq1).add(&bq2);
Renate 20:a6a5bdd7d118 318 bqc2.add(&bq3).add(&bq4);
Renate 20:a6a5bdd7d118 319 emgSampleTicker.attach(&emgSampleFilter, 0.01f);
Renate 12:93ad9781eeef 320 loop_ticker.attach(&ProcessStateMachine, 5.0f);
Renate 8:c7d3b67346db 321 while(true)
Renate 11:4bc0304978e2 322 { /* do nothing */}
Renate 8:c7d3b67346db 323 }