Meranie dĺžky impulzu: Rozdiel medzi revíziami
Zo stránky SensorWiki
Bez shrnutí editace |
|||
(4 medziľahlé úpravy od rovnakého používateľa nie sú zobrazené.) | |||
Riadok 1: | Riadok 1: | ||
=== Úloha === | |||
# Vytvoriť simulátor PWM signálu snímača teploty: SMT 160-30, resp. SMT 172 | |||
#* TC0 bude na pine PD5 generovať PWM signál s 𝑓_𝑃𝑊𝑀=1𝑘𝐻𝑧 a plnením v intervale DC = (0,1 až 0,9). | |||
#* DC budeme zadávať v %. | |||
# Na meranie parametrov PWM signálu: T1 - čas v log. 1 a T_opak – trvanie jednej periódy PWM signálu použijeme TC1 (16b). TC1 nastavíme do módu „odpamätanie“ stavu počítadla pri výskyte hrany na pine PB.0. Využijeme ISR(). | |||
# Pomocou TC2, bude generovať presnú periodu vzorkovania. Periódu opakovania výpisov, ako aj zmeny plnenia o definovaný prírastok, napr. 1, budeme realizovať s krokom 0,5sek. Využijeme ISR(). | |||
# Výpisy na LCD, resp. terminál treba realizovať vo formáte, xx,x. (Pevná rádova čiarka). Pri výpočtoch nemôže byť použitá float aritmetika. | |||
# Vo výpisoch sa musí objaviť: Nastavené plnenie. Trvanie T_1, resp. T_opak v SC a us. Ako aj plnenie v % vo formáte: xx,x. Rovnako aj danému plneniu odpovedajúca teplota vo formáte +-xx,x °C . | |||
# Ako úloha naviac: Navrhnite filter typu kĺzavý priemer z 8-ich vzoriek. | |||
<FONT Color="blue" Size="+1"> | |||
[http://senzor.robotika.sk/mmp/cvicenie10.pdf Slajdy k teoretickému rozboru cvičenia] | |||
</font> | |||
<tabs> | |||
<tab name="main.c"><source lang="c++" style="background: LightYellow;"> | |||
//Hlavný program | |||
#include <avr/io.h> | |||
#include <avr/interrupt.h> | |||
#include "p_f_1.h" | |||
#include "p_f_2.h" | |||
// deklarovanie premenných | |||
int main(void){ | |||
/* Ini PORT‘s, TCx, prerušení | |||
Konfiguracia UART:Tx, Rx */ | |||
ini_usart_0(MYUBRR); | |||
ini_TC0(); ini_TC1(); ini_TC2(); | |||
sei(); // Enable interrupts in general | |||
sprintf(Riadok,"Meranie plnenia impulzu \r\n" ); | |||
zob_text_UART(Riadok); | |||
/* main loop */ | |||
while (1) { | |||
if(flag_Vypisov){ | |||
flag_Vypisov = 0; | |||
Vypis(); | |||
Zmena_plnenia(); // DC = (10 az 90 %) | |||
} | |||
} | |||
} | |||
</source></tab> | |||
<tab name="p_f_1.h"><source lang="c++" style="background: LightYellow;"> | |||
// ********************************* p_f_1.h | |||
/* | |||
* p_f_1.h | |||
*/ | |||
#ifndef P_F_1_H_ | |||
#define P_F_1_H_ | |||
#define F_CPU 16000000UL /* Define CPU frequency here 16MHz */ | |||
#include <avr/io.h> | |||
#include <util/delay.h> | |||
#include <avr/interrupt.h> | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
void zob_text_UART(char *); | |||
void ini_usart_0(unsigned int ); | |||
void USART_Transmit( unsigned char ); | |||
void zob_text(char *); | |||
void Zmena_plnenia(void); | |||
unsigned char Prepocet_plnenia_PWM(unsigned char ); | |||
void Vypis(void); | |||
extern char Riadok[]; | |||
extern volatile unsigned int T1_no_vz; | |||
extern volatile unsigned int T1_st_vz; | |||
extern volatile unsigned int pl_PWM_pocitane_Percent; | |||
extern volatile unsigned long T_log_1; | |||
extern volatile unsigned long T_log_1_us; | |||
extern volatile long T_opak; | |||
extern volatile int T_M; | |||
extern unsigned char DC_PWM_percent; | |||
extern uint8_t T_vypis; // cca 0,5 sek , potom doladim | |||
#define BAUD 115200 | |||
//UCSR0A.U2X0 = 1 | |||
#define MYUBRR | |||
#endif /* P_F_1_H_ */ | |||
</source></tab> | |||
<tab name="p_f_1.c"><source lang="c++" style="background: LightYellow;"> | |||
// ********************************* p_f_1.c | |||
/* | |||
* p_f_1.c | |||
*/ | |||
#include "p_f_1.h" | |||
#include "p_f_2.h" | |||
// Inicializacia UARTu | |||
void ini_usart_0(unsigned int mybr){ | |||
UBRR0 = mybr; | |||
... | |||
} | |||
void zob_text_UART(char *s){ | |||
register unsigned char c; | |||
while((c = *s++)) USART_Transmit(c); // retazec konci "nulou" | |||
} | |||
void USART_Transmit( unsigned char data ){ | |||
/* Wait for empty transmit buffer */ | |||
while ( !( UCSR0A & (1<<UDRE0)) ); | |||
/* Put data into buffer, sends the data */ | |||
UDR0 = data; | |||
} | |||
void Vypis(void){ | |||
// formátovaný výpis | |||
//printf("Plnenie:?????? ", DC_PWM_percent, T_log_1, T_opak ); | |||
Výpis:Plnenie: dd%, ddd [SC], ddd [SC] | |||
Výpis:Plnenie: dd%, ddd [us], ddd [us] | |||
printf("Plnenie:?????? ", DC_PWM_percent, pl_PWM_pocitane_Percent ); | |||
Výpis:Plnenie: dd%, dd,d% | |||
zob_text_UART(Riadok); | |||
} | |||
void Zmena_plnenia(void){ // rozsah 10 az 90 % | |||
DC_PWM_percent+=?; | |||
if (DC_PWM_percent >90)DC_PWM_percent = 10; | |||
// prepocitam rozsah v percentach na odpovedajuce cislo | |||
if (DC_PWM_Percent > 90) DC_PWM_Percent = 10; | |||
OCR0B = f(DC_PWM_Percent); | |||
} | |||
unsigned char Prepocet_plnenia_PWM(unsigned char pln_per){ | |||
... | |||
} | |||
</source></tab> | |||
<tab name="p_f_2.h"><source lang="c++" style="background: LightYellow;"> | |||
// ********************************* p_f_2.h | |||
/* | |||
* p_f_2.h | |||
*/ | |||
#ifndef P_F_2_H_ | |||
#define P_F_2_H_ | |||
#define set_bit(Adress,Bit) (Adress |= (1<<Bit)) | |||
#define clear_bit(Adress,Bit) (Adress &= ~(1<<Bit)) | |||
#define toggle_bit(Adress,Bit) (Adress ^= (1<<Bit)) | |||
extern volatile unsigned char poc_T_vypis ; | |||
extern volatile unsigned char flag_Vypisov ; | |||
#define f_opak_TC0 1000 // 1000 Hz <-> 1ms | |||
#define N_D_TC0 // Delic pre TC0 | |||
#define OCR0A_f_opak_TC0 // Vysledkom je perioda opakovania 1ms !!!!! | |||
#define f_opak_TC2 500 // 500 Hz -> 2ms | |||
#define N_D_TC2 // Delic pre TC2 | |||
#define OCR2A_f_opak_TC2 // Vysledkom je 2ms casova vzorka !!!!! | |||
#define T__050 250 // 0,5 sek = 250 * 2ms | |||
void ini_TC0(void); | |||
void ini_TC1(void); | |||
void ini_TC2(void); | |||
#endif /* P_F_2_H_ */ | |||
</source></tab> | |||
<tab name="p_f_2.c"><source lang="c++" style="background: LightYellow;"> | |||
// ********************************* p_f_2.c | |||
/* | |||
* p_f_2.c | |||
* | |||
* Created: 4/12/2021 11:29:22 AM | |||
* Author: Admin | |||
*/ | |||
#include <avr/io.h> | |||
#include "p_f_1.h" | |||
#include "p_f_2.h" | |||
void ini_TC0(void){ | |||
// Nastavenie TC0 | |||
set_bit(DDRD,PIND5); //OC0B PWM pin | |||
// 7 6 5 4 3 2 1 0 | |||
// COM0A[1:0] COM0B[1:0] WGM0[1:0] | |||
TCCR0A = ??????;// OC0B PWM mod = ? | |||
// 7 6 5 4 3 2 1 0 | |||
// WGM02 CS0[2:0] | |||
TCCR0B = ??????;// fosc/?? | |||
OCR0B = 𝑓("DC_PWM_percent " ); | |||
// nastvenie frekvencie opakovania na 1ms | |||
OCR0A = OCR0A_f_opak_TC0; | |||
} | |||
void ini_TC1(void){ | |||
// Timer1 Capture | |||
DDRB &= ~(1<<DDB0); //ICP1 = PORTB.0, input | |||
PORTB |= (1<<PORTB0); // Pullup Rezistor | |||
// Nastavenie TC1 | |||
// 7 6 5 4 3 2 1 0 | |||
// WGM12 CS1[2:0] | |||
// fTC1 = f(fosc) chceme max. presnosť merania | |||
TCCR1B ?= ????; | |||
TCCR1B ?= ????; // odchytenie na nabeznu hranu | |||
TIMSK1 ?= ????; // povolenie prerusenia od capture T1 | |||
// sei(); pre všetky naraz | |||
} | |||
void ini_TC2(void){ | |||
// Nastavenie TC2 | |||
// 7 6 5 4 3 2 1 0 | |||
// COM2A[1:0] COM2B[1:0] WGM2[1:0] | |||
TCCR2A ? = ????;// OC2B PWM mod = 7 | |||
// 7 6 5 4 3 2 1 0 | |||
// WGM02 CS0[2:0] | |||
TCCR2B ?= ????;// fosc/?? | |||
// nastavenie frekvencie opakovania na 2ms | |||
OCR2A ? = OCR2A_f_opak_TC2; | |||
// Enable interrupts @ overflow TC2 MOD 7 | |||
TIMSK2 ? = ????; | |||
// sei(); pre všetky naraz | |||
} | |||
ISR(TIMER2_OVF_vect) | |||
{ /// tato slucka sa vykona kazde 2,0ms | |||
OCR2A = OCR2A_f_opak_TC2; | |||
//toggle_bit(PORTD,PIND2); //PD2 - change | |||
poc_T_vypis--; | |||
if (!poc_T_vypis) { | |||
// prednastavim pocitadlo vypisov na 0,5s | |||
poc_T_vypis = T__050; | |||
flag_Vypisov = 1;// nastavim priznak vypisov | |||
//toggle_bit(PORTD,PIND2); //PD2 - change | |||
} | |||
} | |||
ISR(TIMER1_CAPT_vect){ | |||
// globalne prerusenie je zakazane | |||
// POCITADLO SA INKREMENTUJE KAZDU ?us | |||
if(TESTUJEM HRANU){// bola nábežna hrana | |||
....; // tu prepnem na dobežnu hrana | |||
T1_st_vz = T1_no_vz; | |||
T1_no_vz = ICR1; // odpamätám nový “čas“ | |||
T_opak = ... ; | |||
pl_PWM_pocitane_Percent = f(T_log_1,T_opak); | |||
T_M = f( (T_log_1 ,T_opak); | |||
} else {// bola dobežna hrana | |||
....; // tu prepnem na nábežnu hrana | |||
T_log_1 = ICR1 - T1_no_vz; | |||
T_log_1_us =f(.....). | |||
} | |||
} | |||
</source></tab> | |||
</tabs> | |||
=== Literatúra === | === Literatúra === | ||
* [http:// | * SMT 172 [http://senzor.robotika.sk/mmp/SMT172.pdf Temperature sensor Specification sheet] | ||
* [http:// | * SMT 160-30 [http://senzor.robotika.sk/mmp/SMT160.pdf Temperature sensor Specification sheet] | ||
* [http://ww1.microchip.com/downloads/en/AppNotes/Atmel-2505-Setup-and-Use-of-AVR-Timers_ApplicationNote_AVR130.pdf AVR130: Setup and Use the AVR® Timers.] Aplication Note, Atmel Corporation 2002.<BR> + [http://www.atmel.com/dyn/resources/prod_documents/AVR130.zip software download] | |||
* [http://ww1.microchip.com/downloads/en/AppNotes/Atmel-8014-Using-Timer-Capture-to-Measure-PWM-Duty-Cycle_ApplicationNote_AVR135.pdf AVR135: Using Timer Capture to Measure PWM Duty Cycle.] Aplication Note, Atmel Corporation 2005.<BR> + [http://www.atmel.com/dyn/resources/prod_documents/AVR135.zip software download] | |||
* Pozn. pre autora: staršia verzia tohoto cvika je tu [[Meranie dĺžky impulzu 2]] | * Pozn. pre autora: staršia verzia tohoto cvika je tu [[Meranie dĺžky impulzu 2]] | ||
Aktuálna revízia z 14:26, 14. apríl 2021
Úloha
- Vytvoriť simulátor PWM signálu snímača teploty: SMT 160-30, resp. SMT 172
- TC0 bude na pine PD5 generovať PWM signál s 𝑓_𝑃𝑊𝑀=1𝑘𝐻𝑧 a plnením v intervale DC = (0,1 až 0,9).
- DC budeme zadávať v %.
- Na meranie parametrov PWM signálu: T1 - čas v log. 1 a T_opak – trvanie jednej periódy PWM signálu použijeme TC1 (16b). TC1 nastavíme do módu „odpamätanie“ stavu počítadla pri výskyte hrany na pine PB.0. Využijeme ISR().
- Pomocou TC2, bude generovať presnú periodu vzorkovania. Periódu opakovania výpisov, ako aj zmeny plnenia o definovaný prírastok, napr. 1, budeme realizovať s krokom 0,5sek. Využijeme ISR().
- Výpisy na LCD, resp. terminál treba realizovať vo formáte, xx,x. (Pevná rádova čiarka). Pri výpočtoch nemôže byť použitá float aritmetika.
- Vo výpisoch sa musí objaviť: Nastavené plnenie. Trvanie T_1, resp. T_opak v SC a us. Ako aj plnenie v % vo formáte: xx,x. Rovnako aj danému plneniu odpovedajúca teplota vo formáte +-xx,x °C .
- Ako úloha naviac: Navrhnite filter typu kĺzavý priemer z 8-ich vzoriek.
Slajdy k teoretickému rozboru cvičenia
//Hlavný program
#include <avr/io.h>
#include <avr/interrupt.h>
#include "p_f_1.h"
#include "p_f_2.h"
// deklarovanie premenných
int main(void){
/* Ini PORT‘s, TCx, prerušení
Konfiguracia UART:Tx, Rx */
ini_usart_0(MYUBRR);
ini_TC0(); ini_TC1(); ini_TC2();
sei(); // Enable interrupts in general
sprintf(Riadok,"Meranie plnenia impulzu \r\n" );
zob_text_UART(Riadok);
/* main loop */
while (1) {
if(flag_Vypisov){
flag_Vypisov = 0;
Vypis();
Zmena_plnenia(); // DC = (10 az 90 %)
}
}
}
// ********************************* p_f_1.h
/*
* p_f_1.h
*/
#ifndef P_F_1_H_
#define P_F_1_H_
#define F_CPU 16000000UL /* Define CPU frequency here 16MHz */
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include <stdlib.h>
void zob_text_UART(char *);
void ini_usart_0(unsigned int );
void USART_Transmit( unsigned char );
void zob_text(char *);
void Zmena_plnenia(void);
unsigned char Prepocet_plnenia_PWM(unsigned char );
void Vypis(void);
extern char Riadok[];
extern volatile unsigned int T1_no_vz;
extern volatile unsigned int T1_st_vz;
extern volatile unsigned int pl_PWM_pocitane_Percent;
extern volatile unsigned long T_log_1;
extern volatile unsigned long T_log_1_us;
extern volatile long T_opak;
extern volatile int T_M;
extern unsigned char DC_PWM_percent;
extern uint8_t T_vypis; // cca 0,5 sek , potom doladim
#define BAUD 115200
//UCSR0A.U2X0 = 1
#define MYUBRR
#endif /* P_F_1_H_ */
// ********************************* p_f_1.c
/*
* p_f_1.c
*/
#include "p_f_1.h"
#include "p_f_2.h"
// Inicializacia UARTu
void ini_usart_0(unsigned int mybr){
UBRR0 = mybr;
...
}
void zob_text_UART(char *s){
register unsigned char c;
while((c = *s++)) USART_Transmit(c); // retazec konci "nulou"
}
void USART_Transmit( unsigned char data ){
/* Wait for empty transmit buffer */
while ( !( UCSR0A & (1<<UDRE0)) );
/* Put data into buffer, sends the data */
UDR0 = data;
}
void Vypis(void){
// formátovaný výpis
//printf("Plnenie:?????? ", DC_PWM_percent, T_log_1, T_opak );
Výpis:Plnenie: dd%, ddd [SC], ddd [SC]
Výpis:Plnenie: dd%, ddd [us], ddd [us]
printf("Plnenie:?????? ", DC_PWM_percent, pl_PWM_pocitane_Percent );
Výpis:Plnenie: dd%, dd,d%
zob_text_UART(Riadok);
}
void Zmena_plnenia(void){ // rozsah 10 az 90 %
DC_PWM_percent+=?;
if (DC_PWM_percent >90)DC_PWM_percent = 10;
// prepocitam rozsah v percentach na odpovedajuce cislo
if (DC_PWM_Percent > 90) DC_PWM_Percent = 10;
OCR0B = f(DC_PWM_Percent);
}
unsigned char Prepocet_plnenia_PWM(unsigned char pln_per){
...
}
// ********************************* p_f_2.h
/*
* p_f_2.h
*/
#ifndef P_F_2_H_
#define P_F_2_H_
#define set_bit(Adress,Bit) (Adress |= (1<<Bit))
#define clear_bit(Adress,Bit) (Adress &= ~(1<<Bit))
#define toggle_bit(Adress,Bit) (Adress ^= (1<<Bit))
extern volatile unsigned char poc_T_vypis ;
extern volatile unsigned char flag_Vypisov ;
#define f_opak_TC0 1000 // 1000 Hz <-> 1ms
#define N_D_TC0 // Delic pre TC0
#define OCR0A_f_opak_TC0 // Vysledkom je perioda opakovania 1ms !!!!!
#define f_opak_TC2 500 // 500 Hz -> 2ms
#define N_D_TC2 // Delic pre TC2
#define OCR2A_f_opak_TC2 // Vysledkom je 2ms casova vzorka !!!!!
#define T__050 250 // 0,5 sek = 250 * 2ms
void ini_TC0(void);
void ini_TC1(void);
void ini_TC2(void);
#endif /* P_F_2_H_ */
// ********************************* p_f_2.c
/*
* p_f_2.c
*
* Created: 4/12/2021 11:29:22 AM
* Author: Admin
*/
#include <avr/io.h>
#include "p_f_1.h"
#include "p_f_2.h"
void ini_TC0(void){
// Nastavenie TC0
set_bit(DDRD,PIND5); //OC0B PWM pin
// 7 6 5 4 3 2 1 0
// COM0A[1:0] COM0B[1:0] WGM0[1:0]
TCCR0A = ??????;// OC0B PWM mod = ?
// 7 6 5 4 3 2 1 0
// WGM02 CS0[2:0]
TCCR0B = ??????;// fosc/??
OCR0B = 𝑓("DC_PWM_percent " );
// nastvenie frekvencie opakovania na 1ms
OCR0A = OCR0A_f_opak_TC0;
}
void ini_TC1(void){
// Timer1 Capture
DDRB &= ~(1<<DDB0); //ICP1 = PORTB.0, input
PORTB |= (1<<PORTB0); // Pullup Rezistor
// Nastavenie TC1
// 7 6 5 4 3 2 1 0
// WGM12 CS1[2:0]
// fTC1 = f(fosc) chceme max. presnosť merania
TCCR1B ?= ????;
TCCR1B ?= ????; // odchytenie na nabeznu hranu
TIMSK1 ?= ????; // povolenie prerusenia od capture T1
// sei(); pre všetky naraz
}
void ini_TC2(void){
// Nastavenie TC2
// 7 6 5 4 3 2 1 0
// COM2A[1:0] COM2B[1:0] WGM2[1:0]
TCCR2A ? = ????;// OC2B PWM mod = 7
// 7 6 5 4 3 2 1 0
// WGM02 CS0[2:0]
TCCR2B ?= ????;// fosc/??
// nastavenie frekvencie opakovania na 2ms
OCR2A ? = OCR2A_f_opak_TC2;
// Enable interrupts @ overflow TC2 MOD 7
TIMSK2 ? = ????;
// sei(); pre všetky naraz
}
ISR(TIMER2_OVF_vect)
{ /// tato slucka sa vykona kazde 2,0ms
OCR2A = OCR2A_f_opak_TC2;
//toggle_bit(PORTD,PIND2); //PD2 - change
poc_T_vypis--;
if (!poc_T_vypis) {
// prednastavim pocitadlo vypisov na 0,5s
poc_T_vypis = T__050;
flag_Vypisov = 1;// nastavim priznak vypisov
//toggle_bit(PORTD,PIND2); //PD2 - change
}
}
ISR(TIMER1_CAPT_vect){
// globalne prerusenie je zakazane
// POCITADLO SA INKREMENTUJE KAZDU ?us
if(TESTUJEM HRANU){// bola nábežna hrana
....; // tu prepnem na dobežnu hrana
T1_st_vz = T1_no_vz;
T1_no_vz = ICR1; // odpamätám nový “čas“
T_opak = ... ;
pl_PWM_pocitane_Percent = f(T_log_1,T_opak);
T_M = f( (T_log_1 ,T_opak);
} else {// bola dobežna hrana
....; // tu prepnem na nábežnu hrana
T_log_1 = ICR1 - T1_no_vz;
T_log_1_us =f(.....).
}
}
Literatúra
- SMT 172 Temperature sensor Specification sheet
- SMT 160-30 Temperature sensor Specification sheet
- AVR130: Setup and Use the AVR® Timers. Aplication Note, Atmel Corporation 2002.
+ software download - AVR135: Using Timer Capture to Measure PWM Duty Cycle. Aplication Note, Atmel Corporation 2005.
+ software download - Pozn. pre autora: staršia verzia tohoto cvika je tu Meranie dĺžky impulzu 2