Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

problema PWM timer 0

Tipologie, strumenti di sviluppo, hardware e progetti

Moderatore: Foto UtentePaolino

0
voti

[1] problema PWM timer 0

Messaggioda Foto Utentedaniele1996 » 6 ago 2021, 17:15

Ciao a tutti, sto riparando una scheda di un climatizzatore (standard non inverter), in passato ne avevo sistemato uno alla buona ma il mal di gola si fa sentire... così avendo quest'altro da sistemare ho pensato di perderci un po di tempo in più e magari programmare anche qualche funzione in modo che non dia fastidio alla mia salute...
Iniziamo dal fatto che non ho un oscilloscopio e ne sto aspettando uno non troppo eccellente ma che mi dovrebbe permettere di fare misurazioni di tensione in millivolt e anche qualche segnale in regime sinuosidale (il DSO150).
Dando una guardata al circuito sono presenti i sensori di giri del motore, il clock a 50Hz per la frequenza di rete, L'SSR per pilotare la ventola interna,il buzzer, e tutto il resto fa solo ON/OFF (Compressore, Valvola, ventola esterna e lo stepper per direzionare l'aria)... Il micro che ho deciso di usare è l'Atmega328 (che è sufficiente per il ruolo che deve svolgere)
i due segnali di clock (50Hz e Ventola interna) li ho collegati ai due interrupt (PD2 / PD3) e senza pensarci troppo ho collegato il fotoaccoppiatore della ventola interna al PD5 (OC0B) e il buzzer al PD6 (OC0A) (Timer 0).
Di solito ho usato il timer 1 per generare i segnali PWM, avendo a disposizione i registri ICR1 come TOP e OCR1A e OCR1B da impostare per il DutyCycle ( e questo devo dire che non è stato difficile).
Però avendo collegato il buzzer (che non è quello che suona dandoci solo la 5V, richiede un segnale PWM) al Timer 0, sono riuscito a farlo funzionare impostandolo così:
Codice: Seleziona tutto
void beep(){
        TCCR0A = 0x00;
   TCCR0A = (1<<WGM00)|
          (1<<WGM01)|
          (1 << COM0B1);
        TCCR0B = 0x00;
   TCCR0B = (1 << WGM02)| (1<<CS00)|(1<<CS02);
   OCR0A = 3;// beep
   _delay_ms(200);
   OCR0A = 0;// beep
}

Di funzionare funziona (e potrei dire va bene così) ma realmente non riesco a capire come impostare il timer per tagliare la sinusoide della tensione di rete
in teoria dovrei impostare il timer a 100Hz il dutycycle (variabile da 0 al valore di TOP) e farlo partire e riazzerandolo dall'interrupt della 50Hz... Non mi riesce...
Da notare nella funzione che ho scritto: per il buzzer sto usando il canale A, ma nel TCCR0A attivo il COM0B1 che dovrebbe essere per il canale B, ma se attivo quello del canale B il segnale PWM non si genera e il buzzer non suona (è una cosa al quanto strana)...
Potete indicarmi qual è il metodo corretto senza dover spostare i fili sul timer 1?
Avatar utente
Foto Utentedaniele1996
610 3 8 11
Sostenitore
Sostenitore
 
Messaggi: 1554
Iscritto il: 29 ago 2011, 11:29

0
voti

[2] Re: problema PWM timer 0

Messaggioda Foto Utentelelerelele » 8 ago 2021, 12:04

potrei supporre che i due timer vadano in conflitto, cioè sono troppo veloci per essere letti con righe di codice, io proverei a farli lavorare su interrupt.

anche quel delay che hai messo, potrebbe inficiare la lettura del timer.

Il motivo è che quando stai attendendo che un timer arrivi, l'altro passi oltre e magari lo perdi.

saluti.
Avatar utente
Foto Utentelelerelele
4.899 3 7 9
Master
Master
 
Messaggi: 5505
Iscritto il: 8 giu 2011, 8:57
Località: Reggio Emilia

0
voti

[3] Re: problema PWM timer 0

Messaggioda Foto Utentedaniele1996 » 10 ago 2021, 3:09

Attualmente per iniziare a scrivere del codice ho iniziato dal timer 0 (8-Bit)
Timer 0:
Istantanea_2021-08-10_02-12-47.png

Impostandolo nelle modalità 2 5 e 7 il valore di TOP dovrebbe essere impostato su OCRA e provando a compilare mi esce fuori ‘OCRA’ undeclared (first use in this function).
Guardando il datasheet, per il timer 2 dice che esiste un registro di TOP ed è sempre OCRA (inesistente)
Timer 2:
Istantanea_2021-08-10_02-12-08.png

Come è possibile?
I due timer dovrebbero avere due registri separati...
Intanto ho spostato le connessioni del buzzer e del fotoaccoppiatore sul timer 1, il timer 0 invece lo uso come interrupt per temporizzare l'utilizzo del compressore ed il timer 2 per il motore stepper delle alette...
Comunque mi rimane il dubbio per le uscite PWM a 8 Bit.
O_/
Avatar utente
Foto Utentedaniele1996
610 3 8 11
Sostenitore
Sostenitore
 
Messaggi: 1554
Iscritto il: 29 ago 2011, 11:29

0
voti

[4] Re: problema PWM timer 0

Messaggioda Foto UtenteIsidoroKZ » 10 ago 2021, 6:34

Vuoi fare un taglio di fase per regolare la velocita` del motore? Che interruttore usi?
Per usare proficuamente un simulatore, bisogna sapere molta più elettronica di lui
Plug it in - it works better!
Il 555 sta all'elettronica come Arduino all'informatica! (entrambi loro malgrado)
Se volete risposte rispondete a tutte le mie domande
Avatar utente
Foto UtenteIsidoroKZ
121,2k 1 3 8
G.Master EY
G.Master EY
 
Messaggi: 21059
Iscritto il: 17 ott 2009, 0:00

1
voti

[5] Re: problema PWM timer 0

Messaggioda Foto UtentePietroBaima » 10 ago 2021, 13:35

Non trovi OCRA perché l’AT328 è un processore ad 8 bit, mentre L’Output Compare Register A è a 16 bit.
Il datasheet infatti, a pag.91 dice:

The TCNT1, OCR1A/B, and ICR1 are 16-bit registers that can be accessed by the AVR® CPU via the 8-bit data bus.
The 16-bit register must be byte accessed using two read or write operations. Each 16-bit timer has a single 8-bit register for temporary storing of the high byte of the 16-bit access. The same temporary register is shared between all 16-bit registers within each 16-bit timer. Accessing the low byte triggers the 16-bit read or write operation. When the low byte of a 16-bit register is written by the CPU, the high byte stored in the temporary register, and the low byte written are both copied into the 16-bit register in the same clock cycle. When the low byte of a 16-bit register is read by the CPU, the high byte of the 16-bit register is copied into the temporary register in the same clock cycle as the low byte is read.
Not all 16-bit accesses uses the temporary register for the high byte. Reading the OCR1A/B 16-bit registers does not involve using the temporary register.
To do a 16-bit write, the high byte must be written before the low byte. For a 16-bit read, the low byte must be read before the high byte.


Una considerazione: tutti utilizzano sempre il general timer/counter a 16 bit “perché ha più bit”. Questa è una cosa che inizia per c e finisce per azzata.
E’ vero che ha più bit, ma è anche molto più lento, perché richiede il doppio delle operazioni alla CPU e di conseguenza è oneroso.

Come sempre bisogna fare un bilancio e rispondersi alla domanda: “ho davvero bisogno del UTC a 16bit?”
In genere per fare un controllo a taglio di fase la risposta è negativa.

Inoltre non riesci a fare il controllo del taglio di fase perché sbagli approccio: devi generare un INT ogni volta che hai uno zero crossing della tensione di rete (per farlo basta una resistenza, se non vuoi isolare il uC dalla rete) e poi far partire un timer che imposti con un timing che va da 10ms a 0ms e che generi un altro INT all’arrivo a zero.
Quando arriva a zero generi un impulso che assegni ad un bit di uscita.

Facendo un po’ di attenzione puoi generare del codice molto efficiente, in questo modo.
Generatore codice per articoli:
nomi
Sul forum:
[pigreco]=π
[ohm]=Ω
[quadrato]=²
[cubo]=³
Avatar utente
Foto UtentePietroBaima
90,7k 7 12 13
G.Master EY
G.Master EY
 
Messaggi: 12206
Iscritto il: 12 ago 2012, 1:20
Località: Londra

0
voti

[6] Re: problema PWM timer 0

Messaggioda Foto Utentedaniele1996 » 11 ago 2021, 3:33

Inizialmente ho preso questo vecchio climatizzatore perché ho già visto una scheda di un climatizzatore simile ed non è per niente difficile da far funzionare.
Sinceramente penso che se a scuola (Industriale settore elettrotecnico e settore informatico) farebbero riparare queste schede gli alunni proverebbero più interesse nel portare avanti i propri studii...
Detto questo mi piacerebbe scrivere un articolo su come riparare questi apparecchi (anche se obsoleti)
Iniziamo dal circuito "grossolano" nell'unità esterna sono presenti tre elementi: Ventola, compressore e valvola (caldo/freddo), per questi basta semplicemente che facciano ON/OFF (i climatizzatori inverter sono più complicati, gestendo la frequenza delle sinusoidi trifase si regola la potenza refrigerante del climatizzatore, comunque non riguardano questo caso... magari in futuro mi occuperò anche di questo).
Nell'unità interna sono presenti: ventola, sensori di temperatura (ambiente e radiatore) e un piccolo stepper per direzionare l'aria (i led li ometto, si possono anche non considerare).
In tutta la scheda, l'unica cosa che vado a cambiare è il microcontrollore (In questo caso c'era un HYNIX GMS87C1404) che si può programmare solo una volta, quindi non più riutilizzabile...
Ma l'interfacciamento è ottimo, quindi sostituendo il micro e scrivendo un po di codice si rimette in funzione...
Nel circuito cosa c'è?
Tre relè che pilotano il compressore, la ventola esterna e la valvola.
IsidoroKZ ha scritto:Vuoi fare un taglio di fase per regolare la velocita` del motore? Che interruttore usi?

un fotoaccoppiatore MOC3023 che pilota un triac,
Il circuito per il zero crossing: (INT1)

Un buzzer pilotato da un transistor,
Un sensore di giri della ventola interna (INT0) (sarebbe un sensore HALL con un magete sull'asse)
Due sensori di temperatura (semplici partitori da tarare con l'equazione della retta passante per due punti)
Un motore stepper pilotato da un ULN2003 (24BYJ48,per farlo girare basta attivare le uscite in sequenza).
Dando una guardata al circuito, in un pin del micro c'è collegato un induttore che lo collega al punto P1 (l'ho chiamato SINE) ma non lo utilizzero, se non per dare una guardata con l'oscilloscopio (appena mi arriva)...
PietroBaima ha scritto:Non trovi OCRA perché l’AT328 è un processore ad 8 bit, mentre L’Output Compare Register A è a 16 bit.

OCRA non c'è, infatti il compilatore mi restituisce
daniele1996 ha scritto: ... ‘OCRA’ undeclared (first use in this function) ...

La tabella 14-8 è del timer 0 (8Bit) e la 17-8 è del timer 2 (8Bit).
La tabella del timer 1 è la 15-5 dove dice che in alcune modalità il valore di TOP è in ICR1 e in altre è in OCR1A, metre in altre ancora il valore di TOP è prefissato ad un certo valore.
Quello che dici tu è il registro OCR1A che sarebbe il valore di inversione di livello logico del timer 1 canale A (connesso a PB1)...
PietroBaima ha scritto:Una considerazione: tutti utilizzano sempre il general timer/counter a 16 bit “perché ha più bit”

Anche uno a 8 bit sarebbe bastato... Infatti inizialmente volevo usare il timer 0...
PietroBaima ha scritto:E’ vero che ha più bit, ma è anche molto più lento, perché richiede il doppio delle operazioni alla CPU e di conseguenza è oneroso.

Secondo me, no...
Il timer 1 è collegato tramite un prescaler (1/8/64/256/1024) che dividono la frequenza del clock, quindi un incremento di una unità corrisponde a 1 / (fClock/prescaler). L'incremento viene fatto automaticamente tramite una circuiteria a 16 bit presente nel componente, stessa identica cosa per controllare se il valore ha raggiunto il valore di TOP o il valore di inversione di livello logico...
Il timer gira "per i fatti suoi" al momento opportuno o genera un interrupt o inverte il livello logico dell'uscita ad esso collegata, oppure non genera nessun evento ed è il programma a doversi accoregere che il timer ha raggiunto il valore interessato...
Avatar utente
Foto Utentedaniele1996
610 3 8 11
Sostenitore
Sostenitore
 
Messaggi: 1554
Iscritto il: 29 ago 2011, 11:29

0
voti

[7] Re: problema PWM timer 0

Messaggioda Foto UtentePietroBaima » 11 ago 2021, 9:41

daniele1996 ha scritto:
PietroBaima ha scritto:Non trovi OCRA perché l’AT328 è un processore ad 8 bit, mentre L’Output Compare Register A è a 16 bit.

OCRA non c'è, infatti il compilatore mi restituisce
daniele1996 ha scritto: ... ‘OCRA’ undeclared (first use in this function) ...

appunto

daniele1996 ha scritto: La tabella 14-8 è del timer 0 (8Bit) e la 17-8 è del timer 2 (8Bit).
La tabella del timer 1 è la 15-5 dove dice che in alcune modalità il valore di TOP è in ICR1 e in altre è in OCR1A, metre in altre ancora il valore di TOP è prefissato ad un certo valore.

ICR sta per Input Capture Register e serve per misurare eventi esterni.
Se vuoi, per esempio, misurare la durata del livello alto di un segnale esterno sincronizzi l’avvio del timer con il fronte in salita di un segnale esterno e leggi il ICR sul fronte in discesa.
Alle volte, per esempio per sincronizzare dei PWM è comodo avere il registro del compare match sull’ICR.

daniele1996 ha scritto: Quello che dici tu è il registro OCR1A che sarebbe il valore di inversione di livello logico del timer 1 canale A (connesso a PB1)...

No, è connesso a PB1 se lo programmi in tale modo. Puoi programmarlo per invertire il bit di uscita al compare match, portarlo a uno, portarlo a zero… Guarda le tabelle 15.2 e 15.3

daniele1996 ha scritto:
PietroBaima ha scritto:E’ vero che ha più bit, ma è anche molto più lento, perché richiede il doppio delle operazioni alla CPU e di conseguenza è oneroso.

Secondo me, no...
Il timer 1 è collegato tramite un prescaler (1/8/64/256/1024) che dividono la frequenza del clock, quindi un incremento di una unità corrisponde a 1 / (fClock/prescaler). L'incremento viene fatto automaticamente tramite una circuiteria a 16 bit presente nel componente, stessa identica cosa per controllare se il valore ha raggiunto il valore di TOP o il valore di inversione di livello logico...
Il timer gira "per i fatti suoi" al momento opportuno o genera un interrupt o inverte il livello logico dell'uscita ad esso collegata, oppure non genera nessun evento ed è il programma a doversi accoregere che il timer ha raggiunto il valore interessato...

Certo, se tu programmi il timer e poi non lo tocchi mai più ti costa il doppio all’inizio e poi basta.
Spesso però il timer si riprogramma, per esempio per modulare una sinusoide in PWM oppure per adattare un ICR per fare un duty cycle che sia sempre il 10% maggiore di un altro e sia ad esso sincronizzato in fase, ecc…
ICR si usa spesso per leggere degli encoder…
In questi casi non si tratta più di un caso isolato, ma il peso computazionale si sente moltissimo.
Generatore codice per articoli:
nomi
Sul forum:
[pigreco]=π
[ohm]=Ω
[quadrato]=²
[cubo]=³
Avatar utente
Foto UtentePietroBaima
90,7k 7 12 13
G.Master EY
G.Master EY
 
Messaggi: 12206
Iscritto il: 12 ago 2012, 1:20
Località: Londra

1
voti

[8] Re: problema PWM timer 0

Messaggioda Foto UtenteIsidoroKZ » 11 ago 2021, 18:02

daniele1996 ha scritto:
IsidoroKZ ha scritto:Vuoi fare un taglio di fase per regolare la velocita` del motore? Che interruttore usi?

un fotoaccoppiatore MOC3023 che pilota un triac,


Non sono un macchinista elettrico o un motorista, non ne so proprio nulla, ma sono l'unico che ritiene una cattiva idea il fare un controllo a taglio di fase per il motore di un compressore?
Per usare proficuamente un simulatore, bisogna sapere molta più elettronica di lui
Plug it in - it works better!
Il 555 sta all'elettronica come Arduino all'informatica! (entrambi loro malgrado)
Se volete risposte rispondete a tutte le mie domande
Avatar utente
Foto UtenteIsidoroKZ
121,2k 1 3 8
G.Master EY
G.Master EY
 
Messaggi: 21059
Iscritto il: 17 ott 2009, 0:00

0
voti

[9] Re: problema PWM timer 0

Messaggioda Foto Utentedaniele1996 » 12 ago 2021, 4:00

IsidoroKZ ha scritto:Non sono un macchinista elettrico o un motorista, non ne so proprio nulla, ma sono l'unico che ritiene una cattiva idea il fare un controllo a taglio di fase per il motore di un compressore?

Il compressore fa solo on e off, il taglio di fase va nella ventola interna... sinceramente se nello stampato c'è un triac più tosto che un relè un motivo ci sarà...
Comunque, passando al codice...
Codice: Seleziona tutto
void beep(char times){

    ICR1 = 100; //2.5KHz
    OCR1A = 50; //Duty 50
    OCR1B = 00;
    TCCR1A = (1 << COM1A1);
    // set none-inverting mode
    TCCR1A |= (1 << WGM11);    // set Fast PWM mode using ICR1 as TOP
    TCCR1B = (1 << WGM12)|(1 << WGM13);
    //
    for(beeps = 0;beeps<times;beeps = beeps + 1){
       TCCR1B |= (1 << CS11) | (1 << CS10); //Prescaler 64
       _delay_ms(100); // 10 = 1s
       TCCR1B &= ~((1 << CS11) | (1 << CS10));
       _delay_ms(100);
    }
    //init_fan();


}

perfettamente funzionante...
sto scrivendo il codice per l'avvio del taglio di fase, il timer parte (attivando il prescaler) quando si genera l'interrupt (INT1)
ah dimenticavo, beeps è una macro
Avatar utente
Foto Utentedaniele1996
610 3 8 11
Sostenitore
Sostenitore
 
Messaggi: 1554
Iscritto il: 29 ago 2011, 11:29

1
voti

[10] Re: problema PWM timer 0

Messaggioda Foto Utentexyz » 12 ago 2021, 15:47

daniele1996 ha scritto:...
OCRA e provando a compilare mi esce fuori ‘OCRA’ undeclared (first use in this function).
Guardando il datasheet, per il timer 2 dice che esiste un registro di TOP ed è sempre OCRA (inesistente)...

Quale compilatore stai usando ? Se è il GCC per AVR il nome del registro è OCR0A, ogni nome di un registro del timer ha il numero del timer a cui si riferisce.
Avatar utente
Foto Utentexyz
6.864 2 4 6
G.Master EY
G.Master EY
 
Messaggi: 1778
Iscritto il: 5 dic 2009, 18:37
Località: Italy Turin

Prossimo

Torna a Realizzazioni, interfacciamento e nozioni generali.

Chi c’è in linea

Visitano il forum: Nessuno e 7 ospiti