Go Down

Topic: Controllo servomotori tramite protocollo DMX (Read 219 times) previous topic - next topic

ginopezzini

Buongiorno a tutti,

non ho mai pubblicato nulla fino ad oggi pur essendo iscritto da tempo perchè molte risposte le ho trovate direttamente nel forum, ma stavolta proprio non riesco ad uscirne vivo...Premesso che sono un progettista meccanico e non un elettronico e ne tantomeno un programmatore chiedo con umiltà se qualcuno può darmi gentilmente una mano a capire cosa c'è che non va nel codice che qui allego ( dopo le spiegazioni di cosa è e cosa deve fare ). Ho testato la parte hardware montando i pochi componenti sulla breadboard ed utilizzando codici semplici per ogni funzione e tutto sembra funzionare. Quando carico il software completo sull'Arduino UNO, non ottengo errori ma neppure risultati. Sono quasi sicuro che ci sia un errore di logica nel codice che ho scritto.
Il progetto: voglio comandare 2 o 3 servomotori in funzione del segnale DMX 512 proveniente da una centralina dedicata.  Il segnale DMX512 arriva a un MAX485 il quale agendo da porta seriale RS485 ( grazie alla libreria Conceptinetics https://codebender.cc/library/Conceptinetics#Conceptinetics.cpp )porta il segnale di controllo al pin RX di Arduino UNO. Questi però deve " ascoltare " solo i segnali identificati da un range di canali ( 1-255) impostati tramite DIP switch e spediti ad Arduino tramite uno shift register PISO CD4021B.
Ora, se provo su questo hardware il codice per testare il segnale DMX, funziona; se provo quello per testare la codifica del CD4021B funziona ( non si capisce però il perchè se imposto a ON il DIP 1 come risultato decimale mi viene restituito 2).
La versione del software senza l'implementazione dei canali ( quindi senza shift register , tutto sul canale 1 preimpostato nel codice ) che avevo scritto, funziona tutto egregiamente. Se utilizzo il "filtro" dei canali non funziona più un tubo. Io ho esaurito le mie risorse e mi serve aiuto esterno.
C'è qualche anima caritatevole che mi può aiutare ?

Grazie mille in anticipo

Code: [Select]




#include <Conceptinetics.h>
#include <Servo.h>

//


//imposta la quantità di canali del device.


#define DMX_SLAVE_CHANNELS   3

//definizione dei pin dello shift register
int latchPin = 8;
int dataPin = 9;
int clockPin = 7;

//variabili dei canali DMX
int cn0;
int cn1;
int cn2;

//variabili inizializzate dei valori dei canali DMX;
int valcn0 = 0;
int valcn1 = 0;
int valcn2 = 0;

Servo myservo; //l'oggetto servomotore pan
Servo myservo1;//l'oggetto servomotore tilt
//manca la definizione del terzo servo


byte switchVar1 = 72;  //01001000 inizializza con un numero a caso la variabile restituita dallo switch register


//Configura il dispositivo come Slave
DMX_Slave dmx_slave ( DMX_SLAVE_CHANNELS );




// la routine setup gira una sola volta quando si avvia

void setup() {             
 
  //la riga seguente assegna a switchVar il risultato della funzione shiftIn ovvero il valore
  //del dipswitch
  switchVar1 = shiftIn(dataPin, clockPin);
  cn0 = switchVar1;
  cn1 = switchVar1+1;
  cn2 = switchVar1+2;
 
  // Abilita l'interfaccia slave e comincia a registrare i valori DMX
  dmx_slave.enable (); 
 
  // Imposta come indirizzo iniziale
  //  la variabile restituita dalla funzione di lettura dei dip switch
  dmx_slave.setStartAddress (cn0);
 

 
  //le righe seguenti sono riferite alla lettura dei dipswitch
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, INPUT);
  digitalWrite(latchPin,1);
  delayMicroseconds(20);
  digitalWrite(latchPin,0);
 
  myservo.attach(9);  //il pin del servomotore x il 9
  myservo1.attach(10); //il pin del secondo servomotore y  10

}

//comandi per il movimento dei servo

void loop()
{

valcn0 = dmx_slave.getChannelValue (cn0);//recupera il valore DMX dal canale cn0 
valcn1 = dmx_slave.getChannelValue (cn1);//recupera il valore DMX dal canale cn1
valcn2 = dmx_slave.getChannelValue (cn2);//recupera il valore DMX dal canale cn2


valcn0 = map (valcn0, 0, 255, 0, 179); //mappa la variabile in modo che il range diventi 0 180

myservo.write(valcn0); //fa girare il servo con il valore della variabile 

valcn1 = map (valcn1, 0, 255, 0, 179); //mappa la variabile in modo che il range diventi 0 180
 
myservo1.write(valcn0); //fa girare il servo con il valore della variabile

//manca il codice del terzo servo


delay(15);


}





//La funzione shiftIn è quella che legge il flusso di dati dallo shift register
//NOTA BENE: questa è la versione a un solo shiftregister solo 8 bit -256. dovrà essere
//modificata per utilizzare 2 CD4021B ed ottenere un massimo di 512

byte shiftIn(int myDataPin, int myClockPin) {
  int i;
  int temp = 0;
  int pinState;
  byte myDataIn = 0;

  pinMode(myClockPin, OUTPUT);
  pinMode(myDataPin, INPUT);

  for (i=7; i>=0; i--)
  {
    digitalWrite(myClockPin, 0);
    delayMicroseconds(0.2);
    temp = digitalRead(myDataPin);
    if (temp) {
      pinState = 1;
      //set the bit to 0 no matter what
      myDataIn = myDataIn | (1 << i);
    }
    else {
     
      pinState = 0;
    }

   

    digitalWrite(myClockPin, 1);

  }
 
  return myDataIn;
}



vlc0617

A me pare che ci sia un errore nella lettura del CD4021B.

Il valore dei dipswitch dovrebbe venire caricato nel registro del CD4021B portando il pin di latch HIGH, e poi letto da Arduino con la funzione shiftIn.

Al contrario, nella tua funzione di setup, la funzione shiftIn legge il contenuto del registro interno del CD4021B prima di averlo caricato con i dipswitch

Inoltre hai impostato il pinMode di latchPin, clockPin e dataPin dopo (e non prima) di usare shiftIn.

In sostanza, a mio avviso, la funzione di setup corretta dovrebbe essere questa:

Code: [Select]

void setup() {             
 
// imposti latchPin e clockPin ad OUTPUT, dataPin ad INPUT

  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, INPUT);

// carichi il valore dei dipswitch nel registro del CD4021B

  digitalWrite(latchPin,1);
  delayMicroseconds(20);
  digitalWrite(latchPin,0);
  delayMicroseconds(20);
 
// trasferisci nella variabile switchVar1 il valore caricato nel registro del CD4021B dalle istruzioni precedenti

  switchVar1 = shiftIn(dataPin, clockPin);

//

  cn0 = switchVar1;
  cn1 = switchVar1+1;
  cn2 = switchVar1+2;
 
  // Abilita l'interfaccia slave e comincia a registrare i valori DMX
  dmx_slave.enable (); 
 
  // Imposta come indirizzo iniziale
  //  la variabile restituita dalla funzione di lettura dei dip switch
  dmx_slave.setStartAddress (cn0);
 

  myservo.attach(9);  //il pin del servomotore x il 9
  myservo1.attach(10); //il pin del secondo servomotore y  10

}



ginopezzini

Ti ringrazio sinceramente per il tuo aiuto. Appena mi libero provo a mettere in pratca.

Go Up