Sunteți pe pagina 1din 10

UNIVERSIDADE FEDERAL DA BAHIA

ENGENHARIA ELÉTRICA – SISTEMAS


MICROPROCESSADOS

PROBLEMA 3: HARDWARE-IN-THE-LOOP
(HIL) COM O ATMEGA328P

SALVADOR - 2018
UNIVERSIDADE FEDERAL DA BAHIA
ENGENHARIA ELÉTRICA – SISTEMAS
MICROPROCESSADOS

HARDWARE-IN-THE-LOOP (HIL) COM O


ATMEGA328P
GRUPO 3: ALLAN ALMEIDA, DOUGLAS OLIVEIRA, FELIPE
ARAÚJO, ÍCARO AUGUSTO, LUIZ HENRIQUE E KELVIN NUNES

Trabalho apresentado para avaliação na disciplina de Sistemas


Microprocessados, do curso de Engenharia Elétrica, da Universidade Federal da
Bahia ministrado pelo professor Paulo Cesar.

SALVADOR - 2018
1. Introdução
O problema abordado baseia-se em criar um controlador, implementa-lo
no arduino sem o uso de sketches e comunica-lo via serial com o software
Matlab.
Este trabalho foi dividido em cinco seções, contendo Introdução, Objetivo,
Metodologia, Códigos e Conclusão. A seção 3 foi subdividida em cinco
etapas, que são referentes ao passo-a-passo da metodologia utilizada na
execução do projeto. Por sua vez, a seção 4 foi subdividida em duas,
contendo os códigos do arduino e do matlab.

2. Objetivo
Implementar um controlador no ATmega328p para interagir com uma
planta simulada através do ferramental disponível no software
Matlab/Simulink.

3. Metodologia
3.1. Softwares necessários
Alguns dos nossos integrantes da equipe já trabalharam com Arduino e
Matlab, usando o IDE do Arduino. Então descobrimos primeiro como
programar o Arduino em C usando o Atmel Studio. A primeira dificuldade foi
passar o código para o Arduino, sendo necessário fazer o download do
compilador AVRdude que é um utilitário que serve para manipular a memória
dos microcontroladores AVR. Com o programa instalador e usado como
ferramenta externa no Atmel Studio, foi possível escrever e reescrever
códigos no Arduino usando USB, sem a necessidade de uma placa
programadora.
O Matlab foi utilizado para pegar os dados enviados pelo Arduino na porta
serial, e aplicar na planta e retornar para o arduino o valor da planta em
100ms para que o controlador possa atuar novamente.

3.2. Comunicação serial entre o Arduino e o Matlab


No Arduino, um código fornecido a nós com algumas funções básicas foi
utilizado. Nesse código o ATmega328p é configurado para funcionar com
comunicação serial a uma taxa de transmissão de 9600. Também se
encontra funções como usart_GetSer para pegar um caractere da porta
serial, usart_PutSer para enviar um caractere para porta serial e usart_PutStr
para enviar um conjunto de caracteres para a porta serial, dentre outras que
não foram utilizadas.
Para agilizar a coleta de dados pelo Arduino, foi criado uma função
chamada de uart_GetStr que serve para pegar um conjunto de caracteres da
porta serial até haver um “Carriagem return”, que é o famoso enter de
parágrafo ou o código ‘13’ em ASCII.
No Matlab já existe funções definidas para comunicação serial, basta usar
o comando g=serial(‘COM9’) que relaciona a variável g com a porta serial
COM9. Os comandos fget1(g) para pegar informação da porta serial e o
comando fprintf(g,’%s’,nomeVariavel) para enviar o valor de nomeVariavel
para a porta serial em forma de String.
Antes de testar a comunicação serial entre o Matlab e o Arduino, primeiro
testamos a comunicação do software com a porta serial, ou seja, se eles
enviam as informações corretamente para a porta serial. Isso foi feito usando
a IDE do Arduino, que possui uma ferramenta chamada serial monitor, onde
é possível visualizar os valores que estão sendo enviado para a porta serial
e, além disso, consegue escrever valores para a porta serial.
Foi observado a necessidade de enviar os dados no formato String. No
entanto, vamos trabalhar com números, ou seja, foi necessário converter as
variáveis que serão enviadas para a porta serial em String e depois
convertida em números de novo.
Essa conversão foi feita com alguns problemas que serão ditos
posteriormente. Após a conversão das variáveis transmitidas, a segunda
etapa foi finalizada. Com a comunicação pronta entre os dois softwares,
bastava agora fazer a simulação da planta e a atuação do controlador.

3.3. Escolha da planta


A planta escolhida foi a de um tanque com a saída de fluxo controlável, e
consequentemente, a possibilidade de controlar o nível da água do tanque.
O modelo da planta escolhida é representado em Laplace pela equação:
1/(s+5)
Uma equação simples, apenas para aplicamos o controle que será
implementado no Arduino e podermos visualizarmos a resposta do sistema.
O nível desse tanque pode chegar até no máximo em 15m. E antes de
iniciar a simulação, devesse informar as condições iniciais ao matlab, para
ele saber em que nível o tanque se encontra.

3.4. Programa do controlador dentro do arduino


Foi escolhido o controlador mais simples possível, um controlador
proporcional. No código do Arduino foram escolhidos setpoints para
tentarmos controlar a planta do matlab. O setpoint começa no valor máximo,
de 15m e a cada 10 segundos o se reduz para a metade.

3.5. Teste
Foi configurado no matlab para que o nível da água inicie em 0m de altura,
e no Arduino inicie com o setpoint de 15 m. O arduino recebe do matlab o
valor do nível atual e calcula o erro entre o valor desejado e a altura atual do
nível da água, e multiplica essa diferença para o valor Kp (ganho
proporcional), do PID. Como foi escolhido o controlador mais simples, os
ganhos Ki e Kd são zeros. Por simplicidade, o valor de Kp é 1.
O Arduino, após o cálculo do valor a ser corrigido, envia o valor para o
Matlab, que coleta o dado e simula como a planta irá atuar com aquele sinal
durante 100ms. O valor da planta após 100ms é retornado para o Arduino,
que recebe o novo nível da água para calcular o novo erro e com isso aplicar
um sinal maior ou menor, dependendo do erro.
Depois de 10 segundo, o setpoint muda de 15m para a metade. E depois
de mais 10 segundo, o setpoint reduz novamente pela metade. A simulação
acontece durante como é possível visualizar no gráfico:

É possível observar uma diferença entre o setpoint e o valor estacionário


do sistema ao final de cada 10 segundos. Isso se deve ao fato de não
conseguirmos converter números decimais (float ou double) em string e
envia-lo do arduino para o matlab.
Um jeito de superar essa dificuldade foi usar apenas números inteiros, o
que causou esta pequena diferença entre o setpoint e valor estacionário.

4. Códigos
4.1. Código Arduino (atmel studio)
/*
* HIL.c
*
* Created: 7/17/2018 10:43:03 AM
* Author : Ruffeny
*/

#include <stdlib.h>
#include <string.h>
#include <avr/io.h>
#include <util/delay.h>

#define F_CPU 16000000UL // provided by boards.txt

/*******************************************************************
* constants & helper macros *
*******************************************************************/

#define _BAUD 9600 // baud rate


#define _UBRR (F_CPU/16)/_BAUD-1

#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~(1<<bit))


#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= 1<<bit)

/*******************************************************************
* variables *
*******************************************************************/
int error;
int p;
float kp=1;

/*******************************************************************
* functions *
*******************************************************************/

char usart_GetSer(void) // GetSer (blocking)


{ while(!(UCSR0A & 1<<RXC0)); // wait char available
return UDR0; //
} //
/******************************************************************/
void uart_GetStr(char *calledstring)
{
DDRD |= (1<<5);
char ch;
int cntr = 0;

while (1)
{

ch = usart_GetSer();

if (ch == 13) // New Line


{
calledstring[cntr] = 0;
return;
}
else
{
calledstring[cntr] = ch;
cntr++;
}
}
}
/*******************************************************************/
void usart_PutSer(char data) // PutSer (blocking)
{ while(!(UCSR0A & 1<<UDRE0)); //
UDR0 = data; //
} //
/*******************************************************************/
void usart_PutStr(char * data) // PutStr
{ while(*data!=0) //
usart_PutSer(*data++); //
} //
/*******************************************************************/
void usart_PutNib(char work) // PutNib (hex nibble to ASCII)
{ work &= 0x0F; // lo nibble only
if(work > 9) work += 7; // 'A'..'F' values
usart_PutSer(work + '0'); // put ascii nibble
} //
/*******************************************************************/
void usart_PutHex(char value) // PutHex
{ usart_PutNib(value >> 4); //
usart_PutNib(value); //
}

/*******************************************************************
* main setup *
*******************************************************************/
int main (void) //
{ UBRR0H = (_UBRR) >> 8; // setup USART port
UBRR0L = (_UBRR); // "
//UCSR0B |= _BV(TXEN0); // "
//UCSR0B |= _BV(RXEN0); // "
//sbi(UCSR0B, TXEN0); // "
//sbi(UCSR0B, RXEN0); // "
UCSR0B |= 1<<TXEN0 | 1<<RXEN0; // "

char teste[50]; //criando uma string para teste


int numero=2;
char input[255];
char* pEND[255];
float decimal;
sprintf(teste,"%i",numero);

int setpoint = 16;


int t = 0;

//usart_PutStr("Hello world\n\r "); // test


//usart_PutHex(0x3C); // test

/*******************************************************************
* main loop *
*******************************************************************/
while(1) //
{

uart_GetStr(input);
decimal = atof(input);
error = setpoint - decimal;

p = kp*error;

sprintf(teste,"%i",p);
usart_PutStr(teste);
usart_PutStr("\n");
t=t+1;
if (t==100){
setpoint = setpoint/2;
t=1;
}
} //
}

4.2. Código Matlab

delete(instrfindall); %limpa todos os instrumentos


anterioarmente abertos na serial
clear all;
close all;
clc;

s = tf('s');
g = serial('COM9'); % atribui o objeto à porta serial

FT = 1/(s+5);
sistema = c2d(FT,1/100);

set(g, 'InputBufferSize', 16); % Número de bytes no


buffer de entrada
%set(s, 'FlowControl', 'hardware');
set(g, 'BaudRate', 9600);
set(g, 'Parity', 'none');
%s.Terminator = 'CR';
%s.ReadAsyncMode = 'continuous';

set(g, 'DataBits', 8); % Procura por "Serial


Configurada" no help
set(g, 'StopBit', 1);
set(g, 'Timeout', 1000); % Tempo em segundos que o
matlab aguarda por novos dados.

disp(get(g, 'Name')); % Mostra o nome "Serial - COM9"

prop(1) = (get(g, 'BaudRate')); % Prop é apenas um vetor


de strings que nesse caso tem 4 posições
prop(2) = (get(g, 'DataBits'));
prop(3) = (get(g, 'StopBit'));
prop(4) = (get(g, 'InputBufferSize'));

disp(['Port Setup Done!!', num2str(prop)]); % help


num2str: converte numeros para uma string
fopen(g); % Abre a porta serial.
t=1;
disp('Running');
% while(t <= 20) % Executa 100 ciclos - se você não
consegue ver o símbolo, isto é sinal de "menos de"
% a = fgetl(s); % fread(a, 4, 'single');%
('SIZE', 16.000, 'PRECISION','%f');%Reads the data from
fprintf('%s', a);
% x(t) = t; % Multiplicando pela taxa de
amostragem % x(t) e y(t) são para construir um
% y(t) = str2double(a); % a é uma string, srt2num
converte uma string para um número
% %fprintf(s,'%s',num2str(y(t)));
% t = t+1;
% a = 0; % Limpa o buffer
% pause(1);
% end
%while (t<=20)
% pause(1)
%cr = "\n"
pause(2);
valorinicial=0;
valorMaximo = 15;
ultimovalor = 0;
t=1;
while (t<=(31/0.1)) %0.1, eh o tempo de amostragem,
poderia ser Ts (para ficar mais generico))
%comeca do 6, mas na verdade t=1, entao passara 300
amostras = 30s
nstring = num2str(ultimovalor(t));
tamanho = length(nstring);
nstring(tamanho+1)=13;
fprintf(g,'%s',nstring);

a = fgetl(g);
y(t) = str2double(a); %valor do controlador
x = y(t)*step(FT)+ultimovalor(t); %simulacao da
planta com a nova entrada
a = 0;
t=t+1;
ultimovalor(t+1) = x(12); %valor do sistema depois
depois de 100ms;
tempo(t) = t*0.1;

pause(0.1); %tempo de amostragem eh Ts = 0.1


end

tempo(t+1) = (t+1)*0.1;
%fprintf(s,'%s',numero);
% a = fgetl(s);
% y(t) = str2double(s);
% ;
% a=0;%limpa buffer;
% pause(1);%pausa 1 segundo;
%end

fclose(g);

5. Conclusão
Através deste projeto, pudemos colocar em prática o nosso conhecimento
acerca de comunicação serial usando o protocolo USART.
Foi possível, mesmo sem o uso da IDE, programar o arduino usando a
linguagem C e obtivemos um resultado satisfatório com a comunicação entre
os softwares utilizados.
Conseguimos controlar uma planta virtual através de um controlador real,
sendo assim não houve a necessidade de um sistema físico para testar o
controlador, concluindo com êxito o objetivo do projeto.

S-ar putea să vă placă și