quinta-feira, 14 de julho de 2011

MiWi: Criando redes MiWi com PIC18F4550

Depois de nossa série sobre o protocolo MiWi, chega a hora de colocar tudo em prática. Assim, vamos criar aqui um projeto de redes MiWi com o PIC. Vou selecionar o PIC18F4550, pois depois poderemos atualizar o projeto, adicionando o controle através da porta USB.
Se vocês perderam algum dos posts anteriores, podem acessá-los pela lista abaixo:
1- MiWi: Dispositivos e topologias de rede;
2- MiWi: Endereçamento;
3- MiWi: Relatórios de protocolo;
4- MiWi: Mensagens de Stack e Serviços
5- MiWi: Segurança
Como a biblioteca da Microchip para o MiWi foi desenvolvida recentemente, há ainda alguns bugs e também muitas atualizações. Ela é fornecida com o Microchip Application Libraries, e a última versão disponível agora, enquanto escrevo este artigo, é a versão de junho de 2011 (Stack MiWi 4.2). Quem estiver com sua versão desatualizada, é bom atualizar.

Hardware do projeto

Desenhamos o circuito do projeto no KiCad, que pode ser visto abaixo:


Criamos o componente MRF24J40MA, já que o KiCad não o possui. Você poderá obter todos os datasheets relacionados a este módulo no site da Microchip.
O módulo MRF24J40MA é o módulo que fará todo o trabalho de transmissão e recepção de pacotes. Você o controla via barramento SPI. Ele na verdade é um transceiver feito pela Microchip para os protocolos ZigBee ou MiWi... Mas como um transceiver, você poderá criar qualquer protocolo de comunicação com ele. O Stack MiWi não está no módulo, mas é implementado pelas bibliotecas da Microchip.
Para você ter uma visão geral dos registradores disponíveis deste módulo, procure pelo datasheet do circuito integrado principal dele, o MRF24J40. Há ainda uma versão deste módulo de maior alcance, chamado de MRF24J40MB.
A alimentação do módulo é de 3.3V. Para simplificar o desenho acima, não incluímos a fonte. Portanto, quando você for implementar este projeto, lembre-se de incluí-la.

Incluindo os arquivos do projeto

Vamos agora ao PCAD, e vamos criar um novo projeto com PICF4550. Os arquivos que devemos incluir são os arquivos abaixo:

ArquivoPasta
Console.c\Microchip Solutions\Microchip\WirelessProtocols\
MSPI.c\Microchip Solutions\Microchip\WirelessProtocols\
SymbolTime.c\Microchip Solutions\Microchip\WirelessProtocols\
MiWi.c\Microchip Solutions\Microchip\WirelessProtocols\MiWi\
MRF24J40.c\Microchip Solutions\Microchip\Transceivers\MRF24J40\
MiWi.c\Microchip Solutions\Microchip\WirelessProtocols\MiWi\

Os cabeçalhos relacionados com estes arquivos podem ser adicionados para facilitar a visualização. Por fim, devemos copiar três arquivos que serão necessários para o projeto: ConfigApp.h, HardwareProfile.h, SystemProfile.h. Para o projeto de um dispositivo End Device, nós vamos copiar estes arquivos do diretório Microchip Solutions\MiWi DE Demos\Node 2. Para Coordinators, devemos copiar estes arquivos do diretório Microchip Solutions\MiWi DE Demos\Node 1. São eles que conterão as configurações de rede do projeto, bem como o esquema de ligação deste projeto.
Assim que copiar estes arquivos para a pasta do projeto, inclua-os. Fazendo isto, vamos editar o arquivo HardwareProfile.h, para que ele reflita o nosso esquemático:
#ifndef _HARDWARE_PROFILE_H
    #define _HARDWARE_PROFILE_H
    
    #include "GenericTypeDefs.h"
    #include "ConfigApp.h"
    #include <p18cxxx.h>
    
    #define CLOCK_FREQ          48000000
    
    #define RFIF                INTCON3bits.INT2IF
    #define RFIE                INTCON3bits.INT2IE
    
    #define PHY_CS              LATCbits.LATC2
    #define PHY_CS_TRIS         TRISCbits.TRISC2
    #define RF_INT_PIN          PORTBbits.RB2
    #define RF_INT_TRIS         TRISBbits.TRISB2
    
    #define SPI_SDI             PORTBbits.RB0               
    #define SDI_TRIS            TRISBbits.TRISB0
    #define SPI_SDO             LATCbits.LATC7
    #define SDO_TRIS            TRISCbits.TRISC7
    #define SPI_SCK             LATBbits.LATB1
    #define SCK_TRIS            TRICBbits.TRISB1

    #define PHY_RESETn          LATCbits.LATC0
    #define PHY_RESETn_TRIS     TRISCbits.TRISC0
    #define PHY_WAKE            LATCbits.LATC1
    #define PHY_WAKE_TRIS       TRISCbits.TRISC1
    
    #define LED_1               PORTEbits.RE0
    #define LED_1_TRIS          TRISEbits.TRISE0
    #define LED_2               PORTEbits.RE1
    #define LED_2_TRIS          TRISEbits.TRISE1
    #define LED_3               PORTEbits.RE2
    #define LED_3_TRIS          TRISEbits.TRISE2

    #define TMRL                TMR0L
    
    #define TOOGLE(c)           c = ~c

#endif
Aqui nós definimos todas as ligações feitas com o módulo MRF24J40MA. Se alguma destas definições faltar, o compilador gerará erros. O clock e o registrador do timer usado também devem ser definidos aqui, para que o Stack MiWi possa fazer as temporizações corretamente. Portanto, você não poderá usar este timer.

Configurando o projeto

A configuração do projeto é feita no arquivo ConfigApp.h. Veja quais opções você poderá selecionar neste arquivo:

ConfiguraçãoDescrição
ENABLE_CONSOLEHabilita a impressão de mensagens pela serial do microcontrolador. Comente esta definição, para desabilitá-la.
SIMPLE_EXAMPLEDesabilita todas as funções mais avançadas do Stack. Insira esta definição no projeto, para habilitá-la.
ENABLE_NETWORK_FREEZERGrava todos os dados mais importantes de uma conexão em memória não volátil, para rápido restabelecimento da rede. É necessário ter esta memória no projeto.
HARDWARE_SPIUtiliza o módulo SPI nativo do microcontrolador para comunicação. Comentando-se esta definição, o Stack tentará emular uma SPI. Recomendável usar o SPI nativo.
PROTOCOL_P2PHabilita a rede P2P. Não pode ser definido juntamente com PROTOCOL_MIWI
PROTOCOL_MIWIHabilita a rede MiWi Mesh. Não pode ser definido juntamente com PROTOCOL_P2P
NWK_ROLE_COORDINATORDefine o dispositivo como Coordinator. Não pode ser definido juntamente com NWK_ROLE_END_DEVICE.
NWK_ROLE_END_DEVICEDefine o dispositivo como End Device. Não pode ser definido juntamente com NWK_ROLE_COORDINATOR.
MRF24J40Define que o módulo MRF24J40MA de 2.4GHz será usado. Não pode ser definido junto com outros transceivers.
MRF49XADefine que o módulo subGHz MRF49XA da Microchip será usado. Não pode ser definido junto com outros transceivers.
MRF89XADefine que o módulo subGHz MRF89XA da Microchip será usado. Não pode ser definido junto com outros transceivers.
MY_ADDRESS_LENGTHDefine o tamanho do endereço permanente do nó, em bytes.
EUI_0 - EUI_7Esta é a definição do endereço EUI do módulo. Cada dígito é um byte do endereço.
TX_BUFFER_SIZEDefine o tamanho do buffer de transmissão.
RX_BUFFER_SIZEDefine o tamanho do buffer de recepção.
MY_PAN_IDDefine o PANID do dispositivo.
ADDITIONAL_NODE_ID_SIZEDefine o tamanho dos dados adicionais que serão anexados à requisição P2P. Estas são informações que os dispositivos querem compartilhar com outros pontos na conexão. Estes dados serão definidos pela aplicação.
CONNECTION_SIZEDefine o máximo de conexões P2P que este dispositivo permite ao mesmo tempo.
TARGET_SMALLRemove algumas funcionalidades para diminuir o código gerado.
ENABLE_PA_LNAHabilita o amplificador de potência em transceivers que o possuem.
ENABLE_HAND_SHAKEHabilita o hand-shake antes da comunicação. Sem isto, os transceivers RF só poderão fazer broadcast, ou possuir o endereço de destino programado no firmware para comunicação com um dispositivo.
ENABLE_SLEEPPermite que o dispositivo vá para o modo sleep e volte dele.
ENABLE_ED_SCANHabilita a detecção de energia, para descobrir qual o canal que possui menos ruído.
ENABLE_ACTIVE_SCANHabilita o Active Scan, para detectar as conexões atualmente existentes.
ENABLE_SECURITYHabilita a encriptação de dados na transmissão.
ENABLE_INDIRECT_MESSAGEFará com que o dispositivo guarde mensagens para dispositivos que estão em modo sleep, até que eles retornem ao funcionamento normal.
ENABLE_BROADCASTFará com que o dispositivo envie broadcasts aos dispositivos em modo sleep, até que eles retornem ao funcionamento normal.
RFD_WAKEUP_INTERVALDefine o intervalo de wakeup para dispositivos RFD em segundos. Esta definição no entanto não é utilizada pelos dispositivos RFD, mas pelos dispositivos FFD, para calcular seus vários timeouts.
ENABLE_FREQUENCY_AGILITYFaz com que o dispositivo possa mudar de canal, quando houver uma súbita mudança no ruído.
Alterando o valor destas definições, você poderá configurar seu projeto de acordo com suas necessidades. É sempre bom dar uma olhada nestas configurações depois de copiar os arquivos.

Arquivo principal do projeto

No arquivo principal, você precisará definir algumas coisas também. Vamos ao esqueleto básico deste arquivo:
#include <stdio.h>
#include "GenericTypeDefs.h"
#include "Compiler.h"
#include "WirelessProtocols/MSPI.h"
#include "WirelessProtocols/MCHP_API.h"

#include "HardwareProfile.h"

#if ADDITIONAL_NODE_ID_SIZE > 0
 BYTE AdditionalNodeID[ADDITIONAL_NODE_ID_SIZE] = {0x01};
#endif

BYTE myChannel = 11;

#pragma config FOSC=HSPLL_HS
#pragma config CPUDIV=OSC1_PLL2
#pragma config PLLDIV=5
#pragma config USBDIV=2
#pragma config CCP2MX=ON
#pragma config WDT=OFF
#pragma config WDTPS=32768
#pragma config MCLRE=ON
#pragma config LVP=OFF
#pragma config VREGEN=ON
#pragma config IESO=OFF
#pragma config PWRT=ON
#pragma config BOR=OFF
#pragma config CP0=OFF
#pragma config CP1=OFF
#pragma config CP2=OFF
#pragma config CP3=OFF
#pragma config CPB=OFF
#pragma config CPD=OFF
#pragma config WRT0=OFF
#pragma config WRT1=OFF
#pragma config WRT2=OFF
#pragma config WRT3=OFF
#pragma config WRTB=OFF
#pragma config WRTC=OFF
#pragma config WRTD=OFF
#pragma config EBTR0=OFF
#pragma config EBTR1=OFF
#pragma config EBTR2=OFF
#pragma config EBTR3=OFF
#pragma config EBTRB=OFF
#pragma config DEBUG=ON
#pragma config XINST=ON

void UserInterruptHandler(void)
{
}              

void main(void)
{
 BYTE i=0xFF;
 
 RCON = 0x80;           // Habilita prioridades para interrupções
 ADCON0 = 0x00;
 ADCON1 = 0x0F;       // PORTA só como entradas e saídas digitais.
 CMCON = 0x07;        // Comparadores desligados.
 TRISA = 0xFF;
 TRISB = 0x05;
 TRISC = 0x00;
 PORTC = 0x06;
 TRISD = 0x00;
 PORTD = 0x00;
 TRISE = 0x07;
 PORTE = 0xFF;
 INTCON = 0x00;
 INTCON2 = 0x00;
 INTCON3 = 0x00;
 // Configura o módulo SPI
 SSPSTAT = 0xC0;
 SSPCON1 = 0x20;
 
 INTCONbits.GIEH = 1;
 RFIF = 0;               // Limpa o interrupt flag do chip.
 RFIE = 1;
 INTCON2bits.INTEDG2 = 0;

 MiApp_ProtocolInit(FALSE);
 if(MiApp_SetChannel(myChannel) == FALSE)
 {
  return;
 }
 MiApp_ConnectionMode(ENABLE_ALL_CONN);
 while((i = MiApp_EstablishConnection(0xFF, CONN_MODE_DIRECT)) == 0xFF);
 #ifdef ENABLE_DUMP
        DumpConnection(0xFF);
 #endif
 LED_2 = 1;
 for(;;)
 {
  if(MiApp_MessageAvailable())
  {
   // Aqui tratamos a mensagem recebida.
   MiApp_DiscardMessage();
  }
 }
}
O código acima é de um arquivo prinpipal para o projeto de dispositivo End Device. A diferença entre o End Device e o Coordinator é apenas a função main. Duas definições devem ser feitas no arquivo principal. A primeira é a definição da variável AdditionalNodeID, conforme pode ser visto acima. Os arquivos do Stack MiWi usam esta variável, portanto é necessário pelo menos definí-la. A segunda definição é a da função UserInterruptHandler. Esta função é chamada depois que a interrupção do MiWi for executada, e precisa também ser declarada, mesmo que nada seja feito ali.
Além destas declarações, você deverá ainda configurar o módulo SPI e habilitar a interrupção que você definiu para o módulo MRF24J40MA (o Stack não faz isto como acontece em outras bibliotecas Microchip). Feito isto, seu projeto está pronto para funcionar.
As diferenças existentes neste arquivo acima, para o projeto do Coordinator são poucas. Compare com o código abaixo (do Coordinator):
MiApp_ProtocolInit(FALSE);
 if(MiApp_SetChannel(myChannel) == FALSE)
 {
  return;
 }
 MiApp_ConnectionMode(ENABLE_ALL_CONN);
 MiApp_StartConnection(START_CONN_DIRECT, 10, 0);
 #ifdef ENABLE_DUMP
        DumpConnection(0xFF);
 #endif
 LED_2 = 1;
 for(;;)
 {
  if(MiApp_MessageAvailable())
  {
   MiApp_DiscardMessage();
  }
 }
Pode-se observar que o End Device usa a função MiApp_EstablishConnection, enquanto o Coordinator usa a função MiApp_StartConnection. Esta função inicializa a rede MiWi, e somente com uma rede estabelecida, é que os dispositivos End Device podem estabelecer conexões.

Conclusão

Terminamos aqui com a criação de um projeto MiWi. No nosso próximo post, iremos desvendar um pouco mais as rotinas usadas pelo Stack, para implementar a comunicação via protocolo MiWi, comparando com o que já foi escrito sobre o protocolo, aqui.

12 comentários:

  1. Gustavo, tem alguma limitação que impeça este projeto de trabalhar com o pic 18f2550?

    ResponderExcluir
  2. Bem, não existe, pois a única limitação que poderia existir é limitações de memória. Neste ponto, a memória do PIC18F4550 é igual à do PIC18F2550.

    ResponderExcluir
  3. Gustavo fiz todo o passo a passo, aparentemente tudo certo, mas o mplab ta me dando erro "syntax error", no arquivo hardware profile.h, o que posso ter feito errado? casso seja possivel me manda um email para que eu possa entrar em contato com você. dayvsonleandro@gmail.com , obrigado pela atenção.

    ResponderExcluir
  4. Nós temos que ver o motivo que o MPLAB dá para o erro... Além do "syntax error", o que mais ele avisa?

    ResponderExcluir
  5. Olá, Tenho alguns modulos MRF24J40MA para ultilizar em um sistema de comunicação de fultebol de robôs, Categoria Small-Size. Estou com bastante dificuldades em implementar o protocolo ZigBee, Vc está me ajudando muito, e agora vou tentar implementar o miwi. Vou usar o computador via USB como PAN coordinator e os robos seram End devices q só recebem os dados.
    O protocolo Miwi Pelo visto é bem mais facil de ser implementado, possuo algumas duvidas ainda e tbm como fazer uma interface dos dados via USB para o MRF24J40MA.
    Se puder me ajudar mais um pouco ficaria muito agradecido.
    meu e-mail: victorcastro89@hotmail.com
    Obrigado

    ResponderExcluir
  6. Olá. Tenho 2 módulos MRF24J40MB. Você poderia me enviar os aquivos do projeto en C que descreve neste post? Meu endereço de e-mail:
    carlos-seoane@hotmail.es Regards. Obrigado.

    ResponderExcluir
  7. AMIGO GOSTEI DO SITE, ESTOU COMEÇANDO A USAR O ZIGBEE E COMPREI UMA PLACA DA MICROCHIP COM ESSE QUE VOCÊ ESTA DEMOSTRANDO, COMPREI A PLACA COM O PIC18F4520 GOSTARIA QUE VOCÊ PUDESSE ME ENVIAR ALGUNS PROGRAMAS EXEMPLOS DE CONFIGURAÇÃO DESSE ZIGBEE, NO CASO DE VOCÊ TIVER ALGUMA SUGESTÃO.

    vicksonricarte@hotmail.com

    ResponderExcluir
  8. Olá, no datasheet diz que este módulo pode ser usado também com a família 16f, você já utilizou na 16f? Tem algum exemplo no 16f?

    ResponderExcluir
  9. Olá, Oséias.

    Peço perdão pelo atraso na resposta... Provavelmente você poderá sim usar este módulo com o PIC16F, mas eu não cheguei a tentar usá-lo. É necessário ver se as bibliotecas da Microchip cabem na memória de código desta família, do contrário, será necessário codificar as próprias rotinas de MiWi para o módulo.

    ResponderExcluir
  10. Viva, parabéns pelo blog.

    Tenho tentado há algum tempo utilizar o 4550/2550 por causa do USB, mas nem com este tutorial eu consegui. Ele não estabelece ligação.

    Eu resolvi este problema utilizando 2 PICs, 1 para comunicar com a antena e outro com o USB e de seguida comunico por USART entre os dois. Isto funciona e já tenho uma pequena aplicação no computador a funcionar.

    Se me pudesse ajudar a perceber porque não consigo colocar o 4550 a funcionar agradecia. Eu fui colocando o LED_1 = 1; e verifiquei que ele fica retido aqui: while( (i = MiApp_EstablishConnection(0xFF, CONN_MODE_DIRECT)) == 0xFF );

    Tenho esta comunicação a funcionar com o 18LF2431, 4620 e 26k20.

    Obrigado.

    ResponderExcluir
  11. Olá Gustavo, estou iniciando o estudo sobre o miwi, porém tentei seguir todos os seus passos e não consigo fazer a comunicação, você pode me ajudar? Se preferir pode entrar em contado pelo meu e-mail (andre.luiz.p.ferreira@gmail.com). Grato

    ResponderExcluir
  12. Olá para todos e desde já, perdão pela demora em responder.
    Embora eu tenha colocado a documentação acima e até tenha conseguido me comunicar, detectei algo muito errado nas bibliotecas fornecidas pela Microchip para o uso do MiWi. Provavelmente será necessário reescrever o código, pois pelo menos comigo, a comunicação é intermitente. Investiguei por um bom tempo e não consegui achar os motivos. Por falta de tempo não pude prosseguir com os testes. Assim que puder testar mais e descobrir qualquer falha, eu estarei atualizando este post.

    Abraços.

    ResponderExcluir

Você também poderá gostar de