Go Down

Topic: Aide pour le CODE qui va contrôler le toit de mon observatoire avec un PC linux (Read 2563 times) previous topic - next topic

constant1462

Jan 28, 2020, 10:31 am Last Edit: Feb 01, 2020, 12:36 am by constant1462 Reason: changer le titre du sujet
Bonjour

Je suis sur le projet d'ouvrir un toit d'un observatoire à distance, mais et pour l'instant j'essaye de comprendre le système de programmation .

L'idée pour le moment, c'est de commander avec un bouton poussoir l'ouverture(simuler par une led)  et que un fin de course stop l'action .

Et après il y aura ouverture/fermeture  par bouton avec un boutons stop (arrêt d'urgence) et ensuite
quand je serai arrivé a ça,je veux encore rajouter une contrainte de plus ,qui sera
le contrôle de la position "parc" du télescope

Et a la fin de tous ça, je veux pouvoir le commander a distance avec un pc sous driver INDI (linux).

Donc voilà l'idée du projet, mais comme dis plus ,pour l'instant j'arrive pas a faire que un fin de cours
stop l'action .


J'ai essayer deux méthode sans résultat....

La première, c'est qu'une 'impulsion du premier bouton poussoir soit figé dans le temps avec un "delay"(sa pas de soucis),  et stopper cette fonction avec le bouton fin de course , et la pas de résultat.

ET l'autre façon c'est que j'ai copier une prog qui fais que le lorsque, on appuie sur le bouton le commande reste en fonction jusqu'à que l'on appuie sur le même bouton ( sa fonctionne), et faire que le fin de course arrêt aussi cette fonction, de nouveau pas réussi à le faire.  

Bref je commence a essaye de comprendre les finesse de la programmation , mais pour l'instant
c'est pas encore ça. :(

Alors merci de coup de main, et surtout si on peut m'expliqué la démarche.

A bientôt

lesept

Dans ton second programme, tu dois tester le second appui sur le bouton. A cet endroit tu ajoutes un OU dans la condition testée :

Si (second appui OU fin de course) {}

La syntaxe du OU est ||
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

constant1462

hello
Merci de ta réponse ,mais entre temps je suis arrivé a avancé un peu.
J'ai trouvé ça que j'ai adapté a mon schéma de montage.

Code: [Select]
int ledpin = 4;
int pushbutton1 = 2;
int pushbutton2 = 3;



void setup()
{
    pinMode(ledpin,OUTPUT);
    pinMode(pushbutton1,INPUT);
    pinMode(pushbutton2,INPUT);
}


void loop() {
    static bool ledState = LOW; // LED éteinte par défaut
    if ((digitalRead(pushbutton1) == HIGH) && !ledState) { // j'appuie sur le bouton1 la LED s'allume et reste allumé
     digitalWrite(ledpin, HIGH);
     ledState = HIGH;
    }
    if ((digitalRead(pushbutton2) == HIGH) && ledState) { // j'appuie sur le bouton2 la LED s'éteint
     digitalWrite(ledpin, LOW);
     ledState = LOW;
    }
}




Alors je comprend le principe ,mais j'arrive pas encore a écrire comme il faut sans me trompé.
Disons que je suis pas dans la logique de programmation arduino, hélas!

constant1462

Une question ,si je veux rajouté une condition "telescope_parqué" ,et que si cette condition n'est pas remplie, bloque l'action du bouton1 , comment je dois mis prendre ?

Est-ce que dois mettre cette condition en début du programme ou sa place n'a pas d'importance ?


lesept

Ça devient un peu compliqué à suivre, tu dois avoir les idées claires, mais j'ai du mal à voir ce qui doit commander quoi...

Essaye d'écrire un scénario de manière la plus simple possible, par exemple comme une liste :
  • Si ça et ça ou ça : allumer la led
  • Ensuite, si ça et ça et pas ça : éteindre la led
Tu verras qu'il sera alors tout simple d'écrire ton code et les conditions de tes if.

Voici ton code un peu simplifié
Code: [Select]
const int ledpin = 4;
const int pushbutton1 = 2;
const int pushbutton2 = 3;

void setup() {
  pinMode(ledpin, OUTPUT);
  pinMode(pushbutton1, INPUT);
  pinMode(pushbutton2, INPUT);
}


void loop() {
  static bool ledState = LOW; // LED éteinte par défaut
  if ((digitalRead(pushbutton1) == HIGH) && !ledState) { // j'appuie sur le bouton1 la LED s'allume et reste allumé
    ledState = HIGH;
    delay (30);
  }
  if ((digitalRead(pushbutton2) == HIGH) && ledState) { // j'appuie sur le bouton2 la LED s'éteint
    ledState = LOW;
    delay (30);
  }
  digitalWrite(ledpin, ledState);
}

Trois choses à remarquer:
  • Je l'ai mis entre balises CODE (tu as utilisé les QUOTE): tu vois la différence ? Édite ton message pour corriger ça.
  • J'ai mis tes constantes en const int
  • J'ai ajouté un petit délai pour éviter les rebonds de tes boutons
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

constant1462

Hello lesept

Quote
Essaye d'écrire un scénario de manière la plus simple possible, par exemple comme une liste :
Si ça et ça ou ça : allumer la led
Ensuite, si ça et ça et pas ça : éteindre la led
Alors je vois pas encore très bien comment faire.
Par contre peut-on crée des sous-programme ?

comme un qui se nommerais "OPEN-toit" et un autre "CLOSE_toit"

Car voici l'idée:

LES SOUS-PROGRAMMES:

Sous-Progr "OPEN_toit"
(SortiePin RelaisOpen = HIGH)  jusqu'à (EntréePin fin_de_course_Open = HIGH) SI (entréePin position_parc = HIGH)

Sous_Progr "CLOSE_toit"
(SortiePin RelaisCLose = HIGH) jusqu'à (EntréePin fin_de_course_Close = HIGH) SI (entréePin position_parc = HIGH)


LES ACTIONS Manuel:

le Bouton_Open = (EntréePin Bouton_Open = HIGH ) =  OPEN_toit     
le Bouton_Close = (EntréePin Bouton_Close = HIGH ) = CLOSE_toit   
le Bouton_stop = (EntréePin Bouton_Stop = HIGH) = (SortiePin RelaisOpen ET SortiePin RelaisClose = LOW)
                   

Voilà le but de mon programme.....


Je pense qui si j'arrive à se genre de schémas(sous-programme), cela sera plus simple pour la suite ,car je veux pouvoir commander avec un PC sous linux . 

Comme cela je pourrais(enfin j'espère) envoyer une commande style "OPEN_toit"






lesept

Ce genre de problème se prête bien à la programmation par machine d'état, tu peux lire le tutoriel écrit par J-M-L (pub gratuite) dans la section tutos...

Tu peux avoir 4 états :
  • Toit ouvert
  • Toit en fermeture
  • Toit fermé
  • Toit en ouverture

Ces états sont exclusifs, le toit ne peut pas être dans 2 états à la fois. Il y a des actions et des conditions pour passer d'un état à l'autre, et il faut agir sur les relais selon l'état. Tu peux faire un diagramme pour visualiser tout ça :


Celui-ci n'a que 2 états, mais compte tenu de la présence des capteurs fin de course, je préférerais en mettre 4.

Ensuite tu listes les conditions et les actions, par exemple :
  • Transition 1 vers 2 : condition "entréePin position_parc = HIGH" ou "EntréePin Bouton_Close = HIGH"
  • Etat 2 : action "SortiePin RelaisCLose = HIGH"
  • Transition 2 vers 3 : condition "EntréePin fin_de_course_Close = HIGH" ou "EntréePin Bouton_Stop = HIGH"
  • Etat 3 : action "SortiePin RelaisCLose = LOW"
  • etc.


Pour le code, tu peux le mettre sous forme d'un "switch / case", c'est assez facile à écrire et à relire.

Code: [Select]
switch (etat) {
  case 1: // Toit ouvert
    SortiePin_RelaisCLose = LOW;
    SortiePin_RelaisOpen = LOW; // Le toit ne bouge pas
    if (entreePin_position_parc == HIGH || entreePin_Bouton_Close == HIGH) etat = 2;
    break;
  case 2: // Fermeture du toit
    SortiePin_RelaisCLose = HIGH;
    if (entreePin_fin_de_course_Close == HIGH || entreePin_Bouton_Stop = HIGH) etat = 3;
    break;
  case 3 : // Toit fermé
    etc.

}

Enfin, avec un enum, tu peux renommer les états et changer les case, ce qui rend le code plus lisible :
Code: [Select]
enum states {Toit_ouvert, Fermeture, Toit_ferme, Ouverture};
states etat;

...

switch ((int)etat) {
  case Toit_ouvert:
    SortiePin_RelaisCLose = LOW;
    SortiePin_RelaisOpen = LOW; // Le toit ne bouge pas
    if (entreePin_position_parc == HIGH || entreePin_Bouton_Close == HIGH) etat = Fermeture;
    break;
  case Fermeture:
    SortiePin_RelaisCLose = HIGH;
    if (entreePin_fin_de_course_Close == HIGH || entreePin_Bouton_Stop = HIGH) etat = Toit_ferme;
    break;
  case Toit_ferme :
    etc.

}

(tout ça est à ré-écrire avec les bons noms de variables)

Il faut initialiser l'état du toit quelque part dans le code. Là, je ne sais pas comment le faire, ça dépend du contexte.
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

icare

Boujour,
Ce genre de problème se prête bien à la programmation par machine d'état, tu peux lire le tutoriel écrit par J-M-L (pub gratuite) dans la section tutos...
Ce n'est pas de la pub gratuite, juste une reconnaissance de l'excellent travail et partage de JML.  :smiley-mr-green:
2B OR NOT(2B) = FF
Arduino 1.0.5 à 1.8.5 + gEdit + Ubuntu 18.04 LTS

constant1462

Hello lesept

Alors j'ai trouvé un code pour un moteur porte de garage qui ouvre un toit pour un observatoire.
Le truc c'est que visiblement la moteur se comporte un système une impulsion le toit s'ouvre, une
nouvel impulsion le toit se ferme .
Alors que moi je dois faire une inversion de courant.

j'avoue que je comprend pas grand chose de certaine partie .

Il y a non plus pas de boutons de commande ,il est commandé que par pc(visiblement).

Par contre il mes semble ,que t'on idée me parait mieux avec des états et plus logique pour faire
en meme temps une commande par PC ou par bouton.

Je met le code que j'ai trouvé ,et tu verras il met les états de la porte au début des actions qui vont faire bouger le toit.
Code: [Select]
// Ce programme permet d'actionner un moteur de porte de garage utilisé pour déplacer un toit d'observatoire à toit ouvrant (roll off).
// Il fonctionne grâce a un relais 5volts qui simule l'action de presser le bouton pressoir d'un interrupteur mural qui commande l'ouverture
// et/ou la fermeture d'un moteur de  porte de garage et grace à deux contacts magnétiques, il permet en tout temps de connaitre la position
// ou l'état du toit (OUVERT ou FERMÉ). Il est primordial de connaitre le statut du toit (OUVERT ou FERMÉ), surtout dans un contexte d'automatisation
// et de contrôle à distance de votre observatoire via un réseau local ou par Internet.
// Les codes font référence à une porte de garage (DOOR). Il faut comprendre que le moteur de porte de garage est utilisé pour ouvrir et fermer
// un toit d'observatoire à toit ouvrant (roll off. Donc pensez que lorsqu'on fait référence à une porte "DOOR", il s'agit en fait du TOIT amovible
// de l'observatoire.


// Variables

int doorPin  = 10;
int doorPinClose  = 12;
int relayPin = 7;
int inByte = 0;       
int doorState = 0;
int doorStateClose = 0;

// Le protocole de communication avec le driver ASCOM est assez simple et repose sur 5 commandes de base que voici:

int OD = 79;          // Open door, le driver ASCOM va transmettre un O (OPEN)soit le code ascii 79
int CD = 67;          // Close door, le driver ASCOM va transmettre un C (CLOSE) soit le code ascii 67
int DS = 83;          // Door status, le driver ASCOM va transmettre un S (STATUS) soit le code ascii 83
int INFOVERSION = 63; // Info version du code de la carte Arduino, le driver ASCOM va transmettre un ? soit le code ascii 63
int BYPASS = 33;      // Permet de bypasser la vérification des capteurs et de faire déplacer le toit, le driver ASCOM va transmetrte un ! soit le code ascii 33

void setup() {
  digitalWrite(relayPin, HIGH);
  pinMode(doorPin, INPUT);
  pinMode(doorPinClose, INPUT);
  pinMode(relayPin, OUTPUT);
  Serial.begin(9600);
}

// La loop attend une commande provenant du driver ASCOM

void loop()
{
  if (Serial.available() > 0)
  {
    inByte = Serial.read(); // Lecture de la commande du port série, la commande va provenir du driver ASCOM

    if (inByte == DS) // Si le driver ASCOM transmet un S pour STATUT, alors on va retourner le statut du toit (O pour OPEN ou C pour CLOSE)
    {
      GetDoorState();
    }
     
    if (inByte == OD ) // Si le driver ASCOM transmet un O pour OPEN DOOR, alors on va ouvrir le toit
    {
      OpenDoor();
    }

    if (inByte == CD ) // Si le driver ASCOM transmet un C pour CLOSE DOOR, alors on va fermer le toit
    {
      CloseDoor();
    }

   
    if (inByte == INFOVERSION ) // Si le driver ASCOM transmet un ? pour INFO VERSION, alors on va retourner la version du code de la carte Arduino
    {
      InfoVersion();
    }

   
    if (inByte == BYPASS ) // Si le driver ASCOM transmet un ! pour MOVE DOOR, alors on va ouvrir ou fermer le toit dans la vérification sur la position la porte
    {
      moveDoor();
    }
  }     
 
  delay(100);
 
}



// Cette fonction permet de fermer le toit, elle va cependant s'assurer que le toit est bien en position OUVERT avant.   

void CloseDoor()
{
  doorStateClose = digitalRead(doorPinClose); // Interrogation du sensor (contact magnétique du toit en position CLOSE) attribué à l'état CLOSE
  doorState = digitalRead(doorPin);           // Interrogation du sensor (contact magnétique du toit en position OPEN)attribué à l'état OPEN
  if (! (HIGH == doorStateClose && HIGH == doorState ) )  // On s'assure que le toit est bien en position OPEN
  {
    if (HIGH == doorStateClose)
    {
      moveDoor();
    }
  }
}


// Cette fonction permet d'ouvrir le toit, elle va cependant s'assurer que le toit est bien en position CLOSE avant.   

void OpenDoor()
{
  doorStateClose = digitalRead(doorPinClose); // Interrogation du sensor (contact magnétique toit FERMÉ)attribué à l'état CLOSE
  doorState = digitalRead(doorPin);           // Interrogation du sensor (contact magnétique toit OUVERT)attribué à l'état OPEN
  if (! (HIGH == doorStateClose && HIGH == doorState ) ) // On s'assure que le toit est bien en position (fermé)CLOSE
  {
    if (HIGH == doorState)
    {
       moveDoor();
    }
  }
}


// Cette fonction retourne le statut du toit: OPEN, CLOSE ou en MOVE
// Le statut est retourné au driver ASCOM via un port série

void GetDoorState()
{
  doorState = digitalRead(doorPin);
  if (LOW == doorState)
  {
     Serial.print("O");
  }
  doorStateClose = digitalRead(doorPinClose);
  if (LOW == doorStateClose)
  {
     Serial.print("C");
  }

  if (HIGH == doorStateClose && HIGH == doorState )
  {
     Serial.print("M");
  }
 
 
  delay(200);
}


// Cette fonction retourne la version du code Arduino
void InfoVersion()
{
     Serial.print("1.0");
}


// Cette fonction actionne le relais afin de faire déplacer le toit
void moveDoor()
{
  digitalWrite(relayPin, LOW);
  delay(500);
  digitalWrite(relayPin, HIGH);
}


je pense que il y a moyen de combiner des parties ,non ??
A+

 

constant1462

j'ai essayé avec le principe "switch" , mais comment on fais pour commande par exemple la "case 1"

je comprend +/- le principe , mais j'ai de la peine a l'appliqué ,hélas :(

lesept

As-tu lu le tutoriel ?

j'ai essayé avec le principe "switch" , mais comment on fais pour commande par exemple la "case 1"
Je ne comprends pas ta question...
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

constant1462

hello
 j'ai essayer de faire un mini programme pour comprendre le principe Switch,case .....

Un truc tous simple avec des états suivant:
 repos, led_allumer et état led_eteint .

mais j'y arrive pas ,c'est surement tous con ,mais je vois pas.
J'ai lu le topic que tu m'as indiquer pourtant , et essayer de faire comme lui ,mais il a cette fonction
que j'ai pas fais "OneButton.h" ,

enfin regarde se que j'ai essayer de faire et dis moi se que je fais de faux et explique moi (si tu as le temps) bien-sur...  ;)

Code: [Select]
const int Pin_Led = 3;
const int Pin_bouton = 2;


enum states {Repos, allumer, eteinte} etatled;

void Repos_led()
{
  digitalWrite(Pin_Led, lOW);
  digitalWrite(Pin_bouton, LOW);
    etatled = Repos;
}           
   
switch (etatled){
case Repos:
   Pin_Relais = LOW;
   Pin_bouton = LOW;
  if (Pin_Relais == LOW && Pin_Led == LOW)
   break;

   case allumer:
  Pin_Led = HIGH
     if (Pin_bouton == HIGH || Pin_Led == HIGH);
     etatled = allumer
       break;
  case etiente:
  Pin_led = LOW
    if (Pin_Led == HIGH || Pin_bouton == LOW );
    etaled = eteinte
    break;
}   
void setup() {
  pinMode(Pin_Relais, OUTPUT);
  pinMode(Pin_bouton, INPUT);
  Repos_led();
 
}

lesept

Je suis sur un smartphone donc pas facile de corriger ton code...

En quelques mots, un code pour Arduino doit comporter au minimum une fonction setup et une fonction loop. Tu as le setup mais pas la loop : premier problème.

Ton switch est en dehors des fonctions : second problème.

Donc je te conseille de lire les bases sur la programmation pour Arduino. Cherche le tuto d'eskimon ou ceux de openclassrooms sur les bases d'arduino et lis les avant de te lancer dans un programme.

Ensuite, tu verras comment corriger ton code. Il n'a pas de gros problème, mais là je ne peux pas aider efficacement donc commence par ça et je pourrai aider ce week-end ou lundi...
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

constant1462

Bon alors la je vais aller au lit

Mais j'ai enfin compris le principe de se genre de programme.

J'ai essayer avec des leds pour comprendre et j'ai pus faire des variantes pour comprendre.

voici le code de mes essaies
Code: [Select]

//les états possible
enum { ROUGE, BLANC, BLEUE ,ALL, STOP }couleur;

// le N° des connection et fonction
void setup() {
    pinMode(2, OUTPUT);
    pinMode(3, OUTPUT);
    pinMode(4, OUTPUT);

}// fin setup


void startLed (const int couleur){ // début des statuts pour le loop
    // LEDs éteintes si non appelées
    digitalWrite(2, LOW);
    digitalWrite(3, LOW);
    digitalWrite(4, LOW);



switch (couleur)  { // début du switch avec les possibilté
        case ROUGE: digitalWrite(2, HIGH); break;
        case BLANC: digitalWrite(3, HIGH); break;
        case BLEUE: digitalWrite(4, HIGH); break;
        case ALL: digitalWrite(4, HIGH);
                  digitalWrite(2, HIGH); break;
        case STOP: digitalWrite(2, LOW);
                   digitalWrite(3, LOW);
                   digitalWrite(4, LOW);break;
    } //fin switch

}// fin void

void loop() {  // début du programme des fonctions
 
  startLed(ALL);
  delay(1000);
    startLed(ROUGE);
  delay(500);
    startLed(BLANC);
  delay(500);
    startLed(BLEUE);
  delay(500);
  startLed(STOP);
  delay(800);
} // fin loop ou programme


bon maintenant il est juste pour changer des états de leds , donc simple.

lesept

Très bien, maintenant cherche comment utiliser un bouton poussoir. Il y a un bon tuto chez openclassrooms.

Cherche aussi le problème des rebonds, pour savoir ce que c'est. Un moyen de le régler est d'ajouter un
delay(30)
après la lecture du bouton.

Ensuite, apprends à utiliser des noms de variables pour désigner les pin de tes périphériques. Par exemple, dans ton code pour les leds tu peux faire dans l'en-tête

const int ledrouge = 2;

Puis
pinMode (ledrouge, OUTPUT) ;
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

Go Up