Este repositório é o resultado do trabalho de uma equipe de estudantes para criar um protótipo de sistema IoT para monitorar a temperatura e umidade de ambientes usando uma plataforma FPGA. Como sensor, o projeto conta com o DHT11 que por sua vez é acoplado a FPGA Mercurio IV Devkit. Assim a FPGA implementa uma interface UART para receber, executar e responder a comandos enviados através de uma porta serial por um computador. Para que a interação com o computador seja possível, a equipe também desenvolveu um sistema de teste em C para enviar comandos e exibir respostas nos computadores. Será discriminado durante este relatório os conceitos envolvidos durante a construção do protótipo, bem como as decisões de projetos da equipe.
- Antonio Vitor Costa da Silva avcsilva
- Gabriel Costa Baptista BaptistaGabriel
- Luis Pereira de Carvalho LuisBaiano
- Márcio Roberto Fernandes dos Santos Lima MarcioDzn
- Requisitos do projeto
- Recursos utilizados
- Protocolo
- Fluxograma geral
- Módulos utilizados
- Testes
- Interfaces em C
- Conclusão
- Utilização do sensor DHT11.
- Implementação de uma interface de comunicação serial (UART).
- Desenvolvimento de um sistema de testes em linguagem C.
- Escrita do código do FPGA em linguagem Verilog.
- Garantia de modularidade para permitir a substituição de componentes na versão de produção conforme necessário.
- Capacidade de ler, interpretar e executar comandos provenientes do computador, bem como retornar respostas para os comandos.
- Os comandos devem ser compostos por palavras de 8 bits.
- As requisições e respostas com 2 bytes.
- FPGA Mercurio IV Devkit - Cyclone IV EP4CE30F23
- Sensor de temperatura e umidade DHT11
- Quartus 20.1
- Verilog HDL
- Visual Studio Code
O protocolo de comunicação projetado para este projeto possui como base as duas tabelas a seguir, que representam, respectivamente, os comandos de requisição e de resposta. Os códigos de endereço de sensor foram planejados para serem representados em códigos hexadecimais de 0x00 a 0x1F, podendo assim simbolizar até 32 sensores diferentes.
| Comandos de requisição. | Descrição do comando | Comandos de resposta. | Descrição | |
|---|---|---|---|---|
| 0x00 | Solicita a situação atual do sensor | 0x1F | Sensor com problema | |
| 0x01 | Solicita a medida de temperatura atual | 0x07 | Sensor funcionando normalmente | |
| 0x02 | Solicita a medida de umidade atual | 0x08 | Medida de umidade | |
| 0x03 | Ativa sensoriamento contínuo de temperatura | 0x09 | Medida de temperatura | |
| 0x04 | Ativa sensoriamento contínuo de umidade | 0x0A | Confirmação de desativação de sensoriamento contínuo de temperatura | |
| 0x05 | Desativa sensoriamento contínuo de temperatura | 0x0B | Confirmação de desativação de sensoriamento contínuo de umidade | |
| 0x06 | Desativa sensoriamento contínuo de umidade | 0xFF | Resposta nula (SUPER_IDLE) |
Todo o processo de comunicação entre o computador e a FPGA se baseia no envio sempre de 2 bytes. Portanto analisando individualmente:
- Enviados 2 bytes, em ordem: 1 byte de instrução + 1 byte de endereço.
- Exemplo: (requisição de status): [0x00], [0x00].
- Enviados inicialmente 2 bytes de retorno, que representarão a resposta de dados a ser enviada pela FPGA (tabela de comandos de resposta.
- Enviados, se necessário, 2 bytes referentes aos dados coletados pela FPGA através do DHT11 (exemplo: medida de temperatura ou de umidade).
- Requisições como a observação do status de funcionamento ou desativação de sensoriamento contínuo não necessitam de bytes de dados. Portanto, os últimos 2 bytes serão os comandos de resposta mais uma vez.
- Exemplo 1 (resposta de status): [0x07], [0x07], [0x07], [0x07].
- Exemplo 2 (resposta de medida de temperatura): [0x09], [0x09], [Medida do DHT11: Inteiro], [Medida do DHT11: Fracionário].
- De forma resumida, o projeto funciona sob uma máquina de estados que serve de módulo controlador para cada etapa do processo, o qual possui 4 estados: espera (IDLE), coleta (RECEIVE), empacotamento (ORGANIZE) e envio (SEND).
- De início, com a máquina em estado de espera, devem ser recebidos do computador, por meio da UART, os 2 bytes que se referem à requisição e ao endereço do sensor. Recebidos estes, a máquina passa para o estado de coleta e lá permanece até que o módulo DHT11 determine que sua leitura foi finalizada. Após a coleta, a máquina em estado de empacotamento ordena que sejam organizados os dados que deverão ser enviados de volta ao computador mais posteriormente. Com os dados devidamente selecionados e organizados, a máquina entra em estado de envio, e não retorna ao estado de espera até que todo o processo de envio tenha sido finalizado corretamente. A figura 1 representa, de forma simplificada e resumida, o caminho dos dados no funcionamento do projeto.
O módulo UART lida com a comunicação serial entre a FPGA e o computador, bem como entre o computador e a placa. Este é composto por três submódulos, nos subtópicos seguintes é possivél observar cada um deles:
- Este módulo é responsável pela geração da taxa de transmissão para a comunicação serial. Ele recebe o sinal de clock de 50 MHz (
clk_50m) nativo da FPGA e gera os sinaisrxclk_enetxclk_enque são usados para habilitar os clocks de recepção e transmissão, respectivamente.
- O módulo do transmissor (
transmitter) é responsável por enviar dados da FPGA para o dispositivo externo. Ele recebe os dados paralelos de entrada (din), um sinal de escrita habilitado (wr_en), o sinal de clock de 50MHz (clk_50m), e o sinal de habilitação de clock de transmissão (clken). O transmissor então gera o sinal de transmissão (tx) e um sinal indicando se o transmissor está ocupado (tx_busy).
- O módulo do receptor (receiver) é responsável por receber dados do dispositivo externo e transmiti-los para a FPGA. Ele recebe o sinal de recepção (
rx), um sinal indicando se está pronto para receber dados (rdy), um sinal para limpar o indicador de prontidão (rdy_clr), o sinal de clock de 50 MHz (clk_50m), e o sinal de habilitação de clock de recepção (clken). O receptor também gera os dados de saída (dout).
No contexto geral do projeto, o módulo DHT11 permite a coleta de dados de um sensor DHT11 e disponibiliza as medições de temperatura e umidade para uso no projeto. O sinal error indica se ocorreu algum erro durante a coleta de dados, enquanto done indica quando a coleta foi concluída. Este módulo pode ser entendido como uma MEF (Figura 2), a seguir é possivél observar a função de cada estado:
- Neste estado, a máquina de estados se prepara para iniciar a comunicação com o sensor DHT11.
- Se o sinal de
startsubir e o dado de entradadinfor alto (1'b1), a máquina de estados transita para o próximo estado (s2). - A variável
read_flagé configurada para1'b0, indicando que a comunicação é do PC para o DHT11. - O sinal
douté configurado para1'b0, indicando um valor a ser enviado para o DHT11. - Contadores e registradores são inicializados.
- Neste estado, a máquina de estados conta o tempo em que o sinal de
doutestá em nível baixo. - O contador
cnté usado para contar até 19000 ciclos de clock, o que corresponde a 19 ms. - Quando o contador atinge esse valor, a máquina de estados avança para o próximo estado (
s3).
- Aqui, a máquina de estados conta o tempo em que o sinal
doutestá em nível alto. - O contador
cnté usado para contar até 20 ciclos de clock, correspondendo a 20 µs. - Quando o contador atinge esse valor, a máquina de estados avança para o próximo estado (
s4).
- Neste estado, a máquina de estados está pronta para receber a resposta do DHT11.
- Ela verifica se o sinal de entrada
diné baixo (1'b0). Se sim, transita para o próximo estado (s5). - Se o sinal
dinpermanecer alto por muito tempo (mais de 65500 ciclos de clock), um erro é detectado, e a máquina de estados vai para o estadoSTOP.
- Este estado aguarda o sinal
dinentrar em nível alto, indicando o início da resposta do DHT11. - Se o sinal
dinsubir, a máquina de estados transita para o próximo estado (s6). - Da mesma forma que no estado anterior, um tempo muito longo em nível baixo gera um erro e mudança para o estado
STOP.
- Aqui, a máquina de estados aguarda o sinal
dinentrar em nível baixo novamente, indicando o início da transmissão de dados pelo DHT11. - Se o sinal
dinentrar em nível baixo, a máquina de estados transita para o próximo estado (s7). - Um tempo muito longo em nível alto gera um erro e transição para
STOP.
- Neste estado, a máquina de estados inicia a transmissão de dados pelo DHT11.
- Ela verifica se o sinal
diné alto (1'b1). Se for, a máquina de estados transita para o próximo estado (s8). - Novamente, um tempo muito longo em nível baixo gera um erro e transição para o estado
STOP.
- Neste estado, a máquina de estados recebe os bits de dados transmitidos pelo DHT11.
- Ela conta o tempo em que o sinal
dinpermanece em nível alto e, dependendo desse tempo, atribui um valor de0ou1ao dado recebido. Caso o sinal passe um tempo muito longo em nível baixo, o sinal de erro é gerado e há transição para o estadoSTOP. - A máquina de estados continua a receber bits até que todos os 40 bits de dados tenham sido recebidos, então ela transita para o próximo estado (
s9).
- Neste estado, a máquina de estados armazena os dados recebidos no registrador
data. - Ela verifica se o sinal
diné alto (1'b1). Se sim, a máquina de estados transita para o próximo estado (s10). Senão, caso passe um tempo maior que o devido em nível baixo, é gerado um sinal de erro e o estado é transitado paraSTOP.
- Neste estado, a máquina de estados indica que a comunicação foi concluída e que os dados foram recebidos com sucesso.
- Ela configura o sinal
error_regpara1'b0para indicar a ausência de erros e encaminha para o próximo estado (STOP).
- Estado final de todo o processo de leitura, sendo tanto para quando há alguma detecção de erro quanto para leituras bem sucedidas.
- O sinal
error_regé conservado desde quando tiver sido definido. Ou seja, se tiver ocorrido um erro, o sinalerror_regpermanecerá1'b1para indicar o erro, senão permanecerá1’b0tal como definido pelo estados10. - A máquina de estados aguarda um período de cooldown de 5 segundos antes de configurar o sinal
done_regpara nível alto e de retornar ao estado inicial (s1).
O módulo main_state_machine (Figura 3) desempenha um papel crítico na coordenação das várias etapas do sistema e na comunicação entre os módulos envolvidos. Os estados e operações realizadas pelo main_state_machine são:
- No estado IDLE, o sistema aguarda a conclusão da recepção dos dois bytes de dados recebidos pelo receiver do UART. O sinal
done_uart_rxindica quando os dados foram totalmente recebidos. Quando em nível baixo, permanece em IDLE, já em nível alto, duas situações podem ocorrer, a depender do tipo de solicitação enviada pelo usuário. Se não houver uma solicitação para interromper o sensoriamento contínuo (indicado pelo sinalbreak_continuousem nível baixo), o sistema passa para o estado RECEIVE e envia um sinal de start (dht_out) para o módulo DHT11. Entretanto, se foi solicitado para interromper o sensoriamento contínuo, o sistema passa diretamente para o estado ORGANIZE.
- Neste estado, o sistema aguarda até que o módulo DHT11 tenha concluído a coleta e decodificação dos dados de temperatura e umidade. Essa finalização é indicada pelo sinal
done_dht. Quandodone_dhtse torna igual a 1, a coleta de dados advindos do DHT11 foi concluída, e o sistema passa para o estado ORGANIZE.
- No estado ORGANIZE, o sistema está se preparando para enviar os dados coletados pelo DHT11. Nesse sentido, um sinal
packem nível alto é enviado ao módulopacker, onde as respostas cabíveis são empacotadas para serem enviadas. Em seguida, o sistema passa para o estado SEND, a fim de iniciar o envio de dados.
- No estado SEND, os 4 bytes de resposta são enviados para o computador. O sistema aguarda até que o módulo UART tenha concluído o envio dessas informações, indicando com
done_uart_txem nível alto a finalização.
O módulo request_separator é responsável por receber os dados do UART, separar o código de instrução e o endereço do sensor e controlar a indicação de conclusão (DONE_OUT) com base nas ações da máquina de estados finitos e na interpretação da instrução como uma solicitação de sensoriamento contínuo ou não. Isso permite que o sistema processe corretamente as solicitações do usuário e coordene a coleta de dados de sensores. Vamos analisar seu funcionamento em detalhes:
- O módulo possui duas variáveis de registro,
INSTR_REGeADDR_REG, para armazenar temporariamente o código de instrução e o endereço do sensor, respectivamente. Além disso, há uma variável de registrocounterpara controlar se o módulo está atualmente recebendo o código de instrução ou o endereço do sensor.
- O bloco
always @(posedge EN)é sensível à borda de subida do sinalEN(sinal de enable do UART). Ele lida com a atribuição dos dados recebidos às variáveis de registro apropriadas. Quando ocounterestá em 0, o módulo está na fase de receber o código de instrução. Quando ocounterestá em 1, ele está na fase de receber o endereço do sensor. Após receber o endereço do sensor, o sinalDONEé definido como 1 para indicar que os dois bytes foram recebidos.
- O módulo monitora o estado do sistema por meio do sinal
IDLEque vem da máquina de estados finitos (MEF) (presumivelmente, omain_state_machine). Quando o sistema está em um estado que não é IDLE (indicado por!IDLE), o módulo verifica o sinalCONTINUOUS_EN. SeCONTINUOUS_ENestiver alto, significa que a instrução é referente a sensoriamento contínuo, eDONE_OUTpermanece alto para permitir que a MEF solicite novos dados. SeCONTINUOUS_ENestiver baixo,DONE_OUTé definido como 0, indicando que os dados foram processados e que a MEF pode mudar de estado.
- O módulo possui duas saídas:
INSTReADDRque refletem os valores dos registradoresINSTR_REGeADDR_REG, respectivamente. Isso permite que os dados separados sejam usados em outros lugares do sistema.
O módulo instr_decoder interpreta as instruções recebidas e gera os sinais CONTINUOUS_EN e BREAK_CONTINUOUS para controlar o sensoriamento contínuo e parar o sensoriamento contínuo, respectivamente. Além disso, ele determina o tipo de dado desejado com base na instrução e gera o sinal DATA_TYPE para uso posterior no sistema.
- O módulo define parâmetros locais
STATUS,TEMP,HUMID,TEMP_CONT,HUMID_CONT,X_TEMP_CONT,X_HUMID_CONTeIDLEpara representar diferentes instruções. Por exemplo,STATUSrepresenta a instrução relacionada ao status,TEMPà temperatura,HUMIDà umidade,TEMP_CONTà instrução de sensoriamento contínuo de temperatura e assim por diante.
- O módulo utiliza operadores ternários para determinar o valor do sinal
CONTINUOUS_EN. Se a instrução for igual aTEMP_CONTouHUMID_CONT, o sinalCONTINUOUS_ENé definido como 1, indicando que ocorreu uma instrução de sensoriamento contínuo. Caso contrário, é definido como 0.
- Similar ao caso anterior, o módulo usa operadores ternários para determinar o valor do sinal
BREAK_CONTINUOUS. Se a instrução for igual aX_TEMP_CONTouX_HUMID_CONT, o sinalBREAK_CONTINUOUSé definido como 1, indicando que ocorreu uma instrução para parar o sensoriamento contínuo. Caso contrário, é definido como 0.
- O módulo usa operadores ternários para determinar o valor do sinal
DATA_TYPE, que representa o tipo de dado desejado (temperatura, umidade, status ou nenhum). Se a instrução for igual aSTATUS,DATA_TYPEé definido comoS, indicando status. Se a instrução for igual aTEMP,TEMP_CONTouX_TEMP_CONT,DATA_TYPEé definido comoT, indicando temperatura. Se a instrução for igual aHUMID,HUMID_CONTouX_HUMID_CONT,DATA_TYPEé definido comoH, indicando umidade. Caso contrário,DATA_TYPEé definido comoN, indicando nenhum dado específico.
O módulo data_selector atua como um multiplexador para selecionar os dados corretos com base no tipo de dado desejado (DATA_TYPE) e encaminhá-los para as saídas DATA_INT e DATA_FLOAT. Vamos analisar o código em detalhes:
- O módulo define um parâmetro local
T, que representa a opção de seleção de dados para temperatura, eH, que representa a opção de seleção de dados para umidade, eSpara status. Esses parâmetros são usados posteriormente para determinar quais dados serão selecionados.
- A instrução
assign DATA_INT = (DATA_TYPE == T) ? TEMP_INT : HUMI_INT;seleciona os dados inteiros com base no tipo de dado (DATA_TYPE). SeDATA_TYPEfor igual aT(temperatura), os dados inteiros da temperatura (TEMP_INT) são selecionados; caso contrário, seDATA_TYPEfor igual aH(umidade), os dados inteiros da umidade (HUMI_INT) são selecionados. SeDATA_TYPEfor igual aS(status) ou qualquer outro valor, os dados inteiros correspondentes não são selecionados.
- A instrução
assign DATA_FLOAT = (DATA_TYPE == T) ? TEMP_FLOAT : HUMI_FLOAT;seleciona os dados fracionários com base no tipo de dado (DATA_TYPE). Da mesma forma que no caso anterior, seDATA_TYPEfor igual aT, os dados fracionários da temperatura (TEMP_FLOAT) são selecionados; caso contrário, seDATA_TYPEfor igual aH, os dados fracionários da umidade (HUMI_FLOAT) são selecionados. SeDATA_TYPEfor igual aSou qualquer outro valor, os dados fracionários correspondentes não são selecionados.
O módulo packer é responsável por empacotar os dados corretos com base nas informações fornecidas pelos módulos anteriores e gerar os bytes de saída correspondentes para transmissão. Ele também lida com situações de erro e interrupção de sensoriamento contínuo, conforme apropriado. Os bytes empacotados serão posteriormente enviados para a transmissão de dados.
- O módulo define alguns parâmetros locais que representam códigos específicos, como
SENSOR_ISSUEpara indicar problemas no sensor,SENSOR_OKpara indicar que o sensor está funcionando corretamente,HUMIDITY_MEASUREpara indicar uma medição de umidade,TEMPERATURE_MEASUREpara indicar uma medição de temperatura,DIS_TEMP_CONTpara indicar a interrupção do sensoriamento contínuo de temperatura,DIS_HUMI_CONTpara indicar a interrupção do sensoriamento contínuo de umidade eSUPER_IDLEpara indicar um estado de repouso especial.
- O bloco
always @(posedge EN)é ativado na borda de subida do sinalEN. Isso significa que ele é sensível ao sinal de habilitação para empacotar os dados.
- A primeira parte do bloco lida com condições de erro. Se o sinal
ERRORestiver ativo (indicando um erro no módulo DHT11) ou se os dados de temperatura estiverem fora dos limites aceitáveis (0 a 50) ou os dados de umidade estiverem fora dos limites aceitáveis (20 a 90), então o módulo gera códigos de erro (SENSOR_ISSUE) para os bytes de saídaBYTE1,BYTE2eBYTE3.
-
Se não houver erros, o bloco entra na seção de processamento normal. Ele utiliza um bloco
casebaseado no valor deDATA_TYPEpara determinar que tipo de dado está sendo empacotado.-
Se
DATA_TYPEfor igual aT(temperatura), ele verifica seBREAK_CONTINUOUSestá ativo. Se estiver, ele gera um código de interrupção de sensoriamento contínuo (DIS_TEMP_CONT) para os bytes de saída. Caso contrário, ele gera códigos apropriados para medições de temperatura (TEMPERATURE_MEASURE) nos bytes de saídaBYTE1,BYTE2eBYTE3, ondeBYTE2contém a parte inteira eBYTE3contém a parte fracionária. -
Se
DATA_TYPEfor igual aH(umidade), ele segue um processo semelhante ao da temperatura, gerando códigos de interrupção de sensoriamento contínuo (DIS_HUMI_CONT) seBREAK_CONTINUOUSestiver ativo ou códigos apropriados para medições de umidade (HUMIDITY_MEASURE) caso contrário. -
Se
DATA_TYPEfor igual aS(status), ele gera códigos de status (SENSOR_OK) para todos os bytes de saída. -
Se
DATA_TYPEnão corresponder a nenhum dos casos anteriores (neste caso, "Nada" ou qualquer outro valor não reconhecido), ele gera um código especial (SUPER_IDLE) para todos os bytes de saída para indicar um estado de repouso especial.
-
O módulo send_pc controla o envio dos dados empacotados em resposta às solicitações do módulo principal. Ele utiliza uma máquina de estados simples para garantir que os bytes sejam enviados sequencialmente e de forma controlada para o módulo de transmissão UART. O sinal DONE é usado para indicar quando a transmissão foi concluída.
- O módulo começa com a declaração de um registrador de 3 bits chamado
countque é usado para controlar o estado da máquina de estados. Além disso, inicializaRESPONSE_DATAcom 8 bits de "1" (todos os bits altos) e defineDONEeEN_TXcomo 0 (baixo).
-
A principal lógica do módulo está dentro de um bloco
alwayssensível à borda de subida do sinal de clockclk. Esse bloco implementa uma máquina de estados que controla o envio dos bytes empacotados.-
Se o sinal
ENestiver ativo (indicando que o módulo principal deseja iniciar a transmissão), o bloco verifica o sinalBUSY_TX. Se o módulo de transmissão estiver ocupado (BUSY_TXativo), ele mantém os valores atuais deRESPONSE_DATA,EN_TX,DONE, ecount. -
Se o módulo de transmissão não estiver ocupado (
BUSY_TXinativo), ele entra em um estado de máquina de estados controlado porcount. Dependendo do valor atual decount, ele atribui os valores apropriados aRESPONSE_DATA,EN_TX, eDONE.-
Quando
countfor3'b000, ele configuraRESPONSE_DATAparaBYTE1, defineEN_TXpara 1 (ativo), eDONEpara 0. -
Quando
countfor3'b010, ele faz o mesmo paraBYTE1. -
Quando
countfor3'b100, ele configuraRESPONSE_DATAparaBYTE2, defineEN_TXpara 1 (ativo), eDONEpara 0. -
Quando
countfor3'b110, ele configuraRESPONSE_DATAparaBYTE3, defineEN_TXpara 1 (ativo), eDONEpara 0. -
Quando
countfor3'b111, ele mantémRESPONSE_DATAinalterado, defineEN_TXpara 0 (inativo), eDONEpara 1. Este é o estado de conclusão.
-
-
- Se o sinal
ENnão estiver ativo (indicando que o módulo principal não deseja iniciar a transmissão), ele mantém os valores atuais deRESPONSE_DATA,EN_TX,DONE, e redefinecountpara3'b000.
As duas interfaces em C desempenham papéis cruciais no projeto geral, permitindo a comunicação entre um computador e a FPGA para controle e monitoramento de sensores. Aqui está uma descrição da utilidade de cada interface em relação ao projeto geral:
A interface do Receiver é projetada para ser executada em um computador e se comunica com a FPGA por meio de uma conexão serial. Ela é responsável por receber as respostas e dados enviados pela FPGA em resposta às solicitações feitas pelo usuário.
- Permite ao usuário verificar o status do sensor e as medições de temperatura e umidade capturadas pela FPGA.
- Recebe os dados enviados pela FPGA, incluindo medições e informações sobre o funcionamento dos sensores.
- Exibe as informações de maneira legível para o usuário, como temperatura, umidade e status do sensor.
- Facilita a detecção de erros ou problemas de comunicação entre o computador e a FPGA.
- Permite ao usuário monitorar as medições de sensores em tempo real.
- Ajuda a identificar qualquer problema ou falha no funcionamento do sensor ou na comunicação com a FPGA.
- Torna o projeto mais acessível, fornecendo uma interface amigável para interação com o hardware FPGA.
- A interface do Transmitter também é executada em um computador e é usada para enviar comandos e solicitações à FPGA por meio da comunicação serial. Ela permite ao usuário selecionar diferentes modos de operação e solicitar medições específicas dos sensores.
- Facilita a interação do usuário com a FPGA, permitindo que ele escolha entre várias opções, como leitura única de temperatura/umidade ou solicitação de leituras contínuas.
- Configura os comandos necessários, incluindo instruções e endereços de sensores, para serem enviados à FPGA.
- Envia as solicitações para a FPGA e aguarda as respostas.
- Permite ao usuário controlar as operações do dispositivo FPGA a partir de um computador de forma conveniente.
- Possibilita a escolha entre diferentes modos de funcionamento, como leitura única ou contínua, para atender às necessidades específicas do projeto.
- Simplifica o processo de envio de comandos à FPGA, tornando-o mais acessível mesmo para usuários não técnicos.
No geral, essas duas interfaces desempenham um papel fundamental no projeto, proporcionando ao usuário a capacidade de interagir com a FPGA e acessar as medições dos sensores de maneira eficiente e amigável. Elas tornam o projeto mais versátil, permitindo diferentes modos de operação e facilitando a detecção de problemas ou erros durante a comunicação e a coleta de dados. Além disso, tornam a FPGA uma solução mais acessível para monitoramento e controle de sensores em um ambiente de computação pessoal.
A fim de se averiguar o funcionamento do projeto como um todo, foram realizados diversos diversos testes em ambiente controlado. Para assegurar as diversas possibilidades de requisições possíveis, foram realizados testes envolvendo diferentes instruções das presentes no protocolo tendo sido registrados os resultados das: requisição de sensoriamento contínuo de temperatura, desativação do sensoriamento contínuo, solicitação do status atual do sensor, medida de temperatura e medida de umidade. Os resultados desses podem ser visto nas imagens a seguir.
Para verificar o funcionamento das interfaces em C como um todo, se fez necessário conferir o funcionamento das partes que compoem as interfaces.
- A transmissão foi testada ligando a porta serial do computador a um osciloscópio. Desta forma, foi possível garantir que os dados são enviados uma vez que podemos observa-los.
- A recepção foi testada ligando a saída da transmissão diretamente na entrada de recepção. Assim, foi possível assegurar-se que o dado está sendo enviado e que qualquer eventual falha seria algum problema no receptor.
- Para verificar a transmissão da FPGA para o computador, atribui-se pinos de propósito geral aos transmissores da UART, assim, ao ligar tais pinos no osciloscópio é possivel constatar o funcionamento do transmissor da placa (Figura 4 e Figura 5).
Figura 4 - Ponta de prova do osciloscópio conectada a porta serial.
Figura 5 - Resposta no osciloscópio.
- Para testar a recepção, envia-se os dados através do computador que já teve sua transmissão validada. Desta forma é possivel atribuir pinos na matriz de led da placa e validar a recepção dos dados.
- Para testar o sensor DHT11, conduzimos um teste conectando-o diretamente ao osciloscópio. Durante o teste, monitoramos os sinais elétricos gerados pelo sensor, incluindo os pulsos de dados que representam as leituras de temperatura e umidade. Essa abordagem nos permitiu verificar a saída do sensor e confirmar seu funcionamento adequado. A imagem abaixo (Figura 6) é uma captura da tela do osciloscópio dos dados recebidos do DHT11.
- Para testar o produto como um todo, fez-se todas as solicitações possiveis ao sistema. Assim, para definir se as informações obtidas estavam corretas, observou-se se os dados obtidos estavam dentro do raio do sensor (20% a 80% para umidade e 0°C a 50°C para temperatura). Com estes dados validádos, para testar as funcionalidades do código, bastou fazer as solicitações ao sistema e observar suas respostas. As figuras a seguir mostram um exemplo do funcionamento do sistema.
Figura 7 - Solicitação do status do sensor na esquerda e comando de resposta na direita.
Figura 8 - Solicitação da temperatura atual na esquerda e comando de resposta na direita.
Figura 9 - Solicitação da umidade atual na esquerda e comando de resposta na direita.
Figura 10 - Solicitação da temperatura continua na esquerda e comando de resposta na direita.
Figura 11 - Solicitação da interrupção da medida de temperatura continua na esquerda e comando de resposta na direita.
- Finalizados o planejamento do circuito e a descrição do mesmo na linguagem Verilog, foi realizada a compilação e síntese do mesmo por meio do Quartus II. Com o relatório de utilização de recursos, este gerado pelo próprio Quartus II ao compilar o projeto, pôde-se verificar que o circuito se aproveita de 401 dos 28848 elementos lógicos presentes da FPGA para o qual foi projetado, sendo 156 combinacionais sem registros, 40 de apenas registros e 205 combinacionais com registros, com todos eles sendo utilizados em seu modo normal. Desses 401 elementos lógicos, 146 são de LUT (Lookup Table) de quatro entradas, 77 são de três entradas e 138 são de duas ou menos entradas. Além disso, foram utilizados, parcial ou completamente, 33 dos 1803 LABs disponíveis. Essas informações podem ser visualizadas no relatório de uso de recursos (figura 12).
- Para o funcionamento principal do projeto, são necessários apenas 4 pinos principais, sendo eles: entrada de clock de 50 MHz, entrada da porta serial, bidirecional (inout) para o DHT11 e saída da porta serial. Entretanto, com a finalidade de testar e averiguar o funcionamento do projeto, foram criados dois barramentos de 8 bits e um de 2 bits como saída, de forma a se atribuir a estas, respectivamente: dois dos bytes que devem ter sido enviados para o computador pela porta serial e o estado atual da máquina de estados. Com isso, somando-se os pinos principais com os pinos para testes, obtém-se ao final um total de 22 pinos utilizados, como visto no relatório de uso de recursos na figura 12.
- A partir dos testes realizados, foi possível comprovar o funcionamento do sistema como se era esperado. As respostas eram sempre recebidas no devido tempo definido, e os resultados demonstrados eram consistentes e condizentes com o ambiente de testes. Além disso, todos os devidos bytes de envio previstos no protocolo foram corretamente recebidos no computador. Dessa forma, é possível afirmar que o projeto cumpre ao que se promete, atendendo aos requisitos propostos pelo texto problema. Com o projeto em questão, é possível realizar diferentes requisições de medidas e respostas para a FPGA, que, por sua vez, consegue entregar os devidos resultados coletados do sensor DHT11 de volta para o computador.
- Módulo DHT11 original: https://www.kancloud.cn/dlover/fpga/1637659
- DHT11 Datasheet: https://www.mouser.com/datasheet/2/758/DHT11-Technical-Data-Sheet-Translated-Version-1143054.pdf
- Manual Mercurio IV Devkit: https://www.macnicadhw.com.br/sites/default/files/documents/downloads/manual_mercurioiv_v2.pdf
- Repositório com módulos UART originais: https://github.com/jamieiles/uart/tree/master





