Go Down

Topic: Doppio dimmer con attiny85 e triac (Read 2 times) previous topic - next topic

Ultra Phonic 2

leo, ho bisogno di una mano...
ho letto la guida che mi hai dato, ma purtroppo non ho ancora le competenze per comprenderla...

ecco il codice che uso:
Code: [Select]
volatile int i=0, y=0;               // variabili contatore...
volatile boolean zero_cross1=0, zero_cross2=0;  // booleane per lo zero crossing
int out1 = 0, out2 = 1;                // Output >> ai moc...
int pot1 = 3, pot2=4;             // ingressi trimmer
int bright1 = 0, bright2 = 0;   // livello di luminosità (0-128)  0 = on, 128 = 0ff

int freqStep = 78;    // ritardo del timer in microsecondi
void setup() {
pinMode(out1, OUTPUT);
pinMode(out2, OUTPUT);
attachInterrupt(0, zero_cross_detect, RISING); //zero crossing detection con interrupt esterno

}

void zero_cross_detect() {   
  zero_cross1 = true;
zero_cross2 = true;
i=0;
y=0;
  digitalWrite(out1, LOW);
digitalWrite(out2, LOW);
}                                 


void br_check() {              // SUB CHE DEVE ESSERE ESEGUITA OGNI "FREQSTEP [uS]" (78 microsecondi)   
  if(zero_cross1 == true) {             
    if(i>=bright1) {                     
      digitalWrite(out1, HIGH);       
      i=0;                         
      zero_cross1 = false;               
    }
    else {
      i++;                           
    }                               
  } 
if(zero_cross2 == true) {             
    if(y>=bright2) {                     
      digitalWrite(out2, HIGH);       
      y=0;                         
      zero_cross2 = false;               
    }
    else {
      y++;                           
    }                               
  }                                                                 
}                                   

void loop() {                       
  bright1 = analogRead(pot1) / 8; 
  bright2 = analogRead(pot2) / 8;
}


come scritto nel codice, voglio che la sub br_check() venga eseguita indipendentemente dal loop, ogni 78uS.

saresti in grado di inviarmi un pezzo di codice che possa risolvere il mio problema usando un timer?
se possibile, potresti commentare lo sketch, così che io riesca a comprendere determinati passaggi, e se non chiedo troppo, anche una breve spiegazione sull'uso dei timer?

Grazie ;)

leo72

Vediamo un po'...
Sui Tiny85 c'è libero il timer 0, che è ad 8 bit.
1 us, se non ho fatto male i conti, sono 0,000001 secondi.
Avere 78 uS dobbiamo avere una frequenza di overflow del timer di 1/0,000078=12820,50 volte al secondo.
1/12820,50=0,000078 us.
Ok sì è questo  ;)

Allora, poniamo il clock del Tiny a 8 MHz, per avere tale periodo bisogna impostare il tutto così:
(8000000*0,000078)/prescaler /8 = 78
Questo è il valore massimo che deve essere conteggiato dal timer per ottenere 1 overflow ogni 78 us, quindi avendo un contatore a 8 bit, con 256 valori, il valore da caricarci dentro è : 256-78=178
Rifacciamo i conti:
8000000/8/178=12820,5 Hz, perfetto  ;)

Prova con questo codice (richiamalo dal setup solo 1 volta):
Code: [Select]

cli();//fermo gli interrupt
TCCR0A &= ~((1<<COM0A0) | (1<<COM0A1)); //disattivi gli interrupt del timer
//modalità contatore fino all'overflow
TCCR0A &= ~((1<<WGM01) | (1<<WGM00));
TCCR0B &= ~(1<<WGM02);
//prescaler a /8
TCCR0B &= ~((1<<CS02) | (1<<CS00));
TCCR0B |= (1<<CS01);
TCNT0 = 178; //valore iniziale
TIMSK |= (1<<TOIE0); //attivo un interrutp all'overflow
sei(); //riattivo gli interrupt


Ora inserisci questa ISR per gestire l'overflow:
Code: [Select]
ISR (TIM0_OVF_vect) {
    TCNT0 = 178;
    ....... //qui il resto del codice
}

Dove metti il resto del tuo codice.

L'ho scritto senza poterlo provare, dimmi se va.

Ultra Phonic 2

#12
Oct 23, 2012, 03:04 pm Last Edit: Oct 23, 2012, 04:01 pm by Ultra Phonic 2 Reason: 1
Ciao leo,

ho provato il tuo codice, ma durante la verifica mi da quest'errore:
Quote
core.a(wiring.c.o): In function `__vector_5':
C:\Documents and Settings\user\Desktop\arduino-1.0.1\hardware\arduino\cores\arduino/wiring.c:49: multiple definition of `__vector_5'
dimmer.cpp.o:C:\DOCUME~1\user\IMPOST~1\Temp\build3703977071899918311.tmp/dimmer.cpp:243: first defined here


il codice è così adesso...
Code: [Select]
volatile int i=0, y=0;               // variabili contatore...
volatile boolean zero_cross1=0, zero_cross2=0;  // booleane per lo zero crossing
int out1 = 0, out2 = 1;                // Output >> ai moc...
int pot1 = 3, pot2=4;             // ingressi trimmer
int bright1 = 0, bright2 = 0;   // livello di luminosità (0-128)  0 = on, 128 = 0ff

//int freqStep = 78;    // ritardo del timer in microsecondi
void setup() {
cli();//fermo gli interrupt
TCCR0A &= ~((1<<COM0A0) | (1<<COM0A1)); //disattivi gli interrupt del timer
//modalità contatore fino all'overflow
TCCR0A &= ~((1<<WGM01) | (1<<WGM00));
TCCR0B &= ~(1<<WGM02);
//prescaler a /8
TCCR0B &= ~((1<<CS02) | (1<<CS00));
TCCR0B |= (1<<CS01);
TCNT0 = 178; //valore iniziale
TIMSK |= (1<<TOIE0); //attivo un interrutp all'overflow
sei(); //riattivo gli interrupt
pinMode(out1, OUTPUT);
pinMode(out2, OUTPUT);
attachInterrupt(0, zero_cross_detect, RISING); //zero crossing detection con interrupt esterno

}

void zero_cross_detect() {    
 zero_cross1 = true;
zero_cross2 = true;
i=0;
y=0;
 digitalWrite(out1, LOW);
digitalWrite(out2, LOW);
}                                


ISR (TIM0_OVF_vect) {
   TCNT0 = 178;
 if(zero_cross1 == true) {              
   if(i>=bright1) {                    
     digitalWrite(out1, HIGH);      
     i=0;                        
     zero_cross1 = false;                
   }
   else {
     i++;                          
   }                                
 }  
if(zero_cross2 == true) {              
   if(y>=bright2) {                    
     digitalWrite(out2, HIGH);      
     y=0;                        
     zero_cross2 = false;                
   }
   else {
     y++;                          
   }                                
 }                                                                  
}                                  

void loop() {                        
 bright1 = analogRead(pot1) / 8;  
 bright2 = analogRead(pot2) / 8;
}


EDIT: confermo che il chip è stato settato ad 8mhz con quarzo interno... ho tolto il ckdiv
EDIT2:
seguendo questa guida: http://www.atmel.com/Images/doc2505.pdf

a pagina 9 ho visto TIMER0_OVF0_vect, e l'ho modificato nel codice che mi hai dato... adesso non genera errori, ma provandolo, il loop è diventato velocissimo! e la funzione che dovrebbe farmi, non me la fa...

Grazie

leo72

Scusa se ti rispondo solo ora ma in questi giorni ho poco tempo libero ed inoltre ieri sera sono stato anche escluso dal forum per problemi di login.

1) non mi torna il vettore che hai usato: TIM0_OVR_vect funziona benissimo, lo uso sia nella swRTC sia nel leOS. Perché a te dà errori? Ma stai usando il core Tiny oppure un altro core, per il Tiny85? Se usi il core Tiny, potresti controllare nel file /hardware/tiny/cores/tiny/core_build_options.h se intorno alla riga 112, nelle opzioni per il Tinyx5, la voce TIMER_TO_USE_FOR_MILLIS ha il valore 1?
2) che intendi per "il loop è diventato velocissimo"? Come fai ad accorgertene? Hai compilato per un micro ad 8 MHz, dopo aver impostato il chip a questa frequenza?

Ultra Phonic 2

@leo non so che dirti...

io ho solo visto quella stringa in quella guida che ho linkato, e in quel modo non genera errori.

mettendo un semplice blink nel loop, disabilitando la routine ISR... ecc ecc, il loop è moolto veloce, cioè un delay di 1000mS è diventato di neanche metà...

il core che uso l'ho preso da qui: http://hlt.media.mit.edu/?p=1695 e nella cartella "hardware" trovo la cartella "attiny" nella quale trovo "variants" e "boards.txt", in "variants" trovo "tiny8" e "tiny14" nelle quali c'è un file "pins_arduino.h".

potresti cortesemente passarmi il core che usi tu ?

il chip è stato impostato con internal rc osc ad 8mhz - startup 6ck/14ck + 64ms (quello di default), e settando i fuses tramite avrdude gui.

ho tolto il ckdiv8, facendo così diventare il low fuse da 0x62 a 0xE2

se ti serve sapere altro, sono a disposizione

Go Up