Augmenter progressivement PWM

Bonjour, j'ai une projet a faire et je bloque depuis quelque temps sur une chose.
Je gère mon PWM avec un potentiomètre pour faire avancer un moteur, seul problème si je tourne très vite mon moteur d'un seul coup pendant un petit laps de temps, mon skate (oui je fait un skate électrique) va démarrer rapidement, de même pour l'inverse si je veux freiner, je ne veux pas que sa freine brusquement si je tourne très vite le potar. J'aimerai donc svp de l'aide pour éviter de passer d'une vitesse A à B trop rapidement avec le potar, donc d'avoir une vitesse progressive.

:warning:
Post mis dans la mauvaise section, on parle anglais dans les forums généraux. déplacé vers le forum francophone.

Merci de prendre en compte les recommandations listées dans Les bonnes pratiques du Forum Francophone

En gros tu veux une courbe de vitesse comme ça, en fonction de ton potentiomètre :
image

En bas à gauche : tu démarres lentement. Lorsque tu tournes le potentiomètre (c'est à dire lorsque tu te déplaces vers la droite sur la courbe), la vitesse augmente lentement (la courbe monte très peu). Puis au fur et à mesure que tu tournes, la vitesse se met à augmenter plus (c'est la partie intermédiaire qui monte).
En haut à droite : lorsque tu es à vitesse maximale (lorsque le potentiomètre est tourné à fond, la vitesse est maximale), si tu veux ralentir tu tournes le potentiomètre dans l'autre sens (tu te déplaces vers la gauche de la courbe) et la vitesse diminue (la courbe descend). Au début elle diminue peu puis diminue plus fort au fur et à mesure que tu tournes.

Cette courbe (il y en a plusieurs) s'appelle une sigmoïde et se calcule avec la formule suivante :
image
Le paramètre lambda permet de régler la taux d'augmentation (voir lien).

Tu peux la tracer toi même avec Google, et choisir ainsi la valeur de lambda qui te convient : par exemple pour 0.5, tape 1/(1+exp(-0.5*x) dans Google et tu verras ta courbe. Puis pour 0.7 tape 1/(1+exp(-0.7*x) et tu verras la courbe changer.

Il y a d'autres logiciels en ligne pour faire ça. Avec geogebra, tu peux faire une jolie animation :

Une manière de faire peut être de passer par une machine à état.
lors de l'accélération/décélération de limiter le delta de la valeur du PWM et de rester dans le même état, jusqu'à ce que la valeur du PWM rattrape le potar.

Merci, c'est super intéressant et sa m'aide beaucoup, mais je ne sais toujours las comment integrer ceci dans un programme. Pourriez vous m'éclaircir sur comment l'intègrer dans un programme ?

La proposition de @lesept est le mieux de ce que l’on peut faire.

Tu peux y aller directement, ou procéder par étapes.
Ce que je te conseille.

Dans un programme ”brouillon” utilises, pour commencer une droite d’equation y=m1*x.
y = valeur a entrer dans analogueWrite(pin, pwm)
x = temps
m1 = pente de la droite.

Y sera compris entre 0 et 255
X sera compris entre 0 et tmax = valeur que tu aura choisi pour le temps que doit durer l’accélération.
Pour le freinage tu prend une droite
y= - m2*x + 255.
m2 = pente de la droite de freinage s’il est différent de l’accélération.
Les temps de phase d’accélération et de freinage seront probablement différents (ce sera ton choix) donc les valeurs du coefficient directeur de la droite d’accélération et de freinage seront aussi différentes.

Quand cela fonctionnera tu pourra definir les coefficients qui vont bien de la sigmoïde d’accélération et de celle de freinage.

Pour la mise au point tu peux afficher les valeurs de x et y sur le moniteur de l’IDE et tracer les courbes d’accélération et de freinge avant de connecter un moteur.
La mise au point sera plus simple et plus souple.

Ps : un frenage d’urgence sera a prévoir.

Je ne suis pas sûre d'avoir bien compris votre solution.
Que ce passe t'il si on tourne le potar rapidement de 0 à 100% en 2s, quel sera la vitesse au bout de ces 2s ?

Si je continue sur ma lancée : une valeur de 2.5 pour lambda me semble correcte.
Il faut ramener la valeur de la fonction entre 0 et 255 et la décaler vers la droite : ça donne une nouvelle fonction à programmer
image
La courbe devient :


On voit que pour des valeurs en entrée comprises entre 0 et 4 à 4.5, la courbe varie bien de 0 à 255.

Donc il faut écrire une fonction qui reçoit en entrée la valeur lue du potentiomètre, la ramène entre 0 et 4.5, applique la fonction f(x) et renvoie la valeur calculée. Tu sais faire ça ?

Note que si tu veux une accélération plus lente, tu peux diminuer la valeur de lambda. Pour 2, ça donne :


avec (x-3) à la place de (x-2) et il faut ramener la valeur du potard entre 0 et 6 (à peu près).

Le problème c'est juste de répondre doucement à des variations brutales.
Je pense qu'un simple filtre IIR de la forme suivante ferait l'affaire:
y(n) = K * x(n) + (1 - K) * y(n - 1)

Tu ajustes K en fonction de la réponse que tu cherches à avoir.

Bonjour unpezquibrain

Voilà comment je vois la chose, 2 variables pwmBut qui est la position du pot et pwmValeur qui est la valeur sortie sur la pin pwmPin.
Un timer (pwmScanTempo) lit périodiquement la position du potentiomètre (pwmBut), valeur transformée en valeurs PWM (map(analogRead(potPin), 0, 1023, 0, 255). pwmBut est comparée avec pwmValeur, s'il y a une différence, on incrémente ou décrémente (pwmIncrement) pwmValeur et, ceci, au rythme du timer (pwmScanTempo).
Le rythme du timer, pwmScanTempo associé à pwmIncrement, donnent la progressivité de la montée ou de la descente du PWM.

Et ça donne ceci:

const int potPin = A0;     // Pin du potentiomètre
const int pwmPin = 9;     // Pin du PWM

int pwmBut = 0;     // Valeur du PWM à atteindre
int pwmValeur = 0;     // Valeur du PWM à atteindre
int pwmIncrement = 5;

unsigned long pwmScanTempo = 250;     // Donne le tempo de la progression
unsigned long pwmScanMillis = millis();     // Chrono de la progression

void setup()
{
	Serial.begin(115200);

}

void loop()
{
	if (millis() - pwmScanMillis >= pwmScanTempo)
	{
		pwmBut = map(analogRead(potPin), 0, 1023, 0, 255);
		if (pwmBut < pwmValeur)
		{
			pwmValeur -= pwmIncrement;
		}
		if (pwmBut > pwmValeur)
		{
			pwmValeur += pwmIncrement;
		}
		
		analogWrite(pwmPin, pwmValeur);

		Serial.print("PWM but " + String(pwmBut));
		Serial.println("\tPWM valeur " + String(pwmValeur));

		pwmScanMillis = millis();
	}
}

Il y a des indications quant au fonctionnement du programme, dans la console à 115200.

A+
Cordialement
jpbbricole

hello
@jpbbricole , j'ai un doute

ton prog ne fait qu'une recopie de la lecture du potar, ton accélération sera linéaire, et si tu espace les lectures du potar, tu auras des paliers. ton accélération sera un escalier

nos amis étaient partis sur une courbe d'accélération qui doit ressembler à une progression logarithmique

Oui c'est le mieux, mais une sigmoïde est centrée sur l'origine de temps.

Il faut faire un décalage (changement d'origine en mathématique).
Ce décalage dépend de la valeur de lamda (raideur de la sigmoïde).
Régler en priorité le cas de la sigmoïde est, à Mon Humble Avis, une dispersion et une perte de temps, qui empêchera de régler d'autres parties dans le programme.

C'est pour cela que j'ai conseillé de commencer par une droite, bien plus simple. Ce qui permet de régler d'autres problèmes dans le programme comme la commande du moteur.

Si dès le départ le calcul des valeurs de pwm est réalisé dans une fonction, pour passer de la droite à la sigmoïde (ou une autre solution), il y aura juste à modifier le contenu de cette fonction.
Cela signifie qu'avant de se précipiter pour programmer, il faut définir les entrées et sorties de cette fonction.

Tu peux mettre toutes les fonctions que tu veux, si tu ne fais pas intervenir le temps, tu sera limité par les bornes de ta fonction pour intervenir sur l'accélération.
Après @unpezquibrain n'ayant pas donnée les contraintes qu'il veut appliquer sur l'accélération.

Comment fais tu pour limiter l'accélération avec la fonction linéaire ou pas ?

@jpbbricole je suis d'accord avec @dfgh il faudrait ne pas limiter la lecture du potar lorsque celui-ci va moins vite que ta temporisation ?

Bonjour dfgh

Est ce bien nécesaire, @unpezquibrain demande:

donc de "ralentir" l'évolution de la valeur du PWM, ce que mon programme fait.

En jouant avec pwmScanTempo et pwmIncrement on peut avoir une évolution sans escaliers.

Si tu essaies le programme, tu verra la progression du PWM dans la console à 115200.

Cordialement
jpbbricole

Tant que @unpezquibrain ne donne pas plus de renseignements sur sa réalisation, les discussions sont dans le vide.
Comment compte-t-il commander un démarrage ? une vitesse de croisière ? un freinage ?
Vous allez comparer des solutions personnelles, même très personnelles, et dans 30 messages, nous aurons par hasard des informations qui rendront vos solutions non applicables.
Ce sera loin d'être la première fois.

Et puis avant de remplir les paragraphes, on écrit le sommaire.

Je suis complétement d'accord avec toi sur le fond, il manque des informations pour apporter une réponse à @unpezquibrain.

Par contre on peut discuter du fond de chaque solution proposer, surtout si il s'agit de limiter une accélération sans tenir compte du temps.

Bonsoir

parfois les trucs les plus simple ... un petit lissage de la valeur du potentiomètre

Val_lissee = ((Val_lissee * Lissage) + Valeur_demandee) / lissage +1 ;

avec lissage = 5 ça progresse déjà doucement

Aves des parenthèses autour de lissage + 1 ?

oui moi je le calcule avant dans le setup comme valeur divliss... donc la oui l'ordre de priorité l'impose
de meme majuscule minuscule a lissage ca porte a erreur ... dsl

Il manque je pense aussi une contrainte de temps, sinon tu va vite atteindre la valeur maximun.
La valeur maximum étant du coup différente de la valeur demandée :slight_smile:

En tout cas ce n'est pas les solutions qui manques :laughing: