IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Arduino Discussion :

Effectuer une association entre deux tableaux


Sujet :

Arduino

  1. #221
    Membre émérite
    Avatar de jpbbricole
    Homme Profil pro
    Retraité des réseaux informatiques
    Inscrit en
    Février 2013
    Messages
    1 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Retraité des réseaux informatiques
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Février 2013
    Messages : 1 012
    Points : 2 341
    Points
    2 341
    Par défaut
    Bonsoir Jacques Chabrol!

    C'est de 7 à 12V.

    Bonne nuit, moi c'est mes neurones que je vais faire dormir
    jpbbricole
    L'expérience est la seule chose qu'il ne faut acheter que d'occasion!

  2. #222
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 711
    Points : 5 390
    Points
    5 390
    Par défaut
    Merci pour la vidéo Jacques - ( on aurait aimé voir le circuit aussi ! je sais j'abuse )

  3. #223
    Membre éprouvé
    Femme Profil pro
    ..
    Inscrit en
    Décembre 2019
    Messages
    562
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 94
    Localisation : Autre

    Informations professionnelles :
    Activité : ..

    Informations forums :
    Inscription : Décembre 2019
    Messages : 562
    Points : 1 253
    Points
    1 253
    Par défaut
    Bonjour,

    Mais comment vous avez fait pour passer du sujet initial à ça :

    Citation Envoyé par Jsiorat Voir le message
    Si je te dis que je dispose de :
    - 4 cartes Méga 2560
    - 6 cartes UNO R3
    - 2 cartes PCA96685
    - une douzaine de ULN2003
    - un shield écran LCD TFT 3,5p
    Est-ce que ça peut te faciliter les choses ?

    Les R3, je vais m'en servir pour gérer les cantons, zones de ralentissement et d'arrêt
    Pour l'écran, je verrai plus tard pour apprendre comment construire un menu de plusieurs pages et une gestion Gare/triage

  4. #224
    Membre habitué
    Avatar de Jsiorat
    Homme Profil pro
    RETRAITE
    Inscrit en
    Juillet 2005
    Messages
    398
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Ariège (Midi Pyrénées)

    Informations professionnelles :
    Activité : RETRAITE

    Informations forums :
    Inscription : Juillet 2005
    Messages : 398
    Points : 169
    Points
    169
    Par défaut
    Citation Envoyé par Jay M Voir le message
    Merci pour la vidéo Jacques - ( on aurait aimé voir le circuit aussi ! je sais j'abuse )
    Salut Jay,

    ça viendra ! patience !
    Être vieux, c'est être jeune depuis plus longtemps que les autres !

  5. #225
    Membre habitué
    Avatar de Jsiorat
    Homme Profil pro
    RETRAITE
    Inscrit en
    Juillet 2005
    Messages
    398
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Ariège (Midi Pyrénées)

    Informations professionnelles :
    Activité : RETRAITE

    Informations forums :
    Inscription : Juillet 2005
    Messages : 398
    Points : 169
    Points
    169
    Par défaut
    Citation Envoyé par kaitlyn Voir le message
    Bonjour,

    Mais comment vous avez fait pour passer du sujet initial à ça :

    Bonjour Katlyn,

    comment j'ai fait tout ça ? en me procurant les kits d'apprentissage de chez Arduino, Elegoo etc... et puis, ... l'envie d'apprendre à gérer mon train miniature !
    et là, tout le monde ici, m'a été d'un grand et énorme secours !

    Par contre, je cherche des exemples pour écran LCD 3,5p de chez Kuman pour Arduino ; comment placer des traits précisément, créer des boutons cliquables, déssiner des figures géométriques à des points x,y bien précis etc ...
    difficile de trouver ce genre de turoriels sur internet (la pub pour acheter, y en a plus qu'il n'en faut ! mais des exemples ... ???)
    A+, cordialement
    Jacques
    Être vieux, c'est être jeune depuis plus longtemps que les autres !

  6. #226
    Membre éprouvé
    Femme Profil pro
    ..
    Inscrit en
    Décembre 2019
    Messages
    562
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 94
    Localisation : Autre

    Informations professionnelles :
    Activité : ..

    Informations forums :
    Inscription : Décembre 2019
    Messages : 562
    Points : 1 253
    Points
    1 253
    Par défaut
    En fait, je ne m'expliquais pas comment vous en êtes venus à faire tous ces achats pour ce projet, car je trouve que c’est un très mauvais investissement, du gaspillage. Tant qu'à dépenser, au temps que ça ressorte.

  7. #227
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 711
    Points : 5 390
    Points
    5 390
    Par défaut
    Par contre, je cherche des exemples pour écran LCD 3,5p de chez Kuman pour Arduino ; comment placer des traits précisément, créer des boutons cliquables, déssiner des figures géométriques à des points x,y bien précis etc ...
    difficile de trouver ce genre de turoriels sur internet (la pub pour acheter, y en a plus qu'il n'en faut ! mais des exemples ... ???)
    ça mérite un nouveau fil de discussion sans doute. Quel écran exactement avez vous ? (un lien ?)

    je pense que vous aurez besoin de la bibliothèque UTFT et si vous voulez gérer le 'touch' (écran résistif) prenez la bibliothèque URTouch

    si c'est un écran contrôlé par ili9481 ili9468, ili9488 hx8357 ou r61581 il faut la bibliothèque mcufriend_kbv

  8. #228
    Membre habitué
    Avatar de Jsiorat
    Homme Profil pro
    RETRAITE
    Inscrit en
    Juillet 2005
    Messages
    398
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Ariège (Midi Pyrénées)

    Informations professionnelles :
    Activité : RETRAITE

    Informations forums :
    Inscription : Juillet 2005
    Messages : 398
    Points : 169
    Points
    169
    Par défaut
    Citation Envoyé par Jay M Voir le message
    ça mérite un nouveau fil de discussion sans doute. Quel écran exactement avez vous ? (un lien ?)
    Bonsoir Jay,

    J'ai un écran Kuman 3.5k LCD !
    Être vieux, c'est être jeune depuis plus longtemps que les autres !

  9. #229
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 711
    Points : 5 390
    Points
    5 390
    Par défaut
    Citation Envoyé par Jsiorat Voir le message
    J'ai un écran Kuman 3.5k LCD !
    bonsoir Jacques,

    un lien aiderait à savoir quel modèle c'est

    serait-ce celui là ?
    Nom : s.png
Affichages : 115
Taille : 636,5 Ko

  10. #230
    Membre habitué
    Avatar de Jsiorat
    Homme Profil pro
    RETRAITE
    Inscrit en
    Juillet 2005
    Messages
    398
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Ariège (Midi Pyrénées)

    Informations professionnelles :
    Activité : RETRAITE

    Informations forums :
    Inscription : Juillet 2005
    Messages : 398
    Points : 169
    Points
    169
    Par défaut
    Citation Envoyé par Jay M Voir le message
    bonsoir Jacques,

    un lien aiderait à savoir quel modèle c'est
    bonjour Jay,
    Oui, pardon j'aurai dû ! la fatigue, l'âge peut-être !

    Oui c'est bien ça !
    Être vieux, c'est être jeune depuis plus longtemps que les autres !

  11. #231
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 711
    Points : 5 390
    Points
    5 390
    Par défaut
    Salut

    Il faut installer (directement depuis l’IDE) la bibliothèque mcufriend_kbv et vous verrez à l’usage des exemples qu’il faut La bibliothèques d’Adafruit : Adafruit_GFX (MCUFRIEND_kbv hérite de toutes les méthodes de la classe Adafruit_GFX) et si votre écran est un écran resistif permettant donc la détection d’un appui il vous faudra aussi installer La bibliothèque Adafruit Touch-Screen

    Enfichez votre écran sur votre arduino dans le bons sens et branchez en usb sur l’ordinateur.

    Une fois ces 3 bibliothèques installées, vous allez dans les exemples de mcufriend et executez diagnose_Touchpins.ino. Ouvrez la console série à 9600 bauds. Rien ne se passera sur l’écran mais la console devrait afficher les numéros des 4 pins (X-, X+, Y- et Y+) correspondant au digitizer de l’écran resistif.

    Ensuite il faut déterminer les valeurs min et Max du pont de résistances de votre écran pour calibration.

    Ouvrez l’exemple TouchScreen_Calibr_native.ino. Vérifiez que les pins définies ligne 30
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     int XP = 7, YP = A2, XM = A1, YM = 6;  //next common configuration
    correspondent aux X Plus (XP) X Moins (XM) et idem en Y obtenus à l’étape précédente. Si ce n’est pas le cas, changez les Nº de pins. Chargez et exécutez le script qui vous donnera aussi dans la console des valeurs pour votre écran.

    Il faut noter ces pins et valeurs et quand vous ouvrez des exemples il faudra modifier le code pour les adapter à votre écran, vous verrez en début des exemples du code comme cela:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     // ALL Touch panels and wiring is DIFFERENT
    // copy-paste results from TouchScreen_Calibr_native.ino
    const int XP = 6, XM = A2, YP = A1, YM = 7; //ID=0x9341
    const int TS_LEFT = 907, TS_RT = 136, TS_TOP = 942, TS_BOT = 139;
    C’est ce qu’il faut pour votre écran bien sûr qu’il faudra mettre.

    Ensuite vous n’avez plus qu’à tester les exemples, ça devrait marcher...

  12. #232
    Membre habitué
    Avatar de Jsiorat
    Homme Profil pro
    RETRAITE
    Inscrit en
    Juillet 2005
    Messages
    398
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Ariège (Midi Pyrénées)

    Informations professionnelles :
    Activité : RETRAITE

    Informations forums :
    Inscription : Juillet 2005
    Messages : 398
    Points : 169
    Points
    169
    Par défaut
    Jay ... une question ! (désolé pour l'humour ... Jay <==> j'ai !)

    on peut lire dans certain fichier .ino, la forme suivante :
    #if 1

    void setup
    void loop

    #endif

    Utilité de #if / #endif qui englobe tout le code ?

    Merci, a+
    Jacques
    Être vieux, c'est être jeune depuis plus longtemps que les autres !

  13. #233
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 711
    Points : 5 390
    Points
    5 390
    Par défaut
    Citation Envoyé par Jsiorat Voir le message
    Jay ... une question ! (désolé pour l'humour ... Jay <==> j'ai !)



    Salut

    ça permet de virer tout le code à la compilation en modifiant le 1 en 0 dans le #if 1.. bizarre.. vous avez un lien sur un truc en ligne où ils font cela.. si c'est tout le contenu du fichier, autant ne pas coder

  14. #234
    Membre habitué
    Avatar de Jsiorat
    Homme Profil pro
    RETRAITE
    Inscrit en
    Juillet 2005
    Messages
    398
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Ariège (Midi Pyrénées)

    Informations professionnelles :
    Activité : RETRAITE

    Informations forums :
    Inscription : Juillet 2005
    Messages : 398
    Points : 169
    Points
    169
    Par défaut
    Voila l'exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
     
    /* an alternative approach.   swap the #if 1 / 0 values to try it
     * 
     */
    #if 0
     
    #include <Adafruit_GFX.h>
    #include <MCUFRIEND_kbv.h>
    MCUFRIEND_kbv tft;
    #include <TouchScreen.h>
    #define MINPRESSURE 200
    #define MAXPRESSURE 1000
     
    // ALL Touch panels and wiring is DIFFERENT
    // copy-paste results from TouchScreen_Calibr_native.ino
    // const int XP = 6, XM = A2, YP = A1, YM = 7; //ID=0x9341    ORIGINAL !
    const int XP = 23, YP = A1, XM = A2, YM = 32;  //ID=0x9486    MODIFIE le 16/10/2020
    const int TS_LEFT = 907, TS_RT = 136, TS_TOP = 942, TS_BOT = 139;
     
    TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
     
    Adafruit_GFX_Button on_btn, off_btn;
     
    int pixel_x, pixel_y;     //Touch_getXY() updates global vars
    bool Touch_getXY(void)
    {
        TSPoint p = ts.getPoint();
        pinMode(YP, OUTPUT);      //restore shared pins
        pinMode(XM, OUTPUT);
        digitalWrite(YP, HIGH);   //because TFT control pins
        digitalWrite(XM, HIGH);
        bool pressed = (p.z > MINPRESSURE && p.z < MAXPRESSURE);
        if (pressed) {
            pixel_x = map(p.x, TS_LEFT, TS_RT, 0, tft.width()); //.kbv makes sense to me
            pixel_y = map(p.y, TS_TOP, TS_BOT, 0, tft.height());
        }
        return pressed;
    }
     
    #define BLACK   0x0000
    #define BLUE    0x001F
    #define RED     0xF800
    #define GREEN   0x07E0
    #define CYAN    0x07FF
    #define MAGENTA 0xF81F
    #define YELLOW  0xFFE0
    #define WHITE   0xFFFF
     
    void setup(void)
    {
        Serial.begin(9600);
        uint16_t ID = tft.readID();
        Serial.print("TFT ID = 0x");
        Serial.println(ID, HEX);
        Serial.println("Calibrate for your Touch Panel");
        if (ID == 0xD3D3) ID = 0x9486; // write-only shield
        tft.begin(ID);
        tft.setRotation(0);            //PORTRAIT
        tft.fillScreen(BLACK);
        on_btn.initButton(&tft,  60, 200, 100, 40, WHITE, CYAN, BLACK, "ON", 2);
        off_btn.initButton(&tft, 180, 200, 100, 40, WHITE, CYAN, BLACK, "OFF", 2);
        on_btn.drawButton(false);
        off_btn.drawButton(false);
        tft.fillRect(40, 80, 160, 80, RED);
    }
     
    /*  
     * updating multiple buttons from a list
     * 
     * anything more than two buttons gets repetitive
     * 
     * you can place button addresses in separate lists
     * e.g. for separate menu screens
     */
     
    // Array of button addresses to behave like a list
    Adafruit_GFX_Button *buttons[] = {&on_btn, &off_btn, NULL};
     
    /* update the state of a button and redraw as reqd
     *
     * main program can use isPressed(), justPressed() etc
     */
    bool update_button(Adafruit_GFX_Button *b, bool down)
    {
        b->press(down && b->contains(pixel_x, pixel_y));
        if (b->justReleased())
            b->drawButton(false);
        if (b->justPressed())
            b->drawButton(true);
        return down;
    }
     
    /* most screens have different sets of buttons
     * life is easier if you process whole list in one go
     */
    bool update_button_list(Adafruit_GFX_Button **pb)
    {
        bool down = Touch_getXY();
        for (int i = 0 ; pb[i] != NULL; i++) {
            update_button(pb[i], down);
        }
        return down;
    }
     
    /* compare the simplicity of update_button_list()
     */
    void loop(void)
    {
        update_button_list(buttons);  //use helper function
        if (on_btn.justPressed()) {
            tft.fillRect(40, 80, 160, 80, GREEN);
        }
        if (off_btn.justPressed()) {
            tft.fillRect(40, 80, 160, 80, RED);
        }
    }
    #endif
    Être vieux, c'est être jeune depuis plus longtemps que les autres !

  15. #235
    Membre émérite
    Avatar de jpbbricole
    Homme Profil pro
    Retraité des réseaux informatiques
    Inscrit en
    Février 2013
    Messages
    1 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Retraité des réseaux informatiques
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Février 2013
    Messages : 1 012
    Points : 2 341
    Points
    2 341
    Par défaut
    Bonsoir Jacques

    Voilà la première mouture de la gestion multi TCO. Comme dit précédemment, dans cette version, seul le tcoGare (index 0) peut communiquer avec les autres TCO.
    Dans les 3 tco, tcoGare, tcoTriageE et tcoTriageS, on peut envoyer des ordres locaux par leur console respective.
    Seul tcoGare lit, dans les tableaux bp et aig le champs tcoPseudo afin de voire s'il faut executer la commande localement ou la router vers le bon TCO.
    La fonction des boutons LED et autres n'ont pas changé, chaque TCO peut être uitilisé indépendemment des autres.

    Les TCO secondaires (slaves) communiquent, vers le TCO primaire (master) via le port Serial1 (Tx1 18, Rx1 19)

    La câblage est ainsi:
    tcoGare Serial1 Tx1 18 vers tcoTriageE Rx1 19
    tcoGare Serial1 Rx1 19 vers tcoTriageE Tx1 18

    tcoGare Serial2 Tx2 16 vers tcoTriageS Rx2 19
    tcoGare Serial2 Rx2 17 vers tcoTriageS Tx2 18

    Les GND des 3 TCO doîvent être reliés ensembles.
    Nom : 3 Mega TCO Anotée.jpg
Affichages : 112
Taille : 95,7 Ko

    Marche à suivre pour paramétrer l'execution des ordres vers d'autres TCO depuis tcoGare, exemple avec tcoTriageE et fichier Train_Tabl_tcoTriageE_BP.h.
    Pour exécuter cette ligne depuis tcoGare:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    // La ligne de Train_Tabl_tcoTriageE_BP.h
    	{"C1_T6",  "TRIEN", 10,   false,   "G1_G",   "T1_G",   "T2_G",  "T3_G",  "T4_G",  "T5_D",       "",       ""},	   // vers Triage 6
    // Devient,  dans le fichier Train_Tabl_tcoGare_BP.h:
    	{"C1_T6",  "TRIEN", #portBouton_tcoGare,   false, "",  "",      "",     "",      ""}
    Attention à respecter le nombre d'aigCmdx qui est propre au fichier *_BP.h
    la ligne du tcoTriageE a 8 aigCmdx, mais la ligne ajoutée dans tcoGare n'en a que 5 (#define bpMotNombreMax)
    Exemple d'ajout dans Train_Tabl_tcoGare_BP.h pour envoyer des ordres dane tcoTriageEntree (TRIEN) et tcoTriageS (TRISO)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    	{"C1_T6",  "TRIEN", 2,   false, "",  "",      "",     "",      ""},
    	{"T6_ST",  "TRISO", 3,   false, "",  "",      "",     "",      ""},

    Concernant les fichiers de configuration *_BP.h, le nombre de aigCmdx doit être renseigné à la définition #define bpMotNombreMax de chaque TCO (en tête du programme).
    Tout les BP d'un fichier doivent avoir le même nombre d'aigCmdx.

    Le programme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    423
    424
    425
    426
    427
    428
    429
    430
    431
    432
    433
    434
    435
    436
    437
    438
    439
    440
    441
    442
    443
    444
    445
    446
    447
    448
    449
    450
    451
    452
    453
    454
    455
    456
    457
    458
    459
    460
    461
    462
    463
    464
    465
    466
    467
    468
    469
    470
    471
    472
    473
    474
    475
    476
    477
    478
    479
    480
    481
    482
    483
    484
    485
    486
    487
    488
    489
    490
    491
    492
    493
    494
    495
    496
    497
    498
    499
    500
    501
    502
    503
    504
    505
    506
    507
    508
    509
    510
    511
    512
    513
    514
    515
    516
    517
    518
    519
    520
    521
    522
    523
    524
    525
    526
    527
    528
    529
    530
    531
    532
    533
    534
    535
    536
    537
    538
    539
    540
    541
    542
    543
    544
    545
    546
    547
    548
    549
    550
    551
    552
    553
    554
    555
    556
    557
    558
    559
    560
    561
    562
    563
    564
    565
    566
    567
    568
    569
    570
    571
    572
    573
    574
    575
    576
    577
    578
    579
    580
    581
    582
    583
    584
    585
    586
    587
    588
    589
    590
    591
    592
    593
    594
    595
    596
    597
    598
    599
    600
    601
    602
    603
    604
    605
    606
    607
    608
    609
    610
    611
    612
    613
    614
    615
    616
    617
    618
    619
    620
    621
    622
    623
    624
    625
    626
    627
    628
    629
    630
    631
    632
    633
    634
    635
    636
    637
    638
    639
    640
    641
    642
    643
    644
    645
    646
    647
    648
    649
    650
    651
    652
    653
    654
    655
    656
    657
    658
    659
    660
    661
    662
    663
    664
    665
    666
    667
    668
    669
    670
    671
    672
    673
    674
    675
    676
    677
    678
    679
    680
    681
    682
    683
    684
    685
    686
    687
    688
    689
    690
    691
    692
    693
    694
    695
    696
    697
    698
    699
    700
    701
    702
    703
    704
    705
    706
    707
    708
    709
    710
    711
    712
    713
    714
    715
    716
    717
    718
    719
    720
    721
    722
    723
    724
    725
    726
    727
    728
    729
    730
    731
    732
    733
    734
    735
    736
    737
    738
    739
    740
    741
    742
    743
    /******************************************************************************
        Name:       Train electrique gere par Mega en reseau
        Created:    12.10.2020
        Author:     jpbbricole
            
        Remarques:  Multi TCO tcoGare tcoTriageE tcoTriageS
    '******************************************************************************
    */
    #define  progrVersion 0.19
    #include <JC_Button.h>							// https://github.com/JChristensen/JC_Button 
    #include <SoftPWM.h>                            // https://github.com/bhagman/SoftPWM
     
    /*===================================== Selection du TCO pour sa programmation
    	Pour programmer un TCO, connecter le port Serial de l'Arduino
    	Enlever la remarque (//) de devant le _tcoXxxxxx
    	Mettre la remarque  (//) devant les autres.
    	Renseigner, si necessaire, sous Selection des parametres propre au TCO, ci dessous
    	Il ne doit avoir qu'un TCO sans remarque, celui que l'on veur programmer
    	Télécharger le programme.
    */
     
    #define _tcoGare
    //#define _tcoTriageEntree
    //#define _tcoTriageSortie
     
    //------------------------------------- Selection des parametres propre au TCO
    #ifdef _tcoGare
    	#define tcoLocalIndex tcoIndexGare
    	#define tcoRoleInNet tcoRoleMaster
    	#define bpMotNombreMax 5			// Nombre de moteurs max par bouton dans *_BP.h
    #endif
    #ifdef _tcoTriageEntree
    	#define bpMotNombreMax 8			// Nombre de moteurs max par bouton dans *_BP.h
    	#define tcoLocalIndex tcoIndexTriageEntree
    	#define tcoRoleInNet tcoRoleSlave
    #endif
    #ifdef _tcoTriageSortie
    	#define tcoLocalIndex tcoIndexTriageSortie
    	#define tcoRoleInNet tcoRoleSlave
    	#define bpMotNombreMax 7			// Nombre de moteurs max par bouton dans *_BP.h
    #endif
    //===================================== Fin parametres de programmation TCO ==========================
     
    /*===================================== Topologie du r�seau TCO
    	Le nombre de TCO maximum est tcoLocal + 3 (3 ports serie disponibles sur un Mega)
    	Le TCO[0] = Serial TCO[1] = Serial1   TCO[2] = Serial2   TCO[3] = Serial3
    	Dans la premiere phase du developpement, le TCO index 0,  est le "patron" tcoRoleMaster
    */
    enum tcoRolesIndex {tcoRoleMaster, tcoRoleSlave, tcoRoleNombre};                              // Pour indexer les roles dans le reseau
    char* tcoRoleNom[] =    {"Master"   , "Slave"};
     
    enum tcoIndex {tcoIndexGare, tcoIndexTriageEntree, tcoIndexTriageSortie,  tcoIndexNombre};     // Pour indexer le tableau aiguilles[].motGDport[]
    char* tcoNom[] =    {"Gare"   , "Triage Entree",    "Triage Sortie"};
    char* tcoPseudo[] = {"GARE"      , "TRIEN",            "TRISO"};
     
    struct tcoDefinition
    {int localIndex; String nom; String pseudo; byte roleInNet;};
    tcoDefinition tcoLocal;
    tcoDefinition tcoDistant;
     
    /*===================================== Ports serie
    	les TCO slaves communiquent par le port Serial1
    	Serial1,2 et 3 sont initialises dans tcoInitialisation()
    */
    String tcoSlCommandRx;                   // Commande recue
    boolean tcoSlCommandNew;                 // Si nouvelle commande
    #define tcoSlSerial Serial1
     
    //===================================== Aiguilles
    #define aigMotEtatOn HIGH							                      // Etat pour moteur ON
    #define aigMotEtatOnTemps 50						                      // Moteur, temps de l'impulsiom ON
    enum aiguillesPositionIndex {aigPosGauche, aigPosDroite, aigPosNull};     // Pour indexer le tableau aiguilles[].motGDport[]
    String aigPosLabelSh[] ={"G", "D"};
     
    boolean aigCommandOk;
     
    //------------------------------------- Structure de l'objet aiguille
    struct aiguilleDefinition
    {String nom; String Tco; byte position; int motGDport[2]; int ledGDport[2];};
     
    	// contient le tableau de configuration des aiguilles
    	#ifdef _tcoGare
    		#include "Train_Tabl_tcoGare_AIG.h" //"ARDDEV_TrainElectrTabl_AIG_TcoGare.h" 
    	#endif
    	#ifdef _tcoTriageEntree
    		#include "Train_Tabl_tcoTriageE_AIG.h"
    	#endif
    	#ifdef _tcoTriageSortie
    		#include "Train_Tabl_tcoTriageS_AIG.h"
    	#endif
    const int aigNombreMax = sizeof(aiguilles)/sizeof(aiguilles[0]);
     
    //------------------------------------- Structure de l'objet aiguille en utilisation
    struct aigInUseDef
    {int index; String nom; byte motPosition; String motPosLabel; String motPosLabelSh;String tco;};
    aigInUseDef aigIu;                                // Aiguille en utilisation
     
    //===================================== Boutons
    const boolean bpEtatPresseLOW = true;			 // Etat lu du bouton presse
    boolean bpCommandeOk = false; 
     
    //------------------------------------- Structure de l'objet bouton d'aiguuille (bpAig)
    struct bpAigDefinition                                                  
    {String nom; String TcoPseudo; byte port; boolean bpOn; String aig_Dir[bpMotNombreMax];};
     
    /*
    	remplissage de la structure des boutons bp[0] a bp[bpNombreMax-1]
    */
    	// contient le tableau de configuration des aiguilles
    	#ifdef _tcoGare
    		#include "Train_Tabl_tcoGare_BP.h" //"ARDDEV_TrainElectrTabl_BP_TcoGare.h"
    	#endif
    	#ifdef _tcoTriageEntree
    		#include "Train_Tabl_tcoTriageE_BP.h"
    	#endif
    	#ifdef _tcoTriageSortie
    		#include "Train_Tabl_tcoTriageS_BP.h"
    	#endif
     
    const int bpNombreMax = sizeof(bpAig)/sizeof(bpAig[0]);
    Button *bpRead[bpNombreMax];                     // JC_Button.h
     
     //===================================== Led PWM (lpwm)
    #define lpwmPolarite SOFTPWM_NORMAL  // SOFTPWM_NORMAL ou SOFTPWM_INVERTED 
    #define lpwmOn true
     
    byte lpwmValeurOn= 255;                // Valeur pour allumer
    byte lpwmValeurOff= 0;                 // Valeur pour eteindre
    int lpwmTempsToOn = 500;               // Temps ver l'allumage
    int lpwmTempsToOff =500;               // Temps vers l'extinction
     
     //===================================== Commandes moniteur
    String monCommandRx;                   // Commande recue
    boolean monCommandNew;                 // Si nouvelle commande
    boolean cmdMonTrace = false;           // Trace des commandes dans console
     
    struct cmdMonitDef
    {String nom; String paramStr; int paramInt; float paramFl;};
    cmdMonitDef cmdMonitRx;
    //------------------------------------- Liste des commandes index et syntaxe
    enum cmdMoniteurIndex {cmdMonitBp, cmdMonitAig, cmdMonitLpwmTest, cmdMonitLpwmTestAll, cmdMonitCmdTrace, cmdMonitNombre};
    char* cmdMonitSyntax[] = {"BP"      , "AIG",      "LPWMTEST",        "LPWMTESTALL",       "CMDTRACE"};
     
     
    void setup()
    {
    	Serial.begin(115200);
    	delay(500);
     
    	tcoInitialisation();
    	aigLpwmInitialisation();
    	bpInitialisation();
    	aigInitialisation();
    	aigIu.index = -1;                  // Pas d'aiguille selectionnee
     
     
    	cmdMonitHelp();
    	tcoInitBpCommandes(tcoLocal.localIndex);
     
    	Serial.println("\n\t> > > TCO local " + tcoLocal.nom + " < < < (" + tcoLocal.pseudo + " " + 
    	               tcoRoleNom[tcoLocal.roleInNet] + ")");
    }
     
    void loop()
    {
    	if (bpScanStatus())				   // S'il y a un bouton presse                             
    	{
    		delay(250);					   // Attendre d'eventuelles autres bp
    		bpScanStatus();
    		bpPressedAction();
    	}
     
    	/*---------------------------------------------------------------------------------------------------------------------- 
    	   Ecoute du port s�rie pour la r�ception des commandes du TCO Master
    	  ----------------------------------------------------------------------------------------------------------------------
    	*/
    	if (tcoLocal.roleInNet == tcoRoleSlave)
    	{
    		tcoSlSerialEvent();                     // Lecture du port serie
    		if (tcoSlCommandNew)                 // Si re�u une nouvelle commande
    		{
    			cmdMonitRecue(tcoSlCommandRx);   // Evaluation de la commande
     
    			tcoSlCommandRx = "";
    			tcoSlCommandNew  = false;
    		}
    	}
    	/*---------------------------------------------------------------------------------------------------------------------- 
    	   Ecoute du moniteur s�rie pour la r�ception �ventuelle de commandes ou param�tres.
    	  ----------------------------------------------------------------------------------------------------------------------
    	*/
    	serialEvent();                     // Lecture du port serie
    	if (monCommandNew)                 // Si re�u une nouvelle commande
    	{
    		cmdMonitRecue(monCommandRx);   // Evaluation de la commande
     
    		monCommandRx = "";
    		monCommandNew  = false;
    	}
    }
     
    //===================================== TCO
    void tcoInitialisation()
    {
    	tcoLocal.localIndex = tcoLocalIndex;
    	tcoLocal.nom = tcoNom[tcoLocal.localIndex];
    	tcoLocal.pseudo = tcoPseudo[tcoLocal.localIndex];
    	tcoLocal.roleInNet = tcoRoleInNet;
     
    	Serial1.begin(115200);
    	Serial2.begin(115200);
    	Serial3.begin(115200);
    }
    //
    //------------------------------------- Initialisation des aiguillages du TCO
    void tcoInitBpCommandes(int tcoIndex)
    {
    	Serial.print(F("\n\t>>> Initialisation de ")); Serial.println(tcoLocal.nom + " <<<");
    	if (tcoBoPositionInitiale != "-")
    	{
    		cmdMonitRecue(tcoBoPositionInitiale);
    	} 
    	else
    	{
    		Serial.println(F("Pas d'initialisation."));
    	}
     
    	Serial.println(F(""));
    }
     
    //------------------------------------- Recherche de l'index d'un TCO en fonction de son pseudo retourne -1 si pas trouve
    void tcoSelectByPseudo(String tcoRecherche)
    {
    	tcoDistant.localIndex = -1;
    	tcoDistant.nom = "? " + tcoRecherche + " ?";
    	tcoDistant.pseudo = "????";
     
    	for (int t = 1; t < tcoIndexNombre; t ++)
    	{
    		if ((String)tcoPseudo[t] == tcoRecherche)
    		{
    			tcoDistant.localIndex = t;
    			tcoDistant.nom = tcoNom[t];
    			tcoDistant.pseudo = tcoPseudo[t];
    			break;
    		}
    	}
    }
     
    /*------------------------------------- Envoi de commandes aux TCO distants
    	BP=C1_V2     TRIEN
    	BP=C3_V2     TRIEN
    	BP=C3_V3     TRISO
    */
    void tcoSendCommand(String tcoPseudo, String tcoCommand)
    {
    	tcoSelectByPseudo(tcoPseudo);
    	Serial.println("Envoi a " + tcoDistant.nom + + "\t" + tcoCommand);
     
    	switch(tcoDistant.localIndex)
    	{
    		case tcoIndexGare:			
    			Serial.println(tcoCommand);
    			break;
    		case tcoIndexTriageEntree:
    			Serial1.println(tcoCommand);
    			break;
    		case tcoIndexTriageSortie:
    			Serial2.println(tcoCommand);
    			break;
    	}
    }
    //-------------------------------------- Ecoute du port serie arrivant du master
    void tcoSlSerialEvent()                                                   // IDE monitor or DRO serial
    {
    	while (tcoSlSerial.available())
    	{
    		char monChar = (char)tcoSlSerial.read();                          // Char received from IDE monitor
    		if (monChar == '\n')                                         // If new line char received = end of command line
    		{
    			tcoSlCommandNew  = true;
    		}
    		else
    		{
    			if (monChar >= ' ') {tcoSlCommandRx += monChar;}           // >= ' ' to avoid not wanted ctrl char.
    		}
    	}
    }
    //===================================== Aiguilles (aig)
    void aigInitialisation()
    {
    	for (int aig = 0; aig < aigNombreMax; aig ++)
    	{
    		for (int gd = 0; gd < 2; gd ++)
    		{
    			// Initialisation des moteurs d'aiguilles
    			pinMode(aiguilles[aig].motGDport[gd], OUTPUT);
    			digitalWrite(aiguilles[aig].motGDport[gd], !aigMotEtatOn);		// Moteur a l'arr�t
    		}
     
    	}
     
     
    	Serial.println(F("\n\t>>> Mise en positiondes aiguilles <<<"));
    	for (int aig = 0; aig < aigNombreMax; aig ++)
    	{
    		if (aiguilles[aig].position != aigPosNull)   // S'il y a mouvement a faire
    		{
    			String initCmd = aiguilles[aig].nom + "_" + aigPosLabelSh[aiguilles[aig].position];
    			cmdMonitExecute("AIG=" + aiguilles[aig].nom + "_" + aigPosLabelSh[aiguilles[aig].position]);
    		}
    	}
    }
     
    /*------------------------------------- Commande d'aiguille
    	   G1_D                     A1_G  A3_D         00_0 
    	�iguille G1 a droite  �iguille A1 a gauche  Inutilise
    */
    boolean aigCommande(String aigCmd, boolean aigCmdEcho)
    {
    	boolean aigExecOk = false;
     
    	aigCmdSelection(aigCmd);             // Selection des parametres de l'aiguille en fonction de la commande
                                             // dans la structure aigIu (aiguille in use)
    	if (aigIu.index != -1)               // Si aiguille trouvee
    	{
    		if (aigIu.tco == tcoLocal.pseudo)                             // Si commande locale
    		{
    			aigMouvement(aigIu, aigCmdEcho);
    			aigLedOnOff(aigIu, aigCmdEcho);
    		}
    		else
    		{
    			tcoSendCommand(aigIu.tco, "AIG=" + aigCmd);
    		}
    		aigExecOk = true;
    	} 
    	else
    	{
    		Serial.print(F("Commande; >> ")); Serial.print(aigCmd); Serial.println(F(" << Inconnue!!!"));
    	}
     
    	return aigExecOk;
    }
     
    /*------------------------------------- Index de l'aiguille
    	Selectionne une aiguille en fonction de la commande aiguille_parametre
    	G1 ou G1_D, recherche G1 dans le tableau aiguilles.nom[n]
    	retourne true si trouvee et renseigne 
    	aigIu.index (-1 si pas trouvee) et 
    	aigIu.motPosition (aigPosGauche , aigPosDroite ou aigPosNull)
    */
    void aigCmdSelection(String aigCmd)
    {
    	String aigName = "";
    	String aigParam = "";                                  // Ce qui est apres le separateur _
    	aigIu.index = -1;
     
    	aigCmd.toUpperCase();                                  // En majuscules
    	byte sepPos = aigCmd.indexOf("_");                     // Position du separateur _
     
    	if (sepPos)
    	{
    		aigName = aigCmd.substring(0, sepPos);             // On retire le _ et le parametre pour garder le nom
    		aigParam = aigCmd;
    		aigParam.replace(aigName + "_", "");               // On retire le nom et _ pour garder le parametre
    	} 
     
    	for (int aig = 0; aig < aigNombreMax; aig ++)          // Recherche si l'aiguille existe
    	{
    		if (aiguilles[aig].nom == aigName)
    		{
    			aigIu.index = aig;
    			aigIu.nom = aiguilles[aigIu.index].nom;
    			aigIu.tco = aiguilles[aigIu.index].Tco;
    			break;
    		}
    	}
     
    	if (aigParam == "G")
    	{	
    		aigIu.motPosLabelSh = "G";
    		aigIu.motPosLabel = "Gauche";
    		aigIu.motPosition = aigPosGauche;
    	} 
    	else if (aigParam == "D")
    	{	
    		aigIu.motPosLabelSh = "D";
    		aigIu.motPosLabel = "Droite";
    		aigIu.motPosition = aigPosDroite;
    	}
    	else
    	{	aigIu.motPosition = aigPosNull;}
    }
     
    /*------------------------------------- Aiguille mouvement 
    	parametres dans  structure aigIu
    */
    void aigMouvement(aigInUseDef aigMouv, boolean echoCmd)
    {
    	byte motAigPort = aiguilles[aigMouv.index].motGDport[aigMouv.motPosition];
     
    	digitalWrite(motAigPort, aigMotEtatOn);       // Moteur ON
    	delay(aigMotEtatOnTemps);
    	digitalWrite(motAigPort, !aigMotEtatOn);      // Moteur NOT ON
    	delay(aigMotEtatOnTemps);
     
    	if (echoCmd)
    	{
    		Serial.print(F("\tAiguille ")); Serial.println(aiguilles[aigMouv.index].nom + " " + aigMouv.motPosLabel);
    	}
    }
     
    //------------------------------------- Aiguille led On/Off
    void aigLedOnOff(aigInUseDef aigMouv, boolean echoCmd)
    {
    	int ledOnPort = aiguilles[aigMouv.index].ledGDport[aigMouv.motPosition];   // Led a allumer
    	int ledOffPort = 0;
     
    	if (aigMouv.motPosition == aigPosDroite)                                   // Quelle LED eteindre
    	{
    		ledOffPort = aiguilles[aigMouv.index].ledGDport[aigPosGauche];
    	} 
    	else
    	{
    		ledOffPort = aiguilles[aigMouv.index].ledGDport[aigPosDroite];
    	}
     
    	lpwmLedSet(ledOnPort, lpwmOn);		                   // LED allumee
    	lpwmLedSet(ledOffPort, !lpwmOn);		               // LED eteinte
     
    	if (echoCmd)
    	{
    		Serial.print(F("\t\tLED ")); Serial.println(String(ledOnPort) + "\t On");
    		Serial.print(F("\t\tLED ")); Serial.println(String(ledOffPort) + "\t Off");
    	}
    }
    //------------------------------------- Toutes les LED d'aiguilles eteintes
    void aigLedAllOff()
    {
    	for (int aig = 0; aig < aigNombreMax; aig ++)
    	{
    		for (int gd = 0; gd < 2; gd ++)
    		{
    			lpwmLedSet(aiguilles[aig].ledGDport[gd], !lpwmOn);		 // LED a eteindre
    		}
    	}
     
    }
    void aigLpwmInitialisation()
    {
    	SoftPWMBegin(lpwmPolarite);
    	SoftPWMSetFadeTime(ALL, 1800, 1800);
     
    	for (int aig = 0; aig < aigNombreMax; aig ++)
    	{
    		for (int gd = 0; gd < 2; gd ++)
    		{
    			SoftPWMSet(aiguilles[aig].ledGDport[gd], 0);
    		}
    	}
    }
     
    //===================================== Boutons poussoir (bp)
    void bpInitialisation()
    {
    	//--------------------------------- Initialisation des bp
    	for (int b = 0; b < bpNombreMax; b ++)
    	{
    		bpRead[b] = new Button(bpAig[b].port, 25, true, bpEtatPresseLOW);			// Port Antirebonds PULL_UP actif a LOW
    		bpRead[b]->begin();
    	}
    }
     
    /*------------------------------------- Commande de bp
    	   C1_V1 ou C2_V3....
    	   le syntaxe se trouve dans la structure bpAig[bpIndex].nom
    */
    boolean bpCommande(String bpCmd, boolean cmdEcho)
    {
    	boolean bpExecOk = false;
     
    	bpCmd.toUpperCase();
     
    	if (cmdEcho)
    	{
    		Serial.print(F("Commande bp ")); Serial.println(bpCmd);
    	}
     
    	for (int b = 0; b < bpNombreMax; b ++)                           // Balayage des bp
    	{
    		if (bpAig[b].nom == bpCmd)                                   // Si le nom du bp correspond
    		{
    //Serial.println(bpAig[b].Tco);
    			if (bpAig[b].TcoPseudo == tcoLocal.pseudo)                             // Si commande locale
    			{
    				bpMotAction(b, cmdEcho);
    			} 
    			else
    			{
    				tcoSendCommand(bpAig[b].TcoPseudo, "BP=" + bpCmd);
    			}
    			bpExecOk = true;
    		}
    	}
    	return bpExecOk;
    }
     
    //------------------------------------- Lecture de l'etat des bp
    bool bpScanStatus()
    {
    	boolean bpEvent = false;
     
    	for (int b = 0; b < bpNombreMax; b ++)                           // Balayage des bp
    	{
    		bpRead[b]->read();
    		if (bpRead[b]->wasPressed())
    		{
    			bpAig[b].bpOn = true;
    			bpEvent = true;
    		}
    	}
    	return bpEvent;
    }
     
    //------------------------------------- Si bp est presse, action
    void bpPressedAction()
    {
    	Serial.println(F("\t>>> Aiguillage <<<"));
    	aigLedAllOff();                                                  // Etaindre les LED
     
    	for (int b = 0; b < bpNombreMax; b ++)                           // Lister les boutons presses
    	{
    		if (bpAig[b].bpOn)                                           // Si ce bouton est presse
    		{
    			Serial.println(bpAig[b].nom);
    			bpCommande(bpAig[b].nom, cmdMonTrace);
    			//bpMotAction(b, true);
    			bpAig[b].bpOn = false;                                   // tache bp b terminee
    		}
    	}
    	Serial.println("");
    }
    //------------------------------------- Mise en action des aiguilles/moteur du bouton
    void bpMotAction(int bpIndex, boolean cmdEcho)
    {
    	for (int mot = 0; mot < bpMotNombreMax; mot ++)                            // Lister les commandes d'aiguilles concernes
    	{
    		if (bpAig[bpIndex].aig_Dir[mot] != "")
    		{
    			aigCommandOk = aigCommande(bpAig[bpIndex].aig_Dir[mot], cmdEcho);  // Encoi de la commande d'aiguillage
    		}
    	}
    }
    //===================================== LED pwm (lpwm)
    void lpwmLedSet(int ledIndex, boolean ledEtat)
    {
    	byte ledIntensite = ledEtat ? lpwmValeurOn : lpwmValeurOff;
     
    	SoftPWMSetFadeTime(ledIndex, lpwmTempsToOn, lpwmTempsToOff);
    	SoftPWMSet(ledIndex, ledIntensite);
    }
     
    //------------------------------------- Lpwm test
    void lpwmTest(String lpwmCmd)
    {
    	int ledIndex;
     
    	if (lpwmCmd.startsWith("A"))                 // Si c'est un port analogique (A0, A1 ...
    	{
    		lpwmCmd.replace("A", "");                // Enlever le A
    		ledIndex = lpwmCmd.toInt() + A0;         // Ajouter la valeur de A0 (14 pour le UNO et 54 pour le Mega)
    	}
    	else
    	{
    		ledIndex = lpwmCmd.toInt();
    	}
     
    	lpwmLedSet(ledIndex, lpwmOn);
    	delay(2000);
    	lpwmLedSet(ledIndex, !lpwmOn);
    }
     
    void lpwmTestAll(byte luminosite)
    {
    	for (int aig = 0; aig < aigNombreMax; aig ++)
    	{
    		for (int gd = 0; gd < 2; gd ++)
    		{
    			SoftPWMSetFadeTime(aiguilles[aig].ledGDport[gd], lpwmTempsToOn, lpwmTempsToOff);
    			SoftPWMSet(aiguilles[aig].ledGDport[gd], luminosite);
    		}
    	}
    }
    //===================================== Divers
     
    //===================================== Commandes moniteur
    /*
    	Traite les commandes recues via la ligne do commande (moniteur)
    	AIG=B1_G ou BP=C2_V3 commandes individuelles ou 
    	AIG=B1_D, AIG=B3_D,BP=C2_V3,AIG=B1_D commandes groupees separees par une virgule.
    	Les commandes ne sont pas sensibles aux majuscules ou minuscules.
    	Elles peuvent etre mises dans le programme sous la forme:
    	cmdMonitRecue("AIG=B3_D");	ou cmdMonitRecue("BP=C3_V3"); ou
    	cmdMonitRecue("BP=C1_V1,AIG=B3_D,BP=C3_V3");
    */
     
    void cmdMonitRecue(String cmdRx)
    {
    	String cmdExec = "";
     
    	cmdRx.toUpperCase();                                   // Tout en majuscules
    	cmdRx.replace(" ", "");                                // Supprimer les espaces
    	Serial.print(F("\nCommande moniteur:\t")); Serial.println(cmdRx);
     
    	while(cmdRx.indexOf(",") > 0)                          // Tant qu'il y a une virgule pour commande multiple
    	{
    		cmdExec = cmdRx.substring(0, cmdRx.indexOf(",") +1);
    		cmdMonitExecute(cmdExec);
    		cmdRx.replace(cmdExec, "");
    	}
    	if (cmdRx.length() > 3 || cmdRx == "?")                // S'il reste une commande dans la chaine cmdRx
    	{
    		cmdMonitExecute(cmdRx);
    	}
    }
    void cmdMonitExecute(String cmdExec)
    {
    	boolean cmdExecOk;
     
    	cmdExec.replace(",", "");                              // Supprimer les virgules
     
    	if (cmdExec== "?")                                     // Liste des commandes
    	{
    		cmdMonitHelp();
    		cmdExecOk = true;
    	}                                                     
    	else if (cmdMonitCheck(cmdExec, cmdMonitBp))                     // Bouton poussoir
    	{
    		aigLedAllOff();                                              // Etaindre les LED
    		cmdExecOk = bpCommande(cmdMonitRx.paramStr, cmdMonTrace);
    	}
    	else if (cmdMonitCheck(cmdExec, cmdMonitAig))                    // Aiguille       
    	{
    		cmdExecOk = aigCommande(cmdMonitRx.paramStr, cmdMonTrace);
    	}
    	else if (cmdMonitCheck(cmdExec, cmdMonitLpwmTest))               // LED PWM
    	{
    		lpwmTest(cmdMonitRx.paramStr);
    		cmdExecOk = true;
    	}
    	else if (cmdMonitCheck(cmdExec, cmdMonitLpwmTestAll))            // LED PWM toutes OFF
    	{
    		lpwmTestAll((byte)cmdMonitRx.paramInt);
    		cmdExecOk = true;
    	}
    	else if (cmdMonitCheck(cmdExec, cmdMonitCmdTrace))               // LED PWM toutes OFF
    	{
    		if (cmdMonitRx.paramInt > 0)
    		{
    			cmdMonTrace = true;
    		}
    		else
    		{
    			cmdMonTrace = false;
    		}
     
    		cmdExecOk = true;
    	}
    	else
    	{
    		cmdExecOk = false;
    	}
     
    	Serial.print("Execution de: " + cmdExec);
    	if (cmdExecOk)
    	{
    		Serial.println(F("   = OK"));
    	}
    	else
    	{
    		Serial.println(F("   = Commande inconnue !!!"));
    	}
    }
    	/*---------------------------------------------------------------------------------------------------------------------- 
    	  Controle la commande recue
    	  retourne true si OK ou false si pas 
    	  Met les parametres de la commande dans la structure cmdMoniteurRx, le nom = ! si pas reconnue
    	  ----------------------------------------------------------------------------------------------------------------------
    	*/
    boolean cmdMonitCheck(String cmdMonRx, int cmdMonIndex)
    {
    	bool cmdCheckOk;
     
    	String cmdCheck = (String)cmdMonitSyntax[cmdMonIndex]+ "=";
    	if (cmdMonRx.startsWith(cmdCheck))
    	{
    		cmdMonitRx.nom = (String)cmdMonitSyntax[cmdMonIndex];
    		cmdMonRx.replace(cmdCheck, "");                               // Garder que le ou les parametres
     
    		cmdMonitRx.paramStr = cmdMonRx;
    		cmdMonitRx.paramInt = cmdMonRx.toInt();
    		cmdMonitRx.paramFl = cmdMonRx.toFloat();
     
    		cmdCheckOk = true;
    	}
    	else
    	{
    		cmdMonitRx.nom = "!";
     
    		cmdCheckOk = false;
    	}
    	return cmdCheckOk;	
    }
     
    void cmdMonitHelp()
    {
    	Serial.print(F("\n\t> > > Liste des commandes < < <  Prog. vers. ")); Serial.println((String)progrVersion);
    	Serial.println(F("?"));
     
    	for (int cm = 0; cm < cmdMonitNombre; cm ++)
    	{
    		Serial.print(cmdMonitSyntax[cm]); Serial.println("=");
    	}
    	Serial.println("");
    }
     
    //===================================== Ecoute du port serie
    void serialEvent()                                                   // IDE monitor or DRO serial
    {
    	while (Serial.available())
    	{
    		char monChar = (char)Serial.read();                          // Char received from IDE monitor
    		if (monChar == '\n')                                         // If new line char received = end of command line
    		{
    			monCommandNew  = true;
    		}
    		else
    		{
    			if (monChar >= ' ') {monCommandRx += monChar;}           // >= ' ' to avoid not wanted ctrl char.
    		}
    	}
    }
    et des exemples de tableaux AIG et BP du tcoGare:
    Train_Tabl_tcoGare_BP.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    	// Nom du fichier : Train_Tabl_tcoGare_BP.h
    	// modifie le 16/10/2020 a* 11h30
    //===================================== Boutons poussoirs (bp) TCO Gare
    bpAigDefinition bpAig[] =
    {
    	// Nom,     TCO,  Port, presse, aigCmd1, aigCmd2, aigCmd3, aigCmd4, aigCmd5,
    	{"C1_V1",  "GARE",  5,   false, "G1_D",  "A1_G",  "A3_D", "G2_G",      ""},
    	{"C1_V2",  "GARE",  6,   false, "G1_D",  "A1_D",  "A4_D",     "",      ""},
    	{"C2_V1",  "GARE",  7,   false, "B1_G",  "B3_D",  "A2_G", "A3_G",  "G2_G"},
    	{"C2_V2",  "GARE",  8,   false, "B1_G",  "B3_D",  "A2_D", "A4_G",      ""},
    	{"C2_V3",  "GARE",  9,   false, "B1_D",  "B4_D",      "",     "",      ""},
    	{"C3_V1",  "GARE", 10,   false, "B2_G",  "B3_G",  "A2_G", "A3_G",  "G2_G"},
    	{"C3_V2",  "GARE", 11,   false, "B2_G",  "B3_G",  "A2_D", "A4_G",      ""},
    	{"C3_V3",  "GARE", 12,   false, "B2_D",  "B4_G",      "",     "",      ""},
    	{"C1_T6",  "TRIEN", 2,   false, "",  "",      "",     "",      ""},
    	{"T6_ST",  "TRISO", 3,   false, "",  "",      "",     "",      ""},
    };
     
    //------------------------------------- Position initiale des bp tcoGare Si pas de commande mettre -
    #define tcoBoPositionInitiale "BP=C1_V1,BP=C2_V2,BP=C3_V3"
    //#define tcoBoPositionInitiale "-"  // Pour pas d'initialisation
    et Train_Tabl_tcoGare_AIG.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    	// Position donne la position de l'aiguille au demarrage du programme
    	// NOM du fichier : Train_Tabl_tcoTriageS_AIG.h
    	// modifie le 16/10/2020 a* 11h30
    aiguilleDefinition aiguilles[] =
    {
    	//Nom,    TCO,    Position,  Moteur G, Moteur D, Led G, LED D   255 = port inutilise
    	{"G1",  "GARE", aigPosDroite, 255,       22,       41,   42},
    	{"G2",  "GARE", aigPosGauche,  23,       24,       43,   44},
    	{"A1",  "GARE", aigPosGauche,  25,       26,       45,   46},
    	{"A2",  "GARE", aigPosDroite,  27,       28,       47,   48},
    	{"A3",  "GARE", aigPosGauche,  29,       30,       49,   50},
    	{"A4",  "GARE", aigPosDroite,  31,       32,       51,   52},
    	{"B1",  "GARE", aigPosDroite,  33,       34,       53,   A8},
    	{"B2",  "GARE", aigPosDroite,  35,       36,       A9,  A10},
    	{"B3",  "GARE", aigPosDroite,  37,       38,      A11,  A12},
    	{"B4",  "GARE", aigPosDroite,  39,       40,      A13,  A14},
    };
    Pour programmer chaque TCO, lire l'explication, au début du programme, sous:
    //===================================== Selection du TCO pour sa programmation

    Je te donne tout ça à "digérer", il faut que je fasse une pause de 2 ou 3 jours afin de terminer un autre programme.
    Au retour je testerai un ou 2 façon de commander les moteurs d'aiguilles.

    Je te mets, en PJ, un ZIP avec tout les fichiers, j'ai mis les tiens aux nouveaux "standards" du programme.

    A+, bonne soirée et bon week-end
    Cordialement
    jpbbricole
    Fichiers attachés Fichiers attachés
    L'expérience est la seule chose qu'il ne faut acheter que d'occasion!

  16. #236
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 711
    Points : 5 390
    Points
    5 390
    Par défaut
    Citation Envoyé par Jsiorat Voir le message
    Voila l'exemple...
    Ah ça vient de cet exemple je suppose

    Si vous regardez il y a deux fichiers .ino dans ce répertoire et l’auteur suggère deux approches. Comme on ne peut pas avoir deux setup et deux loop il propose de commenter un des deux code, comme indiqué au début du code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     an alternative approach.   swap the #if 1 / 0 values to try it

  17. #237
    Membre habitué
    Avatar de Jsiorat
    Homme Profil pro
    RETRAITE
    Inscrit en
    Juillet 2005
    Messages
    398
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Ariège (Midi Pyrénées)

    Informations professionnelles :
    Activité : RETRAITE

    Informations forums :
    Inscription : Juillet 2005
    Messages : 398
    Points : 169
    Points
    169
    Par défaut
    Merci Jay,

    je commence à comprendre certaines subtilités de code !
    Il faut être intelligent (ce qui n'est pas mon cas ! ) pour programmer ce type de codage.

    Bon WE, JP m'a donné du travail pour aujourd'hui et très certainement pour demain aussi

    Cordialement, Jacques
    Être vieux, c'est être jeune depuis plus longtemps que les autres !

  18. #238
    Membre habitué
    Avatar de Jsiorat
    Homme Profil pro
    RETRAITE
    Inscrit en
    Juillet 2005
    Messages
    398
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Ariège (Midi Pyrénées)

    Informations professionnelles :
    Activité : RETRAITE

    Informations forums :
    Inscription : Juillet 2005
    Messages : 398
    Points : 169
    Points
    169
    Par défaut
    Citation Envoyé par jpbbricole Voir le message
    Bonsoir Jacques

    Voilà la première mouture de la gestion multi TCO.
    Salut JP,

    si j'ai bien compris, LE code est à implanter sur chaque carte en tenant compte de "Selection des parametres propre au TCO" ...

    Je vais donc procéder au câblage complet des breakboard boutons et LEDs de TCO pendant le WE.

    Bon WE, A+, Jacques
    Être vieux, c'est être jeune depuis plus longtemps que les autres !

  19. #239
    Membre émérite
    Avatar de jpbbricole
    Homme Profil pro
    Retraité des réseaux informatiques
    Inscrit en
    Février 2013
    Messages
    1 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Retraité des réseaux informatiques
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Février 2013
    Messages : 1 012
    Points : 2 341
    Points
    2 341
    Par défaut
    Salut Jacques

    Citation Envoyé par Jsiorat Voir le message
    si j'ai bien compris, LE code est à implanter sur chaque carte en tenant compte de "Selection des parametres propre au TCO" ...
    Oui, l'essentiel se passe ici:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    /*===================================== Selection du TCO pour sa programmation
    	Pour programmer un TCO, connecter le port Serial de l'Arduino
    	Enlever la remarque (//) de devant le _tcoXxxxxx
    	Mettre la remarque  (//) devant les autres.
    	Renseigner, si necessaire, sous Selection des parametres propre au TCO, ci dessous
    	Il ne doit avoir qu'un TCO sans remarque, celui que l'on veur programmer
    	Télécharger le programme
    */
     
    #define _tcoGare
    //#define _tcoTriageEntree
    //#define _tcoTriageSortie
    C'est seulement si ti changes le nombre le nombre de aigCmdn dans un fichier *_BP.h qu'il faut réajuster ici:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    //------------------------------------- Selection des parametres propre au TCO
    #ifdef _tcoGare
    	#define tcoLocalIndex tcoIndexGare
    	#define tcoRoleInNet tcoRoleMaster
    	#define bpMotNombreMax 5			// Nombre de moteurs max par bouton dans *_BP.h
    #endif
    #ifdef _tcoTriageEntree
    	#define bpMotNombreMax 8			// Nombre de moteurs max par bouton dans *_BP.h
    	#define tcoLocalIndex tcoIndexTriageEntree
    	#define tcoRoleInNet tcoRoleSlave
    #endif
    #ifdef _tcoTriageSortie
    	#define tcoLocalIndex tcoIndexTriageSortie
    	#define tcoRoleInNet tcoRoleSlave
    	#define bpMotNombreMax 7			// Nombre de moteurs max par bouton dans *_BP.h
    #endif
    A+
    Cordialement
    jpbbricole
    L'expérience est la seule chose qu'il ne faut acheter que d'occasion!

  20. #240
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 711
    Points : 5 390
    Points
    5 390
    Par défaut
    @JP

    Salut

    beau boulot pour le multi TCO.

    Quelques suggestions constructives si je peux me permettre:

    vous avez un ligne 71 du code, je ne pense pas que ce soit nécessaire.

    vous pourriez conserver dans la struct tcoDefinition le port série associé à un TCO et créer dans le code en dur le tableau de tous les TCOs.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    struct tcoDefinition
    {
      int localIndex; // n'est plus vraiment nécessaire, ce sera l'index dans le tableau
      const char* nom;
      const char* pseudo;
      byte roleInNet;
      Stream* portSerie; // Stream permet de mettre un HardwareSerial ou SoftwareSerial
    };
    
    // définition de nos TCO
    tcoDefinition TCO[] = {
      {0, "Gare", "GARE", tcoRoleMaster, &Serial},
      {1, "Triage Entree", "GARE", tcoRoleMaster, &Serial1},
      {2, "Triage Sortie", "TRIEN", tcoRoleSlave, &Serial2},
      //{3, "futur", "FUTUR", tcoRoleSlave, &Serial3}, // pas utilisé pour le moment
    };
    const byte tcoNombre = sizeof TCO / sizeof TCO[0];
    la définition relative à un TCO devient alors simplement la définition du tcoLocalIndex
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    //------------------------------------- Selection des parametres propre au TCO
    #ifdef _tcoGare
    #define tcoLocalIndex tcoIndexGare
    #endif
     
    #ifdef _tcoTriageEntree
    #define tcoLocalIndex tcoIndexTriageEntree
    #endif
     
    #ifdef _tcoTriageSortie
    #define tcoLocalIndex tcoIndexTriageSortie
    #endif
    Je suggère aussi de mettre bpMotNombreMax dans l'include plutôt que le corps du programme principal.

    Comme ça tous les TCO se connaissent entre eux (en prévision d'une discussion bidirectionnelle future TCO <--> TCO) et au lieu de calculer dynamiquement avec des String quel est le tcoLocal ou tcoDistant, vous n'avez plus qu'à extraire un indice dans ce tableau pour avoir accès aux informations relatives à ce TCO
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    byte tcoLocal = tcoLocalIndex; // plus vraiment utile on peut utiliser directement tcoLocalIndex
    byte tcoDistant; // maintenant c'est juste un octet, l'indice dans le tableau TCO
    Pour envoyer une communication directement au tcoDistant on connait son port Série en regardant dans la structure et donc on peut faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TCO[tcoDistant].portSerie->println(tcoCommand);
    De manière générale ça vous permet de travailler ainsi par indice dans un tableau plutôt que par comparaison de String.

    of course, ce n'est qu'une suggestion.

Discussions similaires

  1. Requête pour effectuer une comparaison entre deux dates
    Par ktm26 dans le forum Langage SQL
    Réponses: 2
    Dernier message: 26/04/2017, 08h49
  2. Effectue une soustraction entre deux dates
    Par messi1987 dans le forum Développement
    Réponses: 2
    Dernier message: 05/03/2015, 14h22
  3. [XL-2003] Faire une liaison entre deux tableaux sur 2 classeurs différents
    Par Katell dans le forum Conception
    Réponses: 1
    Dernier message: 22/01/2015, 18h04
  4. implementer une association entre deux classes uml en java
    Par tabbabi dans le forum Persistance des données
    Réponses: 8
    Dernier message: 19/04/2011, 19h39
  5. Réponses: 1
    Dernier message: 11/06/2009, 23h39

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo