Aller au contenu

Messages recommandés

Posté
il y a une heure, Fabrice Teissier a dit :

J'ai même testé mon Flip flat avec Ekos dans KStars et ça a marché nickel à part un petit message de "time out" que j'aimerais bien régler.

 

Salut. Olivier a proposer une solution ici: 

 

Posté
il y a 21 minutes, Fabrice Teissier a dit :

J'ai essayé la commande que tu m'as donné et j'ai eu ça comme réponse :

chmod: impossible d'accéder à '/dev/ttyACM0': Aucun fichier ou dossier de ce type

Ah !, alors débranche l'arduino, puis rebranche là, et fait la commande "dmesg" pour voir ou elle est installé dans le système.

Un exemple du résultat de la commande "dmesg" quand je branche l'arduino sur le port usb, chez moi elle est sur "ttyACM0", en vérité le chemin complet est /dev/ttyACM0" dans ce cas.

Révélation

[10118.450531] usb 5-2: new full-speed USB device number 3 using uhci_hcd
[10118.669562] usb 5-2: New USB device found, idVendor=2a03, idProduct=0043
[10118.669567] usb 5-2: New USB device strings: Mfr=1, Product=2, SerialNumber=220
[10118.669570] usb 5-2: Product: Arduino Uno
[10118.669573] usb 5-2: Manufacturer: Arduino Srl            
[10118.669575] usb 5-2: SerialNumber: 8553431393735110A112
[10118.899703] cdc_acm 5-2:1.0: ttyACM0: USB ACM device
[10118.907074] usbcore: registered new interface driver cdc_acm
[10118.907078] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters

 

 

Sinon tu as aussi la commande "lsusb", elle te diras pas ou est relié l'arduino, mais au moins si le système la reconnait.

Révélation

Bus 001 Device 003: ID 1df7:3010  
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 005 Device 003: ID 2a03:0043 dog hunter AG Arduino Uno Rev3
Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 003 Device 002: ID 046d:c062 Logitech, Inc. M-UAS144 [LS1 Laser Mouse]
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub

 

 

Yves.

 

Posté

@Alarcon yves la commande dmesg me donne ça concernât l'USB:

 

Révélation

               00:00:00.000092 main     Log opened 2019-06-19T17:18:45.375580000Z
[   10.851547] 00:00:00.000691 main     OS Product: Linux
[   10.851615] 00:00:00.000763 main     OS Release: 4.15.0-45-generic
[   10.851687] 00:00:00.000832 main     OS Version: #48-Ubuntu SMP Tue Jan 29 16:28:13 UTC 2019
[   10.851808] 00:00:00.000902 main     Executable: /opt/VBoxGuestAdditions-5.2.18/sbin/VBoxService
               00:00:00.000903 main     Process ID: 1159
               00:00:00.000904 main     Package type: LINUX_64BITS_GENERIC
[   10.854749] 00:00:00.003868 main     5.2.18 r124319 started. Verbose level = 0
[  503.263195] usb 1-2: USB disconnect, device number 3
[  503.263271] usb 1-2: ch341_read_int_callback - usb_submit_urb failed: -19
[  503.265134] ch341-uart ttyUSB0: ch341-uart converter now disconnected from ttyUSB0
[  503.265156] ch341 1-2:1.0: device disconnected
[  506.992533] usb 1-2: new full-speed USB device number 4 using ohci-pci
[  507.334776] usb 1-2: New USB device found, idVendor=1a86, idProduct=7523
[  507.334779] usb 1-2: New USB device strings: Mfr=0, Product=2, SerialNumber=0
[  507.334781] usb 1-2: Product: USB2.0-Serial
[  507.377405] ch341 1-2:1.0: ch341-uart converter detected
[  507.400333] usb 1-2: ch341-uart converter now attached to ttyUSB1
[  840.809187] usb 1-2: USB disconnect, device number 4
[  840.814874] ch341-uart ttyUSB1: ch341-uart converter now disconnected from ttyUSB1
[  840.814887] ch341 1-2:1.0: device disconnected
[  846.056032] usb 1-2: new full-speed USB device number 5 using ohci-pci
[  846.376809] usb 1-2: New USB device found, idVendor=1a86, idProduct=7523
[  846.376813] usb 1-2: New USB device strings: Mfr=0, Product=2, SerialNumber=0
[  846.376814] usb 1-2: Product: USB2.0-Serial
[  846.419467] ch341 1-2:1.0: ch341-uart converter detected
[  846.442432] usb 1-2: ch341-uart converter now attached to ttyUSB0
[ 1145.377658] ch341-uart ttyUSB0: usb_serial_generic_read_bulk_callback - urb stopped: -32
[ 1145.493579] usb 1-2: USB disconnect, device number 5
[ 1145.499647] ch341-uart ttyUSB0: ch341-uart converter now disconnected from ttyUSB0
[ 1145.499658] ch341 1-2:1.0: device disconnected
[ 1234.517081] usb 1-2: new full-speed USB device number 6 using ohci-pci
[ 1234.843684] usb 1-2: New USB device found, idVendor=1a86, idProduct=7523
[ 1234.843687] usb 1-2: New USB device strings: Mfr=0, Product=2, SerialNumber=0
[ 1234.843688] usb 1-2: Product: USB2.0-Serial
[ 1234.886352] ch341 1-2:1.0: ch341-uart converter detected
[ 1234.911624] usb 1-2: ch341-uart converter now attached to ttyUSB1
[ 1552.326377] ch341-uart ttyUSB1: usb_serial_generic_read_bulk_callback - urb stopped: -32
[ 1552.436149] usb 1-2: USB disconnect, device number 6
[ 1552.448696] ch341-uart ttyUSB1: ch341-uart converter now disconnected from ttyUSB1
[ 1552.448709] ch341 1-2:1.0: device disconnected
[ 1557.143623] usb 1-2: new full-speed USB device number 7 using ohci-pci
[ 1557.477897] usb 1-2: New USB device found, idVendor=1a86, idProduct=7523
[ 1557.477900] usb 1-2: New USB device strings: Mfr=0, Product=2, SerialNumber=0
[ 1557.477901] usb 1-2: Product: USB2.0-Serial
[ 1557.520685] ch341 1-2:1.0: ch341-uart converter detected
[ 1557.543335] usb 1-2: ch341-uart converter now attached to ttyUSB0
[ 3286.080171] ohci-pci 0000:00:06.0: frame counter not updating; disabled
[ 3286.080191] ohci-pci 0000:00:06.0: HC died; cleaning up
[ 3286.082554] usb 1-1: USB disconnect, device number 2
[ 3286.189070] usb 1-2: USB disconnect, device number 7
[ 3286.189474] ch341-uart ttyUSB0: ch341-uart converter now disconnected from ttyUSB0
[ 3286.189491] ch341 1-2:1.0: device disconnected
nafa@NAFABox:~$ 

 

 

Et me donne ça pour la commande "lsusb":

 

Bus 001 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
 

Posté (modifié)

Ah c'est sur que FBSD c'est pas la joie ;)

un petit lusb ...ne voit pas ton device ?

Dans ce cas la vbox ne doit pas avoir les bons addons dans ta fenêtre de ta VM les périphériques USB sont ils détectés et activés ?

Modifié par Raphael_OD
Posté

Apparement si, quand je lance la commande, j'ai ça:

nafa@NAFABox:~$ lsusb
Bus 001 Device 003: ID 1a86:7523 QinHeng Electronics HL-340 USB-Serial adapter
Bus 001 Device 002: ID 80ee:0021 VirtualBox USB Tablet
Bus 001 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
nafa@NAFABox:~$ 
 

Et dans les settings usb de Vbox j'ai ça :

 

874608229_Capturedcran2019-06-2010_48_08.thumb.png.217d79f84cd16dac69981cbcc32a076a.png

Posté

Te restes a voir si les drivers FTDI en fonction de ta carte arduino ou clone ...sont bien présents le mieux c'est d'installer l'IDE complet pour Linux /arduino

Posté

J'ai enfin trouvé le problème ! Pfff...

 

En fait, cela n'avait rien à voir avec l'USB. J'avais juste fait une bêtise en voulant rendre mon code propre visuellement.

J'avais effacé deux lignes essentielles à la communication série dans la partie "void handleSerial()"

 

memset(str, 0, 20);

Serial.readBytesUntil('\n', str, 20);  

 

C'est pour cette raison que INDI ne pouvait plus communiquer avec le Flip flat.

 

En revanche, je n'arrive pas à régler le souci du "Time out". J'ai essayé la manip proposé par  @Cedric02700 mais cela ne change rien.

En fait le "time out" n'intervient pas à la connexion mais après les commandes d'ouverture et fermeture du capot.

Je pense que cela vient du fait que j'ai trois servos à commander les uns après les autres et que la séquence complète dure 10 secondes, sans doute trop long pour le drivers INDI.

 

707758072_Capturedcran2019-06-2111_50_41.thumb.png.e4ea00e6bc11de99577300b4693f9b25.png

 

J'ai essayé en doublant la vitesse des servos pour accélérer la séquence et là, j'ai un autre message : "Read Overflow"

 

166629739_Capturedcran2019-06-2111_59_16.thumb.png.667d4bf3954798d62509bc406ec69d36.png

 

Mystère...

 

A priori, cela ne gène en rien le bon fonctionnement mais j'aurais bien aimé trouver un truc pour supprimer ces erreurs.

 

En tout cas, merci à tous pour votre aide...

Posté

On avait eu ce problème au début du post

 

 

Le 21/04/2019 à 03:51, olivier1986 a dit :

@gehelem @supaii @Cedric02700

 

Je viens de résoudre notre problème!! et ça marche du tonnerre! ça m'a travailé toute la journée ^^

Donc en fait je suis resté sur le message de Cédric02700 postulant l'implant d'un delai ... et magie c'était THE reponse!!! un délai dans la fonction void handleserial () juste avant le1er if, et ça a marché! bon biensur je n'ai pas testé cela en 1er et c'est pour cela qu'il est si tard! j'ai choisi après plusieurs essais la valeur de 100ms car:

- en dessous c'était instable avec SGP mais fonctionniel avec INDI

- au dessus on ressent la présence du delay et c'est dommage!!

 

En revanche, puisque pour le coup ce sont deux bonnes nouvelles et pas qu'une, c'est qu'en plus d'un driver indi qui fontionne au poil (essais avec le vrai matos ... un régal!!) et ba ça marche aussi avec SGP tester la aussi en vrai!!

ca devrait en faire plaisir à plus d'un!! héhé!!

 

Bon au dodo car il se fait tard maintenant, et voilà le code!! bonne nuit (bonjour??) tout le monde!!


 

  Révéler le contenu masqué

 

 /*
What: LEDLightBoxAlnitak - PC controlled lightbox implmented using the
    Alnitak (Flip-Flat/Flat-Man) command set found here:
   http://www.optecinc.com/astronomy/pdf/Alnitak Astrosystems GenericCommandsR3.pdf

Who:
    Created By: Jared Wellman - jared@mainsequencesoftware.com

When:
    Last modified:  2013/May/05


Typical usage on the command prompt:
Send     : >S000\n      //request state
Recieve  : *S19000\n    //returned state

Send     : >B128\n      //set brightness 128
Recieve  : *B19128\n    //confirming brightness set to 128

Send     : >J000\n      //get brightness
Recieve  : *B19128\n    //brightness value of 128 (assuming as set from above)

Send     : >L000\n      //turn light on (uses set brightness value)
Recieve  : *L19000\n    //confirms light turned on

Send     : >D000\n      //turn light off (brightness value should not be changed)
Recieve  : *D19000\n    //confirms light turned off.
*/

#include <Servo.h>
Servo myservo;

volatile int ledPin   = 6;      // the pin that the LED is attached to, needs to be a PWM pin.
volatile int servoPin = 9;      // the pin that the servo signal is attached to, needs to be a PWM pin.
int brightness = 0;

enum devices
{
    FLAT_MAN_L = 10,
    FLAT_MAN_XL = 15,
    FLAT_MAN = 19,
    FLIP_FLAT = 99
};

enum motorStatuses
{
    STOPPED = 0,
    RUNNING
};

enum lightStatuses
{
    OFF = 0,
    ON
};

enum shutterStatuses
{
    UNKNOWN = 0, // ie not open or closed...could be moving
    CLOSED,
    OPEN
};


int deviceId = FLIP_FLAT;
int motorStatus = STOPPED;
int lightStatus = OFF;
int coverStatus = UNKNOWN;

void setup()
{
  // initialize the serial communication:
  Serial.begin(9600);
  // initialize the ledPin as an output:
  pinMode(ledPin, OUTPUT);
  analogWrite(ledPin, 0);
  myservo.attach(servoPin,400,2500);  
}

void loop()
{
  handleSerial();
}


void handleSerial()
{
  delay(100);
  if( Serial.available() >= 5 )  // all incoming communications are fixed length at 6 bytes including the \n
  {
    char* cmd;
    char* data;
    char temp[10];
    
    int len = 0;

    char str[20];
    memset(str, 0, 20);
    
    // I don't personally like using the \n as a command character for reading.  
    // but that's how the command set is.
  //  Serial.readBytesUntil('\n', str, 20);
  Serial.readBytes( str, 5);

    cmd = str + 1;
    data = str + 2;
    
    // useful for debugging to make sure your commands came through and are parsed correctly.
    if( false )
    {
      sprintf( temp, "cmd = >%s%s;", cmd, data);
      Serial.println(temp);
    }
    


    switch( *cmd )
    {
      /*
        Ping device
            Request: >P000\n
            Return : *Pii000\n
                id = deviceId
      */
      case 'P':
          sprintf(temp, "*P%d000\n", deviceId);
          Serial.print(temp);
          break;

      /*
        Open shutter
            Request: >O000\n
            Return : *Oii000\n
                id = deviceId

            This command is only supported on the Flip-Flat!
      */
      case 'O':
          sprintf(temp, "*O%d000\n", deviceId);
          SetShutter(OPEN);
          Serial.print(temp);
          break;


      /*
        Close shutter
            Request: >C000\n
            Return : *Cii000\n
                id = deviceId

            This command is only supported on the Flip-Flat!
      */
      case 'C':
          sprintf(temp, "*C%d000\n", deviceId);
          SetShutter(CLOSED);
          Serial.print(temp);
          break;

      /*
        Turn light on
            Request: >L000\n
            Return : *Lii000\n
                id = deviceId
      */
      case 'L':
          sprintf(temp, "*L%d000\n", deviceId);
          Serial.print(temp);
          lightStatus = ON;
          analogWrite(ledPin, brightness);
          break;

      /*
        Turn light off
            Request: >D000\n
            Return : *Dii000\n
                id = deviceId
      */
      case 'D':
          sprintf(temp, "*D%d000\n", deviceId);
          Serial.print(temp);
          lightStatus = OFF;
          analogWrite(ledPin, 0);
          break;

      /*
        Set brightness
            Request: >Bxxx\n
                xxx = brightness value from 000-255
            Return : *Biiyyy\n
                id = deviceId
                yyy = value that brightness was set from 000-255
      */
      case 'B':
          brightness = atoi(data);    
          if( lightStatus == ON )
              analogWrite(ledPin, brightness);   
          sprintf( temp, "*B%d%03d\n", deviceId, brightness );
          Serial.print(temp);
        break;

      /*
        Get brightness
            Request: >J000\n
            Return : *Jiiyyy\n
                id = deviceId
                yyy = current brightness value from 000-255
      */
      case 'J':
        sprintf( temp, "*J%d%03d\n", deviceId, brightness);
        Serial.print(temp);
        break;
      
      /*
        Get device status:
            Request: >S000\n
            Return : *SidMLC\n
                id = deviceId
                M  = motor status( 0 stopped, 1 running)
                L  = light status( 0 off, 1 on)
                C  = Cover Status( 0 moving, 1 closed, 2 open)
      */
      case 'S':
        sprintf( temp, "*S%d%d%d%d\n",deviceId, motorStatus, lightStatus, coverStatus);
        Serial.print(temp);
        break;

      /*
        Get firmware version
            Request: >V000\n
            Return : *Vii001\n
                id = deviceId
      */
      case 'V': // get firmware version
          sprintf(temp, "*V%d001\n", deviceId);
          Serial.print(temp);
          break;
    }    

    while( Serial.available() > 0 )
        Serial.read();
            

  }
}

void SetShutter(int val)
{
    if( val == OPEN && coverStatus != OPEN )
    {
    myservo.write(180);
        coverStatus = OPEN;
        // TODO: Implement code to OPEN the shutter.
    }
    else if( val == CLOSED && coverStatus != CLOSED )
    {
   myservo.write(0);  
        coverStatus = CLOSED;
        // TODO: Implement code to CLOSE the shutter
    }
    else
    {
        // TODO: Actually handle this case
        coverStatus = val;
    }
    
}

 

 

 

Posté

@Fabrice Teissier

Bonjour, à tout hasard, quand vous dites avoir essayé de mettre le delay juste avant la commande handleSerial(), avez vous essayé de modifier cette valeur?

j'avais mis 100ms mais on peut surement augmenter cette valeur.

le fait que INDI renvoie une erreur S000 time out c'est quand INDI n'arrive pas à connaitre le statu du flip flat.

en fait, INDI demande tout le temps à connaitre le status du flip flat.

les 100ms que j'avais mise laisser le temps à l'arduino de vérifier les caractères présents sur le port série.

si c'est trop court il n'a pas le temps de le lire et affiche un time out. Si vous mettez 10s à ouvrir ou fermé, cela n'influence pas le statu car normalement INDI doit indiquer que le flip flat est en mouvement, et je pense que c'est valable quelque soit le nombre de servo car il doit afficher " en mouvement" durant la fonction ouverture().

tant que le flipt flat n'est ni en position ouverte ni fermé alors il est en mouvement!! normal!! mais reste à savoir si INDi le voit.

Je vais regarder votre code car sur mon simulateur celui ci ne fonctionne pas 😕

 

Olivier

Posté

Bah... J'ai beau essayer toutes les valeurs de delay entre 50ms à 1s et rien n'y fait. 

Effectivement, il semblerait qu'INDI n'arrive pas à connaitre le statu du flip flat au bon moment.

Mais pour quelle raison ?

Posté

Deux remarques à propos d'indi :

- le handshake

Lorsque le driver Indi initialise la connection (lorsqu'il ouvre le port série), il envoie immédiatement un "handshake"

C'est une question blanche qui ne sert à rien, juste à s'assurer que la connection fonctionne.

ça ne poserait pas de problème si ces satanés arduino ne s'amusaient pas à envoyer un reset lorsque le port série s'ouvre :

le handshake arrive en plein reboot de l'arduino, et ça part aux fraises.

Le délai qui a été ajouté dans le code permet de contourner ça, j'avoue que je ne pige pas très bien pourquoi

J'ai remarqué  le même comportement avec AstroEQ + driver indi EQmod, et Moonlite + driver indi éponyme, c'est exactement la même limonade.

Et c'est aussi pour cette raison que j'utilise autant que possible des arduino à base d'atmega32u4 et suivants avec la communication USB intégrée

 

- le statut "not open/closed"

En toute rigueur, il faut gérer la période pendant laquelle le moteur bouge

Dans la routine qui s'occupe de fermer et ouvir, il faut ajouter ceci au début :

      motorStatus = RUNNING;    
      coverStatus = UNKNOWN;

Et ceci à la fin si c'est dans le sens ouverture :

      motorStatus = STOPPED;    
      coverStatus = OPEN;

Ou dans le sens fermeture :

      motorStatus = STOPPED;    
      coverStatus = CLOSED;

De cette façon, comme effectivement indi demande le statut toutes les secondes (polling), si la requête tombe pendant que le moteur est en mouvement la réponse est correcte

ça me parait important si la durée d'ouverture/fermeture dure un peu, genre qq secondes ou même moins.

Comme ça Indi attends patiemment que le machin atteigne la position voulue avant d'enclencher la suite (prise de vues)

 

 

Posté (modifié)

@gehelem Merci pour ces infos.

 

Concernant le handshake, j'ai résolu le problème avec mon nano en dessoudant un micro-condensateur sur sa carte.

 

J'ai essayé de placer les motorStatus et coverStatus là ou tu me dis de les placer dans mes routines d'ouverture et fermeture mais cela ne change rien. Mais j'ai toujours un time out en fin d'ouverture et de fermeture.

 

Voilà la dernière version du code:

Révélation

 

#include <Arduino.h>
#include <Servo.h>
 
 
Servo ServoCapot;
Servo ServoRotation;
Servo ServoTranslation;

const int btn_capot = A0;//Bouton de commande d'ouverture et fermeture du capot
const int btn_voltmetre = A2;//Bouton pour vérifier l'état des plies
const int btn_ELpan = A1;//Bouton de commande du panneau lumineux
const int btn_park = A5;//Switch d'ouverture neutralisant la sécu de fermeture auto pour démontage
const int ctc_capot_ouvert = A3;//Contacteur de position ouvert
const int ctc_capot_ferme = A4;//Contacteur de position fermé

const int led_1 = 4;//Visu du niveau du panneau lumineux en commande local et niveau de piles
const int led_2 = 5;
const int led_3 = 6;
const int led_4 = 7;
const int ELpan = 3;//Panneau lumineux

const int relais_ELpan = 13;//Relais d'alimentation du panneau lumineux
const int relais_secu = 8;//Relais d'alimentation secours par les piles
const int relais_servo = 12;//Relais d'alimentation des servos


int AngleServoCapot= 0;
int AngleServoRotation= 137;
int AngleServoTranslation= 47;
int reception;
int compte_btn_ELpan = 0; // le nombre qui sera incrémenté et décrémenté
int etat_btn_ELpan = LOW; // lecture de l'état des boutons (un seul à la fois donc une variable suffit)
int etatprecedent_btn_ELpan = LOW; // état relâché par défaut
int real_vin(); // Variable de la tension mesuré par le voltmetre

const byte BROCHE_CAPTEUR_VIN = A7; // Le numéro de broche analogique pour la mesure de la tension en VIN
const float COEFF_PONT_DIVISEUR_VIN = 1.95; // Coefficient diviseur du pont de résistance
String commande;


 //Alnitak init
int brightness = 0;

enum devices
{
  FLAT_MAN_L = 10,
  FLAT_MAN_XL = 15,
  FLAT_MAN = 19,
  FLIP_FLAT = 99
};

enum motorStatuses
{
  STOPPED = 0,
  RUNNING
};

enum lightStatuses
{
  OFF = 0,
  ON
};

enum coverStatuses
{
  UNKNOWN = 0, // ie not open or closed...could be moving
  CLOSED,
  OPEN
};


int deviceId = FLIP_FLAT;
int motorStatus = STOPPED;
int lightStatus = OFF;
int coverStatus = UNKNOWN;

    
void setup()
{
    Serial.begin(9600);
    
    ServoCapot.attach(9, 500, 2475); // init pin
    ServoRotation.attach(10, 500, 2475); // init pin
    ServoTranslation.attach(11, 500, 2475); // init pin

    ServoCapot.write(AngleServoCapot);
    ServoRotation.write(AngleServoRotation);
    ServoTranslation.write(AngleServoTranslation);
    
    pinMode(btn_capot,INPUT);     
    pinMode(btn_voltmetre,INPUT);
    pinMode(btn_ELpan, INPUT);
    pinMode(btn_park, INPUT);
    pinMode(ctc_capot_ouvert, INPUT);
    pinMode(ctc_capot_ferme, INPUT);    
    pinMode(led_1, OUTPUT);
    pinMode(led_2, OUTPUT);
    pinMode(led_3, OUTPUT);
    pinMode(led_4, OUTPUT);
    pinMode(ELpan, OUTPUT);
    pinMode(relais_ELpan, OUTPUT);
    pinMode(relais_secu,OUTPUT);   
    pinMode(relais_servo,OUTPUT);   

    attachInterrupt(digitalPinToInterrupt(2), secu, FALLING);
    
}
 
unsigned int analogReadReference(void) // Mesure la référence interne à 1.1 volts
{
  
// Elimine toutes charges résiduelles
#if defined(__AVR_ATmega328P__)
    ADMUX = 0x4F;
#elif defined(__AVR_ATmega2560__)
    ADCSRB &= ~(1 << MUX5);
    ADMUX = 0x5F;
#elif defined(__AVR_ATmega32U4__)
    ADCSRB &= ~(1 << MUX5);
    ADMUX = 0x5F;
#endif
    delayMicroseconds(5);
  
// Sélectionne la référence interne à 1.1 volts comme point de mesure, avec comme limite haute VCC
#if defined(__AVR_ATmega328P__)
    ADMUX = 0x4E;
#elif defined(__AVR_ATmega2560__)
    ADCSRB &= ~(1 << MUX5);
    ADMUX = 0x5E;
#elif defined(__AVR_ATmega32U4__)
    ADCSRB &= ~(1 << MUX5);
    ADMUX = 0x5E;
#endif
    delayMicroseconds(200);

  
  ADCSRA |= (1 << ADEN); // Active le convertisseur analogique -> numérique
  
  ADCSRA |= (1 << ADSC); // Lance une conversion analogique -> numérique
  
  while(ADCSRA & (1 << ADSC)); // Attend la fin de la conversion
  
  return ADCL | (ADCH << 8); // Récupère le résultat de la conversion
}

void loop() 
{           
if (digitalRead(ctc_capot_ouvert) == HIGH)
    {
    coverStatus = OPEN; 
    }
    
if (digitalRead(ctc_capot_ferme) == HIGH)
    {
    coverStatus = CLOSED; 
    }

handleSerial();

// Ouverture Fermeture capot  en local 
if((digitalRead(btn_capot) == HIGH) && (digitalRead(ctc_capot_ouvert) == HIGH) && (digitalRead(btn_park) == LOW))
    {
    fermeture(); 
    }
    
if((digitalRead(btn_capot) == HIGH) && (digitalRead(ctc_capot_ferme) == HIGH) && (digitalRead(btn_park) == LOW))
    {    
    ouverture();
    }
    
if((digitalRead(btn_park) == HIGH) && (digitalRead(ctc_capot_ferme) == HIGH))
    {      
    ouverture();
    }

 // Fermeture automatique en cas de coupure de courant 
if (digitalRead(relais_secu)==(HIGH))
    {  
     if (digitalRead(ctc_capot_ouvert) == HIGH)
        {
        fermeture();
        }
        
     if(digitalRead(ctc_capot_ferme) == HIGH)
        {    
        delay(1000);    
        digitalWrite(relais_secu,LOW);
        }    
    }
  
 

// ELpan : control local du panneau EL
etat_btn_ELpan = digitalRead(btn_ELpan);

if (etat_btn_ELpan != etatprecedent_btn_ELpan) // si l'état du bouton a changé
    {
    if (etat_btn_ELpan == HIGH) // et qu'il est haut (= on appuie dessus)
        {
        compte_btn_ELpan++; // on incrémente le compteur
        if (compte_btn_ELpan > 5) // sauf s'il a dépassé 5...
            {
            compte_btn_ELpan = 0; // ...auquel cas on le réinitialise
            }
        }
    }
    
progELpan(); // on execute progELpan
etatprecedent_btn_ELpan = etat_btn_ELpan; // et on stocke l'atat du bouton pour le prochain tour 
         

 
// Voltmetre : control local du niveau des piles 9v
if (digitalRead(btn_voltmetre) == HIGH)
    {
     delay(100);
     voltmetre(); // On execute volmetre
    }
    
else
    {
     analogWrite(led_1,0);
     analogWrite(led_2,0);
     analogWrite(led_3,0);
     analogWrite(led_4,0);
    }
} 

void ouverture() // Routine ouverture capot
{ 
if (compte_btn_ELpan >= 1)// Si le panneau EL est allumé
    {
    compte_btn_ELpan = 0; // On l'éteind          
    analogWrite(led_1,0);
    analogWrite(led_2,0);
    analogWrite(led_3,0);
    analogWrite(led_4,0);
    analogWrite(ELpan,0);
    digitalWrite(relais_ELpan,LOW);
    Serial.println("EL panel éteind");  
    }
  
digitalWrite(relais_servo,HIGH);
motorStatus = RUNNING;
coverStatus = UNKNOWN;
delay(500); 
  
while(!(((AngleServoTranslation)==(137))))
    {
    ServoTranslation.write((AngleServoTranslation) + (1)); 
    AngleServoTranslation += 1;
    delay(20);//_delay(0.02);//Réglage de la vitesse du servo
    }
       
delay(1000);//_delay(1);
        
while(!(((AngleServoCapot)==(180))))
    {
    ServoCapot.write((AngleServoCapot) + (1)); 
    AngleServoCapot += 1;
    delay(20);//_delay(0.02);//Réglage de la vitesse du servo
    }
        
delay(1000);//_delay(1);

while(!(((AngleServoRotation)==(47))))
    {
    ServoRotation.write((AngleServoRotation) - (1)); 
    AngleServoRotation += -1;
    delay(20);//_delay(0.02);//Réglage de la vitesse du servo
    }
    
delay(500); 
  
if (digitalRead(ctc_capot_ouvert) == HIGH)
    {
    digitalWrite(relais_servo,LOW);
    Serial.println("Capot ouvert");
    motorStatus = STOPPED;    
    coverStatus = OPEN;
    } 
}
 
 void fermeture() // Routine fermeture capot 
{ 
digitalWrite(relais_servo,HIGH);
motorStatus = RUNNING;
coverStatus = UNKNOWN;
delay(500); 
  
while(!(((AngleServoRotation)==(137))))
    {
    ServoRotation.write((AngleServoRotation) + (1)); 
    AngleServoRotation += 1;
    delay(20);// _delay(0.02);//Réglage de la vitesse du servo
    }

delay(1000);//_delay(1);

while(!(((AngleServoCapot)==(0))))
    {
    ServoCapot.write((AngleServoCapot) - (1));
    AngleServoCapot += -1;
    delay(20);// _delay(0.02);//Réglage de la vitesse du servo
    }

delay(1000);//_delay(1);

while(!(((AngleServoTranslation)==(47))))
    {
    ServoTranslation.write((AngleServoTranslation) - (1));
    AngleServoTranslation += -1;
    delay(20);// _delay(0.02);//Réglage de la vitesse du servo
    }
    
delay(500); 
  
if (digitalRead(ctc_capot_ferme) == HIGH)
    {
    digitalWrite(relais_servo,LOW);
    Serial.println("Capot fermé");
    motorStatus = STOPPED;    
    coverStatus = OPEN;
    }    
}
 
void handleSerial() // Communication serie protocol Alnitak
{
delay(300);
if( Serial.available() >= 5 )  // all incoming communications are fixed length at 6 bytes including the \n
    {
    char* cmd;
    char* data;
    char temp[10];   
    int len = 0;
    char str[20];
    memset(str, 0, 20);
    Serial.readBytesUntil('\n', str, 20);  
    cmd = str + 1;
    data = str + 2;

    if( false ) // useful for debugging to make sure your commands came through and are parsed correctly.
       {
       sprintf( temp, "cmd = >%s%s;", cmd, data);
       Serial.println(temp);
       } 

    switch( *cmd )
       {
      case 'P':// Ping device
      sprintf(temp, "*P%d000\n", deviceId);
      Serial.print(temp);
      break;

      case 'O': // Open shutter
      sprintf(temp, "*O%d000\n", deviceId);
      Serial.print(temp); 
      analogWrite(ELpan,0);
      digitalWrite(relais_ELpan,LOW);
      lightStatus = OFF;
      ouverture();     
      break;

      case 'C':// Close shutter
      sprintf(temp, "*C%d000\n", deviceId);    
      Serial.print(temp);      
      fermeture();    
      compte_btn_ELpan = 0;
      break;

      case 'L':// Turn light on
      sprintf(temp, "*L%d000\n", deviceId);
      Serial.print(temp);
      compte_btn_ELpan = 5;
      digitalWrite(relais_ELpan,HIGH);
      lightStatus = ON; 
      break;

      case 'D':// Turn light off
      sprintf(temp, "*D%d000\n", deviceId);
      Serial.print(temp);
      lightStatus = OFF;
      compte_btn_ELpan = 0;
      break;

      case 'B':// Set brightness
      brightness = atoi(data);    
      if( lightStatus == ON )  
      sprintf( temp, "*B%d%03d\n", deviceId, brightness );
      Serial.print(temp);
      analogWrite(ELpan,brightness);
      break;

      case 'J':// Get brightness
      sprintf( temp, "*J%d%03d\n", deviceId, brightness);
      Serial.print(temp);
      break;
      
      case 'S':// Get device status     
      sprintf( temp, "*S%d%d%d%d\n",deviceId, motorStatus, lightStatus, coverStatus);
      Serial.print(temp);
      break;

      case 'V': // get firmware version
      sprintf(temp, "*V%d001\n", deviceId);
      Serial.print(temp);
      break;
        }    
    
    while( Serial.available() > 0 )
    Serial.read();

     }
}

void progELpan() // Routine éclairage EL panel
{
if ((compte_btn_ELpan >= 1) && (digitalRead(ctc_capot_ferme) == HIGH))
     {
     digitalWrite(relais_ELpan,HIGH); // on allume le relai
     }
     
else 
     {
     digitalWrite(relais_ELpan,LOW); // on eteind le relai
     } 
     
if (compte_btn_ELpan == 0)
     {
     analogWrite(led_1,0);
     analogWrite(led_2,0);
     analogWrite(led_3,0);
     analogWrite(led_4,0);
     analogWrite(ELpan,0);
     digitalWrite(relais_ELpan,LOW); // on eteind le relai  
     } 

if ((compte_btn_ELpan == 1) && (digitalRead(ctc_capot_ferme) == HIGH))
     {
     analogWrite(led_1,255);
     analogWrite(led_2,0);
     analogWrite(led_3,0);
     analogWrite(led_4,0);
     analogWrite(ELpan,27);
     }
     
if ((compte_btn_ELpan == 2) && (digitalRead(ctc_capot_ferme) == HIGH))
     {
     analogWrite(led_1,255);
     analogWrite(led_2,255);
     analogWrite(led_3,0);
     analogWrite(led_4,0);
     analogWrite(ELpan,50);
     }
     
if ((compte_btn_ELpan == 3) && (digitalRead(ctc_capot_ferme) == HIGH))
     {
     analogWrite(led_1,255);
     analogWrite(led_2,255);
     analogWrite(led_3,255);
     analogWrite(led_4,0);
     analogWrite(ELpan,90);
     }
     
if ((compte_btn_ELpan == 4) && (digitalRead(ctc_capot_ferme) == HIGH))
     {
     analogWrite(led_1,255);
     analogWrite(led_2,255);
     analogWrite(led_3,255);
     analogWrite(led_4,255);
     analogWrite(ELpan,255);
     }
     
if (compte_btn_ELpan == 5)
     {
     analogWrite(ELpan,brightness);//
     }   
}

void voltmetre() // Routine voltmetre
{
// Mesure la tension en VIN et la référence interne à 1.1 volts
unsigned int raw_vin = analogRead(BROCHE_CAPTEUR_VIN);
unsigned int raw_ref = analogReadReference();
  
// Calcul de la tension réel avec un produit en croix
float real_vin = ((raw_vin * 1.1) / raw_ref) * COEFF_PONT_DIVISEUR_VIN;
  
if (real_vin >= 6)
     {
     analogWrite(led_1,255);
     analogWrite(led_2,0);
     analogWrite(led_3,0);
     analogWrite(led_4,0);
     }
     
if (real_vin >= 7)
     {
     analogWrite(led_1,255);
     analogWrite(led_2,255);
     analogWrite(led_3,0);
     analogWrite(led_4,0);
     }
     
if (real_vin >= 8)
     {
     analogWrite(led_1,255);
     analogWrite(led_2,255);
     analogWrite(led_3,255);
     analogWrite(led_4,0);
     }
     
if (real_vin >= 9)
     {
     analogWrite(led_1,255);
     analogWrite(led_2,255);
     analogWrite(led_3,255);
     analogWrite(led_4,255);
     }
  
/* Affichage */
Serial.println(real_vin, 3);
delay(1000);
}

void secu() // Secu fermeture automatique si coupure de courant 
{  
if (digitalRead(btn_park) == LOW)
     {
     digitalWrite(relais_secu,HIGH);
     }
}
    

 

 

J'ai essayer des les placer dans la routine "void handelSerial()" mais là, je ne peux pas compiler le code. IDE me donne des erreurs. Bizard !

 

442929792_Capturedcran2019-06-2202_32_47.thumb.png.c0cf276e3ce06da6e6d48cc94ba0c08d.png

Modifié par Fabrice Teissier
Posté

@Fabrice Teissier l'erreur stray machin truc c'est parce que tu as fait un copier/coller du bout de code depuis ces pages web, tu as dû te ramasser des caractères spéciaux :

Essaie d'écrire directement sans copier/coller

Posté

@gehelem Encore merci !

 

Effectivement, je n'ai plus d'erreur en écrivant directement les commandes. Mais cela ne change toujours rien.

J'ai toujours ces time out.

 

Ce que je remarque, c'est qu'a aucun moment, les statuts du capot et moteur sont en UNKNOWN ou RUNNING dans la fenêtre de contrôle INDI.

Le moteur est toujours STOPPED et le capot soit OPEN ou CLOSED.

 

Est-ce normal ?

Posté (modifié)

Bonjour, il faut comprendre le fonctionnement d'indi et de la liaison série.

Pour la liaison série, le 100ms est un délais d'attente pour éviter la surcharge et la perte de communication, mais se délais peut très bien descendre en dessous de cette valeurs, dépend de la vitesse d'échange entre les deux appareils, mais ce n'est pas forcement là ton problème.

 

Le plus gros problème, c'est que tu utilise la fonction delay(), or la fonction delay(), bloque l'arduino et la communication série, pendant toute la duré que tu lui indique, et dans cas évidement "Indi" râle car pendant se temps tu ne lui répond pas !

 

Pour éviter la fonction delay() soit tu utilise la fonction millis() qui compte le nombre de milliseconde depuis le début du programme, soit tu utilise la lib MsTimer2 qui permet de créer un timer.

Exemple de 3 codes arduino pour faire clignoter une led toutes les 1 secondes.

 

Code avec la fonction delay(1000), mais qui en fait bloque l'arduino quasiment tous le temps.

Révélation

// on fait clignoter une led toutes les secondes avec la fonction delay()

Byte LED = 13;

void setup()
{
  pinMode (LED, OUTPUT);
}

void loop()
{
  digitalWrite(LED, HIGH);
  delay(1000);
  digitalWrite(LED, LOW);
  delay(1000);
}

// problème, avec ce code, l'arduino est arreté pendant 1 secondes.
// ce n'est pas génant pour cet exemple.
// mais si on veut que l'arduino fasse autre chose pendant les 1 s, c'est mort !
// en vérité dans cet exemple l'arduino est quasiment à l'arret tous le temps !

 

 

Code avec la fonction millis(), là on ne fait aucun blocage.

Révélation

// on fait clignoter une led toutes les secondes avec la fonction milli()

byte LED = 13;
unsigned long temps = 0;
unsigned long t1 = 0;
byte etat_led = 0;

void setup()
{
  pinMode (LED, OUTPUT);
  digitalWrite(LED, LOW);
  temps = millis();
  t1 = temps;
}

void loop()
{
  unsigned long val_t = 0;
  temps = millis();

  // on fait cligloter la led
  val_t = t1 + 1000;
  if (val_t < temps)
  {
    if (etat_led == 0)
    {
      digitalWrite(LED, HIGH);
      etat_led = 1;
    }
    else
    {
      digitalWrite(LED, LOW);
      etat_led = 0;
    }
    t1 = temps;
  }
  // a partir d'ici l'arduino peut faire autre chose
  // --------------
  
}

// avec se code l'arduino n'est pas bloqué
// on peut faire d'autre tache entre deux clignotement

 

 

Code avec la lib MsTimer2, idem aucun blocage

Révélation

// on fait clignoter une led toutes les secondes avec la lib Mstimer2

#include <MsTimer2.h> // pour avoir un timer

byte LED = 13;

// ******************** les sous-programmes ***********************
void r_timer2()
{
  // cette routine est appelée toutes les 100 ms par le timer 2
  static byte t1 = 0;

  if (t1 > 10)
  {
    // on execute la routine toute les 10 * 100ms = 1s
    allume_led();
    t1 = 0;
  }

  t1++;
}

// ************************
void allume_led()
{
  // cette routine allume ou éteint une led
  // est appelé toutes les seconde par r_timer2
  
  static byte etat_led = 0;

  if (etat_led == 0)
  {
    digitalWrite(LED, HIGH);
    etat_led = 1;
  }
  else
  {
    digitalWrite(LED, LOW);
    etat_led = 0;
  }
}


// ************************
void setup()
{
  pinMode (LED, OUTPUT);
  digitalWrite(LED, LOW);

  // on met en place un timer de 100 ms, pointant sur la routine r_timer2
  MsTimer2::set(100, r_timer2);
  MsTimer2::start(); // a partir de maintenant r_timer2 est appelée toute les 100 milli-seconde
}

void loop()
{
  // on met ici le code que l'on veut
  // toute les 100 milli-secondes la fonction loop est interrompue
  // pour faire la fonction r_timer_2()
  // quand celle-ci à terminé
  // le programme reprend ou il s'était arreté
  // --------------
  
}

// avec se code l'arduino n'est pas bloqué
// on peut faire d'autre tache entre deux clignotement

 

 

Bref, il faut éviter la fonction delay(), quand on utilise l'arduino avec une communication série, c'est toujours source de problème, après il faut bien lire la doc avec la lib MsTimer2, car elle utilise un timer interne qui peut être utilisé par d'autre lib, à vérifier pour éviter des conflits, évidement la fonction appelée par MsTimer2, doit être une fonction non bloquante et son temps d’exécution inférieur au temps de répétition.

 

Yves.

 

Modifié par Alarcon yves
  • Merci / Quelle qualité! 1
Posté (modifié)

@Alarcon yves heu... Merci pour cette leçon de délais mais je croit que ça commence à dépasser mes compétences en programmation 😱

Mon « problème » effectivement, c’est que j’en ai mis partout et je ne vois pas comment arriver à les remplacer tous avec ce que tu proposes 😳

je croyais l’arduino monotache, c’est à dire que lorsqu’il joue une routine void, il ne fait rien d’autre avant la fin de son exécution et qu’ensuite seulement il revient dans loop pour continuer sa boucle de programme. Donc peu importe les délais dans les routines void. Je veux dire par là que je pensais que les délais dans un void n’affectaient pas les autres void. 

Donc ma question : dois je réécrire tous mes délais de chaque routine avec millis() ou avec la lib. MsTimer2 ? Et dans ce cas, c’est mort. Je ne m’en sens pas capable et du coup, tant pis, il y aura des Time Out.

Ou bien dois je seulement modifier les délais dans la routine void handelSerial()  ? Un peu plus accessible pour moi 😅

Modifié par Fabrice Teissier
Posté

Bonjour, oui l'arduino est monotâche, mais possède un système d'interruption, en clair dans certaine situation quand une interruption est levé, le programme en coure est stoppé et on lance une sous-fonction, quand celle-ci se termine, le programme reprend à l'endroit ou il c'était arrêté, bien sur il ne faut pas que la routine d'interruption dure trois plombes.

Laisse moi une semaine que je regarde de plus prés ton code.

Yves.

 

Posté (modifié)

Voilà la dernière version du code documenté là ou je suis sur de ce qui se passe.

 

Révélation

 

#include <Arduino.h>
#include <Servo.h>
 
 
Servo ServoCapot;// Assignation du servo Capot
Servo ServoRotation;// Assignation du servo Rotation
Servo ServoTranslation;// Assignation du servo Translation

const int btn_capot = A0;//Bouton de commande d'ouverture et fermeture du capot
const int btn_voltmetre = A2;//Bouton pour vérifier l'état des piles
const int btn_ELpan = A1;//Bouton de commande du panneau lumineux
const int btn_park = A5;//Switch d'ouverture neutralisant la sécu de fermeture auto pour démontage
const int ctc_capot_ouvert = A3;//Contacteur de position ouvert
const int ctc_capot_ferme = A4;//Contacteur de position fermé

const int led_1 = 4;//Visu du niveau du panneau lumineux en commande local et niveau de piles
const int led_2 = 5;
const int led_3 = 6;
const int led_4 = 7;
const int ELpan = 3;//Panneau lumineux

const int relais_ELpan = 13;//Relais d'alimentation du panneau lumineux
const int relais_secu = 8;//Relais d'alimentation secours par les piles
const int relais_servo = 12;//Relais d'alimentation des servos


int AngleServoCapot= 0;// Angle du servo capot lorsque le capot est fermé
int AngleServoRotation= 137;// Angle du servo rotation lorsque le capot est fermé
int AngleServoTranslation= 47;// Angle du servo translation lorsque le capot est fermé
int compte_btn_ELpan = 0; // Variable du nombre qui sera incrémenté et décrémenté lors de l'appui du bouton ELpan
int etat_btn_ELpan = LOW; // Variable de lecture de l'état du bouton ELpan (un seul à la fois donc une variable suffit)
int etatprecedent_btn_ELpan = LOW; // Variable de l'état précèdent du bouton ELpan. Relâché par défaut
int real_vin(); // Variable de la tension mesuré par le voltmetre

const byte BROCHE_CAPTEUR_VIN = A7; // Le numéro de broche analogique pour la mesure de la tension en VIN
const float COEFF_PONT_DIVISEUR_VIN = 1.95; // Coefficient diviseur du pont de résistance et calibration du voltmetre
String commande;


 //Alnitak init
int brightness = 0;// Variable de la puissance lumineuse de l'ELpan (0-255). Eteind par défaut

enum devices // Variable définissant le modèle du Flip flat Alnitak
{
  FLAT_MAN_L = 10,
  FLAT_MAN_XL = 15,
  FLAT_MAN = 19,
  FLIP_FLAT = 99
};

enum motorStatuses // Variable définissant le statu des servo
{
  STOPPED = 0,
  RUNNING
};

enum lightStatuses // Variable définissant l'état du panneau EL (off-on)
{
  OFF = 0,
  ON
};

enum coverStatuses // Variable définissant la position du capot
{
  UNKNOWN = 0, // ie not open or closed...could be moving
  CLOSED,
  OPEN
};

// Ecriture par défaut de l'état des variables à l'allumage
int deviceId = FLIP_FLAT;
int motorStatus = STOPPED;
int lightStatus = OFF;
int coverStatus = UNKNOWN;

    
void setup()// Routine setup au démarrage
{
    Serial.begin(9600);// Réglage du débit de la communication série
    
    ServoCapot.attach(9, 500, 2475); // Le servo capot est branché à la pin 9 avec réglage du débattement
    ServoRotation.attach(10, 500, 2475); // Le servo rotation est branché à la pin 10 avec réglage du débattement
    ServoTranslation.attach(11, 500, 2475); // Le servo translation est branché à la pin 11 avec réglage du débattement

    ServoCapot.write(AngleServoCapot);// On positionne le servo capot à la valeur définie dans la variable (0°)
    ServoRotation.write(AngleServoRotation);// On positionne le servo rotation à la valeur définie dans la variable (137°)
    ServoTranslation.write(AngleServoTranslation);// On positionne le servo translation à la valeur définie dans la variable (47°)

    // Définition des entrées/sorties
    pinMode(btn_capot,INPUT);     
    pinMode(btn_voltmetre,INPUT);
    pinMode(btn_ELpan, INPUT);
    pinMode(btn_park, INPUT);
    pinMode(ctc_capot_ouvert, INPUT);
    pinMode(ctc_capot_ferme, INPUT);    
    pinMode(led_1, OUTPUT);
    pinMode(led_2, OUTPUT);
    pinMode(led_3, OUTPUT);
    pinMode(led_4, OUTPUT);
    pinMode(ELpan, OUTPUT);
    pinMode(relais_ELpan, OUTPUT);
    pinMode(relais_secu,OUTPUT);   
    pinMode(relais_servo,OUTPUT);   

    attachInterrupt(digitalPinToInterrupt(2), secu, FALLING);// Fonction de détection de la chute de tension déclenchant l'alimentation secours
    
}
 
unsigned int analogReadReference(void) // Mesure la référence interne à 1.1 volts
{
  
// Elimine toutes charges résiduelles
#if defined(__AVR_ATmega328P__)
    ADMUX = 0x4F;
#elif defined(__AVR_ATmega2560__)
    ADCSRB &= ~(1 << MUX5);
    ADMUX = 0x5F;
#elif defined(__AVR_ATmega32U4__)
    ADCSRB &= ~(1 << MUX5);
    ADMUX = 0x5F;
#endif
    delayMicroseconds(5);
  
// Sélectionne la référence interne à 1.1 volts comme point de mesure, avec comme limite haute VCC
#if defined(__AVR_ATmega328P__)
    ADMUX = 0x4E;
#elif defined(__AVR_ATmega2560__)
    ADCSRB &= ~(1 << MUX5);
    ADMUX = 0x5E;
#elif defined(__AVR_ATmega32U4__)
    ADCSRB &= ~(1 << MUX5);
    ADMUX = 0x5E;
#endif
    delayMicroseconds(200);

  
  ADCSRA |= (1 << ADEN); // Active le convertisseur analogique -> numérique
  
  ADCSRA |= (1 << ADSC); // Lance une conversion analogique -> numérique
  
  while(ADCSRA & (1 << ADSC)); // Attend la fin de la conversion
  
  return ADCL | (ADCH << 8); // Récupère le résultat de la conversion
}

void loop() // Routine principale
{           
if (digitalRead(ctc_capot_ouvert) == HIGH)// Si le contacteur du capot ouvert est ON
    {
    coverStatus = OPEN; // On écrit que la variable coverStatus est OPEN
    }
    
if (digitalRead(ctc_capot_ferme) == HIGH)// Si le contacteur du capot fermé est ON
    {
    coverStatus = CLOSED;  // On écrit que la variable coverStatus est CLOSED
    }

handleSerial();// On joue la sous routine handelSerial servant à communiquer en USB avec l'ordinateur

// Fonctions d'Ouverture Fermeture du capot en local 
if((digitalRead(btn_capot) == HIGH) && (digitalRead(ctc_capot_ouvert) == HIGH) && (digitalRead(btn_park) == LOW))// Si on appuit sur le bouton capot et que le contacteur du capot ouvert est ON et que le switch park est OFF
    {
    fermeture(); // On joue la sous-routine fermeture
    }
    
if((digitalRead(btn_capot) == HIGH) && (digitalRead(ctc_capot_ferme) == HIGH) && (digitalRead(btn_park) == LOW))// Si on appuit sur le bouton capot et que le contacteur du capot fermé est ON et que le switch park est OFF
    {    
    ouverture(); // On joue la sous-routine ouverture
    }
    
if((digitalRead(btn_park) == HIGH) && (digitalRead(ctc_capot_ferme) == HIGH)) // Si le switch park est ON et que le contacteur du capot fermé est ON
    {      
    ouverture(); // On joue la sous-routine ouverture
    }

 // Fonction de Fermeture automatique en cas de coupure de courant 
if (digitalRead(relais_secu)==(HIGH))// Si le relais sécu est ON
    {  
     if (digitalRead(ctc_capot_ouvert) == HIGH)// Et que le contacteur du capot ouvert est ON
        {
        fermeture();// On joue la sous-routine fermeture
        }
        
     if(digitalRead(ctc_capot_ferme) == HIGH)// Au retour de la sous-routine fermeture, on controle l'état du contacteur du capot fermé et si il est ON
        {    
        delay(1000); // On attend 1s   
        digitalWrite(relais_secu,LOW);// On éteind le relais sécu
        }    
    }
  
 

// Fonction du control local du panneau EL
etat_btn_ELpan = digitalRead(btn_ELpan);// On indique à la variable l'état du bouton ELpan

if (etat_btn_ELpan != etatprecedent_btn_ELpan) // si l'état du bouton a changé
    {
    if (etat_btn_ELpan == HIGH) // et qu'il est haut (= on appuie dessus)
        {
        compte_btn_ELpan++; // on incrémente le compteur
        if (compte_btn_ELpan > 5) // sauf s'il a dépassé 5...
            {
            compte_btn_ELpan = 0; // ...auquel cas on le réinitialise
            }
        }
    }
    
progELpan(); // on execute la sous-routine progELpan
etatprecedent_btn_ELpan = etat_btn_ELpan; // Au retour de la sous-routine progELpan on stocke l'état du bouton pour le prochain tour 
         

 
// Fonction du Voltmetre : control local du niveau des piles 9v
if (digitalRead(btn_voltmetre) == HIGH)// Si le bouton du voltmetre est appuyé
    {
     delay(100);// On attend 100ms
     voltmetre(); // On execute la sous-routine volmetre
    }
    
else// Si non et au retour de la sous routine-voltmetre on s'assure d'éteindre les LED
    {
     analogWrite(led_1,0);
     analogWrite(led_2,0);
     analogWrite(led_3,0);
     analogWrite(led_4,0);
    }
} 

void ouverture() // Sous-routine ouverture capot
{ 
if (compte_btn_ELpan >= 1)// Si le panneau EL est allumé
    {
    compte_btn_ELpan = 0; // On l'éteind          
    analogWrite(led_1,0);
    analogWrite(led_2,0);
    analogWrite(led_3,0);
    analogWrite(led_4,0);
    analogWrite(ELpan,0);
    digitalWrite(relais_ELpan,LOW);
    Serial.println("EL panel éteind");  
    }
  
digitalWrite(relais_servo,HIGH);// On allume le relais d'alimentation des servo
delay(500); // On attend 500ms
motorStatus = RUNNING; // On indique que le statu des moteurs est RUNNING
coverStatus = UNKNOWN; // On indique que le statu du capot est UNKNOWN
  
while(!(((AngleServoTranslation)==(137))))// Jusqu'a ce que le servo translation soit à 137°
    {
    ServoTranslation.write((AngleServoTranslation) + (1)); // On lui demande d'avancer de 1°
    AngleServoTranslation += 1;// On ajoute 1° à la variable de la position translation
    delay(20);//_delay(0.02);//Réglage de la vitesse du servo
    }
       
delay(1000);// On attend 1s
        
while(!(((AngleServoCapot)==(180))))// Jusqu'a ce que le servo capot soit à 180°
    {
    ServoCapot.write((AngleServoCapot) + (1));  // On lui demande d'avancer de 1°
    AngleServoCapot += 1;// On ajoute 1° à la variable de la position capot
    delay(20);//_delay(0.02);//Réglage de la vitesse du servo
    }
        
delay(1000);// On attend 1s

while(!(((AngleServoRotation)==(47))))// Jusqu'a ce que le servo rotation soit à 47°
    {
    ServoRotation.write((AngleServoRotation) - (1));  // On lui demande de reculer de 1°
    AngleServoRotation += -1; // On soustrait 1° à la variable de la position rotation
    delay(20);//_delay(0.02);//Réglage de la vitesse du servo
    }
    
delay(500); // On attend 500ms
  
if (digitalRead(ctc_capot_ouvert) == HIGH)// On controle que l'état du capteur du capot ouvert est bien en position ON
    {
    digitalWrite(relais_servo,LOW);// On éteind le relais d'alimentation des servo
    motorStatus = STOPPED; // On indique que le statu des moteurs est STOPPED   
    coverStatus = OPEN; // On indique que le statu du capot est OPEN   
    } 
}
 
 void fermeture() // Sous-routine fermeture capot 
{ 
digitalWrite(relais_servo,HIGH);
motorStatus = RUNNING; // On indique que le statu des moteurs est RUNNING
coverStatus = UNKNOWN; // On indique que le statu du capot est UNKNOWN
delay(500);  // On attend 500ms
  
while(!(((AngleServoRotation)==(137))))// Jusqu'a ce que le servo rotation soit à 137°
    {
    ServoRotation.write((AngleServoRotation) + (1));   // On lui demande d'avancer de 1°
    AngleServoRotation += 1;// On ajoute 1° à la variable de la position rotation
    delay(20);// _delay(0.02);//Réglage de la vitesse du servo
    }

delay(1000);// On attend 1s

while(!(((AngleServoCapot)==(0))))// Jusqu'a ce que le servo capot soit à 0°
    {
    ServoCapot.write((AngleServoCapot) - (1));  // On lui demande de reculer de 1°
    AngleServoCapot += -1; // On soustrait 1° à la variable de la position capot
    delay(20);// _delay(0.02);//Réglage de la vitesse du servo
    }

delay(1000);// On attend 1s

while(!(((AngleServoTranslation)==(47))))// Jusqu'a ce que le servo translation soit à 47°
    {
    ServoTranslation.write((AngleServoTranslation) - (1));  // On lui demande de reculer de 1°
    AngleServoTranslation += -1; // On soustrait 1° à la variable de la position translation
    delay(20);// _delay(0.02);//Réglage de la vitesse du servo
    }
    
delay(500);// On attend 500ms
  
if (digitalRead(ctc_capot_ferme) == HIGH)// On controle que l'état du capteur du capot fermé est bien en position ON
    {
    digitalWrite(relais_servo,LOW);// On éteind le relais d'alimentation des servo
    motorStatus = STOPPED; // On indique que le statu des moteurs est STOPPED   
    coverStatus = OPEN; // On indique que le statu du capot est OPEN   
    }    
}
 
void handleSerial() // Communication usb/serie protocol Alnitak
{

if( Serial.available() >= 5 )  // all incoming communications are fixed length at 6 bytes including the \n
    {
    char* cmd;
    char* data;
    char temp[10];   
    int len = 0;
    char str[20];
    memset(str, 0, 20);
    Serial.readBytesUntil('\n', str, 20);  
    cmd = str + 1;
    data = str + 2;

    if( false ) // useful for debugging to make sure your commands came through and are parsed correctly.
       {
       sprintf( temp, "cmd = >%s%s;", cmd, data);
       Serial.println(temp);
       } 

    switch( *cmd )
       {
      case 'P':// Ping device
      sprintf(temp, "*P%d000\n", deviceId);
      Serial.print(temp);
      break;

      case 'O': // Open shutter
      sprintf(temp, "*O%d000\n", deviceId);
      Serial.print(temp); 
      analogWrite(ELpan,0);// On éteind le panneau EL
      digitalWrite(relais_ELpan,LOW);// On éteind le relais d'alimentation du panneau EL
      lightStatus = OFF; // On indique que le statu du panneau EL est OFF
      ouverture(); // On joue la sous-routine ouverture
      motorStatus = STOPPED; // On indique que le statu des moteurs est STOPPED   
      coverStatus = OPEN; // On indique que le statu du capot est OPEN   
      Serial.print(temp); 
      break;

      case 'C':// Close shutter
      sprintf(temp, "*C%d000\n", deviceId); 
      Serial.print(temp);  
      fermeture(); // On joue la sous-routine fermeture     
      compte_btn_ELpan = 0;// On met la variable du compteur du bouton ELpan à 0. Cela évite que le panneau se rallume si il était resté en position ON avant l'ouverture
      motorStatus = STOPPED; // On indique que le statu des moteurs est STOPPED   
      coverStatus = CLOSED; // On indique que le statu du capot est OPEN   
      Serial.print(temp);  
      break;

      case 'L':// Turn light on
      sprintf(temp, "*L%d000\n", deviceId);
      Serial.print(temp);
      compte_btn_ELpan = 5;// On met la variable du compteur du bouton ELpan à 5. Etat du bouton spécifique à la commande du panneau EL par la commande usb/série
      digitalWrite(relais_ELpan,HIGH);// On allume le relais ELpan
      lightStatus = ON;  // On indique que le statu du du panneau EL est ON
      break;

      case 'D':// Turn light off
      sprintf(temp, "*D%d000\n", deviceId);
      Serial.print(temp);
      lightStatus = OFF;lightStatus = ON;  // On indique que le statu du du panneau EL est OFF
      compte_btn_ELpan = 0;// On met la variable du compteur du bouton ELpan à 0. Ce qui éteind le panneau EL et son relais d'alimentation.
      break;

      case 'B':// Set brightness
      brightness = atoi(data);    
      if( lightStatus == ON )  // Si le statu du panneau lumineus est ON
      sprintf( temp, "*B%d%03d\n", deviceId, brightness );
      Serial.print(temp);
      analogWrite(ELpan,brightness);// On écrite la valeur de la luminosité dans la variable brightness
      break;

      case 'J':// Get brightness
      sprintf( temp, "*J%d%03d\n", deviceId, brightness);
      Serial.print(temp);
      break;
      
      case 'S':// Get device status    
      sprintf( temp, "*S%d%d%d%d\n",deviceId, motorStatus, lightStatus, coverStatus);
      Serial.print(temp);
      break;

      case 'V': // get firmware version
      sprintf(temp, "*V%d001\n", deviceId);
      Serial.print(temp);
      break;
        }    
    
    while( Serial.available() > 0 )
    Serial.read();

     }
}

void progELpan() // Sous-routine de commande du panneau EL en mode local
{
if ((compte_btn_ELpan >= 1) && (digitalRead(ctc_capot_ferme) == HIGH))// Si le compteur du bouton ELpan est supérieur ou égal à 1
     {
     digitalWrite(relais_ELpan,HIGH); // on allume le relais d'alimentation du panneau EL
     }
     
else // Si non
     {
     digitalWrite(relais_ELpan,LOW); // on eteind le relais d'alimentation du panneau EL
     } 
     
if (compte_btn_ELpan == 0)// Si le compteur du bouton ELpan est égal à 0
     {
     analogWrite(led_1,0);// On éteind toutes les LED
     analogWrite(led_2,0);
     analogWrite(led_3,0);
     analogWrite(led_4,0);
     analogWrite(ELpan,0);// On éteind le panneau EL
     digitalWrite(relais_ELpan,LOW); // on eteind le relais d'alimentation du panneau EL
     } 

if ((compte_btn_ELpan == 1) && (digitalRead(ctc_capot_ferme) == HIGH))// Si le compteur du bouton ELpan est égal à 1 et que le capteur de position du capot fermé est ON
     {
     analogWrite(led_1,255);// On allume la LED n°1
     analogWrite(led_2,0);
     analogWrite(led_3,0);
     analogWrite(led_4,0);
     analogWrite(ELpan,27);// On allume le panneau EL à une valeur de 27/255
     }
     
if ((compte_btn_ELpan == 2) && (digitalRead(ctc_capot_ferme) == HIGH))// Si le compteur du bouton ELpan est égal à 2 et que le capteur de position du capot fermé est ON
     {
     analogWrite(led_1,255);// On allume la LED n°1
     analogWrite(led_2,255);// On allume la LED n°2
     analogWrite(led_3,0);
     analogWrite(led_4,0);
     analogWrite(ELpan,50);// On allume le panneau EL à une valeur de 50/255
     }
     
if ((compte_btn_ELpan == 3) && (digitalRead(ctc_capot_ferme) == HIGH))// Si le compteur du bouton ELpan est égal à 3 et que le capteur de position du capot fermé est ON
     {
     analogWrite(led_1,255);// On allume la LED n°1
     analogWrite(led_2,255);// On allume la LED n°2
     analogWrite(led_3,255);// On allume la LED n°3
     analogWrite(led_4,0);
     analogWrite(ELpan,90);// On allume le panneau EL à une valeur de 90/255
     }
     
if ((compte_btn_ELpan == 4) && (digitalRead(ctc_capot_ferme) == HIGH))// Si le compteur du bouton ELpan est égal à 4 et que le capteur de position du capot fermé est ON
     {
     analogWrite(led_1,255);// On allume la LED n°1
     analogWrite(led_2,255);// On allume la LED n°2
     analogWrite(led_3,255);// On allume la LED n°3
     analogWrite(led_4,255);// On allume la LED n°4
     analogWrite(ELpan,255);// On allume le panneau EL à une valeur de 255/255
     }
     
if ((compte_btn_ELpan == 5) && (digitalRead(ctc_capot_ferme) == HIGH))// Si le compteur du bouton ELpan est égal à 5 et que le capteur de position du capot fermé est ON
     {
     analogWrite(ELpan,brightness);// On allume le panneau EL à une valeur envoyé par la liaison usb/série
     }   
}

void voltmetre() // Sous-routine voltmetre
{
// Mesure la tension en VIN et la référence interne à 1.1 volts
unsigned int raw_vin = analogRead(BROCHE_CAPTEUR_VIN);
unsigned int raw_ref = analogReadReference();
  
// Calcul de la tension réel avec un produit en croix
float real_vin = ((raw_vin * 1.1) / raw_ref) * COEFF_PONT_DIVISEUR_VIN;
  
if (real_vin >= 6)// Si la tension mesurée est supérieur ou égale à 6v
     {
     analogWrite(led_1,255);// On allume la LED n°1
     analogWrite(led_2,0);
     analogWrite(led_3,0);
     analogWrite(led_4,0);
     }
     
if (real_vin >= 7)// Si la tension mesurée est supérieur ou égale à 7v
     {
     analogWrite(led_1,255);// On allume la LED n°1
     analogWrite(led_2,255);// On allume la LED n°2
     analogWrite(led_3,0);
     analogWrite(led_4,0);
     }
     
if (real_vin >= 8)// Si la tension mesurée est supérieur ou égale à 8v
     {
     analogWrite(led_1,255);// On allume la LED n°1
     analogWrite(led_2,255);// On allume la LED n°2
     analogWrite(led_3,255);// On allume la LED n°3
     analogWrite(led_4,0);
     }
     
if (real_vin >= 9)// Si la tension mesurée est supérieur ou égale à 8v
     {
     analogWrite(led_1,255);// On allume la LED n°1
     analogWrite(led_2,255);// On allume la LED n°2
     analogWrite(led_3,255);// On allume la LED n°3
     analogWrite(led_4,255);// On allume la LED n°4
     }
  
delay(1000);// On attend 1s
}

void secu() // Sous-routine Secu fermeture automatique si coupure de courant 
{  
if (digitalRead(btn_park) == LOW)// Si le switch park est en position LOW
     {
     digitalWrite(relais_secu,HIGH);// On allume le relais d'alimentation secours
     }
}
    

 

 

Modifié par Fabrice Teissier
Posté

Pourquoi ????

 

J arrive à connecter l arduino uno à SGP mais pas l arduino micro.

Je télécharge le même code dans l un et dans l autre. Ils marchent parfaitement avec l Ide de l arduino et le moniteur série.

J ai essayé également avec le code du github orignal:

Avec le UNO, SGP se connecte et communique

Avec le micro, SGP tourne en rond communique à peine puis annoncé un échec de connexion "time out".

 

Y a un truc particulier à faire ? Une formule

magique ? Une incantation ?

 

Bref si vous avez une idée ?

Posté

 

Il y a 2 heures, Fabrice Teissier a dit :

@ursus Ça ne viendrait pas du fameux petit délai à mettre devant le 1er « if » de la routine void handelserial ?

Voir le lien proposé par cedric02700 en haut de cette page. 

 

Je regarderais. Le micro serait plus rapide que le Uno?

Posté
Il y a 12 heures, Fabrice Teissier a dit :

@ursus Ça ne viendrait pas du fameux petit délai à mettre devant le 1er « if » de la routine void handelserial ?

Voir le lien proposé par cedric02700 en haut de cette page. 

 

Bon, je viens d'essayer plusieurs valeurs de delay avant le if, toujours le mème résultat.

 

Je suis en train d'éplucher cela https://forum.arduino.cc/index.php?topic=396450.0

Je comprends mieux les commandes d'Alnitak et il me semble que le code ne profite pas de la structure des commandes --> cf exemple 5

Rejoignez la conversation !

Vous pouvez répondre maintenant et vous inscrire plus tard. Si vous avez un compte, connectez-vous pour poster avec votre compte.

Invité
Répondre à ce sujet…

×   Collé en tant que texte enrichi.   Coller en tant que texte brut à la place

  Seulement 75 émoticônes maximum sont autorisées.

×   Votre lien a été automatiquement intégré.   Afficher plutôt comme un lien

×   Votre contenu précédent a été rétabli.   Vider l’éditeur

×   Vous ne pouvez pas directement coller des images. Envoyez-les depuis votre ordinateur ou insérez-les depuis une URL.

  • En ligne récemment   0 membre est en ligne

    • Aucun utilisateur enregistré regarde cette page.
×
×
  • Créer...

Information importante

Nous avons placé des cookies sur votre appareil pour aider à améliorer ce site. Vous pouvez choisir d’ajuster vos paramètres de cookie, sinon nous supposerons que vous êtes d’accord pour continuer.