Comment écriveriez-vous en arduino cette formule?
la racine Kème d'un nombre c'est comme prendre ce nombre à la puissance 1 / K. (par exemple la racine carrée de 9 c'est comme 91/2)
ça ce fait avec la fonction pow()
double K = 1.5;
double Vr = 3.5;
double Vi = 2.3;
double Vo = Vr - pow(pow(Vr, K) - pow(Vi, K), 1.0 / K);
attention sur AVR il n'y a pas de coprocesseur à virgule flottante donc ce sont des calculs lents et un double n'est que sur 4 octets donc la précision n'est pas géniale
à titre de curiosité à quoi sert cette formule ?
Oh mince ... je suis arduino pro mini
Les données et les résultats seront à une décimale ... y a-t-il moyen d'accroitre la rapidité?
Maintenant qu'appelle-t-on lenteur?
Tension Vi lineaire (abscisses) .... tension corrigée en fonction de K (ordonnées)
K=1=sortie linéaire
A une certaine valeur de K , on obtient un 1/2 cercle parfait
le plus simple c'est d'essayer et voir si ça vous va
Pourquoi faut-il utiliser Double au lieu de Floating?
Pour le respect des types parce que c'est ce qu'attend la fonction pow.
mais de toutes façons sur votre pro mini c'est comme un float (4 octets) donc quand même quelques chiffres après la virgule de précision
sur le dessin - quels sont les axes ? Vo en ordonnée ? qu'est-ce qui bouge sur l'axe des abscisses Vr, Vi ?
effectivement
j'ai mis ça dans géogébra pour regarder
donc c'est Vi qui est sur l'axe des X et Vo sur l'axe des Y
exactement
Question : peut-on utiliser les sorties analogiques de l'Arduino pro mini pour envoyer les signaux CS,SCK,SDI vers la DAC MCP4921?
quand je veux faire une interpolation entre un point A et un point B avec un vecteur (tangente) de départ Va et d'arrivée Vb j'utilise plus souvent Une courbe de Bézier cubique
la formule est définie par quatre points de contrôle (ceux que l'on retrouve souvent dans les logiciels de dessins vectoriels) P0, P1, P2, et P3.
f(t) = (1 - t)3 * P0 + 3*(1 - t)2 * t * P1 + 3*(1 - t)*t2*P2 + t3*P3
où t représente le parcours sur la courbe, c'est un paramètre variant de 0 à 1.
Dans le cas des 2 points et 2 vecteurs (vitesse initiale, vitesse arrivée), P0 correspond à A, P3 correspond à B, et les vecteurs Va et Vb seront utilisés pour définir les tangentes aux points A et B.
P0 = A(Xa, Ya)
P1 = A + Va
P2 = B - Vb
P3 = B(Xb, Yb)
si on a un peu de mémoire, et qu'on sait qu'on veut 101 points d'interpolation entre 0 et 1 pour t alors on peut mettre dans une look up table les valeurs des coefficients (1 - t)3, 3*(1 - t)2 * t, 3*(1 - t)*t2 et t3 et on n'a pas à faire ces calculs à chaque fois
On peut avec une émulation du SPI sur ces broches mais c'est beaucoup moins rapide que si tu utilisais l'interface SPI dédié.
Cette courbe en tension commande un moteur, elle doit etre continue et je crains que des valeurs d'une table appelées ne produisent des secousses ... c'est un risque ou je n'ai rien compris?
Votre fonction (comme la mienne) est continue, mais vous aurez un pas sur l’axe des X au même titre que j’ai un pas sur t
Plus vous faites des petits pas sur votre axe ou plus mon delta t est faible, et moins il y a d’écart entre deux points consécutifs, donnant cette fluidité que vous recherchez. Mais vous n’êtes pas en analogique, forcément en numérique on fait de l échantillonnage
De plus, votre moteur a une inertie, et donc c’est lui qui absorbera tout doucement l’évolution de la valeur.
Bizarre
J'ai fait mon essai avec ma formule, une nano et un MCP4921
Lorsque K=1 j'ai une parfaite linearité jusqu'au bout : Vin = 3,5v .--> Vout = 3,5v
Mais lorsque K=2 par exemple : Vin = 3,5v --> Vout = 2v alors que la fonction donne mathematiquement 3,5v
Pourquoi?
Ma formule : tensionVoulueEnSortie = tensionEYE3max - pow(pow(tensionEYE3max, Bchoisi) - pow(tensionEYE3atraiter, Bchoisi), 1.0 / Bchoisi);
Avec tout en Floating
Avec en entrée un echantillonnage 5.0/1023 et en sortie 4095/5.0
Donnez moi un code qui montre ce que vous faites parce que wokwi dit que ça fonctionne
Voilà le code dans l'état ultra brut actuel ... il sera simplifié par des fonctions etc ..
//===========================================
// MAAPER-XIAO-HF4- 5 novembre
//===========================================
//#include <FlashStorage.h>
// #include <SAMD_AnalogCorrection.h>
#include "MCP_DAC.h"
#include <EEPROM.h> // bibliotheque pour lire et ecrire dans Eeprom
MCP4921 MCP(11, 13); //attribution entrées -> MCP4921 MCP(MOSI, SCK)
float tensionEYE3 = 0; // tension mesurée en volt
float tensionEYE3max = 4.0;
float tensionEYE3atraiter = 0; // tension EYE3 mesurée
float tensionVoulueEnSortie = 0; // Tension souhaitée en sortie du XIA0, exprimée en volts (entre 0 et 5V)
//float A = 0;
float valeurAenvoyer = 0; // valeur numerique envoyée au DAC
int LedChoix = 7; // sortie sur D2
int ClignotementsLed;
int adresse =0;
int i;
int A;
float Bchoisi;
//Choix des pines d'entrée
int boutonA = 6; // the number of the RF output D0 = pine D6 = (B=2)- acceleration très faible
int boutonB = 5; // the number of the RF output D1 = pîne D5 = (B=1,5)
int boutonC = 4; // the number of the RF output D2 = pine D4 = (B=1,2)
int boutonD = 3; // the number of the RF output D3 = pine D3 = (B=1)- accéleration très forte
//variables niveau de tension entrés
int etatboutonA = 0;
int etatboutonB = 0;
int etatboutonC = 0;
int etatboutonD = 0;
// ========================
// Initialisation programme
// ========================
void setup() {
// Initialise la liaison série (arduino nano -> PC)
Serial.begin(115200);
// initialise les pines boutton en mode entrée
pinMode(boutonA, INPUT);
pinMode(boutonB, INPUT);
pinMode(boutonC, INPUT);
pinMode(boutonD, INPUT);
pinMode(10,OUTPUT);
pinMode(11,OUTPUT);
pinMode(13,OUTPUT);
//ClignotementsLed = 0 ;
//i=0;
Bchoisi = EEPROM.read(adresse);
delay(50);
if (Bchoisi == 255) {
Bchoisi = 2;
}
// analogReadResolution(12);
// analogWriteResolution(10);
pinMode(LedChoix, OUTPUT);
MCP.begin(10); // commande chip slect (CS) attribuée à la pine D10
}
// =================
// Boucle principale
// =================
void loop() {
// ======= CHOIX COURBES ==================================================
// ----------- Pour choisir acceleration très faible (B=2),presser le bouton A
//------------ 4 clignotements
etatboutonA = digitalRead(6);
if (etatboutonA == HIGH) {
Bchoisi = 2.00; // acceleration très faible
ClignotementsLed = 4; // 4 clignotements
EEPROM.write(adresse, Bchoisi); // ------------- ecrire Bchoisi dans EEPROM
delay(100);
// ---- clignotement
for (int i = 1; i <= ClignotementsLed; i++) {
delay(500);
digitalWrite(LedChoix, HIGH);
delay(500);
digitalWrite(LedChoix, LOW);
}
}
// ----------- Pour choisir aceleration faible (=1,5) ,presser le bouton B
//------------ 3 clignotements
etatboutonB = digitalRead(5);
if (etatboutonB == HIGH) {
Bchoisi = 1.50; // accelereration faible
ClignotementsLed = 3; // 3 clignotements
EEPROM.write(adresse, Bchoisi); // ------------- ecrire Bchoisi dans EEPROM
delay(50);
// --- clignotement
for (int i = 1; i <= ClignotementsLed; i++) {
delay(500);
digitalWrite(LedChoix, HIGH);
delay(500);
digitalWrite(LedChoix, LOW);
}
}
// ----------- Pour choisir acceleration forte (= 1,2),presser le bouton C
//------------ 2 clignotements
etatboutonC = digitalRead(4);
if (etatboutonC == HIGH) {
Bchoisi = 1.20; // acceleration forte
ClignotementsLed = 2; // 2 clignotements
EEPROM.write(adresse, Bchoisi); // ------------- ecrire Bchoisi dans
delay(50);
// --- clignotement
for (int i = 1; i <= ClignotementsLed; i++) {
delay(500);
digitalWrite(LedChoix, HIGH);
delay(500);
digitalWrite(LedChoix, LOW);
}
}
// ----------- Pour choisir acceleration très forte (=1),presser le bouton D
//------------ 1 clignotements
etatboutonD = digitalRead(3);
if (etatboutonD == HIGH) {
Bchoisi = 1.00; // acceleration très forte
ClignotementsLed = 1; // 1 clignotement
EEPROM.write(adresse, Bchoisi); // ------------- ecrire Bchoisi dans EEPROM
delay(50);
// --- clignotement
for (int i = 1; i <= ClignotementsLed; i++) {
delay(500);
digitalWrite(LedChoix, HIGH);
delay(500);
digitalWrite(LedChoix, LOW);
}
}
ClignotementsLed = 0;
i=0;
// ======= MESURE SIGNAL,TRAITEMENT ET ENVOI VERS DAC ===============
Serial.print("Bchoisi=");
Serial.println(Bchoisi,2);
delay(1000);
// lecture signal sur la pine A3 en Volt
tensionEYE3 = analogRead(A7);
// conversion en valeur numerique
tensionEYE3atraiter = (tensionEYE3 * 5.0 / 1023); //10 bits - 1023
// calcul de la courbe à sortir
// tensionVoulueEnSortie = tensionEYE3max - pow(pow(tensionEYE3max, Bchoisi) - pow(tensionEYE3atraiter, Bchoisi), 1.0 / Bchoisi);
tensionVoulueEnSortie = tensionEYE3max - pow(pow(tensionEYE3max, Bchoisi) - pow(tensionEYE3atraiter, Bchoisi), 1.0 / Bchoisi);
// calcul de la valeur correspondante à la tension voulue en sortie du DAC et son envoi
int valeurAenvoyer = tensionVoulueEnSortie * 4095 / 5.0; // 12 bits - 4095 et ajustement à 4.9796v (au lieu de 5v) pour avoir 2.00 en sortie avec 2.00 en entrée
Serial.print("tensionEYE3=");
Serial.println(tensionEYE3);
Serial.print("tensionVoulueEnSortie=");
Serial.println(tensionVoulueEnSortie);
Serial.print("tensionEYE3atraiter=");
Serial.print("valeurAenvoyer=");
Serial.println(valeurAenvoyer);
Serial.println(tensionEYE3atraiter);
Serial.println("");
delay(2000);
// envoi sur sortie DAC
MCP.analogWrite(valeurAenvoyer); // ecriture signal sur la pine 8 du MCP4921
// Nota : la tension souhaitée ici est exprimée en volts (entre 0 et 5V), mais la valeur à transmettre
// pour ce faire doit être comprise entre 0 et 1023. D'où la nécessité de faire une conversion avant tout
}
J'ai utilisé double mais c'est pareil
voici ce que donne le moniteur série avec une tension d'entrée de 3.5v
Et vous voudriez quoi?