Auteur Sujet: Les SATELLITES AUTONOMES : Une solution simple pour la gestion de réseaux.  (Lu 51115 fois)

rNe

  • Newbie
  • *
  • Messages: 48
    • Voir le profil
    • Le blog à René
Re : Les SATELLITES AUTONOMES : Une solution simple pour la gestion de réseaux.
« Réponse #135 le: août 28, 2024, 02:18:41 pm »
Bonjour theodami
Bienvenue dans le monde des satellites autonomes

Avant toute chose il est bon de vous assurer de la (non/)conformité du PCB; car j'ignore à quel moment vous avez téléchargé les fichiers GERBER.
Pour cela un ohm-mètre suffit :
Enlever l'ESP32 de son support
Vérifier la continuité entre la broche Signal du servo 0 et le port IO19 de l'ESP32
Vérifier la continuité entre la broche Signal du servo 2 et le port IO2 de l'ESP32
Si cette vérification est correcte vous avez le bon PCB. Vous n'avez aucune modification à apporter.
Si les liaisons entre ces deux servos et les port de l'ESP sont inversées, alors il suffit de modifier le fichier config.h, tout en bas du fichier :
Au lieu de lire #define AIG_PIN_SIGNAL_0 GPIO_NUM_19 modifier par #define AIG_PIN_SIGNAL_0 GPIO_NUM_2
Au lieu de lire #define AIG_PIN_SIGNAL_2 GPIO_NUM_2 modifier par #define AIG_PIN_SIGNAL_0 GPIO_NUM_19
Ceci afin que la sérigraphie du PCB soit juste.

Autre solution, plus pragmatique, inverser le raccordement des servos 0 et 2 et se rappeler que la sérigraphie est inexacte...

Mais en aucun cas (config.h modifié ou non) le fonctionnement du satellite est altéré.

Surtout avant de sauter sur le clavier pour faire des modifications assurez vous de la conformité du PCB par rapport au schéma de principe actuel (celui qui est maintenant en ligne) et éventuellement identifiez exactement les écarts...
Enfin, et pour bien appréhender le fonctionnement des satellites autonomes je vous encourage à relire la série d'articles les présentant sur le site éditorial.
Cordialement

L'expérience a ceci d'étrange : elle ressemble aux cure-dents - personne veut s'en servir après vous...

theodami

  • Newbie
  • *
  • Messages: 3
    • Voir le profil
Re : Les SATELLITES AUTONOMES : Une solution simple pour la gestion de réseaux.
« Réponse #136 le: août 28, 2024, 04:36:00 pm »
Bonsoir,

J'ai bien la mauvaise version. Merci pour les solutions.

Christophe.

bobyAndCo

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1049
  • HO avec DCC++
    • Voir le profil
Re : Les SATELLITES AUTONOMES : Une solution simple pour la gestion de réseaux.
« Réponse #137 le: août 29, 2024, 07:28:20 am »
J'ai déplacé ici le post de phenixpopol  car il concerne les satellites autonomes :

Bonjour Christophe et merci pour la réponse,
J’ai essayé de comprendre le bus CAN car je m’intéresse aux satellites et j’avoue que malgré plusieurs lectures de tes différents articles sur les satellites autonomes, je ne comprends pas grand-chose. J’ai vu ’il y a quelques mois sur le forum que LocoFred avait essayé de démarrer les satellites autonomes, il me semblait aussi perdu que moi. Ou en est-il ?
Pour l’instant, j’ai un réseau que j’ai cantonné, Je commande mes locomotives par « la box » soit en WI FI par une tablette avec l’application Z21 ou, je trouve que c’est plus commode par une ou plusieurs manettes avec des HC12.
Mes aiguillages ont des micro moteurs MP5 de chez mtb-model avec retour d’info, que je commande manuellement.
J’attends la nouvelle box pour avoir un cut out et la possibilité d’utiliser rail com. Pour l’instant j’ai « bricolé » des détecteurs de présence.
Je vais un peu dans tous les sens et je ne sais pas par ou prendre le problème pour arriver à installer les satellites autonomes et j’ai du mal à voir la relation entre les satellites et les commandes DCC des locos.
En résumé, j’ai besoin d’une marche à suivre ; Dois-je commencer par un TCO alors que théoriquement les satellites peuvent s’en passer ? L’automne arrivant, je vais avoir du temps pour travailler !

phenixpopol

  • Newbie
  • *
  • Messages: 23
    • Voir le profil
Re : Les SATELLITES AUTONOMES : Une solution simple pour la gestion de réseaux.
« Réponse #138 le: août 29, 2024, 10:34:56 am »
Suite du post précédent :
Bonjour Christophe,
Je vais essayer d’expliciter mes problèmes à l’aide la vidéo qui illustre l’article «  les satellites autonomes (1) « .
D’où vient la trame DCC de la loco 1 qui démarre la séquence.
J’ai bien compris que le satellite détecte l’occupation du canton et l’adresse de la loco 1 ; Comment et sous quelle forme renvoie-t-il l’information qui ralenti et arrête cette loco.
En résumé, ce qui me pose problème c’est la relation entre les satellites et la centrale DCC, d’où mon intérêt pour le bus CAN, j’ai hâte de voir les relations entre les satellites et la future box qui intégrera le CAN.
Cordialement.

bobyAndCo

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1049
  • HO avec DCC++
    • Voir le profil
Re : Les SATELLITES AUTONOMES : Une solution simple pour la gestion de réseaux.
« Réponse #139 le: août 29, 2024, 10:48:26 am »
Ok, je comprends mieux.

Je suppose que ce que tu appelles "la trame DCC" est en fait l'adresse de la locomotive, c'est bien cela ?

A chaque satellite est-associé une carte Railcom. Cette carte lit donc l'adresse de la locomotive et en fonction de l'état des satellites environnants actionne la signalisation qui va bien et adresse les ordres à la centrale pour la locomotive du canton.

C'est du code que l'utilisateur n'a pas normalement pas besoin de connaitre et l'on comprendra facilement pourquoi à la simple lecture, mais puisque tu me le demandes, c'est dans le fichier GestionReseau.cpp à partir de la ligne 264 : https://github.com/BOBILLEChristophe/Satellites_autonomes_client/blob/main/src/GestionReseau.cpp

Je répète bien que, heureusement pour l'utilisateur, il n'a pas besoin de comprendre ce code !!!


if (node->nodeP[index] != nullptr)
            {
                if (node->nodeP[index]->acces()) // Le canton SP1/SM1 est accessible
                {
                    // debug.printf("[GestionReseau %d] Le canton %s est accessible\n", __LINE__, cantonName);
                    if (node->nodeP[index]->busy()) // Le canton SP1/SM1 est occupé
                    {
                        // debug.printf("[GestionReseau %d] Le canton %s est accessible mais occupe\n", __LINE__, cantonName);
                        signalValue[i] = Rouge;
                    }
                    else // Le canton SP1/SM1 est accessible et libre
                    {
                        // debug.printf("[GestionReseau %d] Le canton %s est accessible et libre\n", __LINE__, cantonName);
                        signalValue[i] = Vert;

                        if (access) // Le canton SP2 est-il accessible ?
                        {
                            // debug.printf("[GestionReseau %d] SP2 accessible\n", __LINE__);
                            if (busy) // Le canton SP2 est-il occupé ?
                            {
                                // debug.printf("[GestionReseau %d] SP2 occupe\n", __LINE__);
                                signalValue[i] = Ralentissement;
                            }
                            else // Le canton SP2 n'est pas occupé
                            {
                                // debug.printf("[GestionReseau %d] SP2 libre\n", __LINE__);
                                signalValue[i] = Vert;
                            }
                        }
                        else // Le canton SP2 n'est pas accessible
                        {
                            // debug.printf("[GestionReseau %d] SP2 non accessible\n", __LINE__);
                            signalValue[i] = Ralentissement;
                        }
                    }
                }
                else // Le canton SP1/SM1 est n'est pas accessible
                {
                    // debug.printf("[GestionReseau %d] Le canton %s n'est pas accessible\n", __LINE__, cantonName);
                    signalValue[i] = Carre;
                }
            }
            else // Le canton SP1/SM1 n'existe pas
            {
                // debug.printf("[GestionReseau %d] Le canton %s n'existe pas\n", __LINE__, cantonName);
                signalValue[i] = Carre;
            }

            // debug.printf("[GestionReseau %d] node->loco.sens() %d\n", __LINE__, node->loco.sens());

            switch (signalValue[i])
            {
            case Carre:
            case Rouge:
                if (node->sensor[sens0].state())
                    node->loco.stop();
                else if (node->sensor[sens1].state())
                    node->loco.speed(30);
                break;
            case Ralentissement:

                break;
            }
        }

        // Envoi des commandes à la loco
        if (node->loco.address() > 0)
        {
            // if (node->loco.address() != oldLocAddress || node->loco.speed() != oldLocSpeed || node->loco.sens() != oldLocSens)
            if (node->loco.speed() != oldLocSpeed)
                comptCmdLoco = 0;

            if (comptCmdLoco < 5)
            {
                CanMsg::sendMsg(1, 0xF0, node->ID(), CENTRALE_DCC_ID, 0,
                                (node->loco.address() & 0xFF00) >> 8,
                                node->loco.address() & 0x00FF,
                                node->loco.speed(),
                                node->loco.sens()); // Message à la centrale DCC++
#ifdef debug
                debug.printf("[GestionReseau %d] Loco %d vitesse %d\n", __LINE__, node->loco.address(), node->loco.speed());
#endif

« Modifié: août 29, 2024, 11:01:05 am par bobyAndCo »

bobyAndCo

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1049
  • HO avec DCC++
    • Voir le profil
Re : Les SATELLITES AUTONOMES : Une solution simple pour la gestion de réseaux.
« Réponse #140 le: août 29, 2024, 10:58:22 am »
Le message CAN, ordre adressé à la locomotive vu dans le code précédent, est reçu par la centrale (laBox) dans le fichier CanMarklin que Thierry a justement ajouté et qui agit sur la centrale laBox.

Voici le code côté centrale (dont je ne garanti pas non plus une compréhension aisée !)


/*

  CanMsg.cpp

 */

#include "CanMarklin.h"

#ifdef ENABLE_CANMARKLIN

// - Config, voir lignes 184 à 186 de config.h
gpio_num_t CanMarklin::RxPin = GPIO_NUM_4;
gpio_num_t CanMarklin::TxPin = GPIO_NUM_5;
uint32_t CanMarklin::DESIRED_BIT_RATE = 1000ul * 1000ul;
uint8_t CanMarklin::thisId = 100;
bool CanMarklin::SendCommands = false;

uint8_t CanMarklin::getId() { return thisId; }

QueueHandle_t xQueue; // Queue pour stocker les messages retour

/************************************************************************
Retour de LaBox pour les commandes de traction, la fonction emergency stop
la fonction power on / power off et plus generalement par la suite, toutes
les fonctions qui emettent une confirmation dans DCC-Ex
*************************************************************************/

void ackTask(void *pvParameters)
{
  BaseType_t status;
  CANMessage frame;
  //frame.ext = true;

  for (;;)
  {
    status = xQueueReceive(xQueue, &frame, pdMS_TO_TICKS(100));
    if (status == pdPASS)
    {
      frame.id &= ~ 0x18000000;
      frame.id |= 3 << 27;               // Priorite 0, 1, 2 ou 3
      frame.id &= ~ 0x7F800;
      frame.id |= CanMarklin::getId() << 11; // ID expediteur
      frame.id &= ~ 0x04;
      frame.id |= 1 << 2;                // Réponse
      CanMarklin::sendMsg(frame);
    }
    vTaskDelay(pdMS_TO_TICKS(100));
  }
}

void CanMarklin::begin()
{
DIAG(F("Configure ESP32 CAN"));

if (DESIRED_BIT_RATE < 1000000UL)
DIAG(F("CAN id = %d  Bitrate = %d Kb/s  CANH:%d  CANL:%d"), thisId, DESIRED_BIT_RATE / 1000UL, RxPin, TxPin);
else
DIAG(F("CAN id = %d  Bitrate = %d Mb/s  CANH:%d  CANL:%d"), thisId, DESIRED_BIT_RATE / 1000000UL, RxPin, TxPin);

  ACAN_ESP32_Settings settings(DESIRED_BIT_RATE);
  settings.mRxPin = RxPin;
  settings.mTxPin = TxPin;

  uint32_t errorCode;

  // with filter
  const ACAN_ESP32_Filter filter = ACAN_ESP32_Filter::singleExtendedFilter(
      ACAN_ESP32_Filter::data, 0xF << 23, 0x187FFFFB);
  errorCode = ACAN_ESP32::can.begin(settings, filter);

  // without filter
  //errorCode = ACAN_ESP32::can.begin(settings);
  //Serial.printf("[CanMsg %d] : config without filter\n", __LINE__);

  if (errorCode == 0)
    DIAG(F("CAN Configuration OK !"));
  else
  {
    DIAG(F("CAN Configuration error 0x%x"), errorCode);
    return;
  }
  xQueue = xQueueCreate(50, sizeof(CANMessage));
  xTaskCreate(ackTask, "ackTask", 2 * 1024, NULL, 0, NULL);
}

/*--------------------------------------
  Reception CAN
  --------------------------------------*/

void CanMarklin::loop()
{
  CANMessage frameIn;
  if (ACAN_ESP32::can.receive(frameIn))
  {
    const uint8_t cmde = (frameIn.id & 0x7F80000) >> 19; // Commande
    const uint8_t exped = (frameIn.id & 0x7F800) >> 11;  // Expéditeur
    const uint8_t resp = (frameIn.id & 0x04) >> 2;       // Commande = 0 / Reponse = 1

    char cmdName[20];
    switch(cmde)
    {
      case CAN_LOCO_THROTTLE:        strcpy(cmdName, "Loco Throttle");        break;
      case CAN_LOCO_FUNCTION:        strcpy(cmdName, "Loco Function");        break;
      case CAN_LOCO_WRITECV_MAIN:    strcpy(cmdName, "Loco WriteCv main");    break;
      case CAN_POWERON:              strcpy(cmdName, "Power");                break;
      case CAN_EMERGENCY_STOP:       strcpy(cmdName, "Emergency Stop");       break;
    }

    if (Diag::CANDIAG) DIAG(F("[CanMarklin]------ Sender %d : Command 0x%0X %s"), exped, cmde, cmdName);

    if (frameIn.rtr) // Remote frame
      ACAN_ESP32::can.tryToSend(frameIn);
    else
    {
      uint16_t loco = 0;
      if (cmde < CAN_FIRST_NOTLOCO_COMMAND)
        loco = (frameIn.data[0] << 8) + frameIn.data[1];

      switch (cmde) // Fonction appelée
      {
      case CAN_LOCO_THROTTLE:
        DCC::setThrottle(loco, frameIn.data[2], frameIn.data[3]);
        xQueueSendToBack(xQueue, &frameIn, 0);
        break;
      case CAN_LOCO_FUNCTION:
        DCC::setFn(loco, frameIn.data[2], frameIn.data[3]); // frame.data[2] = fonction, frame.data[3] : 'on' ou 'off'
        break;
      case CAN_LOCO_WRITECV_MAIN:
        // WRITE CV on MAIN <w CAB CV VALUE>
        DCC::writeCVByteMain(loco, frameIn.data[2], frameIn.data[3]);
        break;
      case CAN_POWERON:
        TrackManager::setMainPower(frameIn.data[0] ? POWERMODE::ON : POWERMODE::OFF);
        xQueueSendToBack(xQueue, &frameIn, 0);
        break;
      case CAN_EMERGENCY_STOP:
        DCC::setThrottle(0, 1, 1); // emergency stop
        xQueueSendToBack(xQueue, &frameIn, 0);
        break;
      }
    }
  }

  /*--------------------------------------
    Envoi mesure de courant
    --------------------------------------*/
// #define MESURE_COURANT
#ifdef MESURE_COURANT
  static uint64_t millisRefreshData = 0;
  if (millis() - millisRefreshData > 1000)
  {
    CANMessage frameOut;
    MotorDriver *mainDriver = NULL;
    for (const auto &md : TrackManager::getMainDrivers())
      mainDriver = md;
    if (mainDriver == NULL || !mainDriver->canMeasureCurrent())
      return;

    POWERMODE mode = TrackManager::getMainPower();
    if (mode == POWERMODE::ON)
    {
      uint16_t current = mainDriver->getCurrentRaw();
      sendMsg(0, 0xFD, CanMsg::getId(), 0, 1, (current & 0xFF00) >> 8, current & 0x00FF);
    }
    else if (mode == POWERMODE::OVERLOAD)
      sendMsg(0, 0xFD, CanMsg::getId(), 0, 1, 2);
    else
      sendMsg(0, 0xFD, CanMsg::getId(), 0, 1, 0);
    millisRefreshData = millis();
  }
#endif
}

void CanMarklin::setPower(bool isOn)
{
    CanMarklin::sendMsg(2, CAN_POWERON, CanMarklin::getId(), thisId, 0, isOn);
}

void CanMarklin::setThrottle(uint16_t cab, uint8_t tSpeed, bool tDirection)
{
if (tSpeed == 1) // Emergency_stop !
CanMarklin::emergency();
else
    CanMarklin::sendMsg(2, CAN_LOCO_THROTTLE, CanMarklin::getId(), thisId, 0, (cab & 0xFF00) >> 8, cab & 0x00FF, tSpeed, tDirection);
}

void CanMarklin::setFunction(int cab, int16_t functionNumber, bool on)
{
    CanMarklin::sendMsg(2, CAN_LOCO_FUNCTION, CanMarklin::getId(), thisId, 0, (cab & 0xFF00) >> 8, cab & 0x00FF, functionNumber, on);
}

void CanMarklin::emergency()
{
    CanMarklin::sendMsg(0, CAN_EMERGENCY_STOP, CanMarklin::getId(), thisId, 0);
}

/*--------------------------------------
  Envoi CAN
  --------------------------------------*/

void CanMarklin::sendMsg(CANMessage &frame)
{
  if (0 == ACAN_ESP32::can.tryToSend(frame))
    DIAG(F("[CanMarklin]------ Send error"));
}

auto formatMsg = [](CANMessage &frame, byte prio, byte cmde, byte thisNodeId, byte destNodeId, byte resp) -> CANMessage
{
  frame.id |= prio << 27;       // Priorite 0, 1, 2 ou 3
  frame.id |= cmde << 19;       // commande appelée
  frame.id |= thisNodeId << 11; // ID expediteur
  frame.id |= destNodeId << 3;  // ID destinataire
  frame.id |= resp << 2;        // Réponse
  frame.ext = true;
  return frame;
};

void CanMarklin::sendMsg(byte prio, byte cmde, byte thisNodeId, byte destNodeId, byte resp)
{
  CANMessage frame;
  frame = formatMsg(frame, prio, cmde, thisNodeId, destNodeId, resp);
  frame.len = 0;
  CanMarklin::sendMsg(frame);
}

void CanMarklin::sendMsg(byte prio, byte cmde, byte thisNodeId, byte destNodeId, byte resp, byte data0)
{
  CANMessage frame;
  frame = formatMsg(frame, prio, cmde, thisNodeId, destNodeId, resp);
  frame.len = 1;
  frame.data[0] = data0;
  CanMarklin::sendMsg(frame);
}

void CanMarklin::sendMsg(byte prio, byte cmde, byte thisNodeId, byte destNodeId, byte resp, byte data0, byte data1)
{
  CANMessage frame;
  frame = formatMsg(frame, prio, cmde, thisNodeId, destNodeId, resp);
  frame.len = 2;
  frame.data[0] = data0;
  frame.data[1] = data1;
  CanMarklin::sendMsg(frame);
}

void CanMarklin::sendMsg(byte prio, byte cmde, byte thisNodeId, byte destNodeId, byte resp, byte data0, byte data1, byte data2)
{
  CANMessage frame;
  frame = formatMsg(frame, prio, cmde, thisNodeId, destNodeId, resp);
  frame.len = 3;
  frame.data[0] = data0;
  frame.data[1] = data1;
  frame.data[2] = data2;
  CanMarklin::sendMsg(frame);
}

void CanMarklin::sendMsg(byte prio, byte cmde, byte thisNodeId, byte destNodeId, byte resp, byte data0, byte data1, byte data2, byte data3)
{
  CANMessage frame;
  frame = formatMsg(frame, prio, cmde, thisNodeId, destNodeId, resp);
  frame.len = 4;
  frame.data[0] = data0;
  frame.data[1] = data1;
  frame.data[2] = data2;
  frame.data[3] = data3;
  CanMarklin::sendMsg(frame);
}
#endif

phenixpopol

  • Newbie
  • *
  • Messages: 23
    • Voir le profil
Re : Les SATELLITES AUTONOMES : Une solution simple pour la gestion de réseaux.
« Réponse #141 le: août 29, 2024, 12:01:28 pm »
Merci des 2 réponses :
Préambule : J’aime bien comprendre et réécrire du code pour faire des applications simplifiées, mais là, je crois que ce ne sera pas possible.
Sous réserve d’approfondissement voila ce que j’ai compris :
Au niveau du satellite, il recueille 2 types d’informations ; l’adresse de la loco et l’état du canton suivant qui peut être  (schématiquement) rouge vert ou ralenti. Le satellite envoie un message CAN à la box qui est : l’adresse, la vitesse ( idem, ralenti à 30 ou stop) et le sens.
Au niveau de la box :
Réception du message CAN après filtre, renvoi d’un message CAN dont pour l’instant je ne vois pas l’utilité et envoi d’un ordre DCC à la loco de type <t1 8 30 1> pour un ralentissement.
Je crois que je progresse. Pour l’instant je vérifie mes cantons, je fais un plan et étudie le système découverte. Ensuite réalisation de la nouvelle box puis des cartes satellites lorsque les PCB seront sortis définitivement. Je te tiens au courant et j’aurais sûrement besoin d’autres conseils.
Cordialement.

bobyAndCo

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1049
  • HO avec DCC++
    • Voir le profil
Re : Les SATELLITES AUTONOMES : Une solution simple pour la gestion de réseaux.
« Réponse #142 le: août 29, 2024, 12:59:53 pm »
Oui tu as bien compris le principe général.

Au niveau du satellite, il recueille 2 types d’informations ; l’adresse de la loco et l’état du canton suivant qui peut être  (schématiquement) rouge vert ou ralenti.

Très exactement, et cela est possible grâce au CAN, le satellite envoie toutes les 100 ms ses propres informations et reçoit des informations de ses satellites voisins (occupé, libre) mais aussi les voisins de ses voisins il peut déduire le comportement de la signalisation et des locomotives et donc effectivement envoyer les bonnes commandes à la centrale.

C'est un très bel exemple de l'intérêt de ce que permet le CAN

Le code pour l'envoi de ces informations sur le bus CAN est à partir de la ligne 158 dans https://github.com/BOBILLEChristophe/Satellites_autonomes_client/blob/main/src/GestionReseau.cpp

/*************************************************************************************
         * Envoi sur le bus CAN des informations concernant ce satellite
         ************************************************************************************/

        // SM1
        uint8_t nodeP_SM1_ID = 0;
        bool nodeP_SM1_ACCES = false;
        bool nodeP_SM1_BUSY = false;

        if (node->nodeP[node->SM1_idx()] != nullptr)
        {
            nodeP_SM1_ID = node->nodeP[node->SM1_idx()]->ID();
            if (node->nodeP[node->SM1_idx()]->acces())
                nodeP_SM1_ACCES = true;
            if (node->nodeP[node->SM1_idx()]->busy())
                nodeP_SM1_BUSY = true;
        }

        uint8_t nodeP_SP1_ID = 0;
        bool nodeP_SP1_ACCES = false;
        bool nodeP_SP1_BUSY = false;

        if (node->nodeP[node->SP1_idx()] != nullptr)
        {
            nodeP_SP1_ID = node->nodeP[node->SP1_idx()]->ID();
            if (node->nodeP[node->SP1_idx()]->acces())
                nodeP_SP1_ACCES = true;
            if (node->nodeP[node->SP1_idx()]->busy())
                nodeP_SP1_BUSY = true;
        }

        // debug.printf("[GestionReseau %d ] nodeP_SM1_ID : %d\n", __LINE__, nodeP_SM1_ID);
        // debug.printf("[GestionReseau %d ] nodeP_SP1_ID : %d\n", __LINE__, nodeP_SP1_ID);
        // debug.printf("[GestionReseau %d ] this node busy : %d\n", __LINE__, node->busy());

        // debug.printf("[GestionReseau %d ] SP2_acces : %d\n", __LINE__, node->SP2_acces());
        // debug.printf("[GestionReseau %d ] SP2_busy : %d\n", __LINE__, node->SP2_busy());

        CanMsg::sendMsg(1, 0xE0, node->ID(), 0xE0, 0,
                        node->busy(),
                        nodeP_SP1_ID,
                        nodeP_SM1_ID,
                        nodeP_SP1_ACCES,
                        nodeP_SP1_BUSY,
                        nodeP_SM1_ACCES,
                        nodeP_SM1_BUSY);
« Modifié: août 29, 2024, 01:06:46 pm par bobyAndCo »