Go Down

Topic: Barriera Infrarossi (Read 11 times) previous topic - next topic

Michele Menniti

Jul 24, 2011, 12:02 pm Last Edit: Mar 18, 2013, 10:42 pm by Michele Menniti Reason: 1
NOTA: ci troviamo spesso a consigliare la lettura di questo Topic, le ragioni valide sono diverse:
1 - trovate il codice per generare 38KHz direttamente con i timer dei micro, sia ATmega328 che ATiny85, in modo indipendente dal resto del software, nel caso del 328 addirittura può continuare a lavorare perfino mettendo il micro in stand-by (parziale ovviamente)
2 - trovate info interessanti sul dialogo IR in generale
3 - trovate il codice per mandare in sleep i due micro e per svegliarli mediante interrupt
4 - trovate un sacco di fesserie scritte dal sottoscritto, per farvi due risate, la forte inesperienza di allora, non che ora vada meglio.....


Devo realizzare un controllo tipo barriera infrarossi. Uso un LED IR per la trasmissione ed un TSOP per la ricezione, con questa coppia sono piuttosto immune da disturbi esterni, anche se devo ancora fare prove serie. Il LED devo farlo lavorare, come noto, a 38KHz. Con questo semplice CODE:
Code: [Select]
/*
 Controllo trasmissione IR
*/

void setup() {                

 pinMode(3, OUTPUT);    
}

void loop() {
   
  digitalWrite(3, HIGH);   // set the LED on
  delayMicroseconds(8);              // wait for a second
  digitalWrite(3, LOW);    // set the LED off
  delayMicroseconds(9);              // wait for a second
 
}
ottengo una frequenza di 37,78KHz, più che sufficiente, visto che il range di lavoro del TSOP va da 36 a 42KHz circa (sperimentati). Vorrei però riuscire ad ottenere la frequenza esatta, non tanto per questo circuito ma per altre esigenze in generale, ma mi sono reso conto che il delayMicroseconds ignora i valori decimali. Allora mi sono "rivolto" al pwm perché ricordavo di aver visto una sintassi particolare a tre valori, proprio col comando PWM, che però non trovo, e con analogWrite la frequenza è di circa 500Hz e la variazione del duty cicle ovviamente non serve a nulla nel mio caso.
Mi rassegno?
Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

astrobeed

Riciclare il codice d'esempio che ti avevo dato per generare i 40kHz per le capsule ultrasoniche ?
Code: [Select]

/*
Generatore di impulsi 40 kHz
*/

byte i,j,stato=0;

void setup()
{
  pinMode(13, OUTPUT);     
  pinMode(2,  OUTPUT);   
  digitalWrite(13, HIGH); 
}

void loop()
{
for(j=0;j<255;j++)
{
  stato ^= 1;
  digitalWrite(2,stato);
  for(i=0;i<9;i++)
   {
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
   }
  }

//delay(25);
}


Agendo sul numero delle nop e dei cicli for puoi ottenere una frequenza di 38 kHz esatti.

Michele Menniti

:smiley-red:, l'unica scusa che riesco ad inventarmi è quella (vera) che non mi sono ancora messo a lavorare con gli ultrasuoni e questo codice era ben conservato nella specifica cartellina.
Provo subito, dò per scontato che risolvo (ovviamente!) e quindi sollevo il problema successivo:
Dopo x tempo di NON interruzione del fascio devo mandare in sleep il micro, e fin qui va tutto bene, ma così spengo il LED ed il TSOP va HIGH e mi attiva l'interrupt e riaccende tutto  :smiley-eek:; non t'inczz, chiarisco subito:
Il micro è attivo e la barriera funziona (TSOPout a LOW)
Quando viene interrotta (TSOPout a HIGH) il micro svolge la sua azione di controllo (p.es. un led, un relé, ecc.).
Cosa vorrei fare ora:
Se non viene interrotta per x tempo il micro si spegne, ma dovrebbe restare attiva la barriera, in modo da riaccendere il micro. Usando un tiny85 non dispongo p.es. della separazione di alimentazione dell'ADC altrimenti pensavo di lasciare accesa questa sezione sperando di usarla.
Allora ho notato questa cosa interessante:
Se alimento il LED a tensione fissa a 5V il TSOP ovviamente resta in HIGH, però se interrompo il fascio, al ripristino il TSOP mi dà un impulso LOW e poi torna su HIGH, come se per un'istante ricevesse la frequenza giusta; potrei invertirmi la logica di questo comportamento, ma il problema è che l'impulso ce l'ho non all'interruzione del fascio ma alla fine, quando ormai tutto è ritornato normale.
Che dici metto un 555 e non se ne parla più? Anche se questo va contro l'idea del risparmio energetico, visto che il 555 in azione mi consuma più del micro, credo.
Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

Marbi

Innanzitutto saluto Menniti, Astrobeed e tutti i partecipanti del forum,
sto cercando di capire cosa svolge la routine asm, ma cercando su "san google" sono riuscito a capire che serve per implementare uno straccio di codice in assembly, non riuscendo a spiegarmi cosa centri con la possibilità di avere 40kHz esatte mi chiedevo:


  • asm serve veramente a ad implementare del codice assemly?

  • è una questione di "calcoli" sugli intervalli di tempo?

asm viene ripetuto 2560 volte in un loop
vuol dire che asm impiega 0,015625 hz?
  • perchè proprio da 25?

  • la stringa "nop" è un parametro costante o potevo scriverci anche "abc" ? e "pippo"?


Non dovrebbe interrompersi sul passaggio? (quindi LOW) e se "si vedono" dare un HIGH?
Sto facendo troppe domande :)?

Marbi

[/list]

Michele Menniti

#4
Jul 24, 2011, 12:52 pm Last Edit: Jul 24, 2011, 12:57 pm by menniti Reason: 1
Ciao Marbi, mi pare che NOP stia per "not operation", comunque leggi qui
Comunque è un parametro, non puoi scrivere abc.
Tutto quello schetch serve per "tarare" la frequenza sul pin 2 a circa 40KHz
Il TSOP funziona come ho detto: LOW se si vedono e HIGH se non si vedono.
Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

Michele Menniti

@ astrobeed: secondo le mie misure lo sketch fornisce una frequenza di 39857 Hz, ho fatto un po' di prove e non riesco comunque ad ottenere 40KHz o 38KHz, a questo punto va benissimo qualsiasi valore, siamo vicinissimi alle frequenze richieste ed i sensori hanno buone tolleranze.
Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

uwefed

#6
Jul 24, 2011, 01:39 pm Last Edit: Jul 24, 2011, 01:41 pm by uwefed Reason: 1
ciao a tutti
@menniti
Non capisco perché vuoi spegnere l' arduino ma tener acceso il led IR.
Se vuoi risparmiare corrente risparmi di piú spegnendo il led.
Non so che barriera IR vuoi fare e cosa vuoi trigherare ma basta un controllo 2 a 10 al secondo per rilevare una persona.
A quel punto:
* fari dei brevi treni di impulsi da 38kHz e rilievi in quel momento il segnale del TSOP
* se vuoi risparmiare ancora di piú metti  il ATmega in sleep vedi libreria Narcoleptic.h http://code.google.com/p/narcoleptic/ oppure programmando direttamente i registri e il timer.
* fare la frequenza con un timer (ma non chiedermi a me come si fa, so che si puó fare ma non so come)
* generare i 38Khz con un oscillatore esterno che puó essere spento.

@Marbi
NOP é un istruzione macchina come scrive menniti e non fa niente. Dura un ciclo di clock che sono a 16Mhz 0,0625 µsecondi.
Si deve fare anche i conti con le altre funzioni tradotte in linguaggio macchina hanno bisogno di tempo per essere interpretati. Alla fine il for insieme ai NOP non é nient altro che un ritardo di 12,5µsecondi.
Un riassunto delle istruzioni li trovi a pagina 427 del http://www.atmel.com/dyn/resources/prod_documents/doc8161.pdf

Ciao Uwe

Michele Menniti

Quote

ciao a tutti
@menniti
Non capisco perché vuoi spegnere l' arduino ma tener acceso il led IR.
Se vuoi risparmiare corrente risparmi di piú spegnendo il led.

Ciao Uwe, lo scopo è didattico, quindi non devo risparmiare corrente in assoluto ma solo far vedere che il micro si può spegnere e riattivare all'occorrenza; il circuito sarà alimentato tramite alimentatore.
Quote

Non so che barriera IR vuoi fare e cosa vuoi trigherare ma basta un controllo 2 a 10 al secondo per rilevare una persona.
A quel punto:
* fari dei brevi treni di impulsi da 38kHz e rilievi in quel momento il segnale del TSOP

Questa è un'ottima idea, 5-6 controlli al secondo mi stanno bene, oltretutto così implemento facilmente il controllo dello stato del TSOP
Quote

* se vuoi risparmiare ancora di piú metti  il ATmega in sleep vedi libreria Narcoleptic.h http://code.google.com/p/narcoleptic/ oppure programmando direttamente i registri e il timer.

Io uso la sleep.h con ottimi risultati, cos'ha questa libreria di particolare? E' migliore?
Quote

* fare la frequenza con un timer (ma non chiedermi a me come si fa, so che si puó fare ma non so come)
* generare i 38Khz con un oscillatore esterno che puó essere spento.

Alla prima soluzione avevo pensato ma nemmeno io so come si fa; ne parlarono Leo e Astrobeed ed altri in un Topic sull'RTC ma uscì fuori solo che non era precisa (ma nel mio caso andrebbe bene lo stesso).
La seconda è quella che dicevo col 555, ripeto lo scopo è didattico, quindi il problema del consumo reale non si pone, vorrei però fare tutto col micro (un tiny85 in stand-alone)
Ciò che devo fare in pratica è spegnere il micro e le utenze che controlla, per poi riattivarlo quando la barriera viene interrotta; se la barriera la controllo col micro mi sa che non posso fare quello che vorrei, perché si spegne anche l'uscita a 38KHz e il TSOP si comporta come se fosse stata interrotta.
Grazie.
Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

Michele Menniti

#8
Jul 24, 2011, 04:28 pm Last Edit: Jul 24, 2011, 04:38 pm by menniti Reason: 1
Intanto che tornate da fuori porta vado avanti  :)
Code: [Select]
/*
  Controllo barriera IR
*/

#define TX 6
//#define RX 2
#define LV 8
#define LR 9

void setup()
{               
  pinMode(TX, OUTPUT);     
  //pinMode(RX, INPUT);
  pinMode(LV, OUTPUT);
  pinMode(LR, OUTPUT);
  //digitalWrite(RX, HIGH);
  attachInterrupt(0, Passaggio, RISING); 
}

void loop()
{
  /*Le seguenti quattro righe generano sul pin un'onda quadra
    di circa 38KHz */
   digitalWrite(TX, HIGH);  // setta il pin su HIGH
   delayMicroseconds(9);    // pausa di 8 µsec
   digitalWrite(TX, LOW);   // setta il pin su LOW
   delayMicroseconds(8);    // pausa di 9 µsec
   
}
void Passaggio()        // interruzione barriera
{
  digitalWrite(LR, HIGH); // accende il LED per 1 secondo
  delay(1000);
  digitalWrite(LR,LOW);
  detachInterrupt(0);      //disattiva l'interrupt
 
}

Nelle mie misere intenzioni volevo attivare l'interrupt al passaggio del pin 2 (interrupt 0) da LOW ad HIGH (RISING). Quando lancio lo sketch tutto funziona apparentemente, se interrompo in modo stabile la barriera, la sola prima volta il led fa un rapido lampeggio, poi più niente.
L'altra cosa strana è che in altri schetch avevo definito il pin 2 (INT0) con una costante (p.es. RX) e poi avevo usato la costante per l'interrupt, in questo caso la ignora, devo proprio usare "0" altrimenti non fa nemmeno il lampeggio. Idee?

EDIT: specifico che per ora sto lavorando col 328 di Arduino, il passaggio al tiny85 verrà solo quando funziona tutto.
Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

leo72

Il tuo codice è un PWM a tutti gli effetti  :)
Cmq per fare temporizzazioni precise devi impostare un timer interno collegato ad un interrut. Imposti il timer, poi al raggiungimento del valore massimo il contatore viene resettato: questa operazione genera un interrupt. Intercetti l'interrupt e spedisci il tuo segnale:

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1167000525

Non credo tu possa usare un RTC per farti generare un segnale di clock da usare perché un DS1307 o un PCF8563 generano un clock massimo di 32768 Hz (lo stesso del quarzo), troppo basso per i tuoi 38 kHz.

Michele Menniti

Non ho un problema di temporizzazioni precise, riguardo la frequenza esterna ho detto che eventualmente userei un 555 e con quello non ho problemi di sicuro; il riferimento all'RTC era perché volevo capire come far uscire da un pin del micro una frequenza di riferimento di 38KHz, usando quindi il timer interno, ma non ho idea di come si possa fare. Comunque, nel periodo non collegato ho capito perché il code non andava: il Reference spiega  :smiley-sweat: che lanciando una routine tramite interrupt i delay & Co & timer non funzionano, quindi ho aggirato il problema.
Code: [Select]
/*
  Controllo barriera IR
*/

#define TX 6
#define LV 8
#define LR 9
volatile int stato = LOW;

void setup()
{               
  pinMode(TX, OUTPUT);     
  pinMode(LV, OUTPUT);
  pinMode(LR, OUTPUT);
  attachInterrupt(0, Passaggio, RISING);  // se il pin INT0 (PD2) passa da LOW ad HIGH esegue la routine Passaggio()
  digitalWrite(LR, LOW);
  digitalWrite(LV, HIGH);
}

void loop()
{
  /*Le seguenti quattro righe generano sul pin un'onda quadra
    di circa 38KHz */
   digitalWrite(TX, HIGH);  // setta il pin su HIGH
   delayMicroseconds(8);    // pausa di 8 µsec
   digitalWrite(TX, LOW);   // setta il pin su LOW
   delayMicroseconds(8);    // pausa di 8 µsec
   
   if(stato==HIGH)
     {
       digitalWrite(LR, HIGH);   // accende il LED R per 10 secondi
       digitalWrite(LV, LOW);
       delay(10000);
       stato = !stato;
       digitalWrite(LR, LOW);
       digitalWrite(LV, HIGH);  // accende il LED V fino a nuovo interrupt
     } 
}
void Passaggio()            // interruzione barriera
{
    stato = !stato;
}

Ora mi succede questo: quando si interrompe la barriera per dieci secondi si inverte lo stato dei led, ma se la barriera resta interrotta oltre i 10 secondi c'è comunque un istante in cui i led cambiano di nuovo stato; questa cosa mi crea notevoli problemi: un eventuale meccanismo di sicurezza per un istante non funzionerebbe. Che logica potrei usare per risolvere?

Due domande OT:
1 - c'è una combinazione di tasti per far uscire le due parentesi graffe nell'editazione?
2 - come si fa a far apparire lo sketch con i colori originali dell'IDE?
Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

uwefed


Io uso la sleep.h con ottimi risultati, cos'ha questa libreria di particolare? E' migliore?

Non so perché non conosco la sleep.h .

Ciao Uwe

astrobeed


1 - c'è una combinazione di tasti per far uscire le due parentesi graffe nell'editazione?


Shift + alt graph + [ per la {
Shift + alt graph + ] per la }


Michele Menniti

@ Uwe: nessun problema  XD

@ astrobeed: ottimo, mi ero scocciato di fare ogni volta copincolla delle graffe XD
hai letto i vari post dopo il tuo ultimo intervento? Qualche idea in proposito?
Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

uwefed

Quote
1 - c'è una combinazione di tasti per far uscire le due parentesi graffe nell'editazione?

Usa la tastiera tedesca; li si arriva con
alt graph + 7 per {
alt graph + 0 per }  ;) ;) ;)

La differnza tra sleep.h e Narcoleptic.h dovrebbe essere che Narcoleptic.h ha piú funzionalitá nel senso piú trigger di risveglio rispetto la sleep.h. Non avendo usata ne l' una ne l' altra non sono sicuro in questo.

Ciao Uwe

Go Up