Barriera Infrarossi

leo72:
Interessante :slight_smile:
Ma il compilatore ufficiale è a pagamento? Gira su Linux?

Dipende da che serie vuoi usare, i "piccoli", serie 10 e serie 12, non hanno un compilatore ufficiale Microchip, idem per la serie 16, dalla serie 18 in poi c'è il C18, il C30 e il C32 che sono ufficiali di Microchip, da notare che il C30 e il C32 utilizzano come engine il gcc dotato di librerie di cross compiling proprietarie di Microchip.
L'ambiente di sviluppo ufficiale è MPLAB, l'equipollente di AvrStudio, che fino a poco tempo fa girava solo sotto Windows, da qualche mese Microchip si è impegnata nello sviluppo di un ambiente di lavoro multipiattaforma ed è nato MPLABX che utilizza NetBeans, a mio avviso nettamente meglio di Eclipse, come IDE e gira in modo nativo sotto Windows, Linux e MAC OS.
Per il momento MPLABX è in versione beta 6, la 1.0 dovrebbe arrivare a breve, ed include tutte le feature presenti nell'ultima release di MPLAB standard e varie cose aggiuntive, i compilatori utilizzati da MPLABX sono gli stessi della versione solo windows quindi già maturi e affidabilissimi.
Tutti i compilatori Microchip dispongono di licenze student che ne permettono l'uso assolutamente free a studenti e amatori, unica limitazione rispetto alle versioni commerciali sono i livelli di ottimizzazione che nelle free sono parzialmente limitati, per il resto è tutto presente, inclusi i sorgenti C e ASM delle librerie, e totalmente funzionante.
Se vuoi provare a giocare con i PIC ti consiglio di iniziare con il 18F2620, è un 28 pin, disponibile anche in case dip, come l'ATmega 328 e ha caratteristiche similari.
Una scheda pronta all'uso in stile Arduino, con bootloader già caricato, è la MuIn, è un mio progetto per conto Droids e il firmware di serie è open source, non è diffusa come Arduino, ma ha venduto tanto pure lei, è commercializzata anche da store internazionali come Robot Shop, tutte le schede che appaiono in quella pagina sono miei progetti :slight_smile:

Grazie per tutte le info. Magari nel mio prox ordine... chissà.. :wink:

@Michele:

il seguente codice funziona correttamente. Metti un led rosso sul piedino 7 (pin 2), un led verde sul piedino 6 (pin 1) ed un pulsantino con pull-down da 10K verso GND e collegamento a +5V.
Lo sketch legge correttamente il cambio di stato del pin verso HIGH:

#include <avr/sleep.h>  // libreria standard (avrlib) per lo sleep
#include <PinChangeInterruptSimple.h>

#define LV 1 //led verde sul piedino n° 6 (pin 1)
#define LR 2 //led rosso sul piedino n° 7 (pin 2)
#define BARRIERA 0 //pulsantino pullato basso sul piedino n° 5 (pin 0)

char barra = 0;
unsigned long tempo;
int val1=0;
int val2=0;
int change=0;

void Passaggio()            // interruzione barriera
{
     barra = 1;
}

void Riposo()                      // funzione attivazione sleep
{
    attachPcInterrupt(0, Passaggio, CHANGE); // riattiva l'interrupt
    ADCSRA &= ~(1 << ADEN); // spegne l'ADC
    sleep_mode();           // mette il micro in stato di sleep
    sleep_disable();      // disattiva la modalità sleep e riporta il micro a piena operatività
    detachPcInterrupt(0);   // disattiva l'interrupt
}

void setup() 
{                
  pinMode(LV, OUTPUT);
  pinMode(LR, OUTPUT);
  pinMode(BARRIERA, INPUT);
//  attachInterrupt(0, Passaggio, HIGH);  
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);  
  sleep_enable();                       
  digitalWrite(LV, HIGH);
  digitalWrite(LR, HIGH);
  delay(250);
  digitalWrite(LV, LOW);
  digitalWrite(LR, LOW);
}

void loop() {
    boolean esci=false;
    
    barra=1;
    tempo=millis()+3000; //3 sec di attesa
    digitalWrite(LR, HIGH);
    do {
        val1=digitalRead(BARRIERA);
        delay(10);
        val2=digitalRead(BARRIERA);
        if (val1==val2) {
            if (val1!=change) {  
                if (val1==HIGH) { 
                    tempo+=3000; //altri 3 sec di attesa
                    if (barra==0) { //la barriera era verde
                        digitalWrite(LV, LOW);
                        digitalWrite(LR, HIGH);
                        barra=1;
                    }
                }
            }
        }
        change=val1;
        if (millis()>tempo) {
            if (barra==1) { //la barra era rossa
                digitalWrite(LR, LOW);
                digitalWrite(LV, HIGH);
                tempo=millis()+3000; //ultimi 3  sec
                barra=0;
            } else { //ciclo finito
                digitalWrite(LV, LOW);
                esci=true;
            }
        }
    } while (!esci);
    Riposo();
}

In pratica è quasi identico al mio precedente, cambia solo attachPcInterrupt al posto di attachInterrupt (lo stesso dicasi per il detach).

@ astrobeed
Non ti pare che io abbia abbastanza rogne con gli AVR per andarmi ad imbarcare in un'avventura parallela con i PIC? Ci mancava pure l'astrobuino...]:smiley:
Ho un "ciclo" progettuale da portare a compimento, a quel punto tutto può essere, ma non penso se ne parli prima di febbraio p.v.
Quindi torna in te, recupera le mie ultime domande e, PER FAVORE, dammi risposta XD :grin: :smiley:

@ leo
Grazie, semmai farò la prova con la mia barriera, devo verificare sul campo reale cosa sucede in determinate situazioni, quelle che mi hanno fatto scovare ogni bug nelle varie prove. Ma a questo punto voglio capire a fondo questa cosa dei pin PCINTx, più avanti potrebbero tornare utilissimi. Nei prossimi 2 mesi cercherò di tradurre i 3 link di BB :cold_sweat: :cold_sweat:

La cosa importante è che comunque parte dei problemi dipendono dal fatto che il settaggio dei registri per ottenere la frequenza proprio sul pin fisico 5 del tiny, probabilmente influenzano in qualche modo il comportamento dello sketch.
Visto che il pin INT0 è il pin fisico 7, che per me è libero, a questo punto abolisco la PCI e lavoro senza, o comunque (visto che la PCI mi fa usare il trigger HIGH) uso il pin 7 in ogni caso. Peraltro il datasheet dice chiaramento che posso usare questo pin contemporaneamente come OUTPUT, pur continuando ad utilizzarlo come interrupt, questo mi libera un pin, potendo gestire uno dei due LED; insomma di test da fare ne ho tanti; lunedì intera giornata col tiny, la sera sarò scoppiato o vincitore; orima però devo ricontrollare gli ultimi Vostri post (escluso gli OT_PIC ]:)) e riorganizzare le info che mi avete dato. Di certo mi mancano ancora due risposte, a queste domande:
1 - posso intervenire sui valori dei registri per usare un pin diverso dal 5 fisico del tiny? (la cosa nasce dal fatto che astrobeed diceva che su Arduino potevo usare l'11 o il 3 per i 38KHz, ma a me sescono sull'11, segno che un qualche settaggio ci deve essere.
2 - posso usare il pin da cui escono i 38KHz contemporaneamente come pin di input?

BrainBooster:
è vero che non c'è sul datsheet ma se guardi il sorgente di avrlibc di sleep.h
avr-libc: sleep.h Source File

mmm, vedo che assieme alla libreria sleep.h viene caricata anche una interrupt.h, a che serve? non è che da mesi sto usando un interrupt monco perché gli manca la libreria? :astonished:

@menniti volendo puoi abilitare o disabilitare un pò di tutto, anche selettivamente, guarda qui:
avr-libc: <avr/power.h>: Power Reduction Management

Per usare i comandi che mi interessano devo inserire nello sketch la libreria power.h? ma conflittua con la sleep.h o è solo più segmentata, potendo agire sui singoli componenti invece che per gruppi?

@tutti
http://old.nabble.com/Power-save-mode-in-ATtiny85-vs-avr-libc-td26999346.html

Mi pare di aver capito che posso mettere un oscillatore esterno a 38KHz per far funzionare la power_save. Ma, a questo punto, lo userei per pilotare il LED IR TX, eliminerei il code di astrobeed e potrei usare il power_down. No, al di là di aver appreso questa cosa, non penso che mi può essere utile allo stato attuale.

Se puoi darmi queste risposte avrò una situazione più chiiara per le altre prove di lunedì. Grazie!! XD

Visto che nussuno vuole giocare più con me, solo perché sono piccolo e nero =(, continuo da solo, sperando che prima o poi rispondiate ai miei accorati appelli :frowning:
@ tutti
una risposta l'ho trovata, riguardo i pin PCINT, nel readme.txt contenuto nella libreria PinChangeInterrupt c'è scritto:

Tiny Pin Change Interrupts is a library for hooking the pin-change interrupts on AVR processors.

Quindi ogni pin siglato PCINTx può essere usato come interrupt, con una qualsiasi delle modalità di trigger previste (RISING, FALLING, CHANGE, LOW, HIGH), a patto di caricare questa libreria (o l'equivalente quanto si parla di ATMEGA)

@ leo
dicevi che attach/detach non ti funzionano con i tiny, invece a me risulta di sì, ovviamente col solo pin INT0, hai poi approfondito questa cosa? altrimenti cercherò di darti risposta io nei prossimi giorni

@ astrobeed e brainbooster
non vi fischiano le orecchie? :grin:

menniti:
...
2 - posso usare il pin da cui escono i 38KHz contemporaneamente come pin di input?

Non Ti capisco del tutto.
Contemporaneamente: NO. Intervallato: Sí ma:
Finche escono i 38kHz non puoi usarlo come entrata.
Quando non hai bisogno dei 38kHz puoi usaro come entrata solo se il circuito che piloti (non ho seguito tutto il discorso ma presumo un LED o un transistor) non Ti falsificano il segnale che vuoi leggere. Se per esempio hai attacato un LED con una resistenza per portare l' entrata a H devi dare abbastanza corrente da far accendere il LED. Se é attacato un transistore c sono meno problemi con la corrente ma comunque col segnale da misurare piloti il transistore.
IL circuito di uscita che dovrebbe essere letto dall entrata deve inoltre essere protetto in modo che il segnale di uscita quando usi il pin come uscita non lo rompa. Rimane solo un uscita Open Collector /Drain o un uscita accupiata con una resistenza che probabilmente non funziona visto il carico attacato (LED ecc).
Ciao Uwe

Ciao UWE, i 38KHz li uso per pilotare costantemente un LED IR, effettivamente il tuo ragionamento mi fa capire che potrei fare un altro uso del pin solo interrompendo questa frequenza, cosa che non posso fare, visto che la barriera deve essere tenuta costantemente sotto controllo; dovevo cercare di recuperare un pin del tiny85, ma intanto ho letto sul datasheet che posso usare come OUTPUT il pin che uso per l'interrupt, contemporaneamente, quindi ci metto uno dei due LED (R o V) e il pin lo libero lo stesso.
Grazie del chiarimento!

Il problema di usare un pin sia come entrata che come uscita é che devi disaccoppiare le 2 cose. Perche avendo collegato tutto hai un pin del controller asieme a un uscita e un entrata a bassa resistenza (LED): 2 uscite e 1 entrata (u: controller, circuito che fa da input; e: LED) oppure 1 uscita e 2 entrate (u: circuito che fa da input; e: LED e controller).
Anche l' uso del Interrupt come uscita é problematico perché usando il PIN come uscita non Ti funzione l' interrupt.
Soluzione possibile:
Puoi usare un pin con 2 led. Uno da + al pin e l' altro da massa al pin. Per pilotare un LED metti l'ucita a massa, per pilotare l'altro lo metti a massa, per entrambi metti una oscillazione e per spegnere metti il PIN come entrata. Lo svantaggio é a led spento tutti due si accendono leggermente oppure devi usare led con tensioni Uf alti in modo che la somma delle tensioni forward dei 2 LED sia maggiore di 5V (LED blu e bianco o mettere 2 LED rossi o verdi in serie).
Ciao Uwe

@Michele:
non ho detto che non mi funzionava attacch/detach sui Tiny, ho detto che sbagliavo ad usare le giuste librerie: difatti avevo inizialmente usato il codice scritto per l'Atmega328 senza usare la PCI, che prevede attachPcInterrupt invece che attachInterrupt :smiley:

Detto questo, riassumendo la tua situazione è la seguente:

  1. hai bisogno di 2 LED rosso/verde per il semaforo
  2. hai bisogno di un input per il ricevitore IR
  3. hai bisogno di un output per il trasmettitore IR

La conta fa 4, quindi con l'Attiny85 ci sei perché se da 8 togli: il pin GND, il pin Vcc, il pin di reset, ottieni 5 pin usabili, 1 in più rispetto a quanti te ne servono. XD

Adesso analizziamo il problema. Tu generi i 38 kHz con l'INT0 su un pin. In teoria si potrebbe usare il PCINT con un altro pin per risvegliare il micro quando questo è a nanna.

Ho combinato insieme la produzione del segnale sull'INT0 e la lettura della chiusura della barriera in un solo sketch. Resta solo il problema che usando il POWER-DOWN si spenge la generazione dell'onda. :sweat_smile:

leo72:
Resta solo il problema che usando il POWER-DOWN si spenge la generazione dell'onda. :sweat_smile:

Solo in idle funzionano gli oscillatori sugli ATTiny, non vorrei rompere le OO più di tanto però che senso ha andare in idle quando c'è il led IR che consuma tanti mA ? Che cambia ?

Boh, bisogna sentire Michele :stuck_out_tongue:

Cmq il codice usato è questo (la gestione del timer per la generazione del segnale l'ho ricopiata da quella che Michele ha detto che gli funzionava, non sono stato a controllare. Inoltre non ho un oscilloscopio per cui per capire se l'onda usciva o meno dal pin ho usato un.... LED :roll_eyes:):

#include <avr/sleep.h>  // libreria standard (avrlib) per lo sleep
#include <PinChangeInterrupt.h>

#define LV 1
#define LR 2
#define BARRIERA 4
#define LED 0

char barra = 0;
unsigned long tempo;
int val1=0;
int val2=0;
int change=0;

void Passaggio()            // interruzione barriera
{
     barra = 1;
}

void Riposo()                      // funzione attivazione sleep
{
    attachPcInterrupt(BARRIERA, Passaggio, CHANGE); // riattiva l'interrupt
    ADCSRA &= ~(1 << ADEN); // spegne l'ADC
    sleep_mode();           // mette il micro in stato di sleep
    sleep_disable();      // disattiva la modalità sleep e riporta il micro a piena operatività
    detachPcInterrupt(BARRIERA);   // disattiva l'interrupt
}

void setup() 
{                
  pinMode(LV, OUTPUT);
  pinMode(LR, OUTPUT);
  pinMode(BARRIERA, INPUT);
  pinMode(LED, OUTPUT);
  
  OCR0A = 12;
  TCCR0A = 0b01000011; 
  TCCR0B = 0b00001001;
//  attachInterrupt(0, Passaggio, HIGH);  
  set_sleep_mode(SLEEP_MODE_DOWN);  
  sleep_enable();                       
  digitalWrite(LV, HIGH);
  digitalWrite(LR, HIGH);
  delay(250);
  digitalWrite(LV, LOW);
  digitalWrite(LR, LOW);
}

void loop() {
    boolean esci=false;
    
    barra=1;
    tempo=millis()+3000; //3 sec di attesa
    digitalWrite(LR, HIGH);
    do {
        val1=digitalRead(BARRIERA);
        delay(10);
        val2=digitalRead(BARRIERA);
        if (val1==val2) {
            if (val1!=change) {  
                if (val1==HIGH) { 
                    tempo+=3000; //altri 3 sec di attesa
                    if (barra==0) { //la barriera era verde
                        digitalWrite(LV, LOW);
                        digitalWrite(LR, HIGH);
                        barra=1;
                    }
                }
            }
        }
        change=val1;
        if (millis()>tempo) {
            if (barra==1) { //la barra era rossa
                digitalWrite(LR, LOW);
                digitalWrite(LV, HIGH);
                tempo=millis()+3000; //ultimi 3  sec
                barra=0;
            } else { //ciclo finito
                digitalWrite(LV, LOW);
                esci=true;
            }
        }
    } while (!esci);
    Riposo();
}

Funziona tutto ma appena il micro va in sleep, il led si spenge...

leo72:
Funziona tutto ma appena il micro va in sleep, il led si spenge...

Perché vai in power down, devi andare in idle come modo sleep.

Con l'IDLE il circuito non si spenge :stuck_out_tongue:
Ossia non va mai in sleep, ma passa continuamente dal led rosso al led verde, segno che esegue costantemente il ciclo loop senza mettere a nanna il micro. Forse dipende dai fronti di segnale controllati (CHANGE invece di HIGH). Ora provo.

EDIT:
no, non va in sleep neanche con IDLE. Oppure potrebbe andarci e risvegliarsi subito, ma servirebbe un oscilloscopio per verificarlo.

leo72:
no, non va in sleep neanche con IDLE. Oppure potrebbe andarci e risvegliarsi subito, ma servirebbe un oscilloscopio per verificarlo.

Potrebbe essere colpa della millis, usa l'interrupt sul timer0 e in idle pure questo risveglia il micro.

Bene, bene, le cose si muovono, ho risposte per tutti…. :drooling_face:
@ Uwe:
io ho letto a fatica il DS :sweat_smile:, quindi non so quali sono le controindicazioni di poter usare il pin di INT0 come OUTPUT, ho capito che la cosa si può fare in CONTEMPORANEA, perché il pin INT0 per usarlo come interrupt NON va dichiarato come INPUT ed il disaccoppiamento posso farlo con un banale diodo, ma devo fare le prove; per usare il pin INT0 come uscita è sufficiente dichiarare il pin stesso come OUTPUT e invece nei comandi attach/detach (o gli equivalenti “Pc” per i PCINT del TINY) si mette “0” invece del numero del pin logico. Ma naturalmente devo fare qualche prova in più. :cold_sweat:

@ Leo:

  • quindi diciamo la stessa cosa, infatti vorrei usare il pin INT0 SENZA libreria e quindi con i normali attach/detach, così NON lo disturbo e contemporaneamente, ma devo verificare quanto dice Uwe, lo userei per pilotare il LED Rosso.
  • Il conteggio di pin che hai fatto è giusto ma se avessi detto tutto all’inizio mi avreste mandato a quel paese… :blush:; in realtà dovrei prevedere un “interruttore di sicurezza manuale” ed un’uscita per attivare un utilizzatore esterno. Ovvio che se non riesco mi accontento di dove arrivo e quindi rinuncio all’utilizzatore.
  • Ho detto da subito che già con il 328 non è possibile usare il pwr_down perché “in alcuni casi” spegne l’oscillatore, questo dipende dal momento in cui si ferma, se l’onda è in fase HIGH poi si riaccende, ma questo non è controllabile, quindi sul 328 usavo il pwr_save (ecco perché era uscita la questione sul TINY)

@ Astrobeed e Leo:

  • Confermo che la modalità idle non funziona, credo che in realtà il sistema si riattivi all’istante (come ha intuito astrobeed), ma non sono in grado di stabilirlo, e il mio dubbio è che sia colpa del fatto di usare un PCINTx invece di INT0, ecco il perché di tutta la storia.
  • Il fatto che mi basti la modalità idle, nonostante ciò che dici sia verissimo, circa il consumo dell’IR, sta nel fatto che come ho detto all’inizio il circuito è di tipo didattico, serve per mostrare come si può mandare a dormire il micro e risvegliarlo con un evento esterno; non va pilotato a batterie quindi la situazione del consumo reale non mi interessa.
  • La soluzione dovrebbe essere quella di spostare l’output dei 38KHz su un altro pin o trovare un pin che non disturbi l’idle. Io sto usando il codice che ho scritto da solo, più banale di quello di Leo (se volete lo posto), ed ho lo stesso scherzo dell’idle, mentre in pwr-down va ma non si sveglia, quindi funziona allo stesso identico modo.
  • Ho una sola possibilità e spero nell’aiuto di Astrobeed: imparare come si fa, SUL 328, ha spostare l’uscita dei 38KHz sul pin 3 invece che sull’11 (parliamo di pin Arduino), come tu affermavi proprio all’inizio del Topic, o almeno avere le pagine di riferimento sul DS; se capisco il meccanismo, cerco di applicarlo al TINY, anche se temo che sul 328 sia possibile l’uscita alternativa in base al timer che si usa, cosa non fattibile sul TINY, che ne ha uno solo. :roll_eyes: :roll_eyes: :roll_eyes:

Ho vinto qualcheccosa? :grin:

menniti:

  • Confermo che la modalità idle non funziona, credo che in realtà il sistema si riattivi all’istante (come ha intuito astrobeed), ma non sono in grado di stabilirlo, e il mio dubbio è che sia colpa del fatto di usare un PCINTx invece di INT0,

Ho verificato con il simulatore di AvrStudio, la colpa è proprio della Millis() che fa uscire dallo sleep, in idle, a causa dell'interrupt sul timer 0, non c'è soluzione salvo disattivare la millis spegnendo il timer 0.

Ho una sola possibilità e spero nell’aiuto di Astrobeed: imparare come si fa, SUL 328, ha spostare l’uscita dei 38KHz sul pin 3 invece che sull’11

Non è possibile perché il pin 3 non prevede la modalità "Toggle on Compare Match", relativamente al timer, è disponibile solo per il pin 11, sul pin 3 è solo possibile avere un normale PWM con tutti i limiti nel setup della frequenza.

Non vorrei dire minchiate ma secondo me con il Tiny non ne esci.
Se leggi il datasheet, pagg. 35, trovi questo:

Pag: 35:
Idle Mode
When the SM[1:0] bits are written to 00, the SLEEP instruction makes the MCU enter Idle mode,
stopping the CPU but allowing Analog Comparator, ADC, USI, Timer/Counter, Watchdog, and
the interrupt system to continue operating.
Idle mode enables the MCU to wake up from external triggered interrupts as well as internal
ones like the Timer Overflow.

Quindi, IDLE non va bene perché quando il timer interno usato per generare l'onda va in overflow, fa uscire il micro dallo sleep dato che attiva l'INT0. Ecco perché sembra che non ci vada: in realtà va in sleep ma si risveglia subito perché il timer sta generando un'onda a 38 kHz, quindi lo sleep dura una frazione infinitesima di secondo.

Abbiamo poi già stabilito che in Power-Down i timer vengono spenti.

Secondo me devi cambiare micro.