Voir les contributions

Cette section vous permet de consulter les contributions (messages, sujets et fichiers joints) d'un utilisateur. Vous ne pourrez voir que les contributions des zones auxquelles vous avez accès.


Messages - bricoleau

Pages: [1] 2 3 4
1
Bus CAN / Re : Réception CAN optimale
« le: décembre 28, 2017, 11:50:55 am »
Dans le code de Dominique on voit aussi que l'identifiant de message est stocké sur un seul octet.
Cela veut dire que ce code est prévu pour fonctionner en mode CAN standard, où les identifiants sont véhiculés sur 11 bits, avec une convention de valorisation qui utilise seulement les 8 bits de poids faible.
C'est bien ça ?

2
Bus CAN / Re : Réception CAN optimale
« le: décembre 27, 2017, 07:08:54 pm »
Bonjour

Pour ma part je ne le sens pas trop, de mettre le CAN_recup() dans l'ISR.
Même si effectivement en cherchant sur le sujet, je vois plusieurs avis sur le net qui tendent à montrer que l'on peut utiliser sans trop de risque la communication SPI dans une routine d'interruption.
Je reste un peu inquiet des potentiels effets de bord sur les montages où le SPI est utilisé par ailleurs (shield ethernet par exemple), ou bien ceux où on utilise l'I2C.

Perso je me sens plus à l'aise avec un programme bien structuré en unités d'oeuvres très courtes, capable de lancer un CAN_Recup() à une fréquence suffisante. Ca au moins je suis à peu près sûr d'arriver à le maîtriser sans mauvaises surprises, mais il est vrai que je suis loin du niveau de maîtrise technique de Jean-Luc.

Donc sauf à me retrouver coincé à un moment donné, je crois que je vais rester sur mon réflexe pavlovien acquis de longue date : moins on met de code dans une routine interruption, moins on est emm..bêté.  :D


Il y a aussi un tout autre sujet qui me chatouille avec le code de Dominique : visiblement nous n'utilisons pas tous la même bibliothèque mcp_can.
Et ceci pour une bonne (?) raison : les articles publiés sur le site éditorial ne référencent pas tous la même.

Par exemple :
L'article Une Passerelle entre le bus S88 et le bus CAN pour la rétro signalisation invite à utiliser https://github.com/coryjfowler/MCP_CAN_lib
L'article Mise en oeuvre du Bus CAN entre modules Arduino invite à utiliser https://github.com/Seeed-Studio/CAN_BUS_Shield

J'utilise la première listée, et je vois bien que Dominique utilise la seconde.
Les deux codes me semblent assez proches, mais il y a quelques différences, comme la méthode getCanId() présente d'un côté mais pas de l'autre.

Y a des chances pour que ces bibliothèques soient aussi valables les unes que les autres, mais pour partager nos codes il serait quand même préférable que nous utilisions tous la même.

Quelle est la version officiellement préconisée par Locoduino ? la Seeed-Studio ?

3
Bus CAN / Re : Réception CAN optimale
« le: décembre 23, 2017, 04:33:15 pm »
Oui exact c'est juste du benchmark et ce n'est pas plus intéressant que ça.
Mais sur ce point je n'ai fait que réagir et répondre, je n'ai pas introduit le sujet ici.

Je suis effectivement en train de faire diverses expérimentations pour bien définir les limites d'usage des petites cartes CAN à 8Mhz (oui les "petits chinois" à 2€ pièce).
J'utilise des cartes arduino standard, c'est-à dire tout ce qui a un atmega328p à 16 Mhz (arduino classique / nano / pro mini / arduino ethernet)

Mon projet modélisme est exposé dans un fil de discussion dédié, dans la section du forum prévue à cet effet. C'est là qu'il sera développé au grée de mes avancées.
Ici on est dans les discussions générales autour du bus CAN, il m'a donc semblé naturel d'y mettre ce que j'aurais aimé trouver à ce sujet, et qui pourrait être utile pour les suivants.
Mais bon si tu trouves que c'est sans valeur ajoutée pour le forum, ok je m'adapte sans une once de contrition. Cela me va aussi.

Sur le bus CAN spécifiquement : je travaille d'abord tous les aspects techniques émission/réception. Là j'en suis à l'implémentation du buffer circulaire en réception, qui me semble indispensable.
J'ai encore pas mal de tests à faire, en particulier sur les diverses stratégies possibles d'utilisation des filtres (et donc de codage des identifiants de messages).
Car je pense que ce sont les contraintes techniques qui vont dicter les bonnes règles d'usage des filtres.
Au bout du bout, je vise une implémentation la plus propre possible, packagée sous forme d'une bibliothèque la plus simple possible d'utilisation.
Je peux détailler ce cheminement ici dans la section CAN, ou bien me contenter d'en exposer un exemple de mise en application dans le cadre de mon projet, lorsque j'en serais là. Tout me va.

Bon Noel également  :)

4
Bus CAN / Re : Réception CAN optimale
« le: décembre 23, 2017, 02:04:40 pm »
Par exemple si je prends le tir 150 que l'on peut voir dans le fichier joint ci-dessus CAN_00_E.txt

Declenchement tir 150 delai=00500 nb_envois=1000 taille=5 ... OK duree=00499832 microsecondes.  Accuse reception OK
L'arduino 1 a d'abord émis un tout premier message CAN d'annonce de tir, dans lequel il indique qu'il va envoyer 1000 messages de 5 octets. L'identifiant CAN de chacun de ces 1000 messages est 150 (=le numéro de tir)

L'arduino 2 lit ce tout premier message d'annonce, et se met en attente de la salve

L'arduino 1 envoie les 1000 messages, à raison d'un message toutes les 500 microsecondes (valeur du délai pour ce tir)

L'arduino 2 recoit les 1000 messages, contrôle tout (identifiant, longueur, nombre de messages, contenu des données), puis émet un seul message, qui sert d'accusé de réception pour rendre compte de ses contrôles.

L'arduino 1 reçoit l'accusé de réception en provenance de l'arduino 2. Si un problème a été détecté par l'arduino2, le programme s'arrête, sinon il passe au tir suivant, et on recommence

5
Bus CAN / Re : Re : Réception CAN optimale
« le: décembre 23, 2017, 12:11:36 am »
Lors de mes tests il y a maintenant 2 ans, j’avais développé un générateur de messages avec des données qui étaient incrémentées à l’emission pour détecter les pertes de messages à la réception.

Oui oui t'inquiète j'ai commencé par ça aussi  :D

Un arduino émetteur et un arduino récepteur.
L'arduino émetteur procède à une série de tirs.
Chaque tir est annoncé par un message, qui contient les caractéristiques des messages qui vont suivre : identifiant, longueur et nombre d'envois. Les donnée sont incrémentées de manière circulaire.
L'arduino récepteur vérifie qu'il reçoit tout bien avec les bonnes valeurs, et retourne un message d'acquittement du tir. Côté récepteur, j'affiche aussi la part de cpu dévolue à la récupération des messages.
J'ai fait varier la longueur des messages, la quantité de la rafale, ainsi que la durée entre deux émissions, en mesurant tout sans jamais rien perdre.

Comme on ne peut pas avoir deux terminaux ouverts sur l'IDE arduino, j'ai utilisé putty.

Je mets en pièce jointe les deux programmes et les deux résultats.

Par la suite, je pense faire des tests de tirs croisés avec deux émetteurs et deux récepteurs, histoire d'observer la saturation du bus. Il me faudra un cinquième arduino pour rendre compte des annonces et acquittements sur un terminal unique.

6
Bus CAN / Réception CAN optimale
« le: décembre 22, 2017, 01:30:56 pm »
Un petit sujet de discussion pour partager mon expérimentation de ce matin.
Rien de fracassant, mais quelques infos quand même.

La question de départ était : Depuis le programme arduino, comment vérifier la présence de message reçu dans le MCP2515, de la manière la plus rapide possible ?

En effet, quel que soit le programme, l'arduino va devoir se poser cette question très régulièrement, disons plusieurs milliers de fois par seconde.
Et dans la plupart des cas, la réponse sera négative.
Il serait donc dommage que la question coûte cher en CPU, surtout sur les cas de réponse négative.

Le MCP2515 dispose d'une sortie INT. Celle-ci donne l'état de ses buffers de réception internes.
Elle est à GND tant qu'il y a un message disponible à récupérer.

Par ailleurs, l'arduino peut dialoguer avec le MCP2515 via la liaison SPI, au travers des méthodes CAN.checkReceive() et CAN.readMsgBuf().
Il est donc possible de ne pas utiliser la sortie INT et d'utiliser seulement ces méthodes d'accès.

De plus, comme la méthode CAN.readMsgBuf() retourne la valeur CAN_NOMSG lorsqu'il n'y a rien à lire,  on peut s'interroger sur l'utilité d'appeler systématiquement CAN.checkReceive() avant CAN.readMsgBuf().
Cet appel systématique pourrait être justifié si le checkReceive() répondait significativement plus vite en cas d'absence de message à récupérer.

J'ai donc testé plusieurs cas :
  • sortie INT utilisée via une interruption
  • sortie INT lue par un digitalRead
  • sortie INT lue par accès direct aux registres de l'arduino
  • utilisation de la méthode checkReceive()
  • utilisation directe de la méthode readMsgBuf()

Le test a été effectué à vide, c'est-à-dire avec un bus CAN sur lequel aucun message ne circule, car l'objectif était de vérifier l'absence de message disponible dans le MCP2515, le plus vite possible

Le programme de test
#include <mcp_can.h>

const char* pgm =
"Programme d'evaluation des diverses façons de verifier la presence d'un message CAN a lire";

/* Cablage Arduino <-> MCP2515
 *   D3  <-> INT
 *   D13 <-> SCK
 *   D11 <-> SI
 *   D12 <-> SO
 *   D10 <-> CS
 *   GND <-> GND
 *   5V  <-> VCC
 */
const uint8_t pin_INT = 3;
const uint8_t pin_CS = 10;

MCP_CAN CAN(pin_CS);

const uint32_t nb_tests = 100000UL;

uint32_t bidon;//variable globale bidon pour tromper le compilo

char* reference()
{
  for (uint32_t i=0; i<nb_tests; i++)
  {
    //Si on ne met rien de consistant dans la boucle for,
    //le compilo va optimiser tout ça et virer le code inutile
    if (bidon < 100) bidon++;
    //A cet endroit on va mettre les differentes versions à tester
  }
  return __func__;
}

volatile bool message_a_lire = false; //mise à jour par interruption, non implémentée pour le test
char* version_interruption()
{
  for (uint32_t i=0; i<nb_tests; i++)
  {
    if (bidon < 100) bidon++;
    if (message_a_lire)
    {
      bidon++;//on n'arrive jamais ici car aucun message echangé lors du test
    }
  }
  return __func__;
}

char* version_lecture_pin_INT_digitalRead()
{
  for (uint32_t i=0; i<nb_tests; i++)
  {
    if (bidon < 100) bidon++;
    if (!digitalRead(pin_INT))
    {
      bidon++;
    }
  }
  return __func__;
}

char* version_lecture_pin_INT_directe()
{
  for (uint32_t i=0; i<nb_tests; i++)
  {
    if (bidon < 100) bidon++;
    if (!(PIND & (1 << pin_INT)))
    {
      bidon++;
    }
  }
  return __func__;
}

char* version_CAN_checkReceive()
{
  for (uint32_t i=0; i<nb_tests; i++)
  {
    if (bidon < 100) bidon++;
    if (CAN.checkReceive() == CAN_MSGAVAIL)
    {
      bidon++;
    }
  }
  return __func__;
}

char* version_CAN_readMsgBuf()
{
  uint32_t rxId;
  uint8_t rxTaille;
  uint8_t rxData[8];
  for (uint32_t i=0; i<nb_tests; i++)
  {
    if (bidon < 100) bidon++;
    if (CAN.readMsgBuf(&rxId, &rxTaille, rxData) == CAN_OK)
    {
      bidon++;
    }
  }
  return __func__;
}

void evaluer(char* fonction())
{
  static uint32_t chrono_reference;
 
  uint32_t chrono = micros();
  char* nom = fonction();
  chrono = micros() - chrono;

  if (fonction == reference)
  {
    chrono_reference = chrono;
  }

  Serial.print("\nEvaluation ");
  Serial.print(nom);
  Serial.println(" :");
  Serial.print("  chrono_global_brut=");
  Serial.print(chrono);
  Serial.println(" µs");
  Serial.print("  chrono_unitaire_brut=");
  Serial.print(chrono / (nb_tests / 1000));
  Serial.println(" ns");
  chrono -= chrono_reference;
  Serial.print("  chrono_global_net=");
  Serial.print(chrono);
  Serial.println(" µs");
  Serial.print("  chrono_unitaire_net=");
  Serial.print(chrono / (nb_tests / 1000));
  Serial.println(" ns");
}

void setup()
{
  pinMode(pin_INT, INPUT);
  Serial.begin(115200);
  Serial.println(pgm);
  Serial.print("\nNombre de tests de lecture par tir : ");
  Serial.println(nb_tests);
  evaluer(reference);
  evaluer(version_interruption);
  evaluer(version_lecture_pin_INT_digitalRead);
  evaluer(version_lecture_pin_INT_directe);
  evaluer(version_CAN_checkReceive);
  evaluer(version_CAN_readMsgBuf);
}

void loop()
{
}

Résultat sur le terminal :
Programme d'evaluation des diverses façons de verifier la presence d'un message CAN a lire

Nombre de tests de lecture par tir : 100000

Evaluation reference :
  chrono_global_brut=75968 µs
  chrono_unitaire_brut=759 ns
  chrono_global_net=0 µs
  chrono_unitaire_net=0 ns

Evaluation version_interruption :
  chrono_global_brut=107392 µs
  chrono_unitaire_brut=1073 ns
  chrono_global_net=31424 µs
  chrono_unitaire_net=314 ns

Evaluation version_lecture_pin_INT_digitalRead :
  chrono_global_brut=478392 µs
  chrono_unitaire_brut=4783 ns
  chrono_global_net=402424 µs
  chrono_unitaire_net=4024 ns

Evaluation version_lecture_pin_INT_directe :
  chrono_global_brut=145120 µs
  chrono_unitaire_brut=1451 ns
  chrono_global_net=69152 µs
  chrono_unitaire_net=691 ns

Evaluation version_CAN_checkReceive :
  chrono_global_brut=1974784 µs
  chrono_unitaire_brut=19747 ns
  chrono_global_net=1898816 µs
  chrono_unitaire_net=18988 ns

Evaluation version_CAN_readMsgBuf :
  chrono_global_brut=2006252 µs
  chrono_unitaire_brut=20062 ns
  chrono_global_net=1930284 µs
  chrono_unitaire_net=19302 ns

Il y a une fonction de référence dont on mesure le temps d'exécution, puis les diverses versions testées.
Afin d'évaluer le temps d'exécution spécifique à chacune d'elles, je prends son temps d'exécution brut, duquel je déduis le temps d'exécution de la fonction de référence, pour avoir un résultat net qui correspond exactement aux quelques lignes de différence dans le code.

Evidemment, sans surprise, le test sur un booléen d'état mis à jour par une interruption est le plus rapide. Il ne coûte que 314 nanosecondes.
Encore que, cela me semble vraiment très peu. Je me demande si le compilo n'a pas optimisé ce petit bout de programme trop simple, pour laisser cette variable dans un registre de l'atmega.

On voit bien la différence entre un bon gros digitalRead et une lecture directe du registre PIND. En termes de rapidité, celui-ci n'est d'ailleurs pas loin du cas avec interruption.

Enfin, le checkReceive et le readMsgBuf ont des temps d'exécution voisins à 19 microsecondes (toujours dans le cas où il n'y a rien à lire), avec un petit avantage pour le checkReceive.


Au vu de ces résultats, je pars sur le modèle de réception CAN ci-dessous
#include <mcp_can.h>
/* Cablage Arduino <-> MCP2515
 *   D3  <-> INT
 *   D13 <-> SCK
 *   D11 <-> SI
 *   D12 <-> SO
 *   D10 <-> CS
 *   GND <-> GND
 *   5V  <-> VCC
 */
const uint8_t pin_INT = 3; //valeur 2 ou 3
const uint8_t pin_CS = 10;

MCP_CAN CAN(pin_CS);

volatile bool message_CAN_disponible = false;

void ISR_reception_CAN()
{
  message_CAN_disponible = true;
}

void initialiser_reception_CAN()
{
  pinMode(pin_INT, INPUT);
  int8_t numero_interruption = digitalPinToInterrupt(pin_INT);
  if (numero_interruption != -1)
  {
    attachInterrupt(numero_interruption, ISR_reception_CAN, FALLING);
  }
  else
  {
    //erreur : pas d'interruption disponible pour la valeur de pin_INT
  }
}

void CAN_recup()
{
  if (message_CAN_disponible)
  {
    message_CAN_disponible = false;
    while (!(PIND & (1 << pin_INT)))// ou bien !digitalRead(pin_INT)
    {
      uint32_t rxId;
      uint8_t rxTaille;
      uint8_t rxBuffer[8];
      if (CAN.readMsgBuf(&rxId, &rxTaille, rxBuffer) == CAN_OK)
      {
        traiter_message_CAN_recu(rxId, rxTaille, rxBuffer);
      }
    }
  }
}

void traiter_message_CAN_recu(uint32_t id, uint8_t taille, uint8_t buffer[])
{
  //...ou bien chargement dans un buffer en RAM pour traitement ultérieur
}

void setup()
{
  initialiser_reception_CAN();
  //...
}

void loop()
{
  CAN_recup();
  //...
}

7
Les réseaux / Re : Projet Dominique
« le: décembre 21, 2017, 10:14:38 pm »
Super intéressant

Je te soumets une petite analyse personnelle, en ce qui concerne le LCD texte à interface I2C :

Au travers de la bibliothèque <LiquidCrystal_I2C.h>, l'arduino envoie des données via le bus I2C, à un io expander PCF8574, lui même connecté aux entrées du contrôleur HD44780 de l'écran LCD.
Le PCF8574 a 8 sorties parallèles :
  • 1 est utilisée pour commander directement le rétro-éclairage du LCD (en on/off)
  • 4 sont utilisées pour le transfert de données vers le HD44780, qui est mis en mode 4bits (chargement demi-octet par demi-octet).
  • 2 sont utilisées pour les entrées de commande E et RS du HD44780
  • 1 est non utilisée ou cablée sur l'entrée de commande R/W (pas très utile)
Le principe de fonctionnement du PCF8574 est très simple : l'arduino lui transmet un octet, dont les 8 bits correspondent aux 8 sorties du PCF8574.

Le bus I2C fonctionne au max à 400 kb/s sur arduino (100 kb/s en standard)
Ce qui, déduction faite des bits de contrôle START, ACK etc. permet de faire passer grosso modo un débit de 40 octets par milliseconde, adresse incluse (elle prend aussi un octet).

Pour chaque octet utile à transmettre depuis l'arduino vers le LCD (= un caractère à afficher, ou une commande d'effacement écran, ou une commande de positionnement de curseur), il y a 2x6=12 octets qui passent sur le bus I2C :
  • adresse 0x27 + premier demi-octet
  • adresse 0x27 + premier demi-octet avec activation de la commande "enable"
  • adresse 0x27 + premier demi-octet avec relâchement de la commande "enable"
et pareil pour le second demi-octet

Au niveau du programme, l'instruction de base LCD.print(chaine) ne rend la main qu'à la fin des émissions sur le bus.
Dans le pire de cas, la chaîne fait 20 caractères, soit 20x12 = 240 octets de trafic sur le bus I2C, ce qui va durer 6 ms.

En supposant que je ne me suis pas trompé dans le calcul (de toute manière facile à vérifier par mesure de temps dans le programme), cela fait 6 millisecondes pendant lesquelles l'arduino ne fait aucune lecture des buffers de réception du MCP2515.

Si l'écosystème fait qu'il n'y a aucune chance de recevoir plusieurs messages CAN pendant ce laps de temps, alors pas de problème.
Sinon, il y a un risque de perte de message au niveau du mcp2515, pour cause de buffers de réception pleins.


Pour réduire le risque :
N'afficher que les caractères qui ont changé
Effectuer des LCD.print caractère par caractère, en testant la réception MCP2515 entre chaque, cela réduit le tunnel à 300 µs.

On peut faire mieux, mais il faut réécrire <LiquidCrystal_I2C.h>

8
Discussions ouvertes / Re : Train miniature du futur
« le: décembre 20, 2017, 07:42:33 pm »
Hehe
Je connais assez bien le sacerdoce d'aider les newbies, avec parfois un petit agacement face au temps perdu à devoir répondre à des personnes qui posent des questions avant même de faire un petit effort personnel de recherche et de documentation.
Aussi j'essaye de vous épargner sur ce point, si si j'vous jure  :P

Effectivement le CAN est au centre de mes réflexions en ce moment.
Je ne pense pas être passé à côté des aspects essentiels de la communication sur bus CAN, ou du moins pas à côté de ceux évoqués plus haut.
C'est juste que j'arrive avec un oeil neuf, donc j'ai envie de prendre le temps de réévaluer les questions fondamentales avant d'emprunter les chemins déjà balisés.
Pas de doute sur le fait qu'au niveau physique la communication est bien assurée sur le bus.
Mais sur l'ensemble de la chaîne de liaison, j'ai évalué que la faiblesse se trouve entre l'arduino et le MCP2515, voire dans le MCP2515 lui-même, trop faiblement bufferisé.
Avec un bus à 500 kbs, j'ai mesuré que deux arduino peuvent échanger jusqu'à 4000 trames de 0 octet par seconde (et 2400 trames de 8 octets).
En réception, ca fait potentiellement un message à traiter toutes les 250 microsecondes, qui doit être consommé rapidement par l'arduino sous peine de perte de messages.

Les possibilités de filtre au niveau du MCP2515 apportent un début de réponse au risque de perte de message utile, dans la mesure ou ceux qui sont hors scope sont éliminés dès le départ.
Mais si on reçoit plusieurs messages utiles en rafale, le risque demeure.
Il faut un arduino dont le programme est structuré en unités d'oeuvres très courtes, capable de s'interrompre pour lire les messages du MCP2515, quitte à les placer temporairement dans un buffer plus gros en RAM. Ce n'est pas toujours évident à obtenir.

Par exemple : j'ai en tête de réaliser une mini console de bus can, avec un affichage direct sur écran LCD, pour y restituer tous types d'infos qui peuvent passer sur le bus.
D'habitude j'utilise des LCD 4x20 à interface I2C, très bon marché et simples à mettre en oeuvre, mais dont le principal inconvénient est la lourdeur de la laison I2C avec un PCF8574 en intermédiaire côté LCD.
Visuellement, on peut se contenter d'un rafraichissement d'écran chaque demi seconde. Le problème reste de ne pas perdre de messages CAN pendant ce rafraichissement, qui peut durer jusqu'à 20 millisecondes. Je suis bien parti pour devoir réécrire une bibliothèque LCD_I2C interruptible.

Autre point : en potassant le datasheet du mcp2515, j'ai aussi vu que les deux filtres/buffers de réception ne sont pas traités de manière égale.
Les messages issus du filtre0 peuvent déborder dans le buffer1 si le buffer0 n'a pas été consommé.
Il y a donc intérêt à mettre la sélection des messages importants dans le filtre0.
A mon sens, c'est encore une rustine qui vise à contourner la faible bufferisation du MCP2515.

Perso, si je devais adresser des besoins extrêmes, je serais assez tenté d'ajouter un arduino intermédiaire, dont la seule fonction serait de gérer la bufferisation du MCP2515 en exploitant toute sa RAM.
Et encore, je reste dans le cas favorable où le bus CAN est à seulement 500 kbs, c'est-à-dire un débit utile plus faible que celui de la liaison SPI entre l'arduino et le MCP2515.
Il n'y a donc pas de risque que l'arduino se fasse déborder par le débit sur le bus, tant qu'il garde un mimimum de dispo régulière pour lire le MCP2515.

Dans ce contexte, il me semble raisonnable de prévoir un système où, par exemple, une centrale émet une consigne de bascule d'aiguillage, puis se met à l'écoute d'un message d'information de changement d'état en provenance de l'aiguillage, pour s'assurer que la commande a bien été traitée et éventuellement réemettre la consigne.
Ca c'est déjà ce que j'appelle un sur-protocole, avec un début d'acquittement.
Je me pose donc la question de normer ce sur-protocole, pour que la plupart des cas d'usage puissent s'inscrire dans un modèle générique.
Et effectivement le risque est d'alourdir les trames de base et donc de réduire le débit utile sur le bus.
Il y a certainement un juste curseur à positionner.

Et dans tous ça, il est clair que les règles de valorisation des identifiants des messages CAN sont essentielles, et pas forcéement évidentes à édicter.
Techniquement, on est libre d'utiliser des identifants courts sur 11 bits ou étendus sur 29 bits.
La valorisation des identifiants est également libre. On peut y mettre la notion de type de message et/ou d'émetteur et/ou de destinataire.
Et encore, la notion d'émetteur / destinataire peut correspondre au MCP2515 ou à un dispositif plus fin, comme une commande d'aiguillage ou un capteur quelconque.
Ajoutez à cela les notions de priorisation des messages selon la valeur de l'identifiant (protocole CAN), ainsi que les possibilités de filtrage offertes par le MCP2515.
Au final je trouve qu'il n'est pas évident de se faire une religion sur le bon usage de la bestiole.

9
Discussions ouvertes / Re : Train miniature du futur
« le: décembre 19, 2017, 11:53:39 pm »
Bonsoir

Je peux essayer de vous donner mon humble avis d'arduiniste, en gardant l'hypothèse d'un contrôleur à base d'arduino pour chaque canton, qui est certainement la plus modulaire :

Plus de pins sur la mega, oui ça peut être utile, encore que avec des registres à décalage et autres io expander on arrive à des résultats voisins. Disons que ça peut permettre de faire un programme unique, où toutes les pins sont associées à une fonction précise, même si celle-ci n'est pas mise en oeuvre dans chaque canton. Et en complément, on peut imaginer des locoshield mega pour simplifier la connectique avec les montages électroniques périphériques. Pour ma part, la mega est surtout indispensable quand on a besoin de plus de 32kb de code exécutable.

Une connectivité wifi (ou disons sans fil) par canton cela me semble un peu luxueux, et peut-être aussi moins fiable qu'un réseau local cablé, qu'il soit ethernet ou à base de bus CAN. Un seul point d'accès wifi pour l'ensemble du réseau n'est-il pas suffisant?

Entre CAN et Ethernet pour faire discuter ce petit monde, perso j'ai une préférence pour ethernet car c'est plus ouvert. Une centrale à base de raspberry pi pourrait donner des résultats très sympathiques. Mais j'ai cru comprendre que dans l'environnement électrique perturbé d'un réseau ferroviaire, le bus can était plus fiable pour échanger des infos.

Dans tous les cas, c'est bien d'avoir au démarrage une phase ou chaque participant publie sa signalétique sur le réseau. Cela simplifie l'appréhension de nouveaux éléments par la centrale ou entre eux. L'idéal est d'aller jusqu'à des fonctions d’appairage, que chacun mémorise dans son eeprom pour la fois suivante.
Là par exemple je suis en train de commencer à jouer avec des cartes CAN, je vois assez bien le principe de communication. Je m'interroge néanmoins sur la nécessité d'un sur-protocole standard (acquittements d'échanges, etc.), avec identification des équipements émetteurs/récepteurs. Le but n'est pas de refaire du TCP par dessus le bus CAN, mais je me demande si je ne vais pas commencer par coller un équivalent d'adresse MAC à chaque MCP2515

L'arduinoOTA j'avais déjà commencé à regarder mais c'est un peu chaud. J'en étais arrivé à la conclusion qu'il vaut mieux procéder en deux temps. D'abord récupérer le code exécutable par téléchargement, et le stocker en local (par exemple sur une carte SD - les shields ethernet ont un lecteur), puis modifier le bootloader pour recopier le code vers la flash, lorsqu'une nouvelle version est disponible en local et vérifiée intègre. Ca fait un bootloader un peu plus gros car il doit embarquer la lecture du stockage local. Ecrire en flash au fur et à mesure de la réception des paquets me semble trop fragile, face aux aléas réseau.
Avec un tel système, il serait possible d'héberger le code exécutable sur le cloud, pour qu'il soit partagé par une communauté.
Le programme principal pourrait interroger l'hébergement de référence à intervalles réguliers, en tâche de fond de son fonctionnement normal. Et si une nouvelle version est disponible, la télécharger en local sur un stockage annexe (toujours en tâche de fond), pour qu'elle s'installe au redémarrage suivant.
NB : je ne vois rien qui empêcherait de faire la même chose en passant par un bus CAN : un arduino en guise de passerelle CAN-Ethernet, qui se chargerait de récupérer le nouveau code et de le broadcaster sur le bus, en trame de fond et par paquets de 8 octets.

10
Vos projets / Re : Premiers pas de bricoleau
« le: décembre 19, 2017, 12:08:47 am »
Merci encore.

J'avais bien repéré ce beau PDF avec tous les schémas.
C'est justement la réponse que j'avais peur d'entendre... Les ampli op, un vieux trauma de mes années d'études.  ;D

Je vais prendre le temps d'une remise à niveau théorique, pour bien comprendre ce schéma avant de foncer tête baissée.

11
Vos projets / Re : Premiers pas de bricoleau
« le: décembre 18, 2017, 11:01:16 pm »
Ok ok
Sur le principe c'est ce qui est expliqué par exemple là : http://amfn.nice.free.fr/alim.htm

Donc je coupe l'alim du moteur, j'attends éventuellement un pouillème, puis je mesure la tension résiduelle sur le rail, issue du moteur qui continue à tourner par inertie mécanique, agissant alors comme un générateur.
Je vais tâcher de commencer par observer le phénomène à l'oscillo, pour bien visualiser à quoi j'ai à faire.

Pour mesurer la tension résiduelle, est-ce que ça peut être aussi simple que de passer par un diviseur de tension et des analogread() de l'arduino?
Voire éventuellement de passer directement par les registres de l'atmega pour des lectures plus rapides?

NB : avec ce montage de hachage de tension, j'ai un rail qui reste à 12V, l'autre qui est haché à GND. C'est celui-là qui m'intéresse.
Lorsque le MOSFET est non passant, le rail est "en l'air" (au bémol près de la diode roue libre et du moteur de l'éventuelle loco présente sur la voie).
Je pense ajouter un diviseur de tension entre ce rail et GND, avec par exemple des résistances de 30k et 10k
Je m'attends donc à faire des mesures à l'envers, avec une tension résiduelle qui remonte vers 12V lorsque le moteur ralentit.
Et accessoirement la même lecture de tension (toujours hors alim) devrait me permettre de détecter l'occupation de voie, même avec une loco à l'arrêt. Car en l'absence de loco sur la voie, le rail est vraiment "en l'air" et le diviseur de tension va faire office de pull down. Donc tension à 0V => voie libre. Tension à 12V => voie occupée avec loco à l'arrêt.
Me gourre-je?

12
Vos projets / Re : Premiers pas de bricoleau
« le: décembre 16, 2017, 11:08:47 pm »
Merci pour ces précisions
Bien évidemment, je vais partir sur un asservissement de vitesse, en conservant un hachage à haute fréquence.

Ce qui m'amène à une autre question de néophyte en moteurs : est-ce qu'une mesure du courant consommé permet d'évaluer la vitesse de rotation du moteur de manière fiable?

J'ai un acs712 et un max471 sous la main, je comptais justement voir ce que je pouvais en tirer de manière expérimentale avec une loco... quand j'aurais fini de jouer avec les interface CAN que j'ai reçues cette semaine  :D

13
Vos projets / Re : Premiers pas de bricoleau
« le: décembre 16, 2017, 11:47:45 am »
Bonjour

Avec une loco fleischmann neuve, mêmes symptômes mais en moins prononcés.
Une même valeur (faible) de PWM peut conduire à :
- si la loco est à l'arrêt : rien du tout
- si la loco est en mouvement : un ralentissement suivi d'une vitesse très lente mais constante

Je vais essayer de pousser plus avant les contrôles de mon montage de hachage de tension, mais je me dis que c'est peut-être un comportement normal : la résistance mécanique au mouvement est peut-être plus forte lorsque la loco est à l'arrêt.
Ca m'intéresserait d'avoir vos avis car je suis vraiment néophyte en contrôle de moteurs.

14
Discussions ouvertes / Re : Train miniature du futur
« le: décembre 11, 2017, 02:21:34 pm »
Je vous soumets aussi une autre idée :

Une boussole électronique permettrait de détecter le moindre changement de direction.

J'ai un montage à base de hmc5883L qui tourne en h24 chez moi.
C'est très réactif. Je l'interroge toutes les 250 ms pour déterminer l'angle d'ouverture de la porte sur laquelle il est fixé. La précision est de l'ordre d'un degré.

15
Discussions ouvertes / Re : Train miniature du futur
« le: décembre 11, 2017, 01:42:55 pm »
A mon avis le cas le plus difficile est celui de plusieurs voies parallèles. Comme elles sont proches les unes des autres, il faudrait un dispositif de localisation assez précis pour savoir sur laquelle on est.

Un accéléromètre permettrait à coup sûr de déterminer quelle sortie de chaque aiguillage est empruntée

Pages: [1] 2 3 4