Firmata e relè.

Chiedo aiuto per un problema che mi sta assillando. Ho costruito un mixer audio e video per poter controllare un software di video streaming (Vmix). Questo software genera dei comandi per poter accendere o spegnere delle luci (tally lights) tramite Standard Firmata e sappiamo tutti che i pin digitali di Arduino generano 5V. Collegando dei semplici led il tutto funziona perfettamente e cioè quando dal PC arriva uno stato high i led si accendono mentre quando arriva uno stato low, questi si spengono. Ora, poichè ho bisogno di alimentare delle lampade con un alimentatore da 12V sono ricorso ad un modulo di relè ma il problema che penso conosciate è che questi moduli eccitano i relè con uno stato low e li staccano con uno stato high. La domanda è se c'è un modo, magari modificando lo sketch Standard Firmata, in modo che quando dal Pc arriva uno stato high venga convertito in low e viceversa. Grazie in anticipo per gli eventuali suggerimenti.

I relay dovrebbero avere 3 uscite, una in comune, una per normalmente aperto e una per normalmente chiuso. Perlomeno tutti i relay provenienti da moduli che ho avuto per le mani io e che ho visto. I tuoi come sono? Perchè se hanno le 3 uscite puoi decidere lato hardware come farli aprire e chiudere in base allo stato high e low.

TheAlexx3c:
I relay dovrebbero avere 3 uscite, una in comune, una per normalmente aperto e una per normalmente chiuso. Perlomeno tutti i relay provenienti da moduli che ho avuto per le mani io e che ho visto. I tuoi come sono? Perchè se hanno le 3 uscite puoi decidere lato hardware come farli prime e chiudere in base allo stato high e low.

Infatti è un modo per farli funzionare. il problema risiede nel fatto che però in stato di spento che è lo stato normale i relè rimangono eccitati fino a quando non ricevono un comando low e non credo gli faccia molto bene.

spino50:
Infatti è un modo per farli funzionare. il problema risiede nel fatto che però in stato di spento che è lo stato normale i relè rimangono eccitati fino a quando non ricevono un comando low e non credo gli faccia molto bene.

Allora, i relay dovrebbero essere normalmente aperti. Percui senza segnale stanno aperti e non conducono.

Tu hai bisogno di

  • high su pin---->relay chiuso----> +12v connessa
  • low su pin----->Relay aperto----> +12V sconnessa

Puoi postare lo sketch?

Così magari se passa qualcuno più esperto può aiutarti in maniera migliore.

Intanto puoi provare così:

void loop(){
  
val = digitalRead("Inserire pin");  // read input value
  if (val == HIGH) {         // check if the input is HIGH
    digitalWrite("Inserire pin", LOW);  // turn OFF
  } else {
    digitalWrite("Inserire pin", HIGH);  // turn ON
  }
}

lo sketch è standard firmata negli esempi dell'ide nel menu firmata.

Devi cercare dove esegue la funzione che gli richiedi e modificare il software ...

Esempio, l'attivazione o disattivazione di un pin digitale è eseguita dalla piccola funzione che so trova alle righe 364-378:

/*
 * Sets the value of an individual pin. Useful if you want to set a pin value but
 * are not tracking the digital port state.
 * Can only be used on pins configured as OUTPUT.
 * Cannot be used to enable pull-ups on Digital INPUT pins.
 */
void setPinValueCallback(byte pin, int value)
{
  if (pin < TOTAL_PINS && IS_PIN_DIGITAL(pin)) {
    if (Firmata.getPinMode(pin) == OUTPUT) {
      Firmata.setPinState(pin, value);
      digitalWrite(PIN_TO_DIGITAL(pin), value);
    }
  }
}

come vedi se prima di fare la digitalWrite() di "value" lo inverti, ottieni, per quella funzione, quello che ti serve.

Ripeto, NON so se la tua applicazione richiama esattamente qerlla funzione, comunque l'esempio che ti ho fatto ti spiega come ti devi muovere.

Guglielmo

Fai uno XOR della uscita
digitalWrite(pin, pinstate ^ 1)
Da questo, con pinstate si può usare i valori usuali.

gpb01:
Devi cercare dove esegue la funzione che gli richiedi e modificare il software ...

Esempio, l'attivazione o disattivazione di un pin digitale è eseguita dalla piccola funzione che so trova alle righe 364-378:

/*
  • Sets the value of an individual pin. Useful if you want to set a pin value but
  • are not tracking the digital port state.
  • Can only be used on pins configured as OUTPUT.
  • Cannot be used to enable pull-ups on Digital INPUT pins.
    */
    void setPinValueCallback(byte pin, int value)
    {
      if (pin < TOTAL_PINS && IS_PIN_DIGITAL(pin)) {
        if (Firmata.getPinMode(pin) == OUTPUT) {
          Firmata.setPinState(pin, value);
          digitalWrite(PIN_TO_DIGITAL(pin), value);
        }
      }
    }



come vedi se prima di fare la digitalWrite() di "value" **lo inverti**, ottieni, per quella funzione, quello che ti serve.

Ripeto, NON so se la tua applicazione richiama esattamente qerlla funzione, comunque l'esempio che ti ho fatto ti spiega come ti devi muovere.

Guglielmo

Intanto grazie per la risposta. Quindi, se ho capito bene, per invertire lo stato ad esempio del pin 2, dovrei cambiare quella parte in questo modo:

void setPinValueCallback(byte pin, int value)
{
if (pin < TOTAL_PINS && IS_PIN_DIGITAL(pin)) {
if (Firmata.getPinMode(pin) == OUTPUT) {
Firmata.setPinState(2, HIGH);
digitalWrite(PIN_TO_DIGITAL(2), LOW);
}
}
}

E' corretto?

NO, quella funzione è generica per TUTTI i pin e non puoi metterci dentro né un numero di pin fisso, né un livello fisso ...

O hai tutti i pin che lavorano in modo invertito (attivi LOW) o tutti in modo normale (attivi HIGH).

Se la condizione invertita è solo per alcuni pin ... dovrai fare, dentro quella funzione, all'inizio, o una serie di IF, o uno switch/case, per cambiare il valore della variabile "value" solo per i pin che sono attivi LOW, SENZA toccare il resto del codice.

Guglielmo

ExperimentUno:
Fai uno XOR della uscita
digitalWrite(pin, pinstate ^ 1)
Da questo, con pinstate si può usare i valori usuali.

Scusami ma non ho la base di conoscenza per attuare quanto da te consigliato: potresti farmi un esempio di codice?

Intanto ... hai TUTTI i pin che devono lavorare in modalità invertita o solo alcuni ? E, se solo alcuni, quali sono questi alcuni ?

Guglielmo

gpb01:
NO, quella funzione è generica per TUTTI i pin e non puoi metterci dentro né un numero di pin fisso, né un livello fisso ...

O hai tutti i pin che lavorano in modo invertito (attivi LOW) o tutti in modo normale (attivi HIGH).

Se la condizione invertita è solo per alcuni pin ... dovrai fare, dentro quella funzione, all'inizio, o una serie di IF, o uno switch/case, per cambiare il valore della variabile "value" solo per i pin che sono attivi LOW, SENZA toccare il resto del codice.

Guglielmo

.... e quindi così?:

void setPinValueCallback(byte pin, int value)
{
if (pin < TOTAL_PINS && IS_PIN_DIGITAL(pin)) {
if (Firmata.getPinMode(pin) == OUTPUT) {
Firmata.setPinState(pin, HIGH);
digitalWrite(PIN_TO_DIGITAL(pin), LOW);
}
}
}

gpb01:
Intanto ... hai TUTTI i pin che devono lavorare in modalità invertita o solo alcuni ? E, se solo alcuni, quali sono questi alcuni ?

Guglielmo

Tutti devono lavorare in modalità invertita.

spino50:
.... e quindi così?:

... ma leggi quanto scrivo ? ? ? :o :o :o

gpb01:
NO, quella funzione è generica per TUTTI i pin e non puoi metterci dentro né un numero di pin fisso, né un livello fisso ...

Guglielmo

spino50:
Tutti devono lavorare in modalità invertita.

Se è per tutti la cosa è più facile ...

void setPinValueCallback(byte pin, int value)
{
  if (pin < TOTAL_PINS && IS_PIN_DIGITAL(pin)) {
    if (Firmata.getPinMode(pin) == OUTPUT) {
      value = !value;  // inverto il valore di value, se LOW diventa HIGH e viceversa
      Firmata.setPinState(pin, value);
      digitalWrite(PIN_TO_DIGITAL(pin), value);
    }
  }
}

... sempre che, come ho detto all'inizio, la funzione coinvolta sia questa !!!

Non uso firmata, ma ho semplicemente guardato il programma che hai indicato ...
Nota che, per capire qualche cosa di quello che fai, dovresti studiartelo bene ... ::slight_smile:

Guglielmo

gpb01:
Se è per tutti la cosa è più facile ...

void setPinValueCallback(byte pin, int value)

{
  if (pin < TOTAL_PINS && IS_PIN_DIGITAL(pin)) {
    if (Firmata.getPinMode(pin) == OUTPUT) {
      value = !value;  // inverto il valore di value, se LOW diventa HIGH e viceversa
      Firmata.setPinState(pin, value);
      digitalWrite(PIN_TO_DIGITAL(pin), value);
    }
  }
}




... **sempre che**, come ho detto all'inizio, **la funzione coinvolta sia questa** !!!

Non uso firmata, ma ho semplicemente guardato il programma che hai indicato ... 
Nota che, per capire qualche cosa di quello che fai, dovresti studiartelo bene ... ::)

Guglielmo

Provato ma non inverte nulla.

... perché probabilmente allora NON è quella la funzione coinvolta, ma viene chiamata qualche altra funzione.

Come detto, se vuoi uscirne, tocca che ti studi BENE tutto il codice e vedi, con i comandi che dai tu, quale è la funzione che viene chiamata.

Quel programma è, in pratica, un "interprete" di comandi che tu mandi dalla tua app ... occorre vedere DOVE interpreta i comandi che gli dai ...

Se non sei in grado, l'unica è che inverti con un integrato esterno (es. CD4069) il livello dei segnali ... ::slight_smile:

Guglielmo

Purtroppo l'applicazione che manda il segnale dal PC non è mia ma di un programma di video streaming sul quale ovviamente non posso intervenire.
Vabbè cercherò di contattare gli sviluppatori di quel software per capire se possono fare qualcosa.
Grazie comunque.

Secondo me bisogna anche modificare la funzione
void digitalWriteCallback(byte port, int value)

Inoltre, se usi solo pin digitali e sono ON/OFF (no servo, pwm o altro)
puoi usare SimpleDigitalFirmata.ino versione semplificata rispetto a StandardFirmata

nid69ita:
Secondo me bisogna anche modificare la funzione
void digitalWriteCallback(byte port, int value)

Dato il nome ... è molto probabile :smiley: :smiley: :D, ma ... come detto ... NON uso firmata e gli avevo già segnalato che occorreva studiarsi bene il codice per vedere se c'erano altre possibilità ... :wink:

Guglielmo