Auteur Sujet: Gestion du bus I2C par l'UAD et contrôle de l'ensemble par la CS2  (Lu 1535 fois)

maxou9914

  • Newbie
  • *
  • Messages: 28
    • Voir le profil
Gestion du bus I2C par l'UAD et contrôle de l'ensemble par la CS2
« le: septembre 25, 2015, 10:18:53 pm »
Bonjour,

Mon projet consiste à :

Objectif :

1- le PRINCIPAL - Remplacement des moteurs marklin par des servos (marre de les changer tous les mois !!)

2 - le secondaire  - Gestion des éclairages (candélabres et maison) et des moteurs de grue ou d'attraction

Contrainte :

Pilotable par la CS2

Avec la bibliothèque UAD j'ai réussi  modifier le programme pour contrôler 5 servo et 3 commandes de lumières à partir de commande DCC.

#include "UniversalAccessoryDecoder.h"
#define kDCC_INTERRUPT            3

#define AccessoryServoNumber      2

#define SERVO1 0
#define SERVO2 1

#define AccessoryMotorLightNumber      3

#define LIGHT1 2
#define LIGHT2 3
#define LIGHT3 4

#define LIGHT1_PORT 0
#define LIGHT2_PORT 1
#define LIGHT3_PORT 2

// Accessories

Accessories accessories;
DccCommander dccCommander;
AccessoryGroup groupServos;
AccessoryGroup groupLights;

// Drivers

DriverArduino *arduino;

//////////////////////////////////
//
// Setup
//
void setup()
{
  UAD_StartSetup();

  // Setup of Dcc commander
  dccCommander.Setup(0x00, 0x00, kDCC_INTERRUPT);
  dccCommander.SetStatusLedPin(13);


  // Drivers setups

  arduino = new DriverArduino(AccessoryMotorLightNumber, AccessoryServoNumber);
  arduino->Setup();
  arduino->SetupPortServo(SERVO1, 2); //sortie arduino
  arduino->SetupPortServo(SERVO2, 3); //sortie arduino

  arduino->SetupPortMotor(LIGHT1_PORT, 9, ANALOG); //sortie arduino
  arduino->SetupPortMotor(LIGHT2_PORT, 10, ANALOG); //sortie arduino
  arduino->SetupPortMotor(LIGHT3_PORT, 11, ANALOG); //sortie arduino

  // Accessories setups

  accessories.Setup(
    AccessoryMotorLightNumber + AccessoryServoNumber,

    new AccessoryServo(999, 0, 0), // (address DCC, sous address, durée activation )
    new AccessoryServo(999, 0, 0), // (address DCC, sous address, durée activation )
    new AccessoryLight(1, 0), //(address DCC, sous address, durée activation )
    new AccessoryLight(1, 1), //(address DCC, sous address, durée activation )
    new AccessoryLight(2, 0) //(address DCC, sous address, durée activation )
  );


  SERVO(accessories, SERVO1)->Setup(arduino, SERVO1, 10, 150); // Définition du servo: ( drivers, port de sortie, angle1 , angle 2)
  SERVO(accessories, SERVO2)->Setup(arduino, SERVO2, 10, 150); // Définition du servo: ( drivers, port de sortie, angle1 , angle 2)
  LIGHT(accessories, LIGHT1)->Setup(arduino, LIGHT1_PORT);
  LIGHT(accessories, LIGHT2)->Setup(arduino, LIGHT2_PORT);
  LIGHT(accessories, LIGHT3)->Setup(arduino, LIGHT3_PORT);



  //Servo1
  GroupState *pServo1_1 = new GroupState(320, 0, true); //(Addresse DCC, sous addresse, activation simultané)
  pServo1_1->Setup(1, new GroupStateItem(accessories[SERVO1], MINIMUM)); //(port arduino, choix angle mini ou maxi, délai entre 2 action))

  GroupState *pServo1_2 = new GroupState(320, 1, true);
  pServo1_2->Setup(1, new GroupStateItem(accessories[SERVO1], MAXIMUM));


  //Servo2
  GroupState *pServo2_1 = new GroupState(319, 0, true); //(Addresse DCC, sous addresse, activation simultané)
  pServo2_1->Setup(1, new GroupStateItem(accessories[SERVO2], MINIMUM)); //(port arduino, choix angle mini ou maxi, délai entre 2 action))

  GroupState *pServo2_2 = new GroupState(319, 1, true);
  pServo2_2->Setup(1, new GroupStateItem(accessories[SERVO2], MAXIMUM));

  //Liste des actions servo
  groupServos.Setup(4, pServo2_1, pServo2_2, pServo1_1, pServo1_2); // fusion des 2 actions

 

    // LIGHT 1
GroupState *pLight1_1 = new GroupState(318, 0, true);
pLight1_1->Setup(1,new GroupStateItem(accessories[LIGHT1], LIGHTON));
GroupState *pLight1_2 = new GroupState(318, 1, true);
pLight1_2->Setup(1,new GroupStateItem(accessories[LIGHT1], LIGHTOFF));

    // LIGHT 2
GroupState *pLight2_1 = new GroupState(317, 0, true);
pLight2_1->Setup(1,new GroupStateItem(accessories[LIGHT2], LIGHTON));
GroupState *pLight2_2 = new GroupState(317, 1, true);
pLight2_2->Setup(1,new GroupStateItem(accessories[LIGHT2], LIGHTOFF));

    // LIGHT 3
GroupState *pLight3_1 = new GroupState(316, 0, true);
pLight3_1->Setup(1,new GroupStateItem(accessories[LIGHT3], LIGHTON));
GroupState *pLight3_2 = new GroupState(316, 1, true);
pLight3_2->Setup(1,new GroupStateItem(accessories[LIGHT3], LIGHTOFF));


    // One group state with lights on/off/on, for Dcc code 319/0.
groupLights.Setup(6, pLight1_1, pLight1_2, pLight2_1, pLight2_2, pLight3_1, pLight3_2);




  UAD_EndSetup();
}

void loop()
{
  if (dccCommander.Loop())
  {

    accessories.Loop();
    groupServos.Loop();
    groupLights.Loop();
  }
}

Le problème étant que l'arduino (dans mon cas un mega) ne permet pas d'utiliser plusieurs servo en même temps, pour cela il existe :

soit des Shield de control de moteur + servo  exemple mais limité à 2 servos par shield

ou

Adafruit Controleur PWM Servo 16 canaux 12 bits - I2C interface - PCA9685 exemple avec 16 sorties PWM ( servo ou leds) et montage en série possible par le bus I2C (limite 900).


Mais (bas oui :) ) le problème est que la bibliothèque ne permet pas (encore) de contrôler les ports par l'interface I2C.

De même pour le contrôle de lumière voulant repartir de l'autre bibliothèque light permettant de créer différents effet lumineux je me suis rendu compte que la bibliothèque ne permet pas de "commuter" une instruction

il m'est donc venu l'idée de rendre la bibliothèque plus modulable en y ajoutant( si possible) une commande DCC pointant vers une instruction que le peut écrire dans la partie Setup.

Exemple :

Aujourd’hui :
la CS2 envoie le code DCC 320:1 -> arduino reçoit le code DCC  -> commute le port de l'arduino associé au code dcc
la CS2 envoie le code DCC 320:0 -> arduino reçoit le code DCC  -> commute le port de l'arduino associé au code dcc

Mon idée :
la CS2 envoie le code DCC 320:1 -> arduino reçoit le code DCC  -> active l'instruction associé au code dcc -> envoie les données sur un bus (I2C - CAN - autre ) ou active un sous-programme de gestion de lumière ou moteur)
la CS2 envoie le code DCC 320:0 -> arduino reçoit le code DCC  -> désactive l'instruction associé au code dcc -> envoie les données sur un bus (I2C - CAN - autre ) ou désactive un sous-programme de gestion de lumière ou moteur)

On peut aussi remplacer une instruction par une variable ( vrai ou faux).

En conclusion la programmation peut se révéler plus complexe du fait de la personnalisation, mais laisse une liberté supplémentaire et des possibilités presque infini du fait de l'utilisation du bus I2C et non limité au nombre de sorties de l'arduino.


J’espère avoir été clair  ;D et savoir si il est possible d'améliorer la bibliothèque dans ce sens.


Et je remercie les personnes ayant déjà réalisé tous ce travail !!!!!!!

Bonne soirée.





Thierry

  • Global Moderator
  • Sr. Member
  • *****
  • Messages: 472
    • Voir le profil
Re : Gestion du bus I2C par l'UAD et contrôle de l'ensemble par la CS2
« Réponse #1 le: septembre 25, 2015, 11:41:36 pm »
C'est une bonne idée, et une extension possible pour UAD. Lorsque ça marchera et si tu le permet, je verrai pour l'inclure dans la librairie !

Jean-Luc

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1403
    • Voir le profil
Re : Gestion du bus I2C par l'UAD et contrôle de l'ensemble par la CS2
« Réponse #2 le: octobre 09, 2015, 03:40:44 pm »
Bonjour,

Le problème étant que l'arduino (dans mon cas un mega) ne permet pas d'utiliser plusieurs servo en même temps,

D'après la doc, le Mega permet de contrôler 48 servos en même temps.
Cordialement