Buscar

UTFPR-SO

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 33 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 33 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 33 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

UTFPR
LEONARDO BRAGA DE CRISTO
WILLIAN ALVES SANTIAGO
Sistema on/off para controle e medição de temperatura
Documento para composição de
nota na disciplina Sistemas
Operacionais do curso de
Engenharia Eletrônica da
Universidade Tecnológica Federal
do Paraná sob orientação do
professor Luiz Fernando Copetti.
Curitiba, 18 de dezembro de 2023
Introdução
Este projeto tem por objetivo demonstrar o uso de um sistema
operacional embarcado e as suas funcionalidades. O sistema
operacional escolhido é o freeRTOS.
O projeto escolhido é um sistema de controle “on-off” para controle
de temperatura.
Componentes
Os componentes utilizados são apresentados na lista abaixo:
● Sensor de temperatura - LM35
● Capacitor de poliester - 1uF
● Resistor - 100 Ohm
● Módulo relé
● Microcontrolador - TM4C1294NCPDT
Figura 1 - Esquemático do Projeto
Objetivo do Projeto
O projeto tem por objetivo o controle da temperatura limite
escolhida. Para isso um atuador, que seria uma lâmpada incandescente,
é utilizado para aquecer quando a temperatura ambiente estiver abaixo
do esperado e desligado quando estiver acima do esperado.
Protocolo
UDP (User Datagram Protocol) é um protocolo de comunicação da
camada de transporte usado em redes de computadores. Faz parte da
família de protocolos da Internet (TCP/IP) e é uma alternativa ao
protocolo de controle de transmissão (TCP). Alguns recursos básicos
do UDP incluem:
Sem conexão: UDP é um protocolo sem conexão. Ou seja, não
há conexão até que os dados sejam transmitidos. Cada pacote
(datagrama) é processado separadamente.
Não confiável: Ao contrário do TCP, o UDP não oferece
confiabilidade na transmissão de dados. Não há garantia de que os
dados serão entregues ao destino, e não há mecanismos de
retransmissão em caso de perda de pacotes.
Baixa sobrecarga: A falta de mecanismos de confiabilidade implica
em uma sobrecarga menor no processo de comunicação. Isso torna o
UDP mais eficiente em termos de latência, sendo muitas vezes preferido
em aplicações que demandam respostas rápidas, como jogos online e
transmissões de áudio/vídeo em tempo real.
Transmissão de broadcast e multicast: O UDP suporta
transmissões de dados para múltiplos destinos simultaneamente através
de broadcast e multicast. Isso é útil em aplicações como streaming de
vídeo para vários receptores.
Cabeçalho simples: O cabeçalho do UDP é mais simples que o do
TCP, contendo apenas informações essenciais, como portas de origem
e destino, e o comprimento do datagrama. Isso reduz a sobrecarga de
dados e acelera o processo de encapsulamento e desencapsulamento.
Comunicação
O projeto possui uma interface desenvolvida em linguagem python
de programação. Esta interface possui duas threads, uma para
recebimento de pacotes UDP e outra para envio de pacotes UDP.
A comunicação é feita via sockets em uma rede local, por meio do
roteador.
Na figura 2, a interface é apresentada. Ela possui 2 campos
chamados IP e Porta que devem ser preenchidos com o IP e Porta do
microcontrolador. No projeto em questão, foi utilizado o IP
192.168.18.61 com mascará de sub-rede 255.255.255.0 e porta 12345.
No campo da esquerda estão os pacotes enviados e na direita os
pacotes recebidos.
Existe um campo para envio de mensagens, nesse campo devemos
enviar uma variável do tipo float pressionando o botão Enviar. Esta
variável irá ser utilizada como temperatura limite, para comparação no
sistema de controle de temperatura. Caso não for enviada a
temperatura limite será de 25 C.
Há também um botão para limpar as mensagens da interface e
um botão para sair.
Python
Figura 2 - Interface desenvolvida para comunicação com o sistema
embarcado.
Desenvolvimento da interface
O código utilizado importa a biblioteca PySimpleGUI para criação
das interfaces gráficas, a biblioteca socket para troca de mensagens
UDP, e a biblioteca threading para termos a capacidade de
multiprocessamento, já que teremos que tanto receber pacotes como
enviá-los.
import PySimpleGUI as sg
import socket
import threading
Figura 3 - Bibliotecas importadas no python.
Python
A função para recebimento de mensagens é invocada como um
thread, a implementação dela é apresentada na figura 3. Ela recebe 2
campos, o client_socket, que é criado com a biblioteca socket para
transferência de arquivos via UDP, e o window para manipularmos as
mensagens recebidas na interface gráfica.
A função recv tenta receber até 1024 bytes de dados do socket. O
resultado é armazenado na variável data. Os dados são inseridos na
janela de texto direita da figura 2.
Se um erro ocorrer apenas saímos. O bloco está dentro de um loop
infinito, pois a função, na verdade, é invocada como uma thread.
def receive_messages(client_socket, window):
while True:
try:
data = client_socket.recv(1024)
if not data:
break
window['-OUTPUT-PC'].print(data.decode('utf-8'))
except ConnectionResetError:
break
Figura 4 - Thread de recebimento de pacotes.
Na função main, a função principal, escolhemos o tema
DarkGrey1 para a interface, criamos os campos de texto por meio de
listas, itens na mesma lista são apresentados lado a lado na tela, as
listas dentro de layout serão apresentadas uma abaixo da outra.
O nome da interface chama-se HOST.
Python
Dentro de um loop infinito analisamos os eventos da interface. Os
possíveis eventos são:
● Sair: - Fecha a interface.
● Conectar: - Abre um socket UDP com o HOST na mesma
rede.
● Enviar: - Envia pacotes UDP para o HOST remoto.
● Limpar: - Remove as mensagens da interface.
Existem outros eventos que são intrínsecos da biblioteca
pysimplegui, tais como o fechamento de janela e minimizar.
def main():
sg.theme('DarkGrey1')
layout = [
[sg.Text('IP:'), sg.InputText(key='-IP-')],
[sg.Text('Porta:'),
sg.InputText(key='-PORTA-'),sg.Text('',key = '-IP-TIVA')],
[sg.Button('Conectar', key='-CONECTAR-')],
[sg.Column([[sg.Text('ENVIADOS'),sg.Text('RECEBIDOS',justifica
tion='right')]], justification='center')],
[sg.Multiline(size=(45, 10), key='-OUTPUT-TIVA',
disabled=True),sg.Multiline(size=(45, 10), key='-OUTPUT-PC',
disabled=True)],
[sg.Text('Mensagem:'), sg.InputText(key='-MENSAGEM-')],
[sg.Button('Enviar', key='-ENVIAR-'),sg.Button('Limpar',
key='-LIMPAR-'),sg.Button('Sair')]
]
window = sg.Window('HOST', layout)
client_socket = None
while True:
event, values = window.read()
if event == sg.WINDOW_CLOSED or event == 'Sair':
break
elif event == '-CONECTAR-':
ip = values['-IP-']
porta = int(values['-PORTA-'])
try:
client_socket = socket.socket(socket.AF_INET,
socket.SOCK_DGRAM)
client_socket.connect((ip, porta))
# Iniciar uma thread para receber mensagens
threading.Thread(target=receive_messages,
args=(client_socket, window), daemon=True).start()
window['-IP-TIVA'].update(f"Conectado ao servidor em
{ip}:{porta}")
except Exception as e:
sg.popup_error(f"Erro ao conectar: {str(e)}")
elif event == '-ENVIAR-' and client_socket:
mensagem = values['-MENSAGEM-']
if mensagem:
client_socket.sendall(mensagem.encode('utf-8'))
window['-OUTPUT-TIVA'].print(mensagem)
elif event == '-LIMPAR-':
window["-OUTPUT-TIVA"].update("")
if client_socket:
client_socket.close()
window.close()
Figura 5 - Função Main.
Programa do microcontrolador
O microcontrolador utilizado é o TM4C1294NCPDT, que é um
ARM cortex m4 de 32 bits. Ele possui controlador de rede, que utiliza
DMA para receber e enviar pacotes. Os pacotes são colocados na RAM,
em um endereço descrito por uma estrutura chamada descritor de
arquivos.
Quando um pacote é recebido ou enviado, uma interrupção é
gerada, esta interrupção é tratada por uma função que envia o resultado
para a biblioteca LWIP. A LWIP possui já implementado a interpretação
dos pacotes para socket, http, ftp, ssh, icmp e vários outros protocolos
que computadores de uso geral utilizam.
É possível programar com a LWIP de duas formas, a primeira é de
forma convencional, por interrupções e super loop, a segunda, o nosso
caso, é por meio de umrtos. Utilizamos o freeRTOS, que vai monitorar
está chegada e envio de pacotes.
Cada microcontrolador precisa fazer o port, que é a configuração
específica do microcontrolador, para o uso da LWIP. No nosso caso, a
texas fez um port muito antigo que hoje é obsoleto, então foi escolhido o
port utilizado pela stm.
As tasks utilizadas estão presentes na figura 5. São descritas da
seguinte forma:
● udpProcessingTask:Recebe dados de uma fila, em que
o sensor de temperatura envia, e decide se o atuador
irá ligar ou não.
● sensorTask: Lê dados de temperatura do sensor LM35,
cálcula uma média de 10 medidas espaçadas de
500ms e os envia para uma fila que será lida pela task
udpProcessingTask. Também envia dados via rede
ethernet para o HOST remoto, os dados são a
temperatura atual.
● udpReceiver:Recebe pacotes ethernet do HOST
remoto e redefine a temperatura limite de controle.
● UpLwIp: Grava em flash o MAC do microcontrolador e
obtém um IP local. Cria as tasks udpReceiver e
sensorTask. Esta task pode ser deletada após isso.
● IDLE TASK: É a task padrão que inicializa o clock, as
configurações iniciais do conversor ad utilizado para
ler a tensão do sensor de temperatura, da uart, da
criação das filas e dos semáforos. Além da criação das
tasks UpLwIp e udpProcessingTask.
Para a comunicação entre tasks utilizamos filas, para gerenciar
condições de corrida utilizamos semáforos binários. Para a serial e para
o envio e recebimento de pacotes foram utilizados semáforos. No
sensor não foi necessário pois não foi um recurso compartilhado.
Figura 6 - Tasks
Inicialmente o programa grava o MAC e pega um IP na rede local,
após isso a task do sensor lê 10 temperaturas, tira uma média e envia
para uma fila, que é lida por uma task de processamento, esta task
decide se o atuador ira ligar.A task do sensor também envia as
temperaturas colocadas na fila para a interface python no computador
via socket.
O computador pode enviar , via socket, pacotes UDP para
recebimento no microcontrolador, estes pacotes são interpretados como
temperaturas, é a nossa variável de controle de temperatura.
Conclusões
A implementação do freeRTOS juntamente com a pilha TCP/IP da
LWIP é uma solução inteligente em relação a programação por
interrupções e máquina de estados.
Apenas deve-se ter o cuidado com as condições de corrida, o uso
de periféricos compartilhados, regiões críticas, etc.
Inicialmente utilizei a serial para debug sem semáforo binário e
com o escalonamento algumas tarefas utilizavam a serial sem a tarefa
corrente concluir sua mensagem, com os semáforos esse problema foi
solucionado.
A fila resolve de forma inteligente a comunicação entre as tarefas.
Dentro da LWIP existe um tipo de fila chamada mail box, que pega os
pacotes recebidos, que de forma convencional seriam tratados via
interrupção.
Referências
● https://www.nongnu.org/lwip/2_0_x/group__socket.html
● https://www.freertos.org/
● https://www.ti.com/lit/ds/symlink/lm35.pdf
● https://www.youtube.com/@gustavodenardin
https://www.nongnu.org/lwip/2_0_x/group__socket.html
https://www.freertos.org/
https://www.ti.com/lit/ds/symlink/lm35.pdf
https://www.youtube.com/@gustavodenardin
C/C++
Código do Projeto (Microcontrolador)
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h" //DRIVER UART
#include "utils/uartstdio.h" //DRIVER UART
#include "FreeRTOS.h" //RTOS UTILIZADO
#include "task.h" //Manipulação de TASKS
#include "lwiplib.h" // LWIP
#include "pinout.h" // pinout para config ethernet
#include "lwip/sockets.h" //bilioteca socket da LWIP
#include "driverlib/adc.h" //biblioteca adc para leitura do
sensor
//Temperatura de controle
float temperatura_limite = 25;
int sockfd;
struct sockaddr_in client_addr;
//Protótipo das funcoes e tasks
void DisplayIPAddress(uint32_t ui32Addr);
void lwIPHostTimerHandler(void);
void ConfigureUART(void);
void UpLwIP(void *param);
void initialize(void);
void udpReceiver(void *pvParameters);
void adcConfig(void);
float readTemp(void);
void sensorTask(void *pvParameters) ;
void ConfigureAtuador(void);
float media(float vetor[]);
//Pino do atuador
#define GPIO_PIN_ATUADOR GPIO_PIN_2
//IP interno do PC
#define DEST_IP_ADDR "192.168.18.53"
//Porta interna do PC
#define DEST_PORT 54321
//Porta utilizada para receber os pacotes ethernet
#define PORT 12345
//Estruttura utilizada pela LWIP
struct netif sNetIF;
//Clock do Sistema, utilizado por oitras funcoes
uint32_t g_ui32SysClock;
//Utilizado para controlar se o IP foi obtido ou nao
volatile BaseType_t lwip_link_up = pdFALSE;
//Variavel que armazena o IP obtido
uint32_t g_ui32IPAddress;
//Fila com dados Recebidos via socket
QueueHandle_t udpQueue;
//Semaforo UDP para sincronizar o uso do hardware de envio e
recebimento de pacotes
SemaphoreHandle_t xUDPDataSemaphore;
SemaphoreHandle_t serialSemaphore;
// Mostra o IP obtido na serial
void DisplayIPAddress(uint32_t ui32Addr)
{
static volatile char pcBuf[16];
//
// Convert the IP Address into a string.
//
sprintf(pcBuf, "%d.%d.%d.%d", (int)(ui32Addr & 0xff),
(int)((ui32Addr >> 8) & 0xff),
(int)((ui32Addr >> 16) & 0xff), (int)((ui32Addr >> 24) &
0xff));
//
// Display the string.
//
UARTprintf("%s\n",pcBuf);
}
//************************************************************
*****************
//
// Necessaria para a LWIP
//
//************************************************************
*****************
//Funcao auxiliar para ler o IP obtido
void lwIPHostTimerHandler(void)
{
uint32_t ui32Idx, ui32NewIPAddress;
//
// Get the current IP address.
//
ui32NewIPAddress = lwIPLocalIPAddrGet();
//
// See if the IP address has changed.
//
if(ui32NewIPAddress != g_ui32IPAddress)
{
//
// See if there is an IP address assigned.
//
if(ui32NewIPAddress == 0xffffffff)
{
//
// Indicate that there is no link.
//
//UARTPutString(UART0_BASE, "Waiting for link.\n\r");
}
else if(ui32NewIPAddress == 0)
{
//
// There is no IP address, so indicate that the DHCP
process is
// running.
//
//UARTPutString(UART0_BASE, "Waiting for IP
address.\n\r");
}
else
{
//
// Display the new IP address.
//
lwip_link_up = pdTRUE;
//UARTPutString(UART0_BASE, "IP Address: ");
DisplayIPAddress(ui32NewIPAddress);
//UARTPutString(UART0_BASE, "\n\rOpen a browser and enter
the IP address.\n\r");
}
//
// Save the new IP address.
//
g_ui32IPAddress = ui32NewIPAddress;
//
// Turn GPIO off.
//
// MAP_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1,
~GPIO_PIN_1);
}
//
// If there is not an IP address.
//
if((ui32NewIPAddress == 0) || (ui32NewIPAddress == 0xffffffff))
{
//
// Loop through the LED animation.
//
for(ui32Idx = 1; ui32Idx < 17; ui32Idx++)
{
//
// Toggle the GPIO
//
#if 0
MAP_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1,
(MAP_GPIOPinRead(GPIO_PORTN_BASE, GPIO_PIN_1) ^
GPIO_PIN_1));
// DelayTask(1000/ui32Idx);
#endif
}
}
}
float readTemp(void){
ADCIntClear(ADC0_BASE, 3);
ADCProcessorTrigger(ADC0_BASE, 3);
// Aguardar a conclusão da conversão
while (!ADCIntStatus(ADC0_BASE, 3, false)) {
}
// Ler o valor convertido
float temperaturaCelsius;
uint32_t adcResult;
ADCSequenceDataGet(ADC0_BASE, 3, &adcResult);
// Converte a leitura em temperatura em graus Celsius
// Para 5V e ADC de 12 bits, a fórmula é (leitura * Vcc /
4095) / 0.01
temperaturaCelsius = (adcResult * 5 / 4095.0) / 0.01;
if(temperaturaCelsius>=20)
temperaturaCelsius-=20;//OFFSET DO SENSOR
// Agora 'voltage' contém a tensão lida do pino analógico
return temperaturaCelsius;
}
//Funcao de configuracao do ADC
void adcConfig(void){
SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3);
// Configurara sequência de amostragem do ADC
ADCSequenceConfigure(ADC0_BASE, 3, ADC_TRIGGER_PROCESSOR, 0);
ADCSequenceStepConfigure(ADC0_BASE, 3, 0, ADC_CTL_CH0 |
ADC_CTL_IE | ADC_CTL_END);
ADCSequenceEnable(ADC0_BASE, 3);
ADCIntClear(ADC0_BASE, 3);
}
//Funcao de configuracao da UART
void ConfigureUART(void)
{
//
// Enable the GPIO Peripheral used by the UART.
//
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
//
// Enable UART0
//
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
//
// Configure GPIO Pins for UART mode.
//
ROM_GPIOPinConfigure(GPIO_PA0_U0RX);
ROM_GPIOPinConfigure(GPIO_PA1_U0TX);
ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
//
// Initialize the UART for console I/O.
//
UARTStdioConfig(0, 115200, g_ui32SysClock);
}
//Funcao de configuracao do pino do atuador
void ConfigureAtuador(void){
// Ativar o port E pino 5
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
// Esperar até que o porto E esteja pronto
while (!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOE));
// Configurar o pino como saída
GPIOPinTypeGPIOOutput(GPIO_PORTE_BASE, GPIO_PIN_ATUADOR);
//Deixa desligado por padrao
GPIOPinWrite(GPIO_PORTE_BASE, GPIO_PIN_ATUADOR, 0);
}
//Task de inicializacao de MAC e IP, Cria a task do socket
também, pois ela depende do IP e do MAC iniciados
void UpLwIP(void *param)
{
UARTprintf("UpLwIP - T1\n");
uint32_t ui32User0, ui32User1;
//uint32_t ui32Loop;
uint8_t pui8MACArray[6];
(void)param;
//
// Configure the device pins.
//
PinoutSet(true, false);
vTaskDelay(1500);
//UARTPutString(UART0_BASE, "Ethernet lwIP example\n\r");
// Configure the hardware MAC address for Ethernet Controller
filtering of
// incoming packets. The MAC address will be stored in the
non-volatile
// USER0 and USER1 registers.
ui32User0 = 0x001AB6;
ui32User1 = 0x032DCE;
MAP_FlashUserSet(ui32User0, ui32User1);
MAP_FlashUserGet(&ui32User0, &ui32User1);
if((ui32User0 == 0xffffffff) || (ui32User1 == 0xffffffff)){
//Caso nao tenha MAC ficamos aqui
while(1)
{
}
}
pui8MACArray[0] = ((uint8_t)(ui32User0 >> 0) & 0xff);
pui8MACArray[1] = ((uint8_t)(ui32User0 >> 8) & 0xff);
pui8MACArray[2] = ((uint8_t)(ui32User0 >> 16) & 0xff);
pui8MACArray[3] = ((uint8_t)(ui32User1 >> 0) & 0xff);
pui8MACArray[4] = ((uint8_t)(ui32User1 >> 8) & 0xff);
pui8MACArray[5] = ((uint8_t)(ui32User1 >> 16) & 0xff);
// Iniciamos a LWIP como DHCP, vamos obter o IP
automaticamente
lwIPInit(configCPU_CLOCK_HZ, pui8MACArray, 0, 0, 0,
IPADDR_USE_DHCP, &sNetIF);
while(lwip_link_up != pdTRUE){
vTaskDelay(500);
}
//Cria a task que recebe tasks
xTaskCreate(udpReceiver, "UDPServer",
configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 6, NULL);
//Cria a task de leitura do sensor, que envia dados para o
cliente do sensor
xTaskCreate(sensorTask, "Sensor 1", 1024, NULL,
tskIDLE_PRIORITY + 5, NULL);
//vTaskDelete(NULL);
while(1)
{
vTaskDelay(10000);
}
}
// Configurar o socket como não bloqueante com um timeout
void configureNonBlockingSocket(int sockfd, int timeout_ms) {
lwip_fcntl(sockfd, F_SETFL, O_NONBLOCK); // Configura o socket
como não bloqueante
lwip_setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout_ms,
sizeof(timeout_ms)); // Configura o timeout de recepção
lwip_setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &timeout_ms,
sizeof(timeout_ms)); // Configura o timeout de envio
}
//Task de recebimento de pacotes via socket
void udpReceiver(void *pvParameters) {
struct sockaddr_in server_addr;//, client_addr;
/*int sockfd,*/
int new_sockfd;
socklen_t sin_len = sizeof(client_addr);
char buffer[20];
sockfd = lwip_socket(AF_INET, SOCK_DGRAM, 0);// Cria um socket
UDP
memset(&server_addr, 0, sizeof(server_addr));// Zera o a
estrutura server_addr
//Seta o server_addr
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;// Pega um IP
automatico
server_addr.sin_port = htons(PORT);
//Associa o IP automaticamente
lwip_bind(sockfd, (struct sockaddr*)&server_addr,
sizeof(server_addr));
configureNonBlockingSocket(sockfd,100);
while (1) {
xSemaphoreTake(serialSemaphore, portMAX_DELAY);
UARTprintf("udpReceiver - T2 - LOOP\n");
xSemaphoreGive(serialSemaphore);
//Escuta no socket sockfd e coloca no buffer
xSemaphoreTake(xUDPDataSemaphore, pdMS_TO_TICKS(1000));//
Pega o semaforo UDP
new_sockfd = lwip_recvfrom(sockfd, buffer, sizeof(buffer), 0,
(struct sockaddr*)&client_addr, &sin_len);
// Se dados forem recebidos
if(new_sockfd > 0) {
// Imprimir informações do cliente
char client_ip[16];
inet_ntoa_r(client_addr.sin_addr, client_ip,
sizeof(client_ip));
xSemaphoreTake(serialSemaphore, portMAX_DELAY);
UARTprintf("Cliente IP: %s, Porta: %d\n", client_ip,
ntohs(client_addr.sin_port));
UARTprintf("udpReceiver - T2 - LOOP- > 0\n");
//buffer[new_sockfd] = '\0'; // Fim da string recebida
temperatura_limite = atof(buffer);
UARTprintf("%s\n",buffer);
xSemaphoreGive(serialSemaphore);
}
xSemaphoreGive(xUDPDataSemaphore); // Libera o Semaforo UDP
vTaskDelay(1000/portTICK_PERIOD_MS);
}
}
//Task do atuador
void udpProcessingTask(void *pvParameters) {
char receivedData[20];
float Temp;
//Para DEBUG
xSemaphoreTake(serialSemaphore, portMAX_DELAY);
UARTprintf("Task ATUADOR - T3\n");
xSemaphoreGive(serialSemaphore);
while (1) {
if (xQueueReceive(udpQueue, receivedData, 0)) {//Espera dado
na fila UDP
// Converte a string para float
xSemaphoreTake(serialSemaphore, portMAX_DELAY);
Temp = atof(receivedData);
char buf[10];
sprintf(buf, "%f",Temp);//Converte para String para envio
via UDP
UARTprintf("Temp %s \n",buf );
sprintf(buf, "%f",temperatura_limite);//Converte para
String para envio via UDP
UARTprintf("Limite %s \n",buf );
xSemaphoreGive(serialSemaphore);
if(Temp<=temperatura_limite){
// Acionar atuador = Liga a Lampada
xSemaphoreTake(serialSemaphore, portMAX_DELAY);
UARTprintf("ATUADOR ON \n",buf );
xSemaphoreGive(serialSemaphore);
GPIOPinWrite(GPIO_PORTE_BASE, GPIO_PIN_ATUADOR,
GPIO_PIN_ATUADOR);
}else{
// Desativa o atuador = Desliga a Lampada
xSemaphoreTake(serialSemaphore, portMAX_DELAY);
UARTprintf("ATUADOR OFF \n",buf );
xSemaphoreGive(serialSemaphore);
GPIOPinWrite(GPIO_PORTE_BASE, GPIO_PIN_ATUADOR, 0);
}
}
vTaskDelay(1000/portTICK_PERIOD_MS);
}
}
//Task do sensor 1
void sensorTask(void *pvParameters) {
xSemaphoreTake(serialSemaphore, portMAX_DELAY);
UARTprintf("TASK SENSOR \n" );
xSemaphoreGive(serialSemaphore);
static int count = 0;
float leituras[10];
float temperaturaCelsius;
char leituraBuffer[20];
while (1) {
temperaturaCelsius = readTemp();
if(count==10){
count = 0 ;
temperaturaCelsius = media(leituras);
sprintf(leituraBuffer, "%f",temperaturaCelsius
);//Converte para String para envio via UDP
xQueueSend(udpQueue, leituraBuffer, 0); //Coloca o dado
recebido na fila
xSemaphoreTake(xUDPDataSemaphore, portMAX_DELAY);//Pega o
semaforo para o UDP
// Envia o dado
if(sockfd!=-1){
lwip_sendto(sockfd, leituraBuffer,
strlen(leituraBuffer), 0, (struct sockaddr*)&client_addr,
sizeof(client_addr));
}
xSemaphoreGive(xUDPDataSemaphore);// Libera o Semaforo
UDP
}else{
leituras[count] = temperaturaCelsius;
count++;
}
vTaskDelay(500/portTICK_PERIOD_MS);// Bloqueia para dar
espaco para as outras tasks trabalharem
}
}
float media(float vetor[]){
int i;
float media = 0;
for(i=0;i<10;i++)
media+=vetor[i];
return media/10;
}
//Task IDLE
int main(void)
{
MAP_SysCtlMOSCConfigSet(SYSCTL_MOSC_HIGHFREQ);
// PLL 120 MHz
g_ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ
|SYSCTL_OSC_MAIN |SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480),
120000000);
//Habilita stack extra e interrupcoes floating-points
MAP_FPUEnable();
MAP_FPULazyStackingEnable();
//Configura a UART para Debug
ConfigureUART();
//Configura o pino do atuador (E2)
ConfigureAtuador();
//Configura o adc para ler os sensores
adcConfig();
//Cria um semaforo para o modulo ethernet
xUDPDataSemaphore = xSemaphoreCreateMutex();
//Cria um semaforo para a serial
serialSemaphore = xSemaphoreCreateMutex();//Cria uma fila de 5 strings de 20 caracteres para o sensor
udpQueue = xQueueCreate(5, sizeof(char[20]));
//Cria a task do atuador
xTaskCreate(udpProcessingTask, "UDPProcessing",
configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 5, NULL);
//Cria a task que seta o MAC da placa e pega um IP da rede
local automaticamente
//Dentro há outra task que cria um socket de escuta
xTaskCreate(UpLwIP, "LwIP Task", 1024, NULL, tskIDLE_PRIORITY +
5, NULL);
//Inicia o escalonador
vTaskStartScheduler();
return 0;
}
Figura 7 - Código completo do microcontrolador comentado.

Continue navegando