Comunicação serial do MSP430 via xBee
Autor: Möller | Publicado: 2013-05-02T18:54:00-07:00

Esse foi o trabalho que publicamos na 4ª SECAI.






Pesquisa principal:

O trabalho publicado na 4ª SECAI não propriamente o resultado da pesquisa principal, mas sim um "braço" dela, resultado de uma pesquisa que tivemos que fazer para podermos mudar o hardware que estávamos utilizando. Essa pesquisa secundária durou cerca de três meses, mas a nata, os resultados que foram utilizados para fazer esse trabalho só foram conseguidos nas duas últimas semanas.

A pesquisa principal envolve a implementação do CTCP em uma rede de microcontroladres, medir seu desempenho e comparar com o desempenho obtido em um simulador. O CTCP é uma protocolo de transporte idealizado pela Dra Eugênia Giancoli Jabour, para ser aplicado em redes de sensores e seu trabalho pode ser lido aqui.

A dificuldade:

Durante a pesquisa principal,&nbsp;estávamos&nbsp;usando plataformas de prototipagem arduino, tanto por sua simplicidade em programar, quanto na facilidade de achar componentes compatíveis, como shields e módulos e também pela facilidade de encontrar tutoriais na internet.

No entanto não há como programar uma interrupção nas portas de comunicação serial do Atmel, usando a plataforma arduino. Como criar uma plataforma para o Atmel era um trabalho que fugia aos nossos objetivos, resolvemos trocar a plataforma para o launchpad do MSP430, da Texas Instruments.

Apesar de não ter uma programação tão simples quanto o arduino e não haver tanto material disponível na internet, o launchpad tem a vantagem do preço (cerca de U$5,00 frete incluso). Além disso eu e alguns colegas do grupo PET tivemos um curso de 40h sobre o MSP430.

O trabalho:

O arduino tem funções prontas de comunicação serial, como a serial.println(), que pode receber qualquer dado, int, float, string, char e transmiti-lo para outro arduino, ou um escoador usando um programa tipo terminal sem a necessidade de qualquer adaptação.

Já no MSP430, a comunicação é feita armazenando os dados na variável de buffer, que é uma variável tipo char (ou seja, só recebe um byte). Isso é uma problema, uma vez que nossa rede de sensores vai transmitir valores inteiros ou de ponto flutuante (que são valores de 4 bytes).

Para resolver esse problema criamos três funções, uma para a comunicação com o terminal, outra para a comunicação entre os nós da rede e outra para transformar inteiros em vetores de char (strings).

Transformando números inteiros em "palavras":

Se eu tenho um número inteiros e eu só posso transmitir caracteres, parece sensato que eu transforme esse número num conjunto de char. Na tabela ASCII cada dígito tem um número equivalente, o 0 por exemplo é o char 48.

Implementamos função itoa(), baseada na função de mesmo nome do c++, que pega dígito a dígito do inteiro, os transforma em char e os armazena em uma string. Se temos o inteiro 15980, ela vai criar uma string com os valores [49, 53, 57, 56, 48]. Se você olhar na tabela ASCII vai ver que tais números equivalem aos dígitos 1,5,9,8,0. O código da função está na figura do poster, no início dessa postagem.

Enviando as strings:

Como o MSP430 precisa enviar os dados byte por byte, para mandarmos uma string com os dígitos de um número qualquer, precisamos fazer ele rodar essa string e transmitir cada elemento dela, ou seja, um laço for indo de 0 ao tamanho da string, atribuindo à variável do buffer o valor de cada elemento da string.

No entanto não é tão simples assim, antes de enviar escrever no buffer o MSP precisa verificar se o mesmo está livre, ou seja, se o último dado foi enviado. Conseguimos isso com o comando while(!(IFG2 &amp; UCA0TXIFG)).

Outro problema é que o módulo xBee precisa de um tempo para estar pronto para transmitir corretamente. Esse tempo é bem curto, mas se o sistema launchpad - xBee for orientado a começar a transmitir logo que ligado, alguns dados serão perdidos. Usamos uma espera forçada, deixando o MSP contar de 0 a 2788, na frequência de 1MHz antes de começar a transmitir.

A espera forçada não é um meio recomendável, ela ocupa o microcontrolador, gasta energia e não trás nenhum benefício. O uso de um timer pode trazer o mesmo efeito sem os malefícios da espera forçada. No entanto, usamos a espera por ser mais simples de implementar e porque não&nbsp;tínhamos&nbsp;certeza ainda se ela iria funcionar.

O número 2788 não foi arbitrário, começamos com 500.000 e fomos reduzindo pela metade. A partir de um certo ponto fomos diminuindo de 100 em 100, 10 em 10, 1 em 1, até que, no 2787 tivemos uma taxa de sucesso de 90% em 50 transmissões, aumentamos para 2788 e tivemos 100% em 50 transmissões. Portanto para evitar erros por esse problema, recomendamos uma espera que equivalha a mais de 3000 ciclos do processador à velocidade de 1MHz

A função println() termina com o char 13 sendo enviado, que equivale à um "enter". Sua descrição também se encontra na imagem do poster.

A comunicação entre nós:

Pode parecer natural realizar esses mesmos processos para a comunicação entre os microcontroladores. No entanto há um meio de otimizar a mesma.

Precisamos quebrar cada dígito e converte-los para char, quando vamos nos comunicar com um terminal, porque esse tipo de programa converte automaticamente cada char recebido para seu símbolo correspondente da tabela ASCII.

No entanto usar tais funções para a comunicação entre microcontroladores seria muito trabalhoso, precisaríamos de uma função para receber as strings e outra para transformar os elementos das strings em um número. Além disso, se o inteiro tivesse 9 dígitos, seriam 9 operações, 12 dígitos 12 operações, não é muita coisa para um microcontrolador, mas dá para melhorar.

Sabendo que todo valor inteiro é composto de 4 bytes e todo char é composto de 1 byte, podemos quebrar os bytes de um inteiro em 4 e transmiti-los. O receptor só precisaria ficar atento e agrupar os bytes de 4 em 4 restituindo o valor inteiro. Fizemos isso com a função decompor(), descrita no poster do trabalho.

E não dá para usar só a decompor?

Infelizmente não, a não ser que outro programa seja usado na base, os programas terminais vão transformar cada código char transmitido em um elemento da tabela ASCII. Um valor inteiro quebrado em quatro byte poderá ter valores como 13 e 10, dando um enter ou delete e impossibilitando que as informações sejam recuperadas.

Conclusão:

O trabalho foi meramente explicativo, de ferramentas que criamos para ajudar em nosso trabalho. As funções de recuperação dos dados ainda não foram criadas e nem sabemos se vamos de fato usar essas funções na pesquisa principal. Nosso trabalho deixa um aberto para a transmissão de valores de ponto flutuante, na função "recompor()" e em outras funções de comunicação.