Asservissement moteurs - fonctionnel ?
This commit is contained in:
parent
901bdeffa1
commit
6162c6f412
102
Asser_Moteurs.c
Normal file
102
Asser_Moteurs.c
Normal file
@ -0,0 +1,102 @@
|
||||
#include "QEI.h"
|
||||
#include "Moteurs.h"
|
||||
#include "Asser_Moteurs.h"
|
||||
|
||||
/*** C'est ici que se fait la conversion en mm
|
||||
* ***/
|
||||
|
||||
// Roues 60 mm de diamètre, 188,5 mm de circonférence
|
||||
// Réduction Moteur 30:1
|
||||
// Réduction poulie 16:12
|
||||
// Nombre d'impulsions par tour moteur : 200
|
||||
// Nombre d'impulsions par tour réducteur : 6000
|
||||
// Nombre d'impulsions par tour de roue : 8000
|
||||
// Impulsion / mm : 42,44
|
||||
|
||||
#define IMPULSION_PAR_MM (1.f)
|
||||
#define ASSERMOTEUR_GAIN_P 2.f
|
||||
#define ASSERMOTEUR_GAIN_I 0.f
|
||||
|
||||
float consigne_mm_s[3]; // Consigne de vitesse (en mm/s)
|
||||
float commande_I[3]; // Terme integral
|
||||
|
||||
void AsserMoteur_Init(){
|
||||
QEI_init();
|
||||
Moteur_Init();
|
||||
for(unsigned int i =0; i< 2; i ++){
|
||||
commande_I[i]=0;
|
||||
consigne_mm_s[i]=0;
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Défini une consigne de vitesse pour le moteur indiqué.
|
||||
/// @param moteur : Moteur à asservir
|
||||
/// @param _consigne_mm_s : consigne de vitesse en mm/s
|
||||
void AsserMoteur_setConsigne_mm_s(enum t_moteur moteur, float _consigne_mm_s){
|
||||
consigne_mm_s[moteur] = _consigne_mm_s;
|
||||
|
||||
}
|
||||
|
||||
/// @brief Envoie la consigne du moteur
|
||||
/// @param moteur : Moteur à asservir
|
||||
float AsserMoteur_getConsigne_mm_s(enum t_moteur moteur){
|
||||
return consigne_mm_s[moteur];
|
||||
}
|
||||
|
||||
|
||||
|
||||
float AsserMoteur_getVitesse_mm_s(enum t_moteur moteur, int step_ms){
|
||||
enum QEI_name_t qei;
|
||||
float distance, temps;
|
||||
switch (moteur)
|
||||
{
|
||||
case MOTEUR_A: qei = QEI_A_NAME; break;
|
||||
case MOTEUR_B: qei = QEI_B_NAME; break;
|
||||
default: break;
|
||||
}
|
||||
distance = QEI_get_mm(qei);
|
||||
temps = step_ms / 1000.0f;
|
||||
|
||||
return distance / temps;
|
||||
}
|
||||
|
||||
/// @brief Indique si le robot est à l'arrêt
|
||||
/// @param step_ms : pas de temps (utilisé pour déterminer les vitesses)
|
||||
/// @return 1 si le robot est immobile, 0 s'il est en mouvement.
|
||||
uint32_t AsserMoteur_RobotImmobile(int step_ms){
|
||||
const float seuil_vitesse_immobile_mm_s = 0.1;
|
||||
if(AsserMoteur_getVitesse_mm_s(MOTEUR_A, step_ms) < seuil_vitesse_immobile_mm_s &&
|
||||
AsserMoteur_getVitesse_mm_s(MOTEUR_B, step_ms) < seuil_vitesse_immobile_mm_s ){
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// @brief Fonction d'asservissement des moteurs, à appeler périodiquement
|
||||
/// @param step_ms
|
||||
void AsserMoteur_Gestion(int step_ms){
|
||||
// Pour chaque moteur
|
||||
for(uint moteur=MOTEUR_A; moteur<MOTEUR_B+1; moteur++ ){
|
||||
float erreur; // Erreur entre la consigne et la vitesse actuelle
|
||||
float commande_P; // Terme proportionnel
|
||||
float commande;
|
||||
|
||||
// Calcul de l'erreur
|
||||
erreur = consigne_mm_s[moteur] - AsserMoteur_getVitesse_mm_s(moteur, step_ms);
|
||||
|
||||
// Calcul du terme propotionnel
|
||||
commande_P = erreur * ASSERMOTEUR_GAIN_P;
|
||||
|
||||
// Calcul du terme integral
|
||||
commande_I[moteur] = commande_I[moteur] + (erreur * ASSERMOTEUR_GAIN_I * step_ms);
|
||||
|
||||
commande = commande_P + commande_I[moteur];
|
||||
|
||||
//Saturation de la commande
|
||||
if(commande > 32760) {commande = 32760;}
|
||||
if(commande < -32760) {commande = -32760;}
|
||||
|
||||
Moteur_SetVitesse(moteur, commande);
|
||||
|
||||
}
|
||||
}
|
8
Asser_Moteurs.h
Normal file
8
Asser_Moteurs.h
Normal file
@ -0,0 +1,8 @@
|
||||
#include "Moteurs.h"
|
||||
|
||||
uint32_t AsserMoteur_RobotImmobile(int step_ms);
|
||||
void AsserMoteur_setConsigne_mm_s(enum t_moteur moteur, float consigne_mm_s);
|
||||
float AsserMoteur_getConsigne_mm_s(enum t_moteur moteur);
|
||||
float AsserMoteur_getVitesse_mm_s(enum t_moteur moteur, int step_ms);
|
||||
void AsserMoteur_Gestion(int step_ms);
|
||||
void AsserMoteur_Init();
|
@ -11,7 +11,10 @@ set(PICO_EXAMPLES_PATH ${PROJECT_SOURCE_DIR})
|
||||
pico_sdk_init()
|
||||
|
||||
add_executable(Mon_Projet
|
||||
Asser_Moteurs.c
|
||||
Moteurs.c
|
||||
main.c
|
||||
Temps.c
|
||||
QEI.c
|
||||
)
|
||||
|
||||
|
98
Moteurs.c
Normal file
98
Moteurs.c
Normal file
@ -0,0 +1,98 @@
|
||||
#include "hardware/pwm.h"
|
||||
#include "Moteurs.h"
|
||||
|
||||
#define MOTEUR_A 0
|
||||
#define MOTEUR_B 1
|
||||
#define MOTEUR_C 2
|
||||
|
||||
#define MOTEUR_A_VITESSE 6
|
||||
#define MOTEUR_B_VITESSE 8
|
||||
#define MOTEUR_C_VITESSE 10
|
||||
|
||||
#define MOTEUR_A_SENS 5
|
||||
#define MOTEUR_B_SENS 7
|
||||
#define MOTEUR_C_SENS 9
|
||||
|
||||
#define M1_SENS1 7
|
||||
#define M1_SENS2 13
|
||||
#define M1_VITESSE 27 //5B
|
||||
#define M2_SENS1 10
|
||||
#define M2_SENS2 5
|
||||
#define M2_VITESSE 9 //4B
|
||||
|
||||
uint slice_moteur_A, slice_moteur_B, slice_moteur_C;
|
||||
|
||||
/// @brief Initialisation les entrées / sorties requises pour les moteurs
|
||||
void Moteur_Init(){
|
||||
gpio_init(M1_SENS1);
|
||||
gpio_init(M1_SENS2);
|
||||
gpio_init(M2_SENS1);
|
||||
gpio_init(M2_SENS2);
|
||||
gpio_set_dir(M1_SENS1, GPIO_OUT);
|
||||
gpio_set_dir(M1_SENS2, GPIO_OUT);
|
||||
gpio_set_dir(M2_SENS1, GPIO_OUT);
|
||||
gpio_set_dir(M2_SENS2, GPIO_OUT);
|
||||
gpio_put(M1_SENS1, 0);
|
||||
gpio_put(M1_SENS2, 0);
|
||||
gpio_put(M2_SENS1, 0);
|
||||
gpio_put(M2_SENS2, 0);
|
||||
|
||||
gpio_set_function(M1_VITESSE, GPIO_FUNC_PWM);
|
||||
gpio_set_function(M2_VITESSE, GPIO_FUNC_PWM);
|
||||
pwm_set_wrap(5, (uint16_t)65535);
|
||||
pwm_set_wrap(4, (uint16_t)65535);
|
||||
pwm_set_chan_level(5, PWM_CHAN_B, 0);
|
||||
pwm_set_chan_level(4, PWM_CHAN_B, 0);
|
||||
pwm_set_enabled(5, true);
|
||||
pwm_set_enabled(4, true);
|
||||
|
||||
Moteur_SetVitesse(MOTEUR_A, 0);
|
||||
Moteur_SetVitesse(MOTEUR_B, 0);
|
||||
}
|
||||
|
||||
|
||||
/// @brief Configure le PWM et la broche de sens en fonction de la vitesse et du moteur
|
||||
/// @param moteur : Moteur (voir enum t_moteur)
|
||||
/// @param vitesse : Vitesse entre -32767 et 32767
|
||||
void Moteur_SetVitesse(enum t_moteur moteur, int16_t vitesse ){
|
||||
uint16_t u_vitesse;
|
||||
|
||||
// Le PWM accepte 16 bits de résolution, on se remet sur 16 bits (et non sur 15 + signe)
|
||||
if (vitesse < 0){
|
||||
u_vitesse = -vitesse;
|
||||
}else{
|
||||
u_vitesse = vitesse;
|
||||
}
|
||||
u_vitesse = u_vitesse * 2;
|
||||
|
||||
switch(moteur){
|
||||
case MOTEUR_A:
|
||||
pwm_set_chan_level(5, PWM_CHAN_B, u_vitesse);
|
||||
if(vitesse > 0){
|
||||
gpio_put(M1_SENS1, 0);
|
||||
gpio_put(M1_SENS2, 1);
|
||||
}else{
|
||||
gpio_put(M1_SENS1, 1);
|
||||
gpio_put(M1_SENS2, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case MOTEUR_B:
|
||||
pwm_set_chan_level(4, PWM_CHAN_B, u_vitesse);
|
||||
if(vitesse < 0){
|
||||
gpio_put(M2_SENS1, 0);
|
||||
gpio_put(M2_SENS2, 1);
|
||||
}else{
|
||||
gpio_put(M2_SENS1, 1);
|
||||
gpio_put(M2_SENS2, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Moteur_Stop(void){
|
||||
Moteur_SetVitesse(MOTEUR_A, 0);
|
||||
Moteur_SetVitesse(MOTEUR_B, 0);
|
||||
}
|
14
Moteurs.h
Normal file
14
Moteurs.h
Normal file
@ -0,0 +1,14 @@
|
||||
#include "pico/stdlib.h"
|
||||
|
||||
#ifndef MOTEURS_H
|
||||
#define MOTEURS_H
|
||||
enum t_moteur {
|
||||
MOTEUR_A=0,
|
||||
MOTEUR_B=1,
|
||||
MOTEUR_C=2
|
||||
};
|
||||
#endif
|
||||
|
||||
void Moteur_Init(void);
|
||||
void Moteur_SetVitesse(enum t_moteur moteur, int16_t vitesse );
|
||||
void Moteur_Stop(void);
|
12
QEI.c
12
QEI.c
@ -17,9 +17,9 @@
|
||||
// Nombre d'impulsions par tour de roue : 8000
|
||||
// Impulsion / mm : 42,44
|
||||
|
||||
#define IMPULSION_PAR_MM (95.4929658551372f)
|
||||
#define ASSERMOTEUR_GAIN_P 160
|
||||
#define ASSERMOTEUR_GAIN_I .80f
|
||||
#define IMPULSION_PAR_MM (1.f)
|
||||
#define ASSERMOTEUR_GAIN_P 2
|
||||
#define ASSERMOTEUR_GAIN_I .0f
|
||||
|
||||
struct QEI_t QEI_A, QEI_B;
|
||||
|
||||
@ -87,11 +87,11 @@ int QEI_get(enum QEI_name_t qei){
|
||||
switch (qei)
|
||||
{
|
||||
case QEI_A_NAME:
|
||||
return QEI_A.delta;
|
||||
return -QEI_A.delta;
|
||||
break;
|
||||
|
||||
case QEI_B_NAME:
|
||||
return -QEI_B.delta;
|
||||
return QEI_B.delta;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -103,5 +103,5 @@ int QEI_get(enum QEI_name_t qei){
|
||||
/// @param qei : Nom du module à lire (QEI_A_NAME, QEI_B_NAME ou QEI_C_NAME)
|
||||
/// @return la distance parcourue en mm calculée lors du dernier appel de la function QEI_Update()
|
||||
float QEI_get_mm(enum QEI_name_t qei){
|
||||
return (float) QEI_get(qei) / (float)IMPULSION_PAR_MM;
|
||||
return ((float) QEI_get(qei)) / (float)IMPULSION_PAR_MM;
|
||||
}
|
24
Temps.c
Normal file
24
Temps.c
Normal file
@ -0,0 +1,24 @@
|
||||
#include <stdio.h>
|
||||
#include "pico/stdlib.h"
|
||||
#include "Temps.h"
|
||||
|
||||
uint32_t temps_ms=0;
|
||||
bool temps_est_init=false;
|
||||
struct repeating_timer timer;
|
||||
|
||||
bool Temps_increment(struct repeating_timer *t){
|
||||
temps_ms++;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Temps_init(void){
|
||||
if(!temps_est_init){
|
||||
temps_ms=0;
|
||||
add_repeating_timer_ms(-1, Temps_increment, NULL, &timer);
|
||||
temps_est_init = true;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t Temps_get_temps_ms(void){
|
||||
return temps_ms;
|
||||
}
|
5
Temps.h
Normal file
5
Temps.h
Normal file
@ -0,0 +1,5 @@
|
||||
#include "pico/stdlib.h"
|
||||
|
||||
bool Temps_increment(struct repeating_timer *t);
|
||||
void Temps_init(void);
|
||||
uint32_t Temps_get_temps_ms(void);
|
135
main.c
135
main.c
@ -4,7 +4,11 @@
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/multicore.h"
|
||||
#include "hardware/pwm.h"
|
||||
#include "Asser_Moteurs.h"
|
||||
#include "Moteurs.h"
|
||||
#include "Temps.h"
|
||||
#include <stdio.h>
|
||||
#include "QEI.h"
|
||||
|
||||
@ -16,119 +20,52 @@
|
||||
#define M2_SENS2 5
|
||||
#define M2_VITESSE 9 //4B
|
||||
|
||||
void Moteur_init(void);
|
||||
void M1_forward(int speed);
|
||||
void M1_backward(int speed);
|
||||
void M1_speed(int speed);
|
||||
void M2_forward(int speed);
|
||||
void M2_backward(int speed);
|
||||
void M2_speed(int speed);
|
||||
void affichage(void);
|
||||
|
||||
void main(void)
|
||||
{
|
||||
int ledpower = 500;
|
||||
|
||||
|
||||
stdio_init_all();
|
||||
QEI_init();
|
||||
Moteur_init();
|
||||
AsserMoteur_Init();
|
||||
Temps_init();
|
||||
uint32_t temps_ms = Temps_get_temps_ms();
|
||||
uint32_t step_ms=1;
|
||||
|
||||
gpio_init(LED1PIN);
|
||||
gpio_set_dir(LED1PIN, GPIO_OUT );
|
||||
gpio_put(LED1PIN, 1);
|
||||
AsserMoteur_setConsigne_mm_s(MOTEUR_A, 6000);
|
||||
AsserMoteur_setConsigne_mm_s(MOTEUR_B, 6000);
|
||||
|
||||
multicore_launch_core1(affichage);
|
||||
Moteur_SetVitesse(MOTEUR_A, 16000);
|
||||
Moteur_SetVitesse(MOTEUR_B, 16000);
|
||||
|
||||
while(1){
|
||||
QEI_update();
|
||||
|
||||
if(temps_ms != Temps_get_temps_ms()){
|
||||
temps_ms = Temps_get_temps_ms();
|
||||
QEI_update();
|
||||
AsserMoteur_Gestion(step_ms);
|
||||
if(temps_ms % 100 == 0){
|
||||
//printf(">c1:%d\n>c2:%d\n", QEI_get(QEI_A_NAME), QEI_get(QEI_B_NAME) );
|
||||
}
|
||||
}
|
||||
|
||||
printf(">c1:%d\n>c2:%d\n", QEI_get(QEI_A_NAME), QEI_get(QEI_B_NAME) );
|
||||
|
||||
M1_speed(1000);
|
||||
M2_speed(1000);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void affichage(void){
|
||||
while(1){
|
||||
|
||||
printf(">c1:%d\n>c1_mm:%f\n", QEI_get(QEI_A_NAME), QEI_get_mm(QEI_A_NAME) );
|
||||
//printf(">c2:%d\n>c2_mm:%f\n", QEI_get(QEI_B_NAME), QEI_get_mm(QEI_B_NAME) );
|
||||
printf(">m1:%f\n>m2:%f\n", AsserMoteur_getVitesse_mm_s(MOTEUR_A, 1), AsserMoteur_getVitesse_mm_s(MOTEUR_B, 1) );
|
||||
printf(">m1_c:%f\n>m2_c:%f\n", AsserMoteur_getConsigne_mm_s(MOTEUR_A), AsserMoteur_getConsigne_mm_s(MOTEUR_B) );
|
||||
sleep_ms(100);
|
||||
}
|
||||
}
|
||||
|
||||
void Moteur_init(void){
|
||||
|
||||
gpio_init(M1_SENS1);
|
||||
gpio_init(M1_SENS2);
|
||||
gpio_init(M2_SENS1);
|
||||
gpio_init(M2_SENS2);
|
||||
gpio_set_dir(M1_SENS1, GPIO_OUT);
|
||||
gpio_set_dir(M1_SENS2, GPIO_OUT);
|
||||
gpio_set_dir(M2_SENS1, GPIO_OUT);
|
||||
gpio_set_dir(M2_SENS2, GPIO_OUT);
|
||||
gpio_put(M1_SENS1, 0);
|
||||
gpio_put(M1_SENS2, 0);
|
||||
gpio_put(M2_SENS1, 0);
|
||||
gpio_put(M2_SENS2, 0);
|
||||
|
||||
gpio_set_function(M1_VITESSE, GPIO_FUNC_PWM);
|
||||
gpio_set_function(M2_VITESSE, GPIO_FUNC_PWM);
|
||||
pwm_set_wrap(5, 1000);
|
||||
pwm_set_wrap(4, 1000);
|
||||
pwm_set_chan_level(5, PWM_CHAN_B, 0);
|
||||
pwm_set_chan_level(4, PWM_CHAN_B, 0);
|
||||
pwm_set_enabled(5, true);
|
||||
pwm_set_enabled(4, true);
|
||||
|
||||
}
|
||||
|
||||
void M1_forward(int speed)
|
||||
{
|
||||
pwm_set_chan_level(5, PWM_CHAN_B, speed);
|
||||
gpio_put(M1_SENS1, 1);
|
||||
gpio_put(M1_SENS2, 0);
|
||||
}
|
||||
|
||||
// Set motor 1 speed backward
|
||||
void M1_backward(int speed)
|
||||
{
|
||||
pwm_set_chan_level(5, PWM_CHAN_B, speed);
|
||||
gpio_put(M1_SENS1, 0);
|
||||
gpio_put(M1_SENS2, 1);
|
||||
}
|
||||
|
||||
// Set motor 1 speed and direction (negative value : backward / positive value : forward)
|
||||
void M1_speed(int speed)
|
||||
{
|
||||
if(speed < 0)
|
||||
{
|
||||
speed = -speed;
|
||||
M1_backward(speed);
|
||||
}
|
||||
else
|
||||
{
|
||||
M1_forward(speed);
|
||||
}
|
||||
}
|
||||
|
||||
// Set motor 2 speed forward
|
||||
void M2_forward(int speed)
|
||||
{
|
||||
pwm_set_chan_level(4, PWM_CHAN_B, speed);
|
||||
gpio_put(M2_SENS1, 0);
|
||||
gpio_put(M2_SENS2, 1);
|
||||
}
|
||||
|
||||
// Set motor 2 speed backward
|
||||
void M2_backward(int speed)
|
||||
{
|
||||
pwm_set_chan_level(4, PWM_CHAN_B, speed);
|
||||
gpio_put(M2_SENS1, 1);
|
||||
gpio_put(M2_SENS2, 0);
|
||||
}
|
||||
|
||||
// Set motor 2 speed and direction (negative value : backward / positive value : forward)
|
||||
void M2_speed(int speed)
|
||||
{
|
||||
if(speed < 0)
|
||||
{
|
||||
speed = -speed;
|
||||
M2_backward(speed);
|
||||
}
|
||||
else
|
||||
{
|
||||
M2_forward(speed);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user