0 Members and 2 Guests are viewing this topic.
#include <stdio.h>#include <math.h>#define MARGE 5 //marge +/- 5 (5 exclu)#define TOUT_DROIT 0#define DROITE 1#define GAUCHE 2int direction (int initiale, int finale, int* angle){ if (abs(initiale - finale) < MARGE || abs(initiale - finale) > (360 - MARGE)) { printf("A/ cas TOUT DROIT\n"); *angle = 0; return TOUT_DROIT; } else if ((initiale - finale) < 0) { if ((initiale - finale + 360) > 180) { printf("B/ cas i-f < 0, i-f+360 > 180 DROITE\n"); *angle = -initiale + finale; return DROITE; } else { printf("C/ cas i-f < 0, i-f+360 < 180 GAUCHE\n"); *angle = initiale - finale + 360; return GAUCHE; } } else { if ((initiale - finale) > 180) { printf("D/ cas i-f > 0, i-f > 180 DROITE\n"); *angle = -initiale + finale + 360; return DROITE; } else { printf("E/ cas i-f > 0, i-f < 180 GAUCHE\n"); *angle = initiale - finale; return GAUCHE; } }}main(){ int angle = 0; int cote = 0; cote = direction(2,358, &angle); printf("i = 2, f = 358, coté = %d, angle = %d\n",cote,angle); cote = direction(356,1, &angle); printf("i = 356, f = 1, coté = %d, angle = %d\n",cote,angle); cote = direction(357,1, &angle); printf("i = 357, f = 1, coté = %d, angle = %d\n",cote,angle); cote = direction(4,360, &angle); printf("i = 4, f = 360, coté = %d, angle = %d\n",cote,angle); cote = direction(5,360, &angle); printf("i = 5, f = 360, coté = %d, angle = %d\n",cote,angle); cote = direction(360,5, &angle); printf("i = 360, f = 5, coté = %d, angle = %d\n\n",cote,angle); cote = direction(20,180, &angle); printf("i = 20, f = 180, coté = %d, angle = %d\n",cote,angle); cote = direction(20,270, &angle); printf("i = 20, f = 270, coté = %d, angle = %d\n",cote,angle); cote = direction(270,20, &angle); printf("i = 270, f = 20, coté = %d, angle = %d\n",cote,angle); cote = direction(190,140, &angle); printf("i = 190, f = 140, coté = %d, angle = %d\n",cote,angle); cote = direction(350,140, &angle); printf("i = 350, f = 140, coté = %d, angle = %d\n\n",cote,angle); cote = direction(10,190, &angle); printf("i = 10, f = 190, coté = %d, angle = %d\n",cote,angle); cote = direction(9,190, &angle); printf("i = 9, f = 190, coté = %d, angle = %d\n",cote,angle); cote = direction(11,190, &angle); printf("i = 11, f = 190, coté = %d, angle = %d\n",cote,angle); cote = direction(190,7, &angle); printf("i = 190, f = 7, coté = %d, angle = %d\n",cote,angle); cote = direction(340,20, &angle); printf("i = 340, f = 20, coté = %d, angle = %d\n",cote,angle); return 0;}
A/ cas TOUT DROITi = 2, f = 358, coté = 0, angle = 0D/ cas i-f > 0, i-f > 180 DROITEi = 356, f = 1, coté = 1, angle = 5A/ cas TOUT DROITi = 357, f = 1, coté = 0, angle = 0A/ cas TOUT DROITi = 4, f = 360, coté = 0, angle = 0C/ cas i-f < 0, i-f+360 < 180 GAUCHEi = 5, f = 360, coté = 2, angle = 5D/ cas i-f > 0, i-f > 180 DROITEi = 360, f = 5, coté = 1, angle = 5B/ cas i-f < 0, i-f+360 > 180 DROITEi = 20, f = 180, coté = 1, angle = 160C/ cas i-f < 0, i-f+360 < 180 GAUCHEi = 20, f = 270, coté = 2, angle = 110D/ cas i-f > 0, i-f > 180 DROITEi = 270, f = 20, coté = 1, angle = 110E/ cas i-f > 0, i-f < 180 GAUCHEi = 190, f = 140, coté = 2, angle = 50D/ cas i-f > 0, i-f > 180 DROITEi = 350, f = 140, coté = 1, angle = 150C/ cas i-f < 0, i-f+360 < 180 GAUCHEi = 10, f = 190, coté = 2, angle = 180C/ cas i-f < 0, i-f+360 < 180 GAUCHEi = 9, f = 190, coté = 2, angle = 179B/ cas i-f < 0, i-f+360 > 180 DROITEi = 11, f = 190, coté = 1, angle = 179D/ cas i-f > 0, i-f > 180 DROITEi = 190, f = 7, coté = 1, angle = 177D/ cas i-f > 0, i-f > 180 DROITEi = 340, f = 20, coté = 1, angle = 40
Houlala, tu m'en a tartiné du code !Mon programme est terminé et fonctionne correctement. Mais dans ton programme il y a des formulations dont je ne connais pas la syntaxe, donc je vais m'y pencher pour en savoir plus.Naturellement, par curiosité je vais soumettre ce code à Arduino et essayer de tout comprendre.OUI, pour le point 3 de symétrisation de la barre c'est enfantin. J'ai défini la valeur comme une constante qu'il est facile de changer si on adopte un autre servomoteur.>>> Tu utilises pour ça un define. Peux-tu me préciser l'avantage de cette écriture par rapport à la précision d'une constante ? (Gain d'un emplacement mémoire ?)
(1) static const int var = 5;(2) #define var 5(3) enum { var = 5 };Si tu dois passer un pointeur, utilise (1). (Mais comme tu ne peux pas changer la valeur d'une constante, tu n'utiliseras pas de pointeur ...)(1) et (3) sont plus facile à debugguer que (2)(1) ne peut être utilisé comme dimension pour des tableaux au niveau global, mais (2) et (3) le peuvent.(1) ne peut être utilisé comme dimension pour des tableaux "static" au niveau d'une fonction,mais (2) et (3) le peuvent.Depuis C99, les 3 méthodes peuvent être utilisées pour dimensionner des tableaux locaux, même si techniquement, (1) signifierait déclarer un tableau de taille variable (même si la variable est une constante), ce que C n'aime pas ...(1) ne peut pas être utilisé dans un switch (... case [...]: ...), mais (2) et (3) le peuvent.Tu peux voir si (2) a été initialisé par le préprocesseur, mais ni (1) ni (3) le peuvent
Calculer le coté vers lequel tourner : J'ai vraiment cherché un bon moment et utilisé les idées des copains, car je me suis heurté à des calculs faux issus du comportement du compilateur qui n'est pas une calculatrice. Comme dans la formule qui gère le CAP + 180° j'ai introduit un "int" et un "long" je me retrouvais avec des erreurs de calcul dues à des "compléments à deux" issus du code compilé. C'est sournois car tu te retrouve avec des valeurs fausses alors que mathématiquement ta formule est bonne.
Pour ce qui est de la zone neutre, c'est facile. Un bouton me permet de choisir entre un minimum de 2° et un maximum de 15°. C'est la plage de chaque coté du CAP désiré où l'écart de route est ignoré. C'est pour éviter que le moteur ne "barbotte" sans interruption dès qu'une vaguelette ou une petite saute de vent altère ta route d'un fifrelin. Par temps calme 2° conviennent, mais avec du clapot et sous vent arrière il faut augmenter la tolérance si l'on veut calmer la nervosité du moteur. De toute façon, quand les circonstances deviennent difficiles ... on barre à la main.Vla toute l'histoire, je vais donc me barrer pour analyses le fruit de tes cogitations.
Eclairage_LED doit varier entre [0 et 255] mais choisir le type unsigned long car le calcul rouge peut arriver à la valeur calculée de 1024 * 255 = 261120.
GLUPPPSSSsssss, mais je n'avais pas vu que j'étais PILEPOILE à 3000 !Le "normalement" pour un compilateur, c'est du théorique. Un langage étant défini, chaque implémentation du compilateur va forcément avoir des spécificités en fonction des choix effectués par les programmeurs.Pour le [0 à 1023] tu as raison, il ne faut pas confondre le nombre de combinaisons et la plus forte valeur rencontrée. Du reste j'ai bien vu quand j'ai fais afficher les valeurs issues du convertisseur A/N que la butée était bien 1023 et non 1024. Par contre, la façon dont fonctionne le compilateur C engendre bien ce "détail" de non homogénéité des variables. On peut forcer les calculs à une taille désirée, c'est ce que l'on nomme "le cast". Mais si tu ne le sais pas au départ, bonjour les problèmes de mise au point de ton programme.Vas sur : http://forum.arduino.cc/index.php?topic=219848.0J'ai détaillé un peu le résultat de ma petite étude.Amicalement : Môamôa.
Byte1=shiftIn(dataPin_in, clockPin_in, MSBFIRST);
for i=0;i<8;++i{Byte1=Byte1⎢(digitaRead(dataPin_in)<<i); //on pousse d'un rang les bits entrantdigitalWrite(clockin_in,HIGH);digitalWrite(clockin_in,LOW); }
Morbleu ... il cogite fort notre Mars Bleue !
#include <HIDKeyboard.h> //chargement de la bibliothèque. Attention, il faut au préalableHIDKeyboard keyboard; //flashouiller la Uno comme écrivait hysot dans la première //page de ce topicconst int dataPin_out=2;const int latchPin_out=3;const int clockPin_out=4;const int dataPin_in=5;const int latchPin_in=6;const int clockPin_in=7; //donc 6 sorties utilisées sur la Uno pour 8 interrupteursbyte switchStatus; //et 16 leds. Avec davantage de registres à décalage, onbyte previousswitchStatus=0; // peut en mettre bien plusbyte i;byte Byte1;long switchtime;void setup() { pinMode (dataPin_out,OUTPUT); pinMode (latchPin_out,OUTPUT); pinMode (clockPin_out,OUTPUT); pinMode (dataPin_in,INPUT); pinMode (latchPin_in,OUTPUT); pinMode (clockPin_in,OUTPUT); Serial.begin(9600); keyboard.begin(); delay(2000); } void loop(){ digitalWrite(latchPin_in,LOW); //mise en lecture delayMicroseconds(20); //attendre 20 μsecondes digitalWrite(latchPin_in,HIGH); //bloquer la lecture for (i=0;i<8;++i){ //boucle qui va "pousser" les états switchStatus=switchStatus|(digitalRead(dataPin_in)<<i); //des switches dans la mémoire digitalWrite(clockPin_in,HIGH); //switchStatus digitalWrite(clockPin_in,LOW); } if (switchStatus!=previousswitchStatus) // si un switch a été manoeuvré=> { switchtime=millis(); if ((switchStatus^previousswitchStatus)==128) //manoeuvre APU { i=updateRegister(switchStatus); // aller à fonction mise à jour des registres keyboard.pressKey(CTRL,'a'); // simuler un "CTRL a" pour toggler l'APU temporelease(); // aller à fonction touche relâchée } if (((switchStatus^previousswitchStatus)==64)&&((switchStatus&128)==128)) { //baydoors i=updateRegister(switchStatus); keyboard.pressKey(CTRL,'u'); temporelease(); } if (((switchStatus^previousswitchStatus)==32)&&((switchStatus&128)==128)) { //nosecone i=updateRegister(switchStatus); keyboard.pressKey(CTRL,'k'); temporelease(); } if (((switchStatus^previousswitchStatus)==16)&&((switchStatus&128)==128)) { //outerdoor i=updateRegister(switchStatus); keyboard.pressKey(CTRL,'o'); temporelease(); } if (((switchStatus^previousswitchStatus)==8)&&((switchStatus&128)==128)) { //innerdoor i=updateRegister(switchStatus); keyboard.pressKey(ALT,'o'); temporelease(); } if (((switchStatus^previousswitchStatus)==4)&&((switchStatus&128)==128)) { //airbrake i=updateRegister(switchStatus); keyboard.pressKey(CTRL,'b'); temporelease(); } if (((switchStatus^previousswitchStatus)==2)&&((switchStatus&128)==128)) { //cabin hatch i=updateRegister(switchStatus); keyboard.pressKey(CTRL,'Y'); temporelease(); } if (((switchStatus^previousswitchStatus)==1)&&((switchStatus&128)==128)) { //radiator i=updateRegister(switchStatus); keyboard.pressKey(ALT,'r'); temporelease(); } }// fin manoeuvre d'un switch previousswitchStatus=switchStatus; switchStatus=0; delay(150);}// sous programme de remplissage des registres int updateRegister(byte Byte1) { digitalWrite(latchPin_out,LOW); //début écriture dans les registres shiftOut(dataPin_out, clockPin_out, LSBFIRST, Byte1); shiftOut(dataPin_out, clockPin_out, LSBFIRST, Byte1); //on remplit les 2 registres digitalWrite(latchPin_out, HIGH); // fin écriture dans les registres }// sous programme de tempo/release d'une touche void temporelease() { delay(100); keyboard.releaseKey(); delay(50); }
Faut que je trouve ce journal, ça peut me donner des idées.Merci, Jacquesmomo, pour cette info!
#include <HIDKeyboard.h>HIDKeyboard keyboard; //Version pour l'APU, baydoors et nosecone //la gestion du transit subordonnée à la marche de l'APU semble fonctionnel pour nosecone //const int dataPin_out=2; //vérifier pour baydoors, et le resteconst int latchPin_out=3;const int clockPin_out=4;const int dataPin_in=5;const int latchPin_in=6;const int clockPin_in=7;byte switchStatus;byte previousswitchStatus=0;byte i;byte bit_rank;byte transitStatus;byte greenlit;byte greenblink;byte yellowlit;byte yellowblink;int transitTime [2][8]={ {320,66,33,100,100,200,330,25}, //durée de transit en dixièmes de secondes {0,0,0,0,0,0,0,0}};int transitDelay [8]={0,0,0,0,0,0,0,0};unsigned long switchTime[8]={0,0,0,0,0,0,0,0};unsigned long deltaTime[8]={0,0,0,0,0,0,0,0};unsigned long timeSwitch;unsigned long deltat;void setup() { pinMode (dataPin_out,OUTPUT); pinMode (latchPin_out,OUTPUT); pinMode (clockPin_out,OUTPUT); pinMode (dataPin_in,INPUT); pinMode (latchPin_in,OUTPUT); pinMode (clockPin_in,OUTPUT); Serial.begin(9600); keyboard.begin(); delay(2000); } void loop(){ digitalWrite(latchPin_in,LOW);//latch à LOW pour lire l'état des switches) delayMicroseconds(20); digitalWrite(latchPin_in,HIGH);//latch à HIGH, verrouillage for (i=0;i<8;++i){ //on "pousse" 8 fois les valeurs lues dans la mémoire switchStatus; c'est le shiftIn switchStatus=switchStatus|(digitalRead(dataPin_in)<<i); digitalWrite(clockPin_in,HIGH); digitalWrite(clockPin_in,LOW); } if (switchStatus!=previousswitchStatus) // si un switch a été manoeuvré=> { if ((switchStatus^previousswitchStatus)==128) //manoeuvre APU { //keyboard.pressKey(CTRL,'a'); pour l'instant, raccourci clavier inactivé durant la mise au point //temporelease(); bit_rank=7; //transmission du rang de bit à traiter timeSwitch=switchTime[bit_rank]; LEDmanagement1(bit_rank, timeSwitch); //appel fonction de gestion des LED avec le bit 8 correspondant à l'APU switchTime[bit_rank]=millis(); } if (((switchStatus^previousswitchStatus)==64)&&((switchStatus&128)==128)) { //baydoors //keyboard.pressKey(CTRL,'u'); //temporelease(); bit_rank=6; //transmission du rang de bit à traiter timeSwitch=switchTime[bit_rank]; LEDmanagement1(bit_rank, timeSwitch); //appel fonction de gestion des LED avec le bit 7 correspondant à baydoors switchTime[bit_rank]=millis(); } if (((switchStatus^previousswitchStatus)==32)&&((switchStatus&128)==128)) { //nosecone //keyboard.pressKey(CTRL,'k'); //temporelease(); bit_rank=5; //transmission du rang de bit à traiter timeSwitch=switchTime[bit_rank]; LEDmanagement1(bit_rank, timeSwitch); //appel fonction de gestion des LED avec le bit 6 correspondant à nosecone switchTime[bit_rank]=millis(); } if (((switchStatus^previousswitchStatus)==16)&&((switchStatus&128)==128)) { //outerdoor //i=updateRegister(switchStatus); keyboard.pressKey(CTRL,'o'); temporelease(); } if (((switchStatus^previousswitchStatus)==8)&&((switchStatus&128)==128)) { //innerdoor //i=updateRegister(switchStatus); keyboard.pressKey(ALT,'o'); temporelease(); } if (((switchStatus^previousswitchStatus)==4)&&((switchStatus&128)==128)) { //airbrake //i=updateRegister(switchStatus); keyboard.pressKey(CTRL,'b'); temporelease(); } if (((switchStatus^previousswitchStatus)==2)&&((switchStatus&128)==128)) { //cabin hatch //i=updateRegister(switchStatus); keyboard.pressKey(CTRL,'Y'); temporelease(); } if (((switchStatus^previousswitchStatus)==1)&&((switchStatus&128)==128)) { //radiator //i=updateRegister(switchStatus); keyboard.pressKey(ALT,'r'); temporelease(); } }// fin manoeuvre d'un switch // Début de gestion des registres lié au passage du temps. bit_rank=7; //transmission du rang de bit timeSwitch=switchTime[bit_rank];//envoi de switchTime[bit_rank] LEDmanagement2(bit_rank,timeSwitch); //appel fonction de gestion des LED avec le bit 8 correspondant à l'APU bit_rank=6; //transmission du rang de bit deltat=millis()-deltaTime[bit_rank];//calcul du temps écoulé depuis dernier passage deltaTime[bit_rank]=millis(); //mise à jour de deltaTime[bit_rank] switchTime[bit_rank]=switchTime[bit_rank]+(deltat*(yellowblink&64)==0); //switchTime rendu "glissant" si APU non en fonction timeSwitch=switchTime[bit_rank];//envoi de switchTime[bit_rank] LEDmanagement2(bit_rank,timeSwitch); //appel fonction de gestion des LED avec le bit 7 correspondant à baydoors bit_rank=5; //transmission du rang de bit deltat=millis()-deltaTime[bit_rank];//calcul du temps écoulé depuis dernier passage deltaTime[bit_rank]=millis(); //mise à jour de deltaTime[bit_rank] switchTime[bit_rank]=switchTime[bit_rank]+(deltat*((yellowblink&64)==0)); //switchTime rendu "glissant" si APU non en fonction timeSwitch=switchTime[bit_rank];//envoi de switchTime[bit_rank] LEDmanagement2(bit_rank,timeSwitch); //appel fonction de gestion des LED avec le bit 6 correspondant à nosecone // Fin de gestion des registres lié au passage du temps. previousswitchStatus=switchStatus; switchStatus=0; delay(150);} //fin loop// sous programme de remplissage des registres int updateRegister(byte Byte1, byte Byte2, byte Byte3, byte Byte4) { digitalWrite(latchPin_out,LOW); //d√©but √©criture dans les registres shiftOut(dataPin_out, clockPin_out, LSBFIRST, Byte2); shiftOut(dataPin_out, clockPin_out, LSBFIRST, Byte4); //on remplit les 2 registres digitalWrite(latchPin_out, HIGH); // fin √©criture dans les registres }// sous programme de tempo/release d'une touche void temporelease() { delay(100); keyboard.releaseKey(); delay(50); }// sous programme de gestion des LEDs lié à un mouvement de switch int LEDmanagement1(byte bit_rank, unsigned long SwitchTime) { //switchTime[bit_rank]=SwitchTime; //transmission du temps de mvtswitch à switchTime[bit_rank] transitTime[1][bit_rank]=((millis()-switchTime[bit_rank])/100) ; //calcul temps écoulé depuis dernier //mouvement switch en 1/10° de sec. Calcul au cas où le transit serait encore en cours if ((transitStatus&(1<<bit_rank))==0) { transitDelay[bit_rank]=transitTime[0][bit_rank] ; //réglage du temps de transit } if ((transitStatus&(1<<bit_rank))==(1<<bit_rank)) // si transit encore en cours { transitDelay[bit_rank]=transitTime[1][bit_rank] ; //réglage du temps de transit } bitWrite(transitStatus, bit_rank,HIGH) ; // positionne le transit pour l'APU if ((switchStatus&(1<<bit_rank))==(1<<bit_rank)) //si démarrage en cours { //bitWrite(greenlit, bit_rank,LOW) ; //| //bitWrite(greenblink, bit_rank,LOW) ; //| traitement des values qui seront //bitWrite(yellowlit, bit_rank,LOW) ; //| envoyées aux registres //bitWrite(yellowblink, bit_rank,HIGH) ; //| bitWrite(greenblink, bit_rank-1,LOW) ; //| bitWrite(greenblink, bit_rank,LOW) ; //| traitement des values qui seront bitWrite(yellowblink, bit_rank-1,LOW) ; //| envoyées aux registres bitWrite(yellowblink, bit_rank,HIGH) ; //|(lignes actives pour le montage actuel) } if ((switchStatus&(1<<bit_rank))==0) //si arrêt en cours { //bitWrite(greenlit, bit_rank,LOW) ; //| //bitWrite(greenblink, bit_rank,HIGH) ; //| traitement des values qui seront //bitWrite(yellowlit, bit_rank,LOW) ; //| envoy√©es aux registres //bitWrite(yellowblink, bit_rank,LOW) ; //| bitWrite(greenblink, bit_rank-1,LOW) ; //| bitWrite(greenblink, bit_rank,HIGH) ; //| traitement des values qui seront bitWrite(yellowblink, bit_rank-1,LOW) ; //| envoyées aux registres bitWrite(yellowblink, bit_rank,LOW) ; //|(lignes actives pour le montage actuel) } updateRegister(greenlit, greenblink, yellowlit, yellowblink); //envoi aux registres } // fin sous programme LEDmanagement1 (gestion des LEDs lié à un mouvement de switch) //sous programme de gestion des LEDs lié au temps int LEDmanagement2(byte bit_rank,long SwitchTime) { // ligne du dessous : si on est en transit depuis un temps supérieur √† transitDelay... if (((transitStatus&(1<<bit_rank))==(1<<bit_rank))&&(((millis()-SwitchTime)/100)>transitDelay[bit_rank])) { bitWrite(transitStatus, bit_rank,LOW) ; //remise à 0 du transit APU if ((switchStatus&(1<<bit_rank))==(1<<bit_rank)) // si démarrage terminé { //bitWrite(greenlit, bit_rank,LOW) ; //| //bitWrite(greenblink, bit_rank,LOW) ; //| traitement des values qui seront //bitWrite(yellowlit, bit_rank, HIGH) ; //| envoyées aux registres //bitWrite(yellowblink, bit_rank,LOW) ; //| bitWrite(greenblink, bit_rank-1,LOW) ; //| bitWrite(greenblink, bit_rank,LOW) ; //| traitement des values qui seront bitWrite(yellowblink, bit_rank-1, HIGH) ; //| envoyées aux registres bitWrite(yellowblink, bit_rank,LOW) ; //|(lignes actives pour le montage actuel) } if ((switchStatus&(1<<bit_rank))==0) // si arrêt terminé { //bitWrite(greenlit, bit_rank,HIGH) ; //| //bitWrite(greenblink, bit_rank,LOW) ; //| traitement des values qui seront //bitWrite(yellowlit, bit_rank,LOW) ; //| envoyées aux registres //bitWrite(yellowblink, bit_rank,LOW) ; //| bitWrite(greenblink, bit_rank-1,HIGH) ; //| bitWrite(greenblink, bit_rank,LOW) ; //| traitement des values qui seront bitWrite(yellowblink, bit_rank-1,LOW) ; //| envoyées aux registres bitWrite(yellowblink, bit_rank,LOW) ; //|(lignes actives pour le montage actuel) } updateRegister(greenlit, greenblink, yellowlit, yellowblink); //envoi aux registres } }//fin LEDmanagement2 (automatisme lié au temps écoulé)