Bonjour la communauté,
j'aurais besoin d'un code de programmation pour un arduino uno svp.
Mon problème : convertir un signal pwm 50hz qui sort d'un récepteur modélisme FRSKY en
tension analogique variable de 0v à 5v, voilà c'est surement simple pour des pros mais pas pour moi.
j'ai acheté des convertisseur pwm - analogique mais je n'ai qu'une variation de 0.9V à 1.2V, c'est pour ça que d'après des recherches je me suis tourné vers un arduino uno mais je débute complétement avec ce type d'appareil, merci beaucoup de votre intérêt.
![]()
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
Faites rentrer cette sortie analogique en A0 et convertissez la pour être dans l’intervalle [0,5]
float mapfloat(float x, float in_min, float in_max, float out_min, float out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
…
// dans la loop
float valeurIn = analogRead(A0) * 5.0 / 1023;
float valeurOut = mapfloat(valeurIn, 0.9, 1.2, 0, 5);
if (valeurOut < 0) valeurOut = 0;
else if (valeurOut > 5) valeurOut = 5;
…
Ok, c'est déjà une solution merci beaucoup.
Est ce qu'il y a une solution sans utiliser mes convertisseurs car je n'ai pas trop confiance en ce matériel, merci.
C'est à dire rentrer directement du pwm dans l'arduino uno.
Votre pwm se fait entre 0 et 5V?
oui
mais en 50 hz
Lisez la durée du front avec pulseIn() - Arduino Reference (si on n’est jamais sans front)
Comme vous savez que la fréquence est 50Hz C’est ensuite un simple calcul
Ou Une interruption (CHANGE) pour calculer le temps HIGH ou simple boucle avec une lecture active
PS: Une simple recherche sur Internet donne des codes
Par exemple Three Ways To Read A PWM Signal With Arduino | BenRipley.com
Il faut surtout une carte ayant une sortie analogique! ou penser au convertisseur numérique analogique qu'il faut alors utiliser.
Ok, merci pour votre réponse, du coup un arduino uno ne pourra pas me sortir une tension
variable de 0V à 5V....
Non, il faudra un DAC
je pense que je vais utiliser une entrée PWM avec mon signal en 50hz, grâce à l'arduino uno convertir la fréquence en 2 khz pour entrer sur mon convertisseur numérique/ analogique en espérant pouvoir avoir une variation 0/5V en sortie de convertisseur.
Donc pour réaliser ça si j'ai bien compris j'utilise des codes comme ceux là ?https://www.benripley.com/diy/arduino/three-ways-to-read-a-pwm-signal-with-arduino/ ?
Bonsoir
on peut tenter d'utiliser une sortie pwm pour integrer/filtrer avec une cellule R/C une sortie 0/5V
On peut aussi filtrer directement le signal d'entrée sans passer par l'Arduino.
L'intérêt de passer par une Arduino est de monter la fréquence du PWM ce qui rend l'ensemble plus réactif.
Oui il faudrait que je monte la fréquence à 2 KHz pour rentrer sur mon convertisseur pwm/analogique qui prend du 1-3khz
Manque quelques précisions sur le cahier des charges.
-
Comment doit-on réagir sur changement du PWM à l'entrée? Par exemple si le PWM de l'entrée passe de 0% à 100%, la tension de sortie va passer de 0V à 5V, mais en combien de temps maximum?
Si on peut aller lentement un simple filtre RC sans Arduino suffit. Si on veut aller un peu plus vite, on peut utiliser l'Arduino en convertisseur PWM 50Hz/PWM 60kHz (resolution 8 bits) et un filtre RC. Si on veut aller au plus vite une mesure type pulsein() peut donner la valeur toutes les 20ms que l'on peut envoyer dans un convertisseur "instantanément". On a donc un retard maximum de 20ms -
Comment se comporte le convertisseur PWM/analogique que tu as? lent? rapide? précis?...
-
Quelle est la précision souhaitée de l'ensemble? On peut retenir comme solution une lecture par pulsin() (moins précis) ou par lecture de la valeur par un timer (meilleure précision) et un CNA en sortie, par exemple une Arduino avec un réseau R/2R. Pour une précision de 6 bits, on peut acheter des résistances discrètes, pour une précision correcte, on peu penser à des résistances en réseau.
Je me demande d'ailleurs si utiliser une Arduino pour passer d'un PWM 50Hz à 60kHz n'est pas aussi rapide que de passer par un CNA.
Oui à la restriction près : faire un filtre passe bas à 50 Hz n'est pas évident.
Soit on prend des composants énormes, soit on utilise un filtre actif avec un AOP.
Le filtre actif est la meilleure solution, mais tout le monde n'a pas les connaissances en électronique analogique nécessaires.
La solution d'Artouste me parait bien adaptée.
Surtout si on configure la PWM de l"arduino" à 64 kHz ce qui demandera un filtrage bien plus aisé à réaliser.
Bonjour,
Quand on parle de sigal pwm, on sous entend souvent un rapport cyclique variant de 0 à 100% et c'est ce que semble croire @rolland123 quand il essaie de convertir son signal en analogique.
Or ici il s'agit sans doute d'un signal radiocommande c'est à dire une impulsion de 1 à 2 ms se répétant toutes le 20 ms (pour la commande de servos par exemple). On parle plutôt de PPM ou PCM.
Si on veut convertir en signal analogique 0-5V il faut mesurer la durée de l'impulsion haute avec pulsein et générer un signal pwm suivit d'un filtre passe bas (ou utiliser un dac).
On peut aussi utiliser les interruptions pour mesurer la durée de l'impulsion, mais ça ne parait pas nécessaire.
Ce genre de module existe certainement tout fait.
Bonjour
J'avais fait il y a longtemps (2015) un petit prog de protection sur position d'une tourelle de char .
Objectif : interdire au canon d'etre < à l'horizontal dans certaines zones de la rotation de tourelle.
çà compile OK
/*
Systeme de mise en securité d'une tourelle de char RC
pour empecher le canon de toucher la caisse du char lors du passage
sur une/des zones depassant l'horizontal
1er jet programme de test simple
on assume là que le servo est en progression creneaux positifs pour une elevation positive
*/
int V1 = 2; // signal servo en provenance du recepteur
int ZS = 3; // detecteur de la zone à securiser
int S1 = 4; // sortie signal vers servo
int LED = 13; // sortie signal vers servo +led13 pour test visuel
int DS1 = 0; // durée creneaux haut servo
int CAL = 5; // pin pour mode calbration directe en manuel
int LS1 = 1500; //durée limite basse creneaux en µs sur la zone à protéger
int LS1T = 0;
int P1 = A0; // curseur potentiometre offset
int P1off = 0; // offset servo
long actu = 0;
void setup() {
Serial.begin(57600);
pinMode(V1, INPUT); // signal servo en provenance du recepteur
pinMode(ZS, INPUT); // detecteur de la zone à securiser
pinMode(S1, OUTPUT); // sortie signal vers servo
pinMode(CAL, INPUT_PULLUP); // mode calibratio directe si LOW
for (int i = 0; i <= 4; i++) { // x acquisitions pour stabiliser l'ADC
P1off = analogRead(P1);
delay(10);
}
// prise en compte de l'offset au reset
P1off = map(P1off, 0, 1023, -150, 150); // decalage max de +/- 150 µs selon position potentiometre
LS1T = LS1 + P1off; // on affecte le decalage
Serial.print(P1off);
Serial.print(" ");
Serial.println(LS1T);
}
void loop() {
if (digitalRead(CAL) == LOW) { // mode calibration manuelle
Serial.println (" MODE CALIBRATION MANUELLE ");
P1off = analogRead(P1);
P1off = map(P1off, 0, 1023, -150, 150);
LS1T = LS1 + P1off; // on affecte le decalage
digitalWrite(S1, HIGH); // injection vers servo
delayMicroseconds(LS1T);
digitalWrite(S1, LOW);
delayMicroseconds(20000); // etat bas inter creneaux
}
if (digitalRead(CAL) == HIGH) { // fontionnement normal
if (digitalRead(ZS) == LOW) digitalWrite(S1, digitalRead(V1)); // on est pas en zone à securiser , simple recopie signal recepteur vers servo
if (digitalRead(ZS) == HIGH) { // on est en zone à securiser, la condition peut etre inverse selon le signal du capteur
DS1 = pulseIn(V1, HIGH, 25000); // Lire durée creneaux venant du recepteur (timeout 25 ms)
if (DS1 < LS1T) DS1 = LS1T; // on est trop bas en zone a securiser, alors on affecte la durée mini creneaux en zone securité
digitalWrite(S1, HIGH); // on met la sortie vers le servo à l'etat haut
delayMicroseconds(DS1); // pour la durée mini de securité ou la durée du recepteur si >
digitalWrite(S1, LOW); // on met la sortie servo à l'etat bas
delayMicroseconds(20000); // etat bas inter creneaux
}
}
}
Bonjour rolland123
Oui, c'est la solution, comme proposé par @J-M-L, mesurer l'impulsion du PWM avec un pulseIn()
Convertir cette mesure, avec un map() de 0 à 4095 pour un DAC 12 bits.
const int pwmPulseMin = 1; // Impulsion minimum
const int pwmPulseMax = 20000; // Impulsion maximum
const int pwmPulseSignal = HIGH; // Valeur du signal à lire
int pwmPulse = 0;
const int pwmInputPin = 7; // Pin d'entrée du PWM
int pwmToDacValue = 0;
void setup()
{
Serial.begin(115200);
pinMode(pwmInputPin, INPUT);
}
void loop()
{
pwmPulse = pulseIn(pwmInputPin, pwmPulseSignal); // Mesure PWM
if (pwmPulse == 0) // Si timout
{
pwmPulse = (digitalRead(pwmInputPin) == HIGH) ? pwmPulseMax : 0;
}
pwmToDacValue = map(pwmPulse, pwmPulseMin, pwmPulseMax, 0, 4095); // Pour DAC12 bits
Serial.println(pwmToDacValue);
}
PS: J'ai testé avec un MCP4725, ça fonctionne impeccable!
Cordialement
jpbbricole