LOCODUINO
Discussions Générales => Bus DCC => Discussion démarrée par: jpjcb66 le février 17, 2016, 01:34:44 pm
-
Bonjour à tous,
J'ai une loco Roco achetée début des années 2000 équipée d'un décodeur Roco.
Elle fonctionne normalement, lumière et moteur avec le système Roco Transfo 15V 40VA+ centrale 10761 + maus2.
J'ai en bon curieux appliqué "locoduino.org/spip.php?article14 et suivants" en lieu et place du matériel Roco.
Mon décodeur est paramétré en 01.
J'ai donc modifié les deux lignes 36 : dps.setFunctions0to4(1,DCC_SHORT_ADDRESS,F0); et 55 : dps.setSpeed128(1,DCC_SHORT_ADDRESS,speed_byte);
Le moniteur série fait bien ressortir une plage de fonctionnement entre -128 et 128 en actionnant le potar.
Mais ça doit être plus sioux que ça car il n'y a que l'éclairage de la machine qui répond au BP.
J'ai tout relu, ce n'est pas forcément évident.
Quelque chose qui vous semblera certainement évident depuis le temps que vous planchez sur le DCC m’échappe.
Si une idée passe par là..... Je continue à chercher et vais essayer avec le nouveau décodeur reçu ce matin.
Merci
-
Bonjour,
Désolé pour le retard (considérable) !!!
Pour diagnostiquer, il faudrait un peu plus de code. Mais une première expérience à faire consiste à répéter les commandes 2, 3, ou 4 fois par seconde.
Si le code marche pour l'éclairage, ça prouve que l'adresse est bonne.
Pour la vitesse, il est certain que certains décodeurs (peut-être tous) ne réagissent que si la commande est répétée.
Dites-moi si ça change, sinon, envoyez moi votre code.
Bon courage
-
Bonsoir Dominique,
En effet ma question date un peu. J'ai du mettre ça en stand by et passer à autre chose, dont mon aiguillage 3 voies.
Je reviendrai la semaine prochaine sur ce problème Dcc.
Merci pour la reponse même tardive, vieux motard.......
Bonne soirée.
-
Bonjour,
Désolé pour le retard (considérable) !!!
Pour diagnostiquer, il faudrait un peu plus de code. Mais une première expérience à faire consiste à répéter les commandes 2, 3, ou 4 fois par seconde.
Si le code marche pour l'éclairage, ça prouve que l'adresse est bonne.
Pour la vitesse, il est certain que certains décodeurs (peut-être tous) ne réagissent que si la commande est répétée.
Dites-moi si ça change, sinon, envoyez moi votre code.
Bon courage
Voici le code très simple que j'ai voulu tester :
Le bouton active la lumière de la machine mais aucune réaction au potar.
Demain si j'ai le temps de câbler un pupitre j'essaierai ton code bien plus complet.
Bonne soirée et merci pour le coup d’œil.
/********************
* Centrale DCC minimum avec un potentiomètre de vitesse connecté
* sur le port analogique 0,
* un bouton poussoir connecté entre le 0V et l'entrée digitale 4
* Le signal DCC est délivré sur la Pin 9, et est capable de piloter
* un booster à base de LMD18200 directement.
********************/
#include <DCCPacket.h>
#include <DCCPacketQueue.h>
#include <DCCPacketScheduler.h>
DCCPacketScheduler dps;
unsigned int analog_value;
char speed_byte, old_speed = 0;
byte count = 0;
byte prev_state = 1;
byte F0 = 0;
void setup() {
Serial.begin(9600);
dps.setup(); // initialisation de la librairie
// Bouton sur la pin 4
pinMode(4, INPUT_PULLUP);
}
void loop() {
// Lecture de l'état du bouton pour la commande de lumière F0
byte button_state = digitalRead(4); //high == relaché; low == appuyé
if(button_state && (button_state != prev_state))
{
// inversion de l'état
F0 ^= 1;
Serial.println(F0,BIN);
dps.setFunctions0to4(1,DCC_SHORT_ADDRESS,F0); // adresse DCC 1
}
prev_state = button_state;
// Potentiomètre de vitesse
analog_value = analogRead(0);
speed_byte = (analog_value >> 2)-127 ;
// Ramène la gamme 0-1023 à +126-126, l'arrêt étant le point milieu du potentiomètre
if(speed_byte != old_speed)
{
if(speed_byte == 0) // On évite l'arrêt brutal (e_stop) en remplaçant le 0 par 1
{
if(old_speed > 0) speed_byte = 1;
else speed_byte = -1;
}
Serial.print("analog = ");
Serial.println(analog_value, DEC);
Serial.print("digital = ");
Serial.println(speed_byte, DEC);
dps.setSpeed128(1,DCC_SHORT_ADDRESS,speed_byte);
old_speed = speed_byte;
}
// Cet appel est impératif pour permettre à la librairie de faire son travail
dps.update();
}
-
J'aurais tendance à penser qu'il faut ajouter dans le SetUp:
pinMode(A0, INPUT);
Et bien désigner la pin analogique par A0 (plutôt que "0")
Si ça peut vous aider, j'ai écrit une classe Loco en C++ qui contient tout ce qu'on a besoin :
class Loco
{
private:
byte index; // 0..MaxLOCO
byte manette;
bool etat; // arrêt (false) ou roule (true)
int adresseDCC; //
int vitesse; // cran en cours
byte prev_vitesse; //
bool dirloco; // direction avant ou arriere
bool inverse; // inversion ou non de la direction
byte maxSpeed;
byte minSpeed;
byte cran30;
byte cran60;
bool change; // true : changement vitesse, direction, et/ou F0
int potarPin;
int potarLu;
int potarPrev;
int pot[16]; // 16 lectures du potentiometre
int indexpot;
int clePin;
int cleDir;
int clePrev;
int boutonPin;
Bounce bloco;
int ledPin;
int ledAcc;
byte lumiere;
public:
// ----------- constructeur complet ------------
Loco(byte a_index, int a_adresseDCC, int a_potarPin, int a_clePin, int a_boutonPin, int a_ledPin, bool a_inverse);
void Setup();
int adrDCC();
void SetadrDCC(byte a_adresseDCC);
void SetmaxSpeed(byte a_maxSpeed);
void SetminSpeed(byte a_minSpeed);
void Setcran30(byte a_cran30);
void Setcran60(byte a_cran60);
void Rafraichir();
void Repeter();
void Nommer();
void AllerAvant();
void AllerArriere();
void SetVitesse(int a_vitesse);
void Stopper();
void SetVitesse30();
void SetVitesse60();
void ResetVitesse();
void Ralentir();
byte Lumiere();
void SetLumiere(bool a_F0);
byte Direction();
void SetDirection(bool a_Dir);
void EtatLoco();
};
// ------------ definition des methodes -----------
Loco::Loco(byte a_index, int a_adresseDCC, int a_potarPin, int a_clePin, int a_boutonPin, int a_ledPin, bool a_inverse)
{
this->index = a_index;
this->manette = this->index;
this->potarPin = a_potarPin;
this->clePin = a_clePin;
this->boutonPin = a_boutonPin;
this->bloco = Bounce();
this->ledPin = a_ledPin;
this->adresseDCC = a_adresseDCC;
this->inverse = a_inverse;
this->vitesse = 0;
this->prev_vitesse = 0;
this->dirloco = true;
this->etat = false;
this->change = false;
this->ledAcc = 0;
this->lumiere = false;
this->maxSpeed = 125;
this->minSpeed = 2;
this->cran30 = 25;
this->cran60 = 50;
this->indexpot = 0;
}
void Loco::Setup()
{
pinMode(this->ledPin, OUTPUT);
digitalWrite(this->ledPin, HIGH); // Led ON
delay (500);
digitalWrite(this->ledPin, LOW); // Led OFF
pinMode(this->boutonPin, INPUT_PULLUP); // bouton
this->bloco.attach(this->boutonPin); // input pin associée
this->bloco.interval(50); // debouce time en millisecondes
pinMode(this->clePin, INPUT_PULLUP); // direction
this->cleDir = digitalRead(this->clePin);
this->dirloco = this->cleDir;
pinMode(this->potarPin, INPUT); // speed pot
this->potarLu = 0;
this->indexpot = 0;
for (int z=0; z<16; z++) {
this->pot[z] = analogRead(this->potarPin) >> 3;
this->potarLu = this->potarLu + this->pot[z];
}
this->potarLu = this->potarLu >> 4;
this->potarPrev = this->potarLu;
this->vitesse = 00;
if (this->dirloco == 0) { // avant = 1 arriere = 0
this->vitesse = -this->vitesse;
}
digitalWrite(this->ledPin, this->ledAcc);
// chargement des parametres depuis le record en RAM
this->adresseDCC = EEPConfig[this->index].dccAddress;
this->maxSpeed = EEPConfig[this->index].MaxSpeed;
this->minSpeed = EEPConfig[this->index].MinSpeed;
this->cran30 = EEPConfig[this->index].cran30;
this->cran60 = EEPConfig[this->index].cran60;
this->inverse = EEPConfig[this->index].inverse;
}
int Loco::adrDCC()
{
return(this->adresseDCC);
}
void Loco::SetadrDCC(byte a_adresseDCC)
{
this->adresseDCC = a_adresseDCC;
}
void Loco::SetmaxSpeed(byte a_maxSpeed)
{
this->maxSpeed = a_maxSpeed;
}
void Loco::SetminSpeed(byte a_minSpeed)
{
this->minSpeed = a_minSpeed;
}
void Loco::Setcran30(byte a_cran30)
{
this->cran30 = a_cran30;
}
void Loco::Setcran60(byte a_cran60)
{
this->cran60 = a_cran60;
}
void Loco::Rafraichir()
{
this->pot[indexpot++] = analogRead(this->potarPin) >> 3; // divide by 8 to take a 0-1023 range number and make it 0-127 range.
if (indexpot > 15) {indexpot = 0;}
this->potarLu = 0;
for (int z=0; z<16; z++) {
this->potarLu = this->potarLu + this->pot[z];
}
this->potarLu = this->potarLu >> 4;
if ((this->potarLu < this->potarPrev -1)||(this->potarLu > this->potarPrev +1)) {
this->potarPrev = this->potarLu;
if (this->potarLu < this->maxSpeed) {
this->vitesse = this->potarLu;
} else {
this->vitesse = this->maxSpeed;
}
if (this->vitesse == 1) {
this->vitesse = 0; // pour eviter l'arrêt d'urgence par potar
}
this->change = true;
}
this->cleDir = digitalRead(this->clePin);
if (this->cleDir != this->clePrev && this->vitesse == 0) {
this->clePrev = this->cleDir;
this->dirloco = this->cleDir ^ this->inverse; // av1 ^ inv1 = 0, ar0 ^ inv1 = 1
this->change = true;
}
if (this->change) {
this->prev_vitesse = this->vitesse; // version sans signe vs direction
if (this->dirloco == 0) { // avant = 1 arriere = 0
this->vitesse = -this->vitesse;
}
dps.setSpeed128(this->adresseDCC,DCC_SHORT_ADDRESS,this->vitesse);
this->change = false;
bufS[0] = this->index;
if (this->lumiere) {
bitSet(bufS[0], 7); // bit 7 = lumière
}
bufS[1] = this->prev_vitesse; // vitesse sans signe, bit 7 = 0
if (this->dirloco) {
bitSet(bufS[1], 7);
}
CAN.sendMsgBuf(TId_LOCO, 0, 2, bufS); // envoi paramêtres de conduite (Index, Vit, Dir, F0)
if (_debug) {
Serial.print(this->vitesse);
Serial.print(" V loco @ ");
Serial.println(this->adresseDCC);
}
}
if (this->bloco.update()) {
if (this->bloco.rose()) { // appui = 1 relaché = 0 : inversion lumiere
if (this->lumiere) {
this->lumiere = 0;
} else {
this->lumiere = 1;
}
dps.setFunctions0to4(this->adresseDCC,DCC_SHORT_ADDRESS,this->lumiere);
digitalWrite(this->ledPin, this->lumiere);
bufS[0] = this->index;
if (this->lumiere) {
bitSet(bufS[0], 7); // bit 7 = lumière
}
CAN.sendMsgBuf(TId_F0, 0, 1, bufS); // envoi paramêtres index et F0
if (_debug) {
Serial.print(this->lumiere);
Serial.print(" F0 loco @ ");
Serial.println(this->adresseDCC);
}
}
}
}
void Loco::Repeter()
{
dps.setSpeed128(this->adresseDCC,DCC_SHORT_ADDRESS,this->vitesse);
dps.setFunctions0to4(this->adresseDCC,DCC_SHORT_ADDRESS,this->lumiere);
}
void Loco::SetVitesse(int a_vitesse) // definit la vitesse maxi
{
this->maxSpeed = a_vitesse;
if (this->prev_vitesse > a_vitesse) { // réduire la vitesse seulement si la vitesse maxi est inférieure
this->vitesse = a_vitesse;
this->prev_vitesse = a_vitesse; // version sans signe vs direction
if (this->dirloco == 0) { // avant = 1 arriere = 0
this->vitesse = -this->vitesse;
}
dps.setSpeed128(this->adresseDCC,DCC_SHORT_ADDRESS,this->vitesse);
bufS[0] = this->index;
if (this->lumiere) {
bitSet(bufS[0], 7); // bit 7 = lumière
}
bufS[1] = this->prev_vitesse; // vitesse sans signe, bit 7 = 0
if (this->dirloco) {
bitSet(bufS[1], 7);
}
CAN.sendMsgBuf(TId_LOCO, 0, 2, bufS); // envoi paramêtres de conduite (Index, Vit, Dir, F0)
if (_debug) {
Serial.print(this->vitesse);
Serial.print(" V loco @ ");
Serial.println(this->adresseDCC);
}
} // sinon pas de changement de vitesse
}
void Loco::Stopper()
{
SetVitesse(0);
}
void Loco::SetVitesse30()
{
SetVitesse(this->cran30);
}
void Loco::SetVitesse60()
{
SetVitesse(this->cran60);
}
void Loco::ResetVitesse() // remonte la vitesse maxi à maxSpeed
{
SetVitesse(this->maxSpeed);
}
void Loco::SetLumiere(bool a_F0)
{
this->lumiere = a_F0;
dps.setFunctions0to4(this->adresseDCC,DCC_SHORT_ADDRESS,this->lumiere);
digitalWrite(this->ledPin, this->lumiere);
bufS[0] = this->index;
if (this->lumiere) {
bitSet(bufS[0], 7); // bit 7 = lumière
}
CAN.sendMsgBuf(TId_F0, 0, 1, bufS); // envoi paramêtres index et F0
if (_debug) {
Serial.print(this->lumiere);
Serial.print(" F0 loco @ ");
Serial.println(this->adresseDCC);
}
}
byte Loco::Lumiere()
{
return(this->lumiere);
}
void Loco::SetDirection(bool a_Dir)
{
this->dirloco = a_Dir;
}
byte Loco::Direction()
{
return(this->dirloco);
}
Je n'aime pas les potentiomètres de vitesse à point milieu (on ne trouve jamais le milieu !!!), donc j'ai une clé pour la direction. D'ailleurs j'interdis le changement de sens sans passer par l'arrêt.
Tenez moi au courant !
Cordialement
-
OK merci Dominique pour votre réponse.
Je vais essayer ça ainsi que l'application du très bel article "Comment piloter trains et accessoires en DCC avec un Arduino". Bravo pour ce travail.
Cdlt JP
-
En fait le court sketch du 30/04 un peu plus haut fonctionne avec un décodeur ESU54400 sur le canal 2
Par contre pour l'instant le décodeur du début des années 2000 ne fonctionne qu'au niveau éclairage avec ce sketch.
Les deux fonctionnent ou fonctionnaient plus exactement avec le kit Roco 10761 et la Lok Maus 2. car une maladresse a mis un terme à la vie des étages de puissance de la digitalbox 10761 : voir les flèches.
Sur la Maus 2 le potar de commande comporte un encliquetage qui permet de sentir le point 0.
Je reconnais qu'avec un potentiomètre normal "ça ne le fait pas".
Je vais donc m'orienter vers la solution d'un switch inverseur en étudiant votre travail.
L'idéal serait de remplacer cette digitalbox en logique câblée (74HCxxx) et autres nands et trigger de scmitt) par une box à base d'arduino avec les mêmes fonctions. Il y a plus de 15 ans entre ces deux technologies.
Je ne doute pas que Roco a évolué depuis. Ses prix aussi....
(http://jp-jacobee.fr/ARDUINO/Roco10761.png)
-
Comme quoi, avant d'accuser le code ... ;D ;D ;D
-
L'idéal serait de remplacer cette digitalbox en logique câblée (74HCxxx) et autres nands et trigger de scmitt) par une box à base d'arduino avec les mêmes fonctions. Il y a plus de 15 ans entre ces deux technologies.
Avec tout ce que vous allez encore découvrir sur Locoduino, sur le thème de la génération DCC, je ne doute pas que vous allez la faire vous-même, cette box ;)
Il y a des choses dans les cartons ou un coin de tête. Il faut juste qu'on trouve le temps...
-
Comme quoi, avant d'accuser le code ... ;D ;D ;D
Je te soupçonne de m'avoir lu en digonale Denis ! :D ;)
Le code n'y est pour rien dans le décès accidentel de mon booster Roco.
C'est juste mon bordelisme qui est en cause. Durant les essais de mon aiguillage triple un malicieux Bout de fil dénudé m'a permis de goûter le délicat fumet du composant qui grille ! :o :-[
C'est après que je suis revenu contraint et forcé à l'arduino.
Et au passionnant article de Dominique qui en effet m'a motivé pour piloter mes locos via l'arduino.
Mais il y a du travail, la bibliothèque DCC m'est a ce stade d'un abord assaz mystérieux.
Bonne soirée.
-
D'ailleurs il ne faut surtout pas oublier la détection de court-circuit, merci d'avoir pointé cette questions !
-
D'ailleurs il ne faut surtout pas oublier la détection de court-circuit, merci d'avoir pointé cette questions !
Oh !J e ne l'ai pas pointée à dessin, j'ai juste avoué une belle négligence. D'ailleurs je crois que la dernière version Roco Centrale Ampli 10764 a anticipé mes distractions.
Malheureusement j'avais la génération 10761.
Il me semble que ce problème est décrit et résolu dans "Comment piloter trains et accessoires en DCC avec un Arduino (3)" à propos des sorties C/S et T/S du LMD18200 et amélioré avec le petit module Max471.
J'y retourne... J'aimerais utiliser F1....F4 :D
-
Je crois que c'est le moins cher que j'ai trouvé (7,92€) !
http://www.ebay.fr/ulk/itm/252503593836 (http://www.ebay.fr/ulk/itm/252503593836)