@@ -47,13 +47,32 @@ volatile int vieuxCount=0; //stocke l'ancienne valeur de count pour ensuite fair
4747volatile byte state=LOW;
4848float mesures[3 ]; // tableau de mesures pour lisser
4949
50- // // I2C
50+ // I2C
5151union floatToBytes {
5252 byte valueBuffer[4 ];
5353 float valueReading;
5454 } converter;
5555
56- // //Voltage
56+ // struct pour la fréquence d'éxécution des fonctions
57+ struct Task {
58+ unsigned long period;
59+ unsigned long last;
60+ void (*run)();
61+ };
62+
63+ enum DriveState {
64+ DRIVE_STOP,
65+ DRIVE_FORWARD,
66+ DRIVE_REV_ARM_1, // neutre
67+ DRIVE_REV_ARM_2, // reverse fort
68+ DRIVE_REV_ARM_3, // retour neutre
69+ DRIVE_REVERSE
70+ };
71+
72+ DriveState driveState = DRIVE_STOP;
73+ unsigned long driveTimer = 0 ;
74+
75+ // Voltage
5776volatile bool dataReceived = false ;
5877volatile char receivedData[32 ]; // Buffer to hold received data
5978volatile int receivedLength = 0 ;
@@ -70,9 +89,8 @@ float voltage_NiMh = 0; // variable to store the value read
7089
7190int out;
7291int marche_avant = 1 ; // on initie la marche avant au début (0 étant la marche arriérer)
73- float marche_arriere_time = 0 ;
7492
75- float dernier_input = millis();
93+ unsigned long dernier_input = millis();
7694// direction millieu 1851
7795// tout a gaucge 1231
7896// tout a droite 2471
@@ -105,50 +123,33 @@ float getMeanSpeed(float dt){
105123
106124float getSpeed (float dt){
107125 int N = count - vieuxCount; // nombre de fronts montant et descendands après chaque loop
108- float V = ((float )N/(float )nb_trous)*distanceUnTour/(dt*1e-3 ); // 16 increments -> 1 tour de la roue et 1 tour de roue = 79 mm
109126 vieuxCount=count;
110- vieuxTemps=millis ();
111- return V;
127+ return ((float )N/(float )nb_trous)*distanceUnTour/(dt*1e-3 ); // 16 increments -> 1 tour de la roue et 1 tour de roue = 79 mm ;
112128}
113129
114130
115131void blink (){ // on compte tous les fronts
116- // Serial.print(count);
117132 count++;
118133}
119134
120135
121136float PID (float cons, float mes, float dt,float old_out) {
122137
123-
124138 if ( old_out <= 0 && cons > 0 ){ // pour pouvoir sauter directement dans la plage de pwm ou la roue bouge et une transition plus fluide entre marche arriere et avant
125139 integral = 2500 ; // valeur experimentale
126140 }
127141 else if (old_out >= 0 && cons <0 ){ // pour pouvoir sauter directement dans la plage de pwm où la roue bouge et une transition plus fluide entre marche avant et arriere
128142 integral = -5000 ; // valeur experimentale
129143 }
130144
131-
132- // Adjust the measured speed based on the sign of the desired speed
133- float adjustedMes = (cons < 0 ) ? -mes : mes;
134-
135- // Calculate the error
136- float e = cons - adjustedMes;
137-
138- // Proportional term
139- float P = Kp * e;
140-
141- // Integral term
142- integral = integral + e * dt;
143- float I = Ki * integral;
144-
145- // Derivative term
146- derivee = (e - vieuxEcart) / dt;
145+ float adjustedMes = (cons < 0 ) ? -mes : mes; // Adjust the measured speed based on the sign of the desired speed
146+ float e = cons - adjustedMes; // Calculate the error
147+ float P = Kp * e; // Proportional term
148+ integral = integral + e * dt; // Integral term
149+ float I = Ki * integral;
150+ derivee = (e - vieuxEcart) / dt; // Derivative term
147151 vieuxEcart = e;
148152 float D = Kd * derivee;
149-
150- // Garde en mémoir pour passer out à 0 directe lorsque l'on change de sens pour ne pas attendre qu'elle change de sens tout seul (que c'est long mdr
151-
152153 return P + I + D;
153154}
154155
@@ -164,114 +165,93 @@ void calculateVoltage(){
164165 // Serial.println(voltage_NiMh);
165166}
166167
167- /*
168- float direction_compensation(float dir_recue, float anciene_dir){
169- if (anciene_dir > )
170- }*/
171-
172- void programme_principal (){
173- calculateVoltage ();
174- // Commandes pour debugger
175- #if 0
176- command=Serial.read();
177- switch (command){ //pour regler les parametres
178- case 'a':
179- Vcons+=200;
180- break;
181- case 'z':
182- Vcons-=200;
183- break;
184- case 's':
185- Vcons=-1000;
186- break;
187- case 'd':
188- Vcons=2000;
189- break;
190- case 'q':
191- Vcons=0;
192- break;
193- case 'b':
194- dir+=10;
195- break;
196- case 'n':
197- dir-=100;
198- break;
199- case 'j':
200- dir+=10;
201- break;
202- case 'k':
203- dir-=10;
204- break;
205- }
206- #endif
207-
208-
209- // Propulsion de la voiture
210- int deltaT = millis ()-vieuxTemps; // temps qui est passé pendant un loop (en millisecondes)
211- vitesse=getMeanSpeed (deltaT); // on recup la vitesse lissée
212-
168+ void updateDirection (){
169+ // Update direction
170+ dir = map (dir_recue,-dir_max,dir_max,dir_min_pwm,dir_max_pwm); // remape en degré
171+ direction.writeMicroseconds (dir);
172+ }
213173
214- if (Vcons == 0 ){
215- out = 0 ;
216- moteur.writeMicroseconds (out+1500 );
217- /*
218- Serial.print("out:");
219- Serial.print(out);
220- */
221- marche_arriere_time = millis ();
174+ void updateSpeed () {
175+ unsigned long now = millis ();
176+ float dt = (now - vieuxTemps) * 0 .001f ;
177+ if (dt <= 0 ) dt = 0 .001f ;
178+
179+ vitesse = getMeanSpeed (now - vieuxTemps);
180+ vieuxTemps = now;
181+
182+ switch (driveState) {
183+
184+ case DRIVE_STOP:
185+ moteur.writeMicroseconds (1500 );
186+ integral = 0 ;
187+ out = 0 ;
188+
189+ if (Vcons > 0 ) {
190+ driveState = DRIVE_FORWARD;
191+ }
192+ else if (Vcons < 0 ) {
193+ driveState = DRIVE_REV_ARM_1;
194+ driveTimer = now;
195+ }
196+ break ;
197+
198+ case DRIVE_FORWARD:
199+ out = PID (Vcons, vitesse, dt, out);
200+ moteur.writeMicroseconds (constrain (1500 + out, 1500 , 2000 ));
201+
202+ if (Vcons == 0 ) {
203+ driveState = DRIVE_STOP;
204+ }
205+ else if (Vcons < 0 ) {
206+ driveState = DRIVE_REV_ARM_1;
207+ driveTimer = now;
208+ }
209+ break ;
210+
211+ case DRIVE_REV_ARM_1: // neutre court
212+ moteur.writeMicroseconds (1500 );
213+ if (now - driveTimer >= 10 ) {
214+ driveState = DRIVE_REV_ARM_2;
215+ driveTimer = now;
216+ }
217+ break ;
218+
219+ case DRIVE_REV_ARM_2: // reverse fort (armement ESC)
220+ moteur.writeMicroseconds (1000 );
221+ if (now - driveTimer >= 150 ) {
222+ driveState = DRIVE_REV_ARM_3;
223+ driveTimer = now;
224+ }
225+ break ;
226+
227+ case DRIVE_REV_ARM_3: // retour neutre
228+ moteur.writeMicroseconds (1500 );
229+ if (now - driveTimer >= 10 ) {
230+ driveState = DRIVE_REVERSE; // marche arrière ENGAGÉE
231+ }
232+ break ;
233+
234+ case DRIVE_REVERSE:
235+ float cons = abs (Vcons);
236+ out = PID (cons, vitesse, dt, out);
237+ moteur.writeMicroseconds (constrain (1430 - out, 500 , 1500 ));
238+
239+ if (Vcons == 0 ){
240+ moteur.writeMicroseconds (1500 );
241+ integral = 0 ;
242+ out = 0 ;
243+ }
244+ else if (Vcons > 0 ) {
245+ driveState = DRIVE_FORWARD;
246+ }
247+ break ;
222248 }
223- else if (Vcons>0 ){
224-
225- out = PID (Vcons,vitesse,float (deltaT)/1e3 ,out);
226- moteur.writeMicroseconds (constrain (1500 + out,1500 ,2000 ));
227- /*
228- Serial.print("out:");
229- Serial.print(constrain(1500 + out,500,2000));
230- */
231- marche_avant = 1 ; // on est en marche avant
232-
233- } else if ( Vcons<0 && old_Vcons>=0 && marche_avant == 1 ){ // on vériefie si il faut enclencher la marche arrière
234- out = PID (-8000 ,vitesse,float (deltaT)/1e3 ,out);
235- moteur.writeMicroseconds (constrain (1500 + out,500 ,1500 ));
236- delay (150 );
237- out = PID (0 ,vitesse,float (deltaT)/1e3 ,out);
238- moteur.writeMicroseconds (constrain (1500 + out,1500 ,2000 ));
239- delay (10 );
240- marche_avant = 0 ; // on est passée en marche arrière
241- marche_arriere_time = millis ();
242249
243- } else {
244- if (vitesse==0 && Vcons<0 && millis ()- marche_arriere_time > 500 ){ // vérifie si on est bien passée en marche arrière car bug parfois et si non on passe en marche arriere
245-
246-
247- out = PID (-8000 ,vitesse,float (deltaT)/1e3 ,out);
248- moteur.writeMicroseconds (constrain (1500 + out,500 ,1500 ));
249- delay (150 );
250- out = PID (0 ,vitesse,float (deltaT)/1e3 ,out);
251- moteur.writeMicroseconds (constrain (1500 + out,1500 ,2000 ));
252- delay (10 );
253- }
254-
255- out = PID (Vcons,vitesse,float (deltaT)/1e3 ,out);
256- moteur.writeMicroseconds (constrain (1500 + out,500 ,1500 ));
257- /*
258- Serial.print("out:");
259- Serial.print(constrain(1500 + out,500,2000));
260- */
261- }
262250
263- old_Vcons = Vcons;
264251
265252
266- // Direction de la voiture
267- dir = map (dir_recue,-dir_max,dir_max,dir_min_pwm,dir_max_pwm); // remape en degré
268- direction.writeMicroseconds (dir);
269-
270253
271- // print debug
272- #if 1
273- Serial.print (" temps en marche arriere: " );
274- Serial.print (millis ()- marche_arriere_time);
254+ #if 0
275255 Serial.print(",integrale");
276256 Serial.print(integral);
277257 Serial.print(",const:");
@@ -282,16 +262,11 @@ void programme_principal(){
282262 Serial.print(vitesse);
283263 Serial.print(",Directino en degré:");
284264 Serial.print(dir_recue);
285- // Serial.print(", Ki : ");
286- // Serial.print(Ki);
287- // Serial.print(", Kp: ");
288- // Serial.print(Kp);
289- // Serial.print(", ");
290265 Serial.print(",out2:");
291266 Serial.println(out);
292267 #endif
293- delay (10 );
294268}
269+
295270void receiveEvent (int byteCount){
296271 // Ignorer le premier octet "commande" du Raspberry
297272 if (Wire.available ()) Wire.read (); // skip cmd byte
@@ -305,9 +280,11 @@ void receiveEvent(int byteCount){
305280 buffer[i] = Wire.read ();
306281 }
307282
308- float * vals = (float *)buffer;
309- Vcons = vals[0 ]; // reçue en milimetre par secondes
310- dir_recue = vals[1 ]; // reçue en degré.
283+ float v, d;
284+ memcpy (&v, buffer, 4 );
285+ memcpy (&d, buffer + 4 , 4 );
286+ Vcons = v; // reçue en milimetre par secondes
287+ dir_recue = d; // reçue en degré.
311288 } else {
312289 while (Wire.available ()) Wire.read (); // vide le buffer
313290 }
@@ -339,14 +316,30 @@ void setup() {
339316}
340317
341318
319+ Task tasks[] = {
320+ {5 , 0 , updateDirection}, // 200 Hz
321+ {20 , 0 , updateSpeed}, // 50 Hz
322+ {500 , 0 , calculateVoltage} // 2 Hz
323+ };
324+
342325void loop () {
343- if (millis ()-dernier_input < 150 ){ // on vérifie si on a recue une commande dans les 100 dernière millisecondes sinon on arrete
344- programme_principal ();
326+ unsigned long now = millis ();
327+
328+ if (now - dernier_input < 150 ){ // on vérifie si on a recue une commande dans les 100 dernière millisecondes sinon on arrete
329+ for (auto &t : tasks) {
330+ if (now - t.last >= t.period ) {
331+ t.last = now;
332+ t.run ();
333+ }
334+ }
345335 }
346336 else {
347337 moteur.writeMicroseconds (1500 );
348338 dir = map (0 ,-dir_max,dir_max,dir_min_pwm,dir_max_pwm);
349339 direction.writeMicroseconds (dir);
340+ driveState = DRIVE_STOP;
341+ integral=0 ;
342+ out=0 ;
350343 }
351344}
352345
0 commit comments