Auteur Sujet: Présentation de Julaye  (Lu 11613 fois)

Julaye

  • Newbie
  • *
  • Messages: 6
    • Voir le profil
Présentation de Julaye
« le: octobre 30, 2021, 11:50:29 pm »
Bonjour à tous,

Débutante en ferromodélisme depuis une année mais tombée dans l'informatique embarquée petite, avec de l'assembleur et un KIM-1 ...

Je m'intéresse à l'Arduino Nano pour réaliser des automatismes sympa sur mon réseau en construction.

Voilà :)

Tony04

  • Hero Member
  • *****
  • Messages: 569
    • Voir le profil
Re : Présentation de Julaye
« Réponse #1 le: octobre 31, 2021, 07:58:00 am »
Bonjour Julaye,

voila une présentation courte et précise comme un sketch Arduino, c'est un bon début....

Bienvenue sur notre forum préféré et bonne découverte avec ce superbe "jouet" qu'est le NANO, par contre oublie l'assembleur (comme j'ai été obligé de le faire) et vive le monde des "objets": https://www.locoduino.org/spip.php?article85

Bien cordialement
Antoine

PS: C'est quoi le "KIM-1" ?

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 3039
  • 100% Arduino et N
    • Voir le profil
Re : Présentation de Julaye
« Réponse #2 le: octobre 31, 2021, 08:16:18 am »
Bienvenue Julaye,

Nul doute que tu vas nous montrer des choses intéressantes en environnement embarqué dans notre domaine chéri  ;D

Bienvenue  ;)
Cordialement,
Dominique

chris_bzg

  • Sr. Member
  • ****
  • Messages: 319
    • Voir le profil
Re : Présentation de Julaye
« Réponse #3 le: octobre 31, 2021, 09:40:03 am »
A mon tour de te souhaiter la bienvenue.

Le monde des objets est effectivement très riche, mais personne n'est obligé d'arrêter l'assembleur. En tout cas, une série d'articles y est consacré.

Sur LOCODUINO, il y en a pour tous les goûts et je suis certain que tu sauras lui apporter ta touche au gré de tes envies. On en rediscute bientôt.  ;)

Christian

Remi

  • Newbie
  • *
  • Messages: 36
  • HO en 3 rails (Marklin)
    • Voir le profil
Re : Présentation de Julaye
« Réponse #4 le: octobre 31, 2021, 09:54:09 am »
Bonjour et bienvenue sur le site de Locoduino  :)
Je pense que tu trouveras ici une aide précieuse pour les animations de ton réseau, que ce soit dans les (excellents) articles du site,
ou par les réponses des membres de Locoduino, toujours très disponible  :D
A+  Rémi  8)

Tony04

  • Hero Member
  • *****
  • Messages: 569
    • Voir le profil
Re : Re : Présentation de Julaye
« Réponse #5 le: octobre 31, 2021, 05:23:03 pm »
mais personne n'est obligé d'arrêter l'assembleur.
Christian

Je parlais juste pour l'Arduino bien sûr  :-[

Julaye

  • Newbie
  • *
  • Messages: 6
    • Voir le profil
Re : Présentation de Julaye
« Réponse #6 le: novembre 02, 2021, 09:01:39 am »
Merci à tous pour l'accueil  8)

@Tony04 J'ai arrêté l'assembleur depuis l'époque où j'avais développé un petit assembleur pour le 68HC11 ... 1998 si je me souviens bien ...

@Remi oui et je m'en suis déjà inspirée, notamment le poste de soudure que j'ai revisité un peu. Cf dans l'imprimerie sur cette vidéo :



@chris_bzg je choisi toujours l'outil et l'architecture la plus adaptée à ce que je souhaite programmer. Les objets sont un outil possible mais pas toujours le plus efficient. Pour l'embarqué sur du matériel comme le Nano, j'aime bien le C (de Ritchie), les machines à état fini et les co-routines.

@Dominique oui j'ai fait un petit projet, parce que en fait je suis paresseuse et je n'aime pas passer mon temps à coder, j'aime bien décrire (meta programmation, même en embarqué c'est possible, low code/no code pour reprendre le jargon à la mode) : https://github.com/Julaye/Lumieres

@Tony04 KIM-1 : le truc avec lequel j'ai commencé, quelques mois avant l'Apple II ... https://fr.wikipedia.org/wiki/KIM-1. Désolée je n'ai aucune photo de l'époque, je me souviens juste que vu mon âge (12 ans je crois), je ne parlais pas encore anglais et que je déchiffrais les docs avec le dictionnaire de mon père.

Bonne semaine,
« Modifié: novembre 02, 2021, 11:43:27 am par Julaye »

msport

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 2217
  • HO avec DCC++ en DIY Réseaux très éphémères
    • Voir le profil
Re : Re : Présentation de Julaye
« Réponse #7 le: novembre 02, 2021, 09:53:44 am »
Cf dans l'imprimerie sur cette vidéo


Jolie petite imprimerie !
« Modifié: novembre 02, 2021, 01:22:36 pm par msport »
Cordialement

chris_bzg

  • Sr. Member
  • ****
  • Messages: 319
    • Voir le profil
Re : Re : Re : Présentation de Julaye
« Réponse #8 le: novembre 02, 2021, 11:42:01 am »
mais personne n'est obligé d'arrêter l'assembleur.
Christian

Je parlais juste pour l'Arduino bien sûr  :-[

Bonjour Tony,

Moi aussi je parlais d'Arduino.  :)
Si tu as lu le premier des articles assembleur, il démontre certains problèmes engendrés par l'IDE avec le C.
Mais j'ai aussi dit que l'assembleur, ça peut être très ch... et que ce langage ne se justifie que dans des cas bien particuliers (quasiment jamais en modélisme ferroviaire).

En fait, je rebondissais juste sur ta remarque quand tu disais avoir été "obligé" ; ça m'a amusé. En tout cas, je n'oblige à rien : chacun fait ce qu'il lui plaît (plaît, plaît...).  ;)

chris_bzg

  • Sr. Member
  • ****
  • Messages: 319
    • Voir le profil
Re : Re : Présentation de Julaye
« Réponse #9 le: novembre 02, 2021, 11:51:24 am »
Merci à tous pour l'accueil  8)

@chris_bzg je choisi toujours l'outil et l'architecture la plus adaptée à ce que je souhaite programmer. Les objets sont un outil possible mais pas toujours le plus efficient. Pour l'embarqué sur du matériel comme le Nano, j'aime bien le C (de Ritchie), les machines à état fini et les co-routines.

Bonne semaine,

Bien que la POO soit un outil extrêmement puissant, je l'utilise assez peu, mais il est vrai aussi que la majorité des montages que je publie s'adresse à des gens qui débutent. Les montages trop compliqués ne sont jamais réalisés par nos lecteurs. Donc le C me suffit dans bien des cas et j'utilise les classes pour les bibliothèques (LightEffect par exemple). Dans l'équipe, Jean-Luc et Thierry maitrisent la POO (entre autres) : si un jour tu veux t'y intéresser, lis leurs articles.

Et pour le reste, c'est sans doute toi qui va nous apprendre des choses intéressantes.  ;)

savignyexpress

  • Invité
Re : Présentation de Julaye
« Réponse #10 le: novembre 02, 2021, 11:56:23 am »
Bonjour Julaye,

À mon tour je te souhaite la bienvenue parmi nous.

@chris_bzg je choisi toujours l'outil et l'architecture la plus adaptée à ce que je souhaite programmer. Les objets sont un outil possible mais pas toujours le plus efficient. Pour l'embarqué sur du matériel comme le Nano, j'aime bien le C (de Ritchie), les machines à état fini et les co-routines.

Les machines à états finis sont très présentes dans les systèmes embarqués. Je les ai utilisées dans la plupart de mes développements pour le modélisme ferroviaire. Au début j'ai réalisé des projets directement en C sur des Attiny2313 et Atmega8, plus récemment je suis passé à l'Arduino pour plus de puissance et utiliser C++. Mon réseau hivernal est contrôlé par plusieurs classes C++ implémentant chacune une machine à états finis. Voir https://forum.locoduino.org/index.php?topic=763.msg13315#new.

Mais les coroutines sont intéressantes lorsque le traitement est majoritairement séquentiel. Une implantation très pratique des coroutines sont les protothreads dont la documentation se trouve ici: http://dunkels.com/adam/pt/. C'est simple à mettre en oeuvre et ne requiert que quelques includes, car implanté sous forme de macros du préprocesseur.
L'exemple ci-après est la gestion en C sur Attiny2313 d'un PN dont les barrières sont actionnées par des servo moteurs. Il y a 3 protothreads: 2 pour faire clignoter les signaux sur les 2 PN, 1 pour actionner les barrières de l'un des PN, l'autre n'en ayant pas.

Au plaisir d'échanger sur ces sujets.
Meilleures salutations.

//
//   PassageNiveau.c
//
//   Programme de contrôle du passage à niveau.
//
//   2010.06.12   MHP   Création.
//   2011.06.14   MHP   Premiers tests concluants de commande du servo-moteur.
//   2011.06.20   MHP   Utilisation des protothreads PC (Adam Dunkels, adam@sics.se).
//   2011.06.22   MHP   Premier essai des prothothreads AVR.
//   2011.06.24   MHP   Correction des timings ville et prise en compte du transistor de sortie (inverser PWM).
//   2011.07.06   MHP   Configuration des entrées/sorties définitive!
//   2011.07.07   MHP   Réglage des délais pour la ville.
//   2011.09.10   MHP   Raccourcissement de la période et attente avant de redécter le train au PN ville.
//   2011.12.20   MHP   Suppression de l'anti-rebond pour la détection des trains et ralentissement des mouvements
//            des barrières.
//   2012.04.01   MHP   Suppression du délai entre 2 détections PN ville car nouveaux circuits de détection unidirectionnels.
//
//   Directives de compilation: PC ou AVR.
//

// Includes standard: types, IO.
#ifdef PC
#include   <stdint.h>
#include   <stdio.h>
#endif

#ifdef AVR
#include <inttypes.h>
#include <avr/io.h>
#endif


// Protothreads.
#include "pt.h"

static struct pt ptGererSignalVille, ptGererBarrieresVille, ptGererSignalGare;


// Timers.
typedef uint16_t   tTimer;

static tTimer   tmrBaisserBarrieresVille, tmrBarrieresVille, tmrClignSignalVille, tmrMvtBarrieresVille;
static tTimer   tmrGareA, tmrGareB, tmrClignSignalGare;

// Tous les délais sont exprimés nombres de périodes de PERIODE millisecondes.
// Période en ms.
#define   PERIODE   10

// La durée durant laquelle le signal fonctionne est exprimée en nombre d'itérations
// plutôt qu'à l'aide d'un timer.
#define DELAI_CLIGN_VILLE   (300/PERIODE)

#define   DUREE_SIGNAL_VILLE   (14000/PERIODE)
#define   NB_ITER_SIGNAL_VILLE   (DUREE_SIGNAL_VILLE/(2*DELAI_CLIGN_VILLE)+1)
#define   DELAI_BAISSER_BARRIERES_VILLE   (400/PERIODE)

// La durée durant laquelle le signal fonctionne est exprimée en nombre d'itérations
// plutôt qu'à l'aide d'un timer.
#define DELAI_CLIGN_GARE   (300/PERIODE)
#define DUREE_SIGNAL_GARE   (8000/PERIODE)
#define NB_ITER_SIGNAL_GARE   (DUREE_SIGNAL_GARE/(2*DELAI_CLIGN_GARE))

// Le délai lorsque les barrières sont à nouveau levées est plus grand que le délai entre
// le début du signal de ville et la descente des barrières.
#define   DELAI_BARRIERES_VILLE   (DUREE_SIGNAL_VILLE - 5*DELAI_BAISSER_BARRIERES_VILLE)
#define   DELAI_SERVO      (60/PERIODE)


// Constantes communes PC et AVR


// Spécifique AVR.
#ifdef AVR

#define F_CPU 1000000UL
#include <util/delay.h>

// Configuration des ports
#define INPUT_VILLE   PD1
#define   INPUT_GARE_A   PD2
#define   INPUT_GARE_B   PD3
#define INPUT_ATTENTE_A   PD4
#define   INPUT_ATTENTE_B   PD5

#define   OUTPUT_SERVO   PB3
#define OUTPUT_SIGNAL_VILLE   PB1
#define   OUTPUT_SIGNAL_GARE   PB0


#define CONFIG_DDRB   (_BV(OUTPUT_SERVO)|_BV(OUTPUT_SIGNAL_VILLE)|_BV(OUTPUT_SIGNAL_GARE))

#define PASSAGE_VILLE   (!(PIND & _BV(INPUT_VILLE)))
#define PASSAGE_GARE_A   (!(PIND & _BV(INPUT_GARE_A)))
#define PASSAGE_GARE_B   (!(PIND & _BV(INPUT_GARE_B)))

#define   CONFIG_PULLUPD   (_BV(INPUT_VILLE)|_BV(INPUT_GARE_A)|_BV(INPUT_GARE_B)|_BV(INPUT_ATTENTE_A)|_BV(INPUT_ATTENTE_B))
#define CONFIG_DDRD   ~CONFIG_PULLUPD

#define   ATTENTE_A   (!(PIND & _BV(INPUT_ATTENTE_A)))
#define   ATTENTE_B   (!(PIND & _BV(INPUT_ATTENTE_B)))

#define   SetClignVille   (PORTB |= _BV(OUTPUT_SIGNAL_VILLE))
#define ClrClignVille   (PORTB &= ~_BV(OUTPUT_SIGNAL_VILLE))

#define   SetClignGare   (PORTB |= _BV(OUTPUT_SIGNAL_GARE))
#define   ClrClignGare   (PORTB &= ~_BV(OUTPUT_SIGNAL_GARE))
#endif

#ifdef PC
// Pour simuler le passage des trains.
static uint8_t   PASSAGE_VILLE, PASSAGE_GARE_A, PASSAGE_GARE_B, ATTENTE_A, ATTENTE_B;
#endif

#define   MIN_SERVO      1000
#define   MAX_SERVO      1900
#define   PAS_SERVO      20

#ifdef AVR

#define CONFIG_TCCR1A   (_BV(COM1A1)|_BV(WGM11))

// Pour le test, prescaler sur 1024.
#if 0
#define CONFIG_TCCR1B   (_BV(CS12)|_BV(CS10)|_BV(WGM12)|_BV(WGM13))
#endif
// Fonctionnement normal, prescaler sur 1.
#define CONFIG_TCCR1B   (_BV(CS10)|_BV(WGM12)|_BV(WGM13))

#define   PERIODE_SERVO      20000
#endif


static PT_THREAD(GererSignalGare(struct pt *pt))
{

   // On doit pouvoir traiter ces événements quelque soit l'endroit où
   // on se trouve dans le protothread.
   if (ATTENTE_A && (tmrGareA > 0))
   {
#ifdef PC
      printf("Train en attente gare A\n");
#endif
      tmrGareA = DUREE_SIGNAL_GARE;
   } // if

   if (ATTENTE_B && (tmrGareB > 0))
   {
#ifdef PC
      printf("Train en attente gare B\n");
#endif
      tmrGareB = DUREE_SIGNAL_GARE;
   } // if

   PT_BEGIN(pt);

   while (1)
   {
      PT_WAIT_UNTIL(pt, PASSAGE_GARE_A || PASSAGE_GARE_B);

      if (PASSAGE_GARE_A && (tmrGareA == 0))
      {
#ifdef PC
         printf("Passage gare A\n");
#endif
         tmrGareA = DUREE_SIGNAL_GARE;
      } // if

      if (PASSAGE_GARE_B && (tmrGareB == 0))
      {
#ifdef PC
         printf("Passage gare B\n");
#endif
         tmrGareB = DUREE_SIGNAL_GARE;
      } // if

      while ((tmrGareA > 0) || (tmrGareB > 0))
      {
#ifdef PC
         printf("Signal gare ON\n");
#endif
#ifdef AVR
         SetClignGare;
#endif

         tmrClignSignalGare = DELAI_CLIGN_GARE;
         PT_WAIT_UNTIL(pt, tmrClignSignalGare == 0);

#ifdef PC
         printf("Signal gare OFF\n");
#endif
#ifdef AVR
         ClrClignGare;
#endif
         tmrClignSignalGare = DELAI_CLIGN_GARE;
         PT_WAIT_UNTIL(pt, tmrClignSignalGare == 0);
      } // while
   } // while

   PT_END(pt);
} // GererSignalGare


static PT_THREAD(GererSignalVille(struct pt *pt))
{
static uint16_t   nIter;

   PT_BEGIN(pt);

   while (1)
   {
      PT_WAIT_UNTIL(pt, PASSAGE_VILLE);

      for (nIter = 0; nIter < NB_ITER_SIGNAL_VILLE; nIter++)
      {
#ifdef PC
         printf("Signal ville ON\n");
#endif
#ifdef AVR
         SetClignVille;
#endif
         tmrClignSignalVille = DELAI_CLIGN_VILLE;
         PT_WAIT_UNTIL(pt, tmrClignSignalVille == 0);

#ifdef PC
         printf("Signal ville OFF\n");
#endif
#ifdef AVR
         ClrClignVille;
#endif
         tmrClignSignalVille = DELAI_CLIGN_VILLE;
         PT_WAIT_UNTIL(pt, tmrClignSignalVille == 0);
      } // for

#ifdef PC
      printf("Fin signal ville\n");
#endif
   } // while

   PT_END(pt);
} // GererSignalVille


static PT_THREAD(GererBarrieresVille(struct pt *pt))
{
static uint16_t   nLen;   // Longueur de l'impulsion des servos.


   PT_BEGIN(pt);

   while (1)
   {
      PT_WAIT_UNTIL(pt, PASSAGE_VILLE);

#ifdef PC
      printf("Attendre pour baisser les barrières\n");
#endif

      tmrBaisserBarrieresVille = DELAI_BAISSER_BARRIERES_VILLE;
      PT_WAIT_UNTIL(pt, tmrBaisserBarrieresVille == 0);

#ifdef PC
      printf("Début baisser les barrières\n");
#endif
      tmrBarrieresVille = DELAI_BARRIERES_VILLE;

      nLen = MIN_SERVO;
      while (nLen <= MAX_SERVO)
      {
#ifdef PC
         printf("Baisser barrières, servo: %0d\n", nLen);
#endif
#ifdef AVR
         OCR1A = nLen;
#endif
         nLen += PAS_SERVO;

         tmrMvtBarrieresVille = DELAI_SERVO;
         PT_WAIT_UNTIL(pt, tmrMvtBarrieresVille == 0);
      } // while

#ifdef PC
      printf("Barrières baissées\n");
#endif
      PT_WAIT_UNTIL(pt, tmrBarrieresVille == 0);

      nLen -= PAS_SERVO;
      while (nLen >= MIN_SERVO)
      {
#ifdef PC
         printf("Lever barrières, servo: %0d\n", nLen);
#endif
#ifdef AVR
         OCR1A = nLen;
#endif
         nLen -= PAS_SERVO;

         tmrMvtBarrieresVille = DELAI_SERVO;
         PT_WAIT_UNTIL(pt, tmrMvtBarrieresVille == 0);
      } // while

#ifdef PC
      printf("Barrières levées\n");
#endif
   } // while

   PT_END(pt);
} // GererBarrieresVille


void main(void)
{
   // Initialiser les protothreads.
   PT_INIT(&ptGererSignalVille);
   PT_INIT(&ptGererBarrieresVille);
   PT_INIT(&ptGererSignalGare);

   // Configuration spécifique AVR.
#ifdef AVR
   DDRD   = CONFIG_DDRD;
   PORTD   = CONFIG_PULLUPD;
   DDRB   = CONFIG_DDRB;

   ICR1 = PERIODE_SERVO;
   OCR1A = MIN_SERVO;   
   TCCR1A = CONFIG_TCCR1A;
   TCCR1B = CONFIG_TCCR1B;
#endif

#ifdef PC
uint16_t   nIter;

   //PASSAGE_VILLE = 1;
   PASSAGE_GARE_A = 1;

   for (nIter = 0; nIter <= 1000; nIter++)
   {
      printf("Temps: %0000d\n", nIter * PERIODE);

      if (nIter == 2)
         PASSAGE_GARE_A = 0;

      if (nIter == 40)
      {
         printf("ATTENTE_A = 1\n");
         ATTENTE_A = 1;
      }
      if (nIter > 45)
         ATTENTE_A = 0;


      if (nIter == 50)
      {
         printf("PASSAGE_GARE = 1\n");
         PASSAGE_GARE_B = 1;
      }
      if (nIter > 50)
         PASSAGE_GARE_B = 0;
#endif

#ifdef AVR
   while (1)
   {
#endif
      // Mettre à jour tous les timers.
      if (tmrBaisserBarrieresVille > 0)   tmrBaisserBarrieresVille--;
      if (tmrBarrieresVille > 0)      tmrBarrieresVille--;
      if (tmrClignSignalVille > 0)      tmrClignSignalVille--;
      if (tmrMvtBarrieresVille > 0)      tmrMvtBarrieresVille--;
      if (tmrGareA > 0)         tmrGareA--;
      if (tmrGareB > 0)         tmrGareB--;
      if (tmrClignSignalGare > 0)      tmrClignSignalGare--;

      // Traiter les événements.
      GererSignalVille(&ptGererSignalVille);
      GererBarrieresVille(&ptGererBarrieresVille);
      GererSignalGare(&ptGererSignalGare);

#ifdef AVR
      _delay_ms(PERIODE);
#endif
   } // while, for
} // main


Julaye

  • Newbie
  • *
  • Messages: 6
    • Voir le profil
Re : Présentation de Julaye
« Réponse #11 le: novembre 02, 2021, 02:25:41 pm »
Re,

@chris_bzg POO oulala ça me rappelle mes cours de PtitLoo à la fac ;) (cf http://www.lirmm.fr/~ferber/Ptitloo/ptitloo.htm)

Je ne vais pas vous apprendre grand chose, vous faites tous pleins de trucs sur les Arduino depuis bien longtemps.

@Marc-Henri Merci pour ces bouts de code très instructif :) Je vais les lire plus en détail, ça donne beaucoup d'idées pour mon automate.

J'avais vu les protothreads que tu mentionnes, c'est effectivement ce que j'envisage d'utiliser pour implémenter des automatismes en // dans mon automate. Beaucoup plus jeune, j'avais implanté des co-routines dans un système embarqué à base de 68HC11. J'allais pour en coder pour l'AVR et j'ai vu que c'était déjà fait lol.

Ton exemple de PN est intéressant, je vais voir si je peux l'implémenter avec le micro code que je propose. J'ai déjà codé un bout de PN dans la doc, mais ton PN est plus complexe.

@+


Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 3039
  • 100% Arduino et N
    • Voir le profil
Re : Présentation de Julaye
« Réponse #12 le: novembre 02, 2021, 06:21:10 pm »
@Marc-Henri,

Ne connaissant pas les protothread, j'ai compilé ton programme PassageNiveau.c et j'ai été obligé de charger la bibliothèque Protothreads (normal), et de changer void main(void) en int main(void) pour qu'il compile sans erreur.
Pourquoi ?

Donc j'ai (toujours) des choses à apprendre...
Merci
Dominique
« Modifié: novembre 03, 2021, 11:09:45 am par Dominique »
Cordialement,
Dominique

savignyexpress

  • Invité
Re : Présentation de Julaye
« Réponse #13 le: novembre 03, 2021, 08:13:01 am »
@Dominique,

Quelques recherches sur le web m'ont permis de voir que void main n'est pas standard, même si certains compilateurs l'acceptent. C'était le cas de la version d'avr-gcc utilisée lors du développement de ce projet, mais cela ne passe plus avec la version actuelle.

Il faut donc bien spécifier int comme type de retour. Je pense que c'est dû au fait qu'un programme en C écrit pour un ordinateur autre qu'un système embarqué doit retourner une valeur à l'issue de son exécution (0: tout s'est bien passé, autre valeur: erreur). Cela ne s'applique évidemment pas à nos programmes constitués d'une boucle principale ne se terminant pas, mais c'est exigé par la plupart des compilateurs.

Meilleures salutations.
« Modifié: novembre 03, 2021, 05:26:20 pm par Marc-Henri »