Go Down

Topic: TELECOMANDO DTMF (Read 2850 times) previous topic - next topic

Paolo S

Jul 29, 2012, 05:17 pm Last Edit: Jul 30, 2012, 07:39 am by Paolo S Reason: 1
ho praticamente concluso la rima versione funzionante del telecomando DTMF.

Funziona in questo modo.
Il segnale DTMF viene decodificato da un MT8870 (http://pdf1.alldatasheet.com/datasheet-pdf/view/77085/MITEL/MT8870.html), cablato secondo lo schema che c'è a pagina 4.20 e  connesso ad arduino così:
Quote

//ARDUINO           PD3              PD4            PD5              PD6            PD7
//MT8870       PIN 15(STD)     PIN 11(Q1)  PIN 12(Q2)    PIN 13(Q3)    PIN 14(Q4)


su PD3 (pin digitale 3) di arduino, viene impostato l'interrupt in modo RISING... sugli altri 4 pin viene "raccolto", tramite i 4 bit Q1-Q4, il codice del carattere decodificato ...

Il telecomando è organizzato in tre banchi di 8 comandi ciascuno, per n° 24 comandi di tipo ON/OFF, controllabili separatamente.
I comandi di tipo ON/OFF vengono eseguiti attraverso 3 integrati tipo 74HC595 (http://www.nxp.com/documents/data_sheet/74HC_HCT595.pdf) collegati come da qui: (http://www.arduino.cc/en/Tutorial/ShiftOut) con il terzo 74HC595 collegato esattamente come il secondo...

i pin utilizzati per lo shift out sono questi:
const byte dataPin  = A3;   // PIN utilizzati per lo shift register
const byte latchPin = A4;   // 24 uscite indipendenti
const byte clockPin = A5;   //


Per fare le prove io uso questo semplicissimo software, scaricabile gratuitamente da qui (http://www.roadkil.net/program.php/P35/DTMF%20Keypad). Questo software genera i codici con la scheda audio, simulando un tastierino telefonico.
Quindi i comandi vengono inviati al telecomando mandando il segnale audio con i toni DTMF all'ingresso dell'MT8870.

Il comando generico è costituito da una sequenza di caratteri. I caratteri, corrispondenti al tastierino telefonico, sono questi: (0,1,2,3,4,5,6,7,8,9,A,B,C,D,*,#) ovvero 16 caratteri diversi decodificati tramite i 4 bit dall'MT8870 ...

la sequenza generica di caratteri avrà la seguente forma:
XXXXXX*1#1*12#0**   dove
-  XXXXXX è una generica password constituta da n caratteri  (da impostare nel codice prima di compilarlo)..
- l'asterisco è un carattere separatore per separare i vari comandi
- il cancelletto separa il generico comando nelle sue due parti, cioè l'"indirizzo" e l'"azione". L'indirizzo (0...23) corrisponde al pin da accendere| spegnere, e l'azione (0|1) determina l'impostazione del livello alto (1) o basso (0) del generico pin ...

il sistema memorizza sulla eeprom l'ultimo stato di funzionamento eseguito così che all'accensione ripete l'ultimo stato di funzionamento attivato,

nella configurazione, prima di compilarlo, bisogna stabilire, oltre alla password, il numero max di caratteri del buffer ricevili, ed il numero max di comandi che si possono inviare nella medesima sequenza ...

la sequenza deve terminare con due asterischi per inviare la stringa all'analisi, oppure se si supera il n° max di caratteri del buffer, comunque la stringa viene inviata all'analisi ...

Siccome questa è la prima versione funzionante mi farebbe piacere che qualcuno volesse provarlo (anche se non credo sia possibile se non avete in casa un MT8870 con il suo quarzo) , o semplicemente dare una controllata al codice per segnalrmi ogni punto dove si potrebbe migliorare, ottimizzare etc....

per facilitare la (mia) lettura ho suddiviso tutto il codice in sub schede ... e raggrupato le istruzioni collegate da una certa logica, anche più di una sulla stessa riga fino a giungere il risultato atteso (lo so che è contro le regole, ma credo che comunque sia più leggibile)...

adesso aggiungo il sorgente... siccome sono più schede .ino le ho zippate in un'unico file
NB .. non infierite è solo la prima versione destinata ad essere migliorata in ogni sua parte ..

grazie per l'interessamento ciao

m_ri


Paolo S

grazie mri.... ma gli hai dato un'occhiata al codice????..

e nessun'altro gli ha dato un'occhiata????

m_ri

si un'occhiata molto veloce..vedi che hai l'abitudine di usare diversi .ino per lo stesso sketch..

sai com'è,molti sono anche in vacanza :)

lesto

di solito non si usano tanti ino, ma si divide il codice in librerie (.h) o in classi (.h e .cpp)

il vantaggio della classe è che in pratica è una variabile che in realtà continene più variabili e anche funzioni; per esempio Serial è una classe. Volendo potresti dire che sono variabili che al loro interno contengono un mini-programma!
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Paolo S

#5
Aug 23, 2012, 11:09 am Last Edit: Aug 23, 2012, 11:12 am by Paolo S Reason: 1
Grazie lesto.... ma non ho mai capito bene la programmazoine ad oggetti... classi... metodi etc...

scrivo il codice così ad occhio, come facevo nel 1984 con il commodore 16 (e sì... non sono giovanissimo!!!) ....

ho ricominciato da poco ... lo sò... dovrei adeguarmi ai tempi.... ma così, suddividendo in gruppi, più o meno omogenei riesco a tenere facilmente sott'occhio il tutto e questo mi aiuta non poco ....

grazie del tuo parere.. comunque!!!

ciao

sid86

Ecco qua.. in allegato lo sketch modificato per le mie esigenze. Ho usato un secondo arduino e una tastiera a matrice per simulare l'8870 (che arriverà fra poco..)

Se volete lo sketch della tastiera fatemi sapere

leo72


scrivo il codice così ad occhio, come facevo nel 1984 con il commodore 16 (e sì... non sono giovanissimo!!!) ....

Anch'io avevo il C16  XD

sid86

scusate, lo sketch è questo..ho modificato una cosetta inutile. Ah, non ho scritto che questo sketch modificato serve per comandi on/off tramite le porte digitali e analogiche di arduino e non tiene conto dell'uso degli shift register

Paolo S

Grazie SID... ho trascurato per qualche mese a causa di impegni di lavoro... ma sto lavorando alla nuova implemnatzione ovvero:
- risponditore audio che ti guida nell'invio dei comandi ...
- conferma audio dell'esecuzione del comando ON/ OFF
- interrogazione e risposta audio sullo stato dei comandi...

lo sto facendo con questa schedina che ormai mi pare di controllare benino ....
http://arduino.cc/forum/index.php/topic,123046.msg925215.html#msg925215
ciao

sid86

Ciao, io ho modificato ulteriormente il tuo sketch. In quello che posterò ora ho "aggiunto":
-uscita audio (per ora simulato con un buzzer) che mi dice se il comando è corretto o no (variabile comando_tono). Se è corretto fa un bip breve, altrimenti lo fa più lungo. Questo tono verrà poi trasmesso via radio (comando_ptt)
-interrogazione stato delle uscite on/off: con la tua sintassi ho aggiunto, oltre alle azioni 0 e 1, l'azione 3. Se lo stato è on, bip breve, se è off bip lungo (praticamente come sopra).
-Possibilità di cambiare la password con la sintassi psw*0#new_psw**, cioè, quello che viene digitato dopo il # sarà la nuova password
-Possibilità di resettare via software arduino con la sintassi psw*13#0**, così se non ci si ricorda la psw si può reimpostarla a quella di default :)

Non sono un fine programmatore, anzi, non sono proprio un programmatore, quindi le mie sono modifiche molto semplici. Ho adattato lo sketch al mio bisogno.
Lo metto in allegato.

Ho fatto anche una specie di shield da mettere su arduino uno. Provvisoria anche questa :) Però funziona!!

Paolo S


lesto

#12
Oct 20, 2013, 04:51 pm Last Edit: Oct 20, 2013, 04:55 pm by lesto Reason: 1
scusa se mi permetto, però se usi un array per contenere il pin, la dichiarazione e inizializzazione dei pin diventa:

Code: [Select]

int comando[] = {8, 9, 10, 12, 2, 1};

void setup (){
  for (int i=0; i < sizeof(comando); i++){  //ATTENZIONE AL SIZEOF! da usare sempre e SOLO con l'array mai con un puntatore all'array
    pinMode(comando[i],OUTPUT);
    digitalWrite(comando[i],LOW);
    [...] //altro codice tuo
  }


a questo punto a finecodice hai una serie di
Code: [Select]
if (str_I=="1" && str_A=="1") {
        digitalWrite(comando_1,HIGH);
        }
     
     if (str_I=="1" && str_A=="0") {
        digitalWrite(comando_1, LOW);
      }
     
      if (str_I=="1" && str_A=="3") {
        if(digitalRead(comando_1)==HIGH) {
          digitalWrite(comando_tono,HIGH);
          delay(100);
          digitalWrite(comando_tono,LOW);
        }
        if(digitalRead(comando_1)==LOW) {
          digitalWrite(comando_tono,HIGH);
          delay(1000);
          digitalWrite(comando_tono,LOW);
        }
       
         
      }

(a priori, il fatto di usare "0" è errato, perchp con le " fai una stringa, con le ' fai un carattere! così facendo rischi di confrontare l'indirizzo della stringa (che ricordo, è un array di char) con la lettera-numero.
quindi usa le '.)

che diventano una sola volta e generica:
Code: [Select]

for (int i=0; i < sizeof(comando); i++){  //ATTENZIONE AL SIZEOF! da usare sempre e SOLO con l'array mai con un puntatore
  if (str_I==i+'0' && str_A=="1") {
        digitalWrite(comando[i],HIGH);
        }
     
     if (str_I==i+'0' && str_A=="0") {
        digitalWrite(comando[i], LOW);
      }
     
      if (str_I==i+'0' && str_A=="3") {
        if(digitalRead(comando[i])==HIGH) {
          digitalWrite(comando_tono,HIGH);
          delay(100);
          digitalWrite(comando_tono,LOW);
        }
        if(digitalRead(comando[i])==LOW) {
          digitalWrite(comando_tono,HIGH);
          delay(1000);
          digitalWrite(comando_tono,LOW);
        }
       
         
      }


notare che uso un bel trucco: al carattere '0' zero sommo un numero; infatti i caretteri-numero sono uno dopo l'altro nella tabella ascii. PERO' dopo il 9 riprendono altri caratterei della tabella ascii, quindi questo sistema funziona solo da 0 a 9... ma visto che stiamo confrontando UN carattere, il problema non si pone, visto che era una limitazione già intrinseca nel codice.

con questi accorgimentoi il codice dovrebbe essere dimezzato, dal punto di vista sorgente, non so che effetti può avere sul compilato.
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

sid86

wow! è stato riesumato questo topic!
ora leggo le correzioni di lesto, sperando di capirci qualcosa!  :)

Go Up