grazie menniti e uwe
per le info che mi avete dato, gli sto dando una guardata (ma non è poi così semplice, l'inglese non è la mia seconda lingua :P).
EDIT:
Non avevo letto questo:
Quote
7.1.1 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. This sleep mode basically halts clkCPU and clkFLASH,
while allowing the other clocks to run
Quindi in teoria un timer continuerebbe ad andare. E se va il timer, puoi usare quello agganciato all'INT0, seguendo l'esempio presente nel link che ti ho postato (ovviamente adattando il codice all'Attiny).
Aspetta, aspetta, io avevo visto nella tabella che l’idle mode non spegneva tutto, ma siccome mi fido ciecamente di Voi anglofoni…. ]
Il link che mi hai postato per me non significa nulla, ogni riga ci metto due ore a leggerla, se vuoi fare le cose per bene copincollami il code che ci sbatto un po’
EDIT2:
uhm... però si ripresenterebbe il problema che in un interrupt non puoi usare la delay per generare i ritardi. Potresti forse inserisci una cascata di asm volatile ("NOP") per rallentare il programma: ogni NOP è 1 ciclo di clock. Però poi rallenteresti anche il tuo codice, quando il micro si risveglia...
mi autoquoto
il Reference spiega che lanciando una routine tramite interrupt i delay & Co & timer non funzionano, quindi ho aggirato il problema.
questo problema lo avevo risolto, usando una variabile “volatile int”, seguendo il Reference del comando attachInterrupt, infatti mi funzionava benissimo, ovviamente senza spegnere il micro.
Poiché ho letto che i pin interrupt non devono essere dichiarati e che possono svolgere la loro funzione anche se parallelamente sono settati come OUTPUT, a questo punto faccio uscire la frequenza da questo pin, imposto la modalità idle e lo uso come interrupt per risvegliare; ma non la vedo così facile la cosa….
Sicuro che non vuoi usare un 555?
Con quello ovviamente è già tutto risolto, il problema è che questo vorrebbe essere uno schema didattico per il risparmio energetico, anche se in realtà sarà alimentato con un alimentatore esterno; il 555 non lo posso spegnere e continuerebbe a consumare corrente. La mia idea era di fare qualcosa come quella dei nanetti. Faccio queste ultime prove e poi me ne vado, sono scoppiato.
Stiamo dicendo la stessa cosa, ossia che la modalità "idle" non spenge tutte le funzioni del micro, difatti i timer e l'Int0 continuano ad andare.
Il link che ti ho postato linka ad una discussione in cui c'è a metà del codice di esempio... MA! è per l'Atmega168: andrebbe controllato se usando le librerie Tiny Core si riesce a compilarlo correttamente.
Sarebbe questo:
#include <avr/interrupt.h>
#include <avr/io.h>//Timer2 overflow interrupt vector handler, called (16,000,000/256)/256 times per second
ISR(TIMER2_OVF_vect) {
//let 10 indicates interrupt fired
digitalWrite(10,true);
};void setup() {
pinMode(9,OUTPUT);
pinMode(10,OUTPUT);//Timer2 Settings: Timer Prescaler /256, WGM mode 0
TCCR2A = 0;
TCCR2B = 1<<CS22 | 1<<CS21;//Timer2 Overflow Interrupt Enable
TIMSK2 = 1<<TOIE2;//reset timer
TCNT2 = 0;//led 9 indicate ready
digitalWrite(9,true);
}void loop() {
}
Va provato, ripeto. Non so come vada. Va inoltre adattato perché come vedi usa pin non presenti sull'Attiny.
I pin di interrupt non li puoi dichiarare per il semplice motivo che sono fisicamente legati a particolari pin. Quindi devi per forza usare quelli.
menniti:
1 - c'è una combinazione di tasti per far uscire le due parentesi graffe nell'editazione?
io uso alt+123 per {
e alt+125 per }
abitudine presa a scuola quando programmavo in c++/c#
non sapevo invece degli altri 2 modi
Grazie pdor90, figlio di kmer65 XD, comunque ormai ho preso la mano con il consiglio di astrobeed, l'avro usato 100 volte stasera.
@ leo:
ho risolto continuando a seguire la strada che avevo iniziato, con le librerie, come giustamente dici tu, non si sa mai; lo so che dicevamo la stessa cosa, solo che io non ne ero sicuro e tu me l'hai detto dopo 3-4000 mila prove in cui davo per scontato che non si potesse
In pratica sto idle non spegne una pitocchia, infatti sono curioso di vedere quanto consumerà il tiny.
Con Arduino ho risolto così (grandi linee, sono troppo morto per farla lunga ):
1 - Un pin digitale qualsiasi mi genera la frequenza
2 - Uno dei pin INT (col tiny ne avrò solo uno, ma ho sempre la libreria specifica che mi fa scegliere quale voglio usare) mi serve per il controllo del TSOP
3 - appena parte la barriera funziona, non è interrotta, led verde
4 - appena interrompo la barriera il TSOP va HIGH e l'INT mi attiva una routine per il cambio stato della variabile che ti dicevo e si accende il led rosso, spegnendo il verde; l'oscillatore non oscilla più
5 - fintanto che la barriera è interrotta resta su rosso (in questo caso però l'oscillatore oscilla)
6 - appena la barriera è libera un delay imposta un giusto ritardo quindi si riaccende il led verde; l'oscillatore continua a non oscillare
7 - dopo un ulteriore x tempo senza che la barriera sia stata interrotta il micro va in idle, si spegne anche il led verde e l'oscillatore riprende ad oscillare ripristinando iml controllo della barriera.
Mi resta solo il problema che mentre è verde, se la barriera viene interrotta non se ne accorge perché l'oscillatore non oscilla, ma questo è il problema della prossima volta, devo risolvere via software penso, forse con i NOP dello sketcvh iniziale di astrobeeed e di cui mi parlavi prima tu, vedremo.
menniti:
In pratica sto idle non spegne una pitocchia, infatti sono curioso di vedere quanto consumerà il tiny.
Lo stato idle è quello a maggior consumo tra i modi sleep, ma è anche quello che lascia in funzione tutte le periferiche, p.e. se sei in idle puoi ricevere un dato da I2C oppure dalla seriale, quando sarà pronto nel buffer il micro viene risvegliato.
Con nessuna modalità di sleep puoi generare i 38 kHz tramite software, ovvero utilizzando le nop, o le delay, all'interno di un ciclo, però puoi generarli via hardware tramite un timer in due modi.
Il primo è programmare un timer per il semiperiodo dei 38 kHz con interrupt attivo e ogni volta che il micro viene risvegliato cambi stato al pin e ricarichi il timer, non è possibile ottenere 38 kHz esatti perché il periodo è 26.316 us, un valore non ottenibile con la base tempi che ha un periodo di 0.0625 us, infatti il rapporto è 421.056, solo se il rapporto tra i due periodi è un valore intero è possibile ottenere l'esatta frequenza.
Il secondo modo è utilizzare un timer in modalità pwm con duty al 50% per generare una frequenza il più possibile vicina a 38kHz, anche in questo caso non è possibile ottenere il valore esatto e tocca verificare se è possibile avvicinarsi perché il carrier del pwm non è impostabile a piacere su tutte le frequenze possibili.
Andando a memoria credo sia possibile arrivare molto vicini ai 38 kHz con il pwm, quasi sicuramente con un valore entro la banda ammessa, più tardi in mattinata verifico in pratica.
Ciao, in effetti quando va in idle continua a generare la frequenza; il problema ora è quando è sveglio, cioè quando inizio la gestione dei led (punti 6 e 7 del mio precedente post) ovviamente la frequenza si interrompe perché il micro non lavora in multitasking; per cui concordo che l'unica soluzione possibile sia quella di dissociare i 38KHz dal software, come suggerisci tu, spero proprio che tu riesca a fare le prove e trovare una soluzione. Grazie. XD
menniti:
ovviamente la frequenza si interrompe perché il micro non lavora in multitasking
Non è un problema di multitasking, è un problema di velocità del micro, se deve generare a software dei ritardi di pochi us non hai modo di fare altre cose nel frattempo, infatti i timer/counter servono proprio per scaricare la cpu dai compiti di conteggio tempo e/o eventi implementandoli in hardware.
Tra parentesi qualunque micro può lavorare in multitasking/multithread, questo vale pure per una piccola mcu a 8 bit, è una questione più software che hardware visto che comunque la cpu può eseguire solo una istruzione per volta a meno che non sia micro multicore.
Il multitasking è usatissimo sulle mcu, esistono appositi sistemi operativi che lo implementano per noi, uno dei più famosi, e usati in ambito industriale, è Salvo che è un RTOS (Real Time Operating System).
Non cominciare a volare già faccio fatica a correrti dietro quando cammini per terra
Ho sbagliato ad esprimere il concetto intendevo appunto dire che il software esegue le istruzioni una per volta sequenzialmente, quindi quando il mio sketch inizia a gestire i led per le indicazioni si ferma la frequenza generata dall'altro pin, e siccome a regime questa cosa potrebbe occuparmi anche 20-30 secondi la mia "barriera di sicurezza" diventa una barzelletta, visto che intanto non funziona; in parole povere quando è verde significa che non c'è passaggio, il problema è che a quel punto inizio un delay al termine del quale vado in sleep, durante questo delay la barriera non controlla il passaggio dei "mezzi" e rischio la strage, ovviamente è tutto simulato, però...
Ma tu non devi fare un delay. In questo modo blocchi la CPU a contare i secondi.
Devi fare con un ciclo e controllare contemporaneamente lo scorrere del tempo e la barriera.
Se al termine del tempo preimpostato non è passato nessuno, metti a nanna il micro.
leo72:
Ma tu non devi fare un delay. In questo modo blocchi la CPU a contare i secondi.
Devi fare con un ciclo e controllare contemporaneamente lo scorrere del tempo e la barriera.
Se al termine del tempo preimpostato non è passato nessuno, metti a nanna il micro.
Infatti, non ci crederai, ma è l'idea che mi è venuta stanotte, ieri mi sono sparato 13-14 ore di laboratorio e stanotte sognavo Arduini, delay, gente che aveva i problemi più svariati ed io che cercavo di risolverli con l'IDE, praticamente un'indigestione Ad un certo punto, ricordandomi il suggerimento di UWE, che mi consigliava di fare un tot di controlli della barriera al minuto, ho pensato di creare un ciclo for che mi lancia la routine per la generazione dei 38KHz per un x tempo, poi un breve delay con un contatore, e via di nuovo fino a raggiungere il tempo prefissato per il sonnellino.
Però se astrobeed trova il modo di generare la frequenza in modo "dissociato" dal software, sarebbe la soluzione ideale.
Ormai le prossime prove domani o giovedì, prima mi devo disintossicare
Ma per "modo dissociato", intendi un oscillatore a parte per i 38khz?
BrainBooster:
Ma per "modo dissociato", intendi un oscillatore a parte per i 38khz?
No, se ti pigli la pazienza di rileggere tutto vedi che quella è un'idea che non vorrei adottare, anche se ad un certo punto sembrava l'unica soluzione possibile, ora risolta.
La mia speranza è che si possa abilitare un pin del micro a sputare fuori questa frequenza, senza doverla creare col software; se ho ben capito ciò che ha scritto e che vorrebbe provare astrobeed, la cosa potrebbe essere fattibile, usando un timer interno.
Male che vada rielaboro lo sketch come ho scritto prima, in risposta al suggerimento di Leo.
menniti:
Però se astrobeed trova il modo di generare la frequenza in modo "dissociato" dal software, sarebbe la soluzione ideale.
Ecco la soluzione
#include <avr/sleep.h>
void setup()
{
pinMode(11, OUTPUT);
pinMode(13, OUTPUT);
//analogWrite(11,50);
OCR2A = 211;
TCCR2A = 0b01000011;
TCCR2B = 0b00001001;
//set_sleep_mode(SLEEP_MODE_PWR_SAVE);
//sleep_enable();
//sleep_mode();
}
void loop()
{
digitalWrite(13, HIGH);
delay(1);
digitalWrite(13, LOW);
delay(1);
}
Ti serve solo la parte contenuta nel setup, cioè come settare i registri TCCR2A e TCCR2B per ottenere sul pin 11, oppure sul 3, un'onda quadra a 37.975 kHz (rilevata su una Luigino 328 con quarzo da 16 MHz).
In pratica si forza il timer2 per il funzionamento in modo 7, fast pwm con TOP in OCRA, e con il Toggle on Compare Match che inibisce il duty cycle a favore di un'onda quadra perfetta.
Il Timer2 non è usato da Arduino per la delay e la millis, nella loop ho messo apposta un ciclo con delay a 1 ms per generare un'onda quadra a 500 Hz come verifica.
Agendo su OCR2A, è il valore che viene caricato in timer2 ad ogni ciclo, è possibile cambiare la frequenza, la granularità non è molto fine, ogni unità su OCR2A modifica da qualche decina di Hertz a qualche centinaio a seconda del suo valore e del prescaler scelto.
Ho provato pure in sleep, in power save il timer2 è attivo e c'è la generazione dell'onda quadra con un basso consumo energetico.
Non ho parole, no, una sì, SPETTACOLARE! XD
Un'ultima domanda : questo metodo è applicabile in qualche modo al tiny85, che mi pare non abbia il doppio timer? Questo è perché il circuito finale prevede questo piccolo micro.
Comunque sia questa tecnica è eccezionale, poter disporre di una frequenza d'appoggio separata dal loop significa risolvere molti problemi, ad iniziare dagli ultrasuoni....
GRAZIE! XD XD XD
Ma non si poteva usare irsend della libreria iremote? (quella dei telecomandi a infrarossi)
menniti:
Un'ultima domanda: questo metodo è applicabile in qualche modo al tiny85, che mi pare non abbia il doppio timer? Questo è perché il circuito finale prevede questo piccolo micro.
Devo controllare il data sheet degli ATTiny, non tanto per il timer da usare, va bene uno qualunque di quelli presenti, ma per vedere se supportano le necessarie modalità.
ad iniziare dagli ultrasuoni....
Con gli ultrasuoni, parliamo di sonar, non serve a nulla perché devi generare dei treni di impulsi composti da un ben preciso numero di impulsi, in questo caso va benissimo la generazione da software, in fin dei conti impegni la cpu solo per un centinaio di us ogni 50-100 ms.
astrobeed:
menniti:
Un'ultima domanda: questo metodo è applicabile in qualche modo al tiny85, che mi pare non abbia il doppio timer? Questo è perché il circuito finale prevede questo piccolo micro.
Devo controllare il data sheet degli ATTiny, non tanto per il timer da usare, va bene uno qualunque di quelli presenti, ma per vedere se supportano le necessarie modalità.
OK, non importa se devo usare una modalità di consumo meno "potente", l'importante è poterla usare.
ad iniziare dagli ultrasuoni....
Con gli ultrasuoni, parliamo di sonar, non serve a nulla perché devi generare dei treni di impulsi composti da un ben preciso numero di impulsi, in questo caso va benissimo la generazione da software, in fin dei conti impegni la cpu solo per un centinaio di us ogni 50-100 ms.
OK, per quello c'è già il code che mi avevi fornito.
BrainBooster:
Ma non si poteva usare irsend della libreria iremote? (quella dei telecomandi a infrarossi)
http://www.arcfn.com/2010/03/detecting-ir-beam-break-with-arduino-ir.html
Traduci ma premetto che non devo usare gli infrarossi come portante per trasmettere comandi (tipo telecomando), sto semplicemente creando una barriera on-off.
Il codice della libreria permetteva di generare il carrier a 38khz con un comando. (essendo una libreria).