je voudrais controler des LED rgb avec le rgb shield et l'arduino uno commander par une radiocommande de modélisme.
Il y a un signal PWM a la sortie du récepteur si j'ai bien compris. maintenant mon problème est:
-quel câble je dois brancher ou?
-il me faut un programme (fini si possible) avec des explications (pour que je comprenne ce que je fait) pour transformer le signal en signal utilisable pour la programmation
- un programme pour la sortie des LED compatible avec le rgb shield arduino en controlant avec un canal, la couleur et l'autre, l'intensité.
Le récepteur envoie un signal au servo sur 3 fils :
- fil noir : GND
- fil rouge +5V
- fil jaune : PWM
Pour le fil noir, c'est assez simple, tu le branches sur GND de l'arduino
Pour le fil rouge, 2 cas possibles :
- si le récepteur est déjà alimenté (généralement par le variateur du moteur de la voiture), alors tu ne branches pas ce fil
- si le récepteur n'est pas alimenté, tu dois brancher ce fil sur le +5V de l'arduino (ainsi, l'arduino alimentera le récepteur)
Pour le fil jaune, tu dois brancher ça sur une pin de l'arduino (peu importe laquelle mais une pin d'interruption serait mieux).
Concernant le signal PWM, il faut savoir que ça ressemble à ça :
Toutes les 20ms, il y a un pulse (état HIGH) qui dure entre entre 1 et 2 ms.
- Si le pulse dure 1 ms, le servo est à fond dans un sens
- Si le pulse dure 1.5 ms, le servo est au neutre
- Si le pulse dure 2 ms, le servo est à fond dans l'autre sens
Pour le reste des valeurs, c'est simplement proportionnel.
Bref, tu l'as probablement déjà deviné, pour connaitre la position qu'envoie la télécommande, il te faudra mesurer le temps du pulse.
Tu peux faire ça avec une fonction bloquante du genre :
unsigned long pulseTime(int pin) {
while ( digitalRead(pin) == LOW ); // Attente que la pin passe à HIGH
unsigned long t1 = micros(); // Enregistrement du temps
while ( digitalRead(pin) == HIGH ); // Attente que la pin repasse à LOW
unsigned long t2 = micros(); // Enregistrement du temps
return ( t2 - t1 ); // Retour du temps du pulse
}
Cette fonction devrait te retourner une valeur entre 1000 (à fond dans un sens) et 2000 (à fond dans l'autre sens).
Par contre, j'insiste sur le fait qu'elle est bloquante : elle va bloquer l'exécution de ton programme pendant les temps d'attente qui peuvent durer jusqu'à 20ms ou une éternité sur le récepteur est HS.
Le mieux, ce serait de connecter le PWM sur un pin d'interruption et de ce servir de cette interruption pour noter et calculer les temps sans bloquer le reste du programme.
Pour faire simple, une interruption (ou plutôt routine d'interruption) est une fonction qui va temporairement mettre en pause l'exécution du code de base pour exécuter un autre bout de code.
Généralement, les interruptions sont utilisées pour être très réactif à évènement.
Petit exemple avec le code suivant :
int inPin = 2;
int ledPin = 13;
void setup()
{
Serial.begin(9600);
pinMode(inPin, INPUT);
pinMode(ledPin, OUTPUT);
}
void loop()
{
digitalWrite(ledPin, digitalRead(inPin));
Serial.println("Hello World ! How are you World ?");
}
C'est plutôt basique : l'arduino recopie l'état de la pin 2 sur la pin 13 en boucle, tout en faisant un println.
Sauf qu'un println, ça prend du temps ... à 9600b, c'est environ 1ms par caractères ...
Du coup, si l'utilisateur change l'état de la pin 2 au début du println, le changement de la pin 13 se fera environ 30ms plus tard.
Il est possible d'être bien plus réactif avec les interruptions :
int irqId = 0; // IRQ#0 = Pin#2 sur arduino
int inPin = 2;
int ledPin = 13;
void processIrq() {
digitalWrite(ledPin, digitalRead(inPin));
}
void setup()
{
Serial.begin(9600);
pinMode(inPin, INPUT);
pinMode(ledPin, OUTPUT);
attachInterrupt(irqId, processIrq, CHANGE);
}
void loop()
{
Serial.println("Hello World ! How are you World ?");
}
Ce code fait exactement la même chose : il écrit sur le Serial en boucle.
Sauf que grâce au attachInterrupt, dès que la pin 2 change d'état, l'arduino met en pause ce qu'il était en train de faire pour exécuter processIrq qui va changer l'état de la pin 13.
Avec ce système, le programme est donc extrêmement réactif au changement d'état de la pin 2.
Par contre, le println peut être être mis en pause en pleins milieux de son action mais ce n'est pas dérangeant car il ne sera interrompu que très peu de temps étant donné que la fonction processIrq est très courte.
Comment fait on des intervalles car il y a pas vraiment de valeurs exacte ( sa varie entre 1490 et 1510 au point neutre) pour vérifier la valeurs pour l'utiliser? ( ce n'est malheureusement pas expliquer dans le cours.)
si je fais mon code comme ceci pour trouver les couleurs a faire:
SI la valeurs est entre 990 et 1010 il fait cette couleur SINON rien ne se passe (if ....else)
SI la valeurs est entre 1010 et 1020 il fait cette couleur SINON rien ne se passe
...
cela va ralentir l’exécution? y a s’il une autre solution?
int val = ...
if ( val < 1000 ) {
val = 1000; // Correction des valeurs trop basse (1000 mini)
} else if ( val > 2000 ) {
val = 2000; // Correction des valeurs trop haute (2000 maxi)
} else if ( ( val >= 1490 ) && ( val <= 1510 ) ) {
val = 1500; // Correction des valeurs centrales (1500)
}
Avec ce code, tu t'assures que la valeur est entre 1000 et 2000 tout en ayant un beau 1500 en point milieux.
Évidement, faire quelques if, ça prend plus de temps que de ne rien faire.
Mais bon, si on par du principe que chaque ligne ralenti un peu plus l'exécution, autant ne rien coder, ce sera extrêmement rapide mais pas très efficace ...
L'arduino tourne quand même à 16 MHz donc il est capable de faire 16 millions d'opérations par secondes, ce n'est pas un petit if/elseif qui va le déranger.
Après, si c'est tout le système qui est instable, tu peux faire un lissage.
Par exemple :
val = ( 1 nouvelleVal + 19 * ancienneVal ) / 20;
Avec ce code, ton système sera extrêmement lissé donc peu d'oscillation mais moins réactif.
Tu peux jouer sur les coefficients pour lisser plus ou moins fort.
int val=0;
int t1=0;
int t2=0;
void setup()
{
}
void loop()
{
unsigned long pulseTime(int val); {
while ( digitalRead(3) == LOW ); // Attente que la pin passe à HIGH
unsigned long t1 = micros(); // Enregistrement du temps
while ( digitalRead(3) == HIGH ); // Attente que la pin repasse à LOW
unsigned long t2 = micros(); // Enregistrement du temps
int val = t2 - t1 ;
return val ; // Retour du temps du pulse
}
}
je ne comprend pas pourquoi ce code marche pas il m'affiche ceci:
sketch_oct23a.ino: In function 'void loop()': sketch_oct23a:15: error: return-statement with a value, in function returning 'void'
Une fonction, cela s'implémente en dehors d'une autre fonction et s'appelle à l’intérieur d'une fonction.
Je ne comprends pas non plus pourquoi tu converti le unsigned long en int pour ensuite faire un return de unsigned long.
Au final, le code devrait être comme ceci :
int pulsePin = 55; // CHANGER CE 55 AVEC LE NUMERO DE LA PIN !!!
void setup()
{
Serial.begin(9600);
}
unsigned long pulseTime(int val); {
while ( digitalRead(3) == LOW );
unsigned long t1 = micros();
while ( digitalRead(3) == HIGH );
unsigned long t2 = micros();
return ( t2 - t1 );
}
void loop()
{
int t = pulseTime(pulsePin);
Serial.print("Pulse Time = ");
Serial.println(t);
}
oui tout a fait et la valeur retourner est bien t ?
et il faut pas mettre le compteur des microseconde dans le void loop? car void setup ne fait pas de boucle donc il vérifie seulement le signal au démarrage du programme non?
Oui, la valeur de retour s'appelle t mais là encore, tu mets ce que tu veux.
Tu peux très bien mettre :
int leTempsDunPulseEnMicroSecondeQueJeCalculAvecLaFonctionPulseTimeJaiCopierCollerSurOpenClassrom = pulseTime(pulsePin);
Serial.print("Pulse Time = ");
Serial.println(leTempsDunPulseEnMicroSecondeQueJeCalculAvecLaFonctionPulseTimeJaiCopierCollerSurOpenClassrom);
Mais faut avouer que ce n'est pas très pratique.
Pour ce que est de l’emplacement, si tu regardes le code d'exemple que j'ai donné, j'appelle bien pulseTime dans le loop donc celle-ci est appelée en boucle.
Oui, la valeur de retour s'appelle t mais là encore, tu mets ce que tu veux.
Tu peux très bien mettre :
int leTempsDunPulseEnMicroSecondeQueJeCalculAvecLaFonctionPulseTimeJaiCopierCollerSurOpenClassrom = pulseTime(pulsePin);
Serial.print("Pulse Time = ");
Serial.println(leTempsDunPulseEnMicroSecondeQueJeCalculAvecLaFonctionPulseTimeJaiCopierCollerSurOpenClassrom);
Mais faut avouer que ce n'est pas très pratique.
mon dieu que j'ai ri! mais tu avoueras qu'avec de l'autocomplétion, ça passe tout seul, et même presque aussi bien que "t", ça. merci la technologie!
a oui donc il faut bein que je garde Serial.print(pulse time= ")
sinon merci bcp pour votre aide!
arduino et modelisme: comment combiner?
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
oui. non. enfin je regarde et je te dis.
oui. non. enfin je regarde et je te dis.