Você está na página 1de 9

UNIVERSIDADE FEDERAL RURAL DO SEMI-ÁRIDO

CENTRO DE CIÊNCIAS EXATAS E NATURAIS-CCEN


CURSO DE CIÊNCIAS DA COMPUTAÇÃO
DISCIPLINA DE SISTEMAS EMBARCADOS
PROFº SILVIO ROBERTO FERNANDES DE ARAUJO

Relatório do Projeto Final de Sistemas Embarcados

Daniel Cabral de Souza

Mossoró-RN
2019
1. Objetivo: 
Este   trabalho   visa   o   desenvolvimento   de   um   Sistema   Embarcado   que   deve   ser
executado em um alimentador automático para animais de baixo custo. Sua principal
função é o acionamento de um motor de maneira automatizada, baseado em horários
pré­definidos   pelo   usuário,   e   que   devem   ser   guardados   em   um   banco   de   dados,
utilizando como interface de captura de dados, uma aplicação web.

2. Introdução
Os   sistemas   embarcados   estão   cada   vez   mais   presentes   em   nossa   vida   cotidiana,   e
tendem a se expandir cada vez mais, chegando a novas áreas que antes não dispunham
de tais tecnologias. Já conseguimos ver sua expansão nos eletrodomésticos, veículos,
telefones, e mais recentemente, nas casas inteligentes. Isso resulta em aparelhos mais
eficientes, de melhor qualidade, e muitas vezes, mais baratos.
O projeto de um sistema embarcado pode possuir muitas limitações, como memoria,
consumo de energia, desempenho, além de uma maior complexidade. Para facilitar o
seu   desenvolvimento,   surgiram   as   plataformas   de   prototipagem,   como   Arduino,
Rapberry  pi, Node  MCU,  etc.  Agora já   não  é  mais  preciso  construir   tudo do  zero,
utiliza­se dispositivos já prontos que podem ter componentes agregados, e que podem
ser programados para qualquer que seja o fim. 

3. Materiais e métodos

3.1. ESP32: 
É uma placa de desenvolvimento com uma ótima performance e baixo consumo
de energia, arquitetura de 32 bits, 240 Mhz de clock (15x mais que o Arduino UNO),
4MB   de   memória   FLASH,   além   de   já   ter   conectividade   sem   fio   via   Wireless   e
Bluetooth, já embutidos. A placa foi escolhida com base principalmente no seu custo
benefício,   além   do   seu   grande   número   de   portas   GPIO   (Portas   de   propósito   geral
Input/Output). 

3.2. IDE: 
Para desenvolvimento do código para a placa ESP32, foi utilizado o Arduino
IDE. O banco de dados MySql foi criado através da ferramenta xampp. O front­end da
aplicação web, foi desenvolvido com HTML e CSS, fazendo uso também da biblioteca
bootstrap, e o back­end em PHP, utilizando a IDE Visual Studio Code.

4. Desenvolvimento
Fora desenvolvidos 2 sistemas, que se comunicam via internet, o primeiro, que
será mostrado adiante, foi desenvolvido em C++ para rodar no ESP32.
Para conectar o Esp na rede Wireless, incluiu­se a biblioteca WifiMulti. Declarada a
variável WiFiMulti wifiMulti, bastou usar a função addAP dentro do setup, passando
como parâmetros, nome da rede e senha.
wifiMulti.addAP("DESKTOP-MY", "12345678");

Logo   abaixo,   utilizou­se   a   função   requisiçãoHTTP,   responsável   por   fazer   uma


requisição   HTTP   ao   servidor   do   banco   de   dados   de   horários.   Para   que   isso   fosse
possível, incluiu­se a biblioteca HTTPClient.h.
A estrutura simplificada da função requisicaoHTTP está abaixo: 
if((wifiMulti.run() == WL_CONNECTED)) {
HTTPClient http;//Variavel HTTPClient responsavel pela
requisição
String url = "/AutoFood/pegarHorarios.php";
http.begin("http://192.168.0.103"+url);
int httpCode = http.GET();
if(httpCode > 0) {
char buff[128]={0}; //char que guarda o retorno da requisição
}else {
//Requisição Http não obteve retorno, exibir mensagem de erro.
}
}else{
//Sem conexão
}

O if na primeira linha testa se há conexão, se houver, o cliente é iniciado pela função
begin, passando a url com o endereço do servidor. Em caso de resposta, o retorno da
requisição será armazenado na variável buff. A mesma será passada para outra função,
denominada quebrarHorarios que é responsável por dar um Split no vetor de char buff.
Acontece   que   o   retorno   dos   horários   é   retornado   do   servidor   no   formato:
hora1@hora2@hora3,...,@horan, então é necessário subdividir essa string, em várias
partes que serão armazenadas no vetor long horários[32] após um parseInt. Ou seja,
teremos no máximo 32 horários diferentes, ordenados do menor para o maior. 
A função responsável por preencher o vetor horários é a inserirHorario, ela atualiza a
variável quantidade, que indica quantos horários já foram inseridos, além de ordenar em
ordem crescente.
Outra função importante é a proximaPosicao. Dentro do loop, apenas uma posição do
vetor horários é testada de cada vez, por isso existe a variável posição que indica qual
horário testar, como mostrado na Figura 1. Quando a posição do vetor bate com a hora
atual, o motor deve ser ligado, e passamos a próxima posição do vetor, com posição
recebendo valor 3.
Figura 1. Vetor de horários e variável posição

Na primeira vez que o sistema inicia e preenche o vetor horários, a variável posição
ainda não tem valor definido. Por isso foi criado a função definirPosicao, com o código
abaixo: 
long horaAtual = hour*3600+m*60;
for(int i=0;i<quantidade;i++){
if(horarios[i]>horaAtual){
posicao=i;
break;
}else{
posicao=i;
}
}

Nela, basicamente percorre­se o vetor de horários, até achar um que seja maior que o
atual, esse será o próximo horário testado no loop.
Dentro da função loop, temos o seguinte código: 
vTaskDelay(pdMS_TO_TICKS(1000));//Espera 1 seg
long tempo=data.tm_hour*3600+data.tm_min*60+data.tm_sec; //Hora
atual em segundos
if (tempo >= horarios[posicao] && tempo <horarios[posicao]+3)
{
printf("Acionando motor durante 3 segundos...\n");
}
//Serial.println(quantidade);
if(tempo==(horarios[posicao]+3)){
proximaPosicao();
}
A função vTaskDelay é responsável pelo delay de 1s. Em seguida, tem­se a variável
tempo   que   recupera   o   horário   atual,   convertendo   para   segundos,   pois   no   banco   de
dados, eles estão armazenados em segundos.
Logo abaixo, temos o primeiro if que testa se a hora atual corresponde a do vetor. Esse
if será verdadeiro durante o tempo de acionamento do motor, neste caso, 3 segundos.
O   if   mais   abaixo   testa   se   já   se   passaram   3   segundos,   neste   caso,   a   função
proximaPosicao() será chamada para incrementar o valor de posição.

Figura 2. Monitor Serial do Arduino IDE

Na figura 2 temos o resultado do acionamento do sistema, que funciona dos segundos 0 
ao 2. No segundo 3, a posição que será testada já passa a ser a 5.
Para   manter   o  relógio   atualizado,  foi  utilizada   a  biblioteca  NtpClient,   que  pode  ser
facilmente baixada através do gerenciador de bibliotecas do Arduino IDE. Ela faz uso
do protocolo NTP (Network Time Protocol), que permite a sincronização do relógio
utilizando o UDP, na porta 123.
Após sua instalação e inclusão, é necessário instanciar as variáveis do servidor, como
mostrado no código abaixo: 
// Configurações do Servidor NTP
const char* servidorNTP = "a.st1.ntp.br"; // Endereço do Servidor NTP
para pesquisar a hora

const int fusoHorario = -10800; // Fuso horário em segundos (-03h =


-10800 seg)
const int taxaDeAtualizacao = 1800000; // Taxa de atualização do
servidor NTP em milisegundos

WiFiUDP ntpUDP; // Declaração do Protocolo UDP


NTPClient timeClient(ntpUDP, servidorNTP, fusoHorario, 60000);

A variável timeClient é usada dentro da função setup, invocando 3 de seus métodos. O
primeiro, begin(), inicia o servidor NTP, já o segundo, update(), faz a atualização do
horário do servidor. O último, getEpochTime(), retorna a data e hora em formato Unix
Timestamp, seu retorno é atribuído a uma variável struct de tempo que é setada no
relógio interno do ESP32 através da função settimeofday, como pode ser visto no trecho
de código abaixo: 
timeval tv;//Cria a estrutura temporaria para funcao abaixo.
tv.tv_sec = timeClient.getEpochTime();//Atribui minha data atual em
formato Unix Timestamp,
settimeofday(&tv, NULL);//Configura o RTC para manter a data
atribuida atualizada.

O relógio interno RTC (Real Time Clock) do ESP32, foi utilizado para manter a hora
atualizada,   mesmo   que   a   conexão   de   internet   caia,   o   sistema   continua   funcionando
normalmente. Só é necessário ter a conexão no momento da inicialização, quando o
horário é carregado através do NTP. 
Para   fazer   uso   do   RTC,   é   necessário   incluir   a   biblioteca   time.h,   e   algumas   outras
bibliotecas   necessárias   para   seu   funcionamento.   Também   é   preciso   declarar   a   uma
variável, struct tm data. O struct tem tem a seguinte estrutura: 

struct tm
{
tm_sec; /* seconds, range 0 to 59 */
tm_min; /* minutes, range 0 to 59 */
tm_hour; /* hours, range 0 to 23 */
tm_mday; /* day of the month, range 1 to 31 */
tm_mon; /* month, range 0 to 11 */
tm_year; /* The number of years since 1900 */
tm_wday; /* day of the week, range 0 to 6 */
tm_yday; /* day in the year, range 0 to 365 */
tm_isdst; /* daylight saving time */
};

Para recuperar a hora atual por exemplo, basta fazer:
int hora = data.tm_hour

Sistema Web
A página inicial, mostrada na figura 3, é onde são listados os horários cadastrados, em
ordem crescente. Quando são feitos  32 cadastros, o botão Adicionar novo horário é
bloqueado. Para adicionar novos horários, deve­se excluir algum dos já existentes.
Figura 3. Página inicial com os horários salvos exibidos em uma
tabela

Ao clicar em adicionar novo horário, uma nova página é carregada (Figura 4).

Figura 4. Pagina de cadastro de horários

O   usuário   deve   inserir   um   horário   valido   no   formato   24h   para   conseguir   efetuar   o
salvamento  e ser redirecionado  a página  anterior.  A  opção de selecionar  os  dias  da
semana não foi implementada. Só após calculado o total de segundos, é feita a inserção
na tabela.
$segundos= ($hora*3600)+($minutos*60);
A   página   pegarHorarios.php   é   acessada   sempre   que   o   ESP32   fizer   uma   requisição
HTTP. Ela faz um select na tabela horários do banco de dados AutoFood. A tabela tem
a estrutura mostrada na Figura 5.
Figura 5. Estrutura da tabela horários no banco de dados

 Com o resultado do select, a coluna segundos de cada registro é concatenada em uma
string, separados com @, como mostrado no código abaixo.
while ($linha = $consulta->fetch(PDO::FETCH_ASSOC)) {
$horarios.=$linha['segundos']."@";
}
$horarios=substr ($horarios , 0, strlen ($horarios)-1);//Remover o
ultimo @ da string
echo "".$horarios;

Quando   o   while   termina,   o   comando   echo   retorna   para   o   cliente   o   resultado   da


concatenação.
O   código   fonte   completo   das   duas   aplicações   pode   ser   consultado   em:
https://github.com/DanielCabral/AutoFood

5. Conclusão
Ao concluir esse relatório, pude visualizar o enorme potencial que a plataforma
NodeMCU tem, principalmente por sua conectividade, tanto via Wifi, quanto bluetooth.
Com   um   código   simples   e   pequeno,   um   problema   que   antes   parecia   complexo   foi
resolvido. O potencial não se resume apenas a esta plataforma, mas como a toda área da
computação onde os sistemas embarcados estão inseridos, e é fato que no futuro, todos
os   dispositivos   estarão  cada  vez  mais   inteligentes  e  conectados   à  rede,  e para  isso,
sistemas embarcados precisarão ser desenvolvidos. Cursar esta disciplina me ajudou a
entender   que   posso   fazer   parte   deste   time   de   desenvolvimento,   aplicando   os
conhecimentos   aprendidos   e   criando   soluções   robustas   que   resolvam   problemas   do
nosso dia a dia.

Referencias
Carro,   Luigi,   and   Flávio   Rech   Wagner.   "Sistemas   computacionais   embarcados."
Jornadas de atualização em informática. Campinas: UNICAMP (2003).
Barros, Edna, and Sérgio Cavalcante.  "Introdução aos sistemas  embarcados." Artigo
apresentado na Universidade Federal de Pernambuco­UFPE (2010): 36.
https://fluxoconsultoria.poli.ufrj.br/blog/tecnologia­informacao/prototipagem­
eletronica­arduino­e­raspberry­pi/
Barros, Edna, and Sérgio Cavalcante.  "Introdução aos sistemas  embarcados." Artigo
apresentado na Universidade Federal de Pernambuco­UFPE (2010): 36.
https://www.fernandok.com/2018/09/instalando­esp32­no­arduino­ide­metodo.html
https://ntp.br/ntp.php
https://github.com/arduino­libraries/NTPClient/blob/master/NTPClient.h
https://portal.vidadesilicio.com.br/esp32­utilizando­o­rtc­interno­para­datas/
https://www.devmedia.com.br/crud­com­php­pdo/28873
https://www.arduino.cc/reference/en/language/variables/data­types/stringobject/
https://getbootstrap.com/
https://www.espressif.com/en/products/hardware/esp32­devkitc/overview