Você está na página 1de 11

Universidade Federal de Minas Gerais

Departamento de Engenharia Eletrônica

Relatório Técnico de Laboratório de Controle e


Automação II
Processamento em Tempo Real e Filtragem Digital

Vítor Alves de Andrade e Aguiar


Leonardo Carvalho Gabrich

Belo Horizonte
2021
1. Descrever o funcionamento detalhado do algoritmo ilustrativo apresentado na seção 3.2.
Elaborar um diagrama temporal com 30 segundos de duração, detalhando os aspectos de
prioridade e preempção das tarefas implementadas.

O algoritmo Multitarefa apresentado é composto pelas funções setup_multitasking,


setup, loop, ISR que são responsáveis por realizar a execução de quatro tarefas (​task0,​
task1, task2​ e​ task3)​ .

O método setup realiza as configurações gerais do código. Ele é responsável por


configurar a taxa de transferência (bit por segundo) para a comunicação serial
(utilizada neste caso para o monitoramento das variáveis do sistema graficamente).
Além disso, ele define o registrador DDRB como 0b00001111 (0x0f), definindo as
portas do PortB do arduino como entrada (0) ou saída (1), e seta os valores das portas
como 0 (todas em nível baixo).

void​ ​setup​()
{
​Serial​.​begin​(​9600​);
DDRB =​0x0f​;
PORTB=​0x00​;
setup_multitasking();
}

.Ao final de sua execução, o método setup chama o método de ajustes de


multitarefa (setup_multitasking). Este método faz configurações referentes ao clock
e a temporização do arduino e habilita a interrupção por tempo do arduíno,
configurando-a para executar a cada 1 ms.

void​ setup_multitasking(​void​)
{
TCCR1A = ​0x00​; ​// CLOCK 16MHz
TCCR1B = ​0x0b​; ​// PRESCALER 64
OCR1A = ​250​; ​// Tint 250*64/16000000 = 1ms
TIMSK1 = ​0x02​; ​// habilita específica do timer
sei(); ​// habilitação geral de interrupções
}
A rotina de interrupção (ISR) possui o controle para executar as quatro tarefas do
código. Ela possui contadores que são incrementados a cada execução da
interrupção, para se controlar o período das tarefas (e.g., task0_counter,
task1_counter). As tarefas têm um valor máximo especificado para cada um dos
contadores definido em tempo de compilação por meio das diretivas ​define no
início do código - “​#define TASK0_COUNTER_MAX 1000​”. Caso o contador atinja
ou ultrapasse esse valor, a tarefa referente aquele contador é executada.

A ​task0 e a ​task1 dependem apenas da rotina de interrupção e são executadas a


cada 1 segundo e 2 segundos, respectivamente. Já a ​task2 e ​task3 d​ ependem
também de uma lógica que é executada no loop infinido definido na função ​loop().​

A ​task2 ​possui é executada quando a variável task2_enable é​ verdadeira, que é


setada caso o contador auxiliar, que é incrementado na ​task3, ​seja maior que 2​. ​A
task3 é chamada a cada 20 segundos e então ela seta a variável que habilita a
execução do restante do código no loop (​task3_go​). Uma vez habilitada, no loop é
impresso a sinalização de entrada na tarefa no monitor serial e resetado o booleano
​ aso o valor da variável auxiliar seja menor que 5 ela é incrementada, e o
task3_go. C
loop entra então em espera por 5 segundos.

A tarefa 2 possui também parte de sua lógica na interrupção por tempo a cada 500
ms. Nela, caso a tarefa esteja habilitada, o LED altera o seu estado.

As tarefas 0 e 1 não são impactadas com o delay apresentado na iteração principal


do código, uma vez que depende somente da interrupção por tempo, que executa
independentemente e possui maior prioridade.

A figura 1 representa o estado de cada uma das tarefas do algoritmo analisado.

Figura 01 - Diagrama temporal representando os estados das tarefas


2. Implementar uma estrutura multitarefa em que realize as seguintes ações: - Executar uma
lei de controle digital com amostragem de 10ms - Executar amostragem em 2ms e
reamostragem em 10ms - Executar exibição de informação em canal serial a cada 200ms -
Executar varredura de teclado (botões) a cada 30ms

/*Template Multitarefa - Cláudio Campos - 2020*/


/* Definções de constantes */
#define​ TRUE ​1
#define​ FALSE ​0
#define​ SET ​1
#define​ RESET ​0
#define​ TASK0_COUNTER_MAX ​10
#define​ TASK1_COUNTER ​2
#define​ TASK1_COUNTER_MAX ​10
#define​ TASK2_COUNTER_MAX ​200
#define​ TASK3_COUNTER_MAX ​30

// Definições de variáveis globais


unsigned​ ​int​ task0_counter=​0​;
unsigned​ ​int​ task1_counter=​0​;
unsigned​ ​int​ task2_counter=​0​;
unsigned​ ​int​ task3_counter=​0​;
unsigned​ ​char​ task0_enable=​TRUE​;
unsigned​ ​char​ task1_enable=​TRUE​;
unsigned​ ​char​ task2_enable=​FALSE​;
unsigned​ ​char​ task3_enable=​TRUE​;
unsigned​ ​char​ task3_go=​FALSE​;

​ har​ task0_data;
unsigned​ c
unsigned​ c​ har​ task1_data;
unsigned​ c ​ har​ task3_data;

/* Protótipos de funções auxiliares */


void​ ​setup_multitasking​(​void​);

/* Rotina de configuração inicial */


void​ ​setup​()
{
​Serial​.​begin​(​9600​);
DDRB =​0x00​; ​// Pins configurations
PORTB=​0x00​;
​setup_multitasking​();
}

/* Rotina principal - loop infinito */


void​ ​loop​()
{
}
/* Configura o sistema de interrupção por timer */
void​ ​setup_multitasking​(​void​)
{
TCCR1A = ​0x00​; ​// CLOCK 16MHz
TCCR1B = ​0x0b​; ​// PRESCALER 64
OCR1A = ​250​; ​// Tint 250*64/16000000 = 1ms
TIMSK1 = ​0x02​; ​// habilita específica do timer
​sei​(); ​// habilitação geral de interrupções
}

/* Rotina de tratamento de interrupção */


ISR​(TIMER1_COMPA_vect) ​// interrompe a cada 1ms
{
​/* Controla as tarefas */
task0_counter++;
​if​(task0_counter>=TASK0_COUNTER_MAX)
{
task0_counter=​0​;
​//Executar uma lei de controle digital com amostragem de 10ms
​if​(task0_enable==​TRUE​)
{
task0_data=PORTB&​0X01​;
}
}

task1_counter++;
​if​(task1_counter%TASK1_COUNTER == ​0​)
{
​//Executar amostragem em 2ms
task1_data = PORTB&​0x02​;
​if​(task1_counter%TASK1_COUNTER_MAX == ​0​)
{
​// Reamostragem em 10ms
task1_counter = ​0​;
task1_data = PORTB&​0x02​;
}
}

task2_counter++;
​if​(task2_counter>= TASK2_COUNTER_MAX )
{
​//Executar exibição de informação em canal serial a cada 200ms
​Serial​.​print​(​"Informação Exibida"​);
task2_counter = ​0​;
}

task3_counter++;
​if​(task3_counter>=TASK3_COUNTER_MAX)
{
task3_counter=​0​;
​// Executar varredura de teclado (botões) a cada 30ms
task3_data = PORTB&​0xFC​;
}
}
3. . Implementar um filtro digital de média móvel, com 8 amostras atrasadas, para o sistema
da seção 3.3, utilizando apenas as informações da resposta ruidosa.

O filtro digital de média móvel foi desenvolvido com a parametrização das quantidades
de amostras atrasadas.

/* Lab 2 UFMG - Cláudio Campos 2020*/ 


/* Leonardo Gabrich e Vítor Alves */ 
#define​SAMPLING 8
​ 
float​S
​ampleValues​
[SAMPLING]; 
int​i; 
float​x1; 
 
float​y
​Med​
(​void​
); 
 
void​​
setup​
() { 
S
​erial​
.b​egin​
(​9600​
); 
r
​andomSeed​
(a​nalogRead​
(0​​
)); 
 
/
​/ Reseta variáveis globais 
f
​or​
(i​nt​j = ​
0​; j < SAMPLING; j++) 

SampleValues​
[j] = 0
​​; 
i = 0
​​; 
x1 = 0
​.0F​

 

void​​
loop​
() { 
f
​loat​Y = ​
yMed​
(); 
S
​erial​
.p​rint​
(Y); ​
// Valor Medido -> Com ruido 
S
​erial​
.p​rint​
(​", "​
); 
S
​erial​
.p​rintln​
(m​ovingAvg​
(Y)); /
​/Valor filtrado pela média móvel 
d
​elay​
(​1)
​; 

float​y
​Med​
(​void​
){ 
f
​loat​randNum, ruido; 
randNum = ​
random​
(-​
100​
,1​00​
)/​
100.0​

ruido = 1
​​+ 5
​​* randNum/​
100​
; /
​/ 5% de ruído 
r
​eturn​
(ruido*​
analogRead​
(​0)
​); 

float​m
​ovingAvg​
(​float​​
medicao​


i++; 
S
​ampleValues​
[i] = medicao; 
i
​f​
(i >= 8
​​) 
i = ​
0;​ 
f
​loat​soma = ​
0​; 
f
​or​
(i​nt​j = ​
0​; j < SAMPLING; j++) 
soma += ​
SampleValues​
[j]; 
r
​eturn​soma/SAMPLING; 

A função “movingAvg” recebe o novo valor medido e o acrescenta na variável


“soma”, removendo o valor mais antigo, retornando então a média móvel. Foi
impresso então no serial os valores dos dados sem tratamento e com o filtro por média
móvel

Figura 2 - Gráfico da resposta do sistema da Seção 3.3. Em azul, o sinal com ruído e em
amarelo o sinal tratado com a média móvel
Pode-se perceber que a média móvel filtra os elementos de alta frequência,
adicionando porém um atraso de 8 amostras no processo.
4. Implementar um filtro digital de primeira ordem para o sistema da seção 3.3 e comparar
os resultados com filtro média móvel. Discutir tecnicamente a aplicabilidade destes filtros
para utilização em sistemas de controle digital.
Foi utilizado um filtro passa-baixa digital para filtrar o sinal ruidoso. A constante beta
foi definida de forma a não se ter a atenuação do sinal principal.

/* Lab 2 UFMG - Cláudio Campos 2020*/


#define​ SAMPLENUMBER ​8
#define​ BETA ​0.85

float​ ​sampleValues​[​SAMPLENUMBER​] = {​0​, ​0​, ​0​, ​0​, ​0​, ​0​, ​0​, ​0​};
float​ ​medicao​, ​dadosMediaMovel​, ​dadosPassaBaixa​;
static​ ​float​ ​medidaAnterior​ = ​0​;
float​ ​yMed​(​void​);
float​ ​mediaMovel​(​float​ ​medida​);
float​ ​passaBaixa​(​float​ ​medida​);

void​ ​setup​()
{
​Serial​.​begin​(​9600​);
​randomSeed​(​analogRead​(​0​));
}
void​ ​loop​()
{
​medicao​ = ​yMed​();
​dadosMediaMovel​ = ​mediaMovel​(​medicao​);
​dadosPassaBaixa​ = ​passaBaixa​(​medicao​);

​Serial​.​print​(​medicao​);
​Serial​.​print​(​", "​);
​Serial​.​print​(​dadosMediaMovel​);
​Serial​.​print​(​", "​);
​Serial​.​println​(​dadosPassaBaixa​);

​delay​(​1​);
}

float​ ​yMed​(​void​)
{
​float​ ​randNum​, ​ruido​;
​randNum​ = ​random​(-​100​, ​100​) / ​100.0​;
​ruido​ = ​1​ + ​5​ * ​randNum​ / ​100​; ​// 5% de ruído
​return​ ​ruido​ * ​analogRead​(​0​);
}

float​ ​mediaMovel​(​float​ ​medida​)


{
​static​ ​short​ ​int​ ​i​ = ​0​;

​sampleValues​[​i​] = ​medida​;
​i​++;
​if​ (​i​ >= ​8​)
{
​i​ = ​0​;
}

​float​ ​sum​ = ​0​;


​for​ (​int​ ​j​ = ​0​; ​j​ < ​SAMPLENUMBER​; ​j​++)
{
​sum​ += ​sampleValues​[​j​];
}

​return​ ​sum​ / ​SAMPLENUMBER​;


}

float​ ​passaBaixa​(​float​ ​medidaAtual​)


{
​medidaAnterior​ = (​1​ - ​BETA​) * ​medidaAtual​ + ​BETA​ * ​medidaAnterior​;
​return​ ​medidaAnterior​;
}
 
Filtros desse tipo são simples de se aplicar em sistemas de controle devido a sua facilidade de
implementação, mas devem ser configurados a depender do espectro de frequências do sinal
medido e também da dinâmica do processo. Em alguns casos, pode ser necessário se aplicar
filtros mais robustos.
▉​Original
▉ ​Média Móvel ( 8 amostras )
▉​ Passa-baixas

Figura 3 - Resultado da filtragem digital. Em azul, o sinal original. Em laranja, o dado


filtrado por média móvel, e em vermelho o sinal filtrado pelo passa-baixa

5. Faça uma resenha técnica sobre a biblioteca FreeRTOS2 do Arduino.

O FreeRTOS é um sistema operacional de tempo real, de código aberto,


voltado para microcontroladores. Ele é distribuído sob licença da MIT e facilita a
programação, implementação, segurança, conexão e gerenciamento de pequenos
dispositivos de borda. Além de ser voltado para a confiabilidade e facilidade de uso, o
FreeRTOS se mostra muito versátil, já que possui um grupo crescente de bibliotecas
que possibilitam o uso dele em aplicações de software de diferentes setores.
O sistema operacional, recentemente comprado pela Amazon, possui um
diferencial em relação aos demais SO’s executados por microcontroladores, que não
têm funcionalidades que permitem a conexão a redes locais ou à nuvem. O FreeRTOS
oferece bibliotecas que permitem que o dispositivo se conecte, com segurança, à
nuvem ou a outros dispositivos.

Ele ainda oferece métodos para operação multithread, mutex, semáforos e


temporizadores, além de permitir a priorização de threads. As aplicações do
FreeRTOS podem ser estaticamente alocadas ou dinamicamente alocadas em um dos
5 esquemas abaixo:

1. apenas alocação
2. alocação e liberação com um algoritmo rápido e simples;
3. alocação e liberação com coalescência;
4. alocação e liberação com coalescência que permite que o heap esteja
corrompido através de várias áreas de memória;
5. alocação e liberação através de biblioteca da linguagem C com algumas
proteções de exclusão mútua.

Você também pode gostar