sábado, 27 de julho de 2013

Medição de Pressão com Netduino Plus - Parte 1

Esses dias encontrei com um amigo meu de longa dada que hoje faz parte de uma comunidade de ASAMCO. Se você é como eu e não entendeu o que significa é bom dar uma olhada na internet. Trata-se de um estilo de arte marcial, tem até uma comunidade no velho orkut.

Bom, eles tem um problema sério, não encontram um medidor de força de impacto que esteja em um preço assim comprei o desafio para mim de fazer um equipamento dessa natureza.

A primeira coisa que fiz foi pesquisar sobre o assunto buscar informações sobre como de fato é feito comercialmente esse tipo de medição: "Como medir a força de um soco ?" Acho que ninguém nunca se preocupou muito com isso quando via um lutador de UFC na TV uma sensação nacional contemporânea....

Eu foi atrás da resposta para isso, a final, a Globo sempre diz o que quer e manipula as informações, o que dirá de uma medida tão subjetiva como a força exercida por um soco humano. Focando no aspecto básico da coisa sabemos que
 F = ma [N]
Yes! Força é medida em Newton's que nada mais do que [kg.m/s²]. Tradicionalmente se utiliza a Libra como medida de força, 0,45359 kg. Não encontrei uma justificativa muito elaborada, mas é simplesmente o valor "Oficial" da força dividido pela aceleração da gravidade, isso ajuda a melhorar a sensibilidade das pessoas quanto é o efeito da força, ou seja, para um soco de 100lbs equivale a 441 N significa algo perto de um peso de 45 kg caindo sobre seus braços... 

Achei um site com uma explicação bem simples "Calculation for Punching Force" que trata da força de um bate-estaca ou um temprano de sondagem a percussão. Pesquisando mais um pouco achei esse videio que mostra o equipamento em ação, já tinha visto pessoalmente mas não com a galera tão sangrenta, nesse videio pude perceber alguns detalhes que comprometem o esquema de medida, o ultimo cara que golpeia não tem a medida executada corretamente porque a canela dele escorrega por cima do ponto de medição. O que tira da parede o medidor está com uma direção tal que a força contrapõe mais a gravidade do que atinge o sensor (vira velocidade não amortecimento).

Outro detalhe que o vídeo mostra é que o colção por trás do medidor contribui para amortecimento do impacto absorvendo parte da energia  ao longo do tempo.



 Pesquisando um pouco mais encontre este site eHow, nada de especifico apenas uma descrição que me deixou mais animado: "Força de perfuração é uma métrica mensurável para a eficácia em treinamento de artes marciais, apesar de não medir a eficácia de uma determinada técnica. A força é medida em Newtons, que expressam a quantidade de energia necessária para mover uma dada massa de uma determinada distância. Impacto da energia é expressa em pascal, que é uma unidade de pressão, e divide força em newtons por a área de superfície da superfície de impacto."

No site tinha uma pequena receita de bolo de como fazer uma medição de força passo-a passo com coisas de casa. Bem simples calcular a força do impacto pela força e a variação do deslocamento do punho entre farmes consecutivos da câmera. Bem engenhoso, mas ainda pouco prático para o nosso sistema automático de medida fia mais complexo. Queria uma solução que pudesse medir massa e aceração através de uma única grandeza o que é difícil, ou que me desse a sessação do valor.


Outro site com informações foi o Hack A Day que tinha um artigo sobre Punching accelerometers, nada de muito profundo só que deixou meio no ar a forma com que o medidor foi realmente feito junto com uma imagem que eu acredito que seja meramente ilustrativa a tomar pelos comentários do artigo. O que tinha mesmo de interessante era o outro artigo relacionado, onde ele pretendia usar o acelerômetro, no Makiwara que é uma tábua para abter originalmente usara por grupos de Karate, o site mostra como fazer uma, aqui tem um video de um cara usando, vovó ninja:



Base para mim de fato foi esse artigo publica na EE Times por Marian Petre onde ele usa um Arduino Mega para medir a dinâmica dos socos num saco de pancadas. De fato o projeto dele é bem mais elaborado que o meu de 1 dia... O objetivo era verificar todas os estimulosos dados pelo lutador no seu treinamento e avaliar a performance através do estilo de ataque e bla blá blá...

Uma das partes mais interessantes deles é exatamente a escolha do sensor a ser usado a final precisaram comprar vários deles para preencher todo o saco de pancadas e obter a posição razoável onde o golpe foi aplicado. A solução no caso deles foi fazer um sensor de membrana por conta própria que separada por um dielétrico funcionava como um sensor razoável. Muito embora seja só a medição de posição do impacto que a intensidade foi estimada com um acelerômetro o sensor me deu mais asas para criar o meu próprio dispositivo de medição.

De qualquer forma o que queremos mesmo é calcular a força de um soco. O que como eu disse no inicio se confunde muito com força execrida pro máquinas para executar cortes e perfurações como é o caso das prensas. Unindo uma coisa na outra podemos considerar que a se colocarmos um saco cheio de ar no meio do podemos calcular a pressão exercida num soco sobre ele através da pressão uniforme que surge sobre cada cm² devido a redução de volume, ou seja, podemos medir a força aplicada por um soco ou um chute com o medidor de pressão.

A bem da verdade é que eu não criei nada. Peguei um sensor de pressão comum, o MPX4250AP que é capaz de medir pressões de 20 kPa até 250kPa. Sabendo que a "pressão" do soco do Magila chega a 240kg (vamos considerar 400kg bem conservativo) que multiplicado pela aceleração da gravidade equivale a uma força de fato de 3920N, como a pressão é dada por:

 p = \frac{F}{A}

 Então temos que ter uma área de 0,0157 m² para que isso produza uma pressão de 250 kPa ( máximo do sensor ). Ou seja uma bolsa térmica! Vou preparar o sensor e ver se testo na semana que vem!






μLiquidCrystal: uma biblioteca universal para LCD's

Primeiramente gostaria de informar aos navegantes das terras do Netduino que eu estou vivo ainda, muito embora debilitado pela falta de tempo ainda companho vagamente os post's no fórum do Netduino que continua sendo uma grande fonte di informação e de perspectivas para novos projetos.

Nesse grande feriado papal a minha única alternativa foi me debruçar nos meus projetos pessoais... Esta semana tinha recebido a ligação de um amigo meu que tinha solicitado um projeto de medição de pressão, que nunca foi concluído por mero descuido meu.

Pegando a placa novamente pude perceber que o estádio de desenvolvimento era bom mas como todo bom engenheiro perdi o tal do código, ou seja, começar tudo outra vez...  Iniciando pelo inicio mesmo, como piscar o LED com Netduino... E como tinha de ser tive que reaprender muitas coisas entre elas a usar o LCD 16x2. A primeira coisa que fiz foi tentar ligar o Netduino depois escreve algo no LCD mas pasmem não consegui... não estava como tinha postado no Blog...

Depois de pesquisar por incessantes 3 horas percebi que tinha usado μLiquidCrystal. Trata-se de um abiblioteca especialmente feita para  interfacear com dispositivos de LCD com o Netduino que está disponível no CodePlex desde 2010.

Qual a grande vantagem dela? Simples, não precisa de nenhum periférico a mais apenas uma ligação direta com o LCD 16x2 sem nenhum periférico, o sonho de qualquer entusiasta. O artigo que encontrei primeiramente foi este: Netduino - Getting Started with LCD do Blog do Jeroen Swart. Depois investiguei mais um pouco e cheguei na Ligação que ele utilizou proveniente do artigo base do Arduino, que está aqui abaixo:

Quando eu li o artigo do Blog do Szymon Kobalczyk's, a primeira impressão que tive era que tratava-se de uma DLL para usar o HD44780 como interface serial/paralela, mas a DLL faz muito mais que isso.

O Resultado de testes está na foto abaixo que tirei ontem a noite  do código funcionando na Placa do Netduino Plus. A única dificuldade que tive é foi para fazer funcionar no Netduino Plus, porque a compilação que está no site (ou melhor, a solução com código fonte que você mesmo compila) foi feita para o Netduino com .NETMF 4.1... A primeira vez dava um erro e não debugava muito embora a compilação da solução fosse feita normalmente... o que me deixou inicialmente bem confuso. Ajustei o .NETMF da solução do MicroLiquidCrystal para 4.2 e nada...

A ultima alternativa foi aplicar o método lusitando e refazer a solução para o Netduino Plus incluindo todos os arquivos da solução convencional do MicroLiquidCrystal e funcionou ! A foto do deste está abaixo:


O código de teste está logo abaixo, veja que você pode configurar cada pino do LCD para ficar em uma IO diferente e o código gerencia tudo isso sozinho, mas fácil que isso impossível.

1:  using System;  
2:  using MicroLiquidCrystal;  
3:  using System.Net;  
4:  using System.Net.Sockets;  
5:  using System.Threading;  
6:  using Microsoft.SPOT;  
7:  using Microsoft.SPOT.Hardware;  
8:  using SecretLabs.NETMF.Hardware;  
9:  using SecretLabs.NETMF.Hardware.NetduinoPlus;  
10:  namespace N__LCD16x2  
11:  {  
12:    public class Program  
13:    {  
14:      public static void Main()  
15:      {  
16:        // write your code here  
17:        // create the transfer provider, use direct GPIO provider  
18:        // Initialize the library with the numbers of the interface pins  
19:        //// Use wiring shown here http://arduino.cc/en/uploads/Tutorial/lcd_schem.png  
20:        var lcdProvider = new GpioLcdTransferProvider(Pins.GPIO_PIN_D12,  // RS  
21:                                Pins.GPIO_PIN_D11,  // ENABLE  
22:                                Pins.GPIO_PIN_D5,   // D4  
23:                                Pins.GPIO_PIN_D4,   // D5  
24:                                Pins.GPIO_PIN_D3,   // D6  
25:                                Pins.GPIO_PIN_D2);  // D7  
26:        // create the LCD interface  
27:        var lcd = new Lcd(lcdProvider);  
28:        // set up the LCD's number of columns and rows:   
29:        lcd.Begin(20, 2);  
30:        // print a message to the LCD.  
31:        lcd.Write("Sonhando com Net!");  
32:        OutputPort led = new OutputPort(Pins.ONBOARD_LED, false);  
33:        while (true)  
34:        {  
35:          // set the cursor to the first column on the second line  
36:          lcd.SetCursorPosition(0, 1);  
37:          // print the number of milliseconds since reset:  
38:          lcd.Write((Utility.GetMachineTime().Ticks / 10000).ToString());  
39:          //Liga  
40:          led.Write(true);  
41:          Thread.Sleep(1000);  
42:          //desliga  
43:          led.Write(false);  
44:          Thread.Sleep(1500);  
45:        }  
46:      }  
47:    }  
48:  }  

Para baixar o código fonte para Netduino Plus clique aqui.

domingo, 28 de abril de 2013

Electricity, Gas and Temperature Monitoring with Netduino Plus



Como fiquei muito tempo sem tocar no meu Netduino simplesmente o tempo passou e coisas novas surgiram. Hoje nas minhas pesquisas no blog tentei buscar saber o que os nossos amigos entusiastas andam fazendo a respeito do quando repentinamente me deparei com um dos projetos mais sagazes que eu já tinha visto com o Netduino Plus: um multimedidor integrado para medição de águal, luz e gás com aplicações em energias renováveis.


A página do Code Plex pode ser acessa através desse LINK. Trata-se de um Medidor de energia elétrica, um verdadeiro Smart Meter que está equipado com uma porta P1 que, se acionado, entrega uma mensagem a cada 10 segundos com informações sobre energia elétrica consumida (kWh), eletricidade entregue (kWh), o uso atual (kW), entrega atual (kW) , que tarifa está sendo usado e, além disso pode ser usado como um Smart Meter para gás, medindo a vazão de gás (m³). Também inclui uma função de medição de energia individualizada que se aplica, por exemplo, registro PV pode ser conectado e logado para PVOutput.org etc (Funciona como Dataloger)

O código do medidor  está escrito em Visual Basic 2010 Express que é executado em um Netduino Plus e / ou um Netduino Plus 2 (pasmem o cara é ninja!!!). O código já possui as configurações para funcionar com as plataformas PVOutput, Cosm e ThingSpeak em um intervalo configurável por serviço além de possibilitar a gravação no cartão microSD com capacidade máxima de 2GB.

O idealizador dessa arte é o Gé Brander responsável pelo suporte a plataforma que começou com força me Março desse ano 2013.

Fica para os entusiastas o vídeo do que o medidor é capaz de fazer!
Netduino Forum Post: http://forums.netduino.com/index.php?/topic/7364-dutch-smart-meter-and-s0-meter-logging/

Netduino Plus 2 - Mais memória e mais processameneto



    Já faz algum tempo que eu não posto nada no blog. Desculpe a demora, acontece que ue mudei de emprego e a demanda lá é diferente e tive que estudar algumas coisas novas.

    Na verdade, muito embora eu goste de eletrônica e tudo mais, eu sou engenheiro elétrico sendo assim eu trabalho com algumas coisa que fogem um pouco a necessidade. Hoje eu estou trabalhando com projetos de Linhas de Transmissão de Energia, nada a ver com o Netduino e eletrônica (a princípio...)

    De todas as formas estou aqui para escrever um post sobre o Netduino Plus 2 que já está ai desde Novembro, se não me engano, e até agora não pude velo em funcionamento.

    O Netduino Plus 2 tem quatro vezes a velocidade (168MHz), seis vezes o espaço de código (384KB), e duas vezes a RAM disponível (100KB +) do que Netduino Plus. Ele também tem mais periféricos como quatro portas seriais, seis canais PWM e um poderoso ADC de 12-bit. O pino de programação nativa também foi modificado, o ICSP 6-pin foi trocado por um header MiniJTAG de 10 pinos. O objetivo é permitir que desenvolvedores de compilar seu próprio firmware usando o GCC e depurar código gerenciado e nativo ao mesmo tempo (muito bom mesmo que ainda não tenha feito nenhuma experiência a respeito).

    Em todos os casos é um hadware muito mais poderoso o que vai resolver muitos problemas que temos hoje em especial com relação as latências na comunicação pela internet (atualização de página) e aos problemas de falta de memória.

    Fato é que isso é uma resposta a nossa pequenina Raspberry PI que chegou no mercado para acabar com qualquer outra plataforma. Em especial para nós brasileiros que temos infinitos problemas de importação a Farnell trouxe a  Raspberry PI por simbólicos R$ 170,00 enquanto o Nteduino Plus custa por ai mas de R$ 200,00 e não tem nem um 15% do desempenho.

    Eu vou continuar investindo no Netduino como uma alternativa (até porque eu tenho algumas placas aqui ainda) e porque a facilidade de programação é grande.

    A facilidade é tão grande que esses dias achei umPost sobre ela num blog sobre AutoCAD .NET (assunto do meu outro blog). KEAN WALMSLEY, especialista em .NET para AutoCAD postou em fevereiro deste ano um artigo sobre o Netduino Plus 2 (veja aqui) o que me deixou realmente surpreso porque ele não é dessa área.

    Por fim, vamos continuar atentos no Projet ShowCase do forum do Netduino que sempre é possível ver onde podemos chegar por ali.

PS.: Vou tentar postar com mais frequência!

domingo, 25 de novembro de 2012

Hora Certa no Netduino - NIST Internet Time Service IP


Assim que comecei a fazer medições a primeira coisa que precisa era atribuir data e hora de cada medição ao salvar no cartão microSD. A boa notícia é que o .NETMF tem suporte ao formato "DateTime"  que é muito usado no .NET normal para pegar a data e hora do windows e usar na aplicação, o problema é que o serviço de hora no Netduino é iniciado quando a placa liga ou chama o serviço de hora a primeira vez, ou seja, a primeira chamada é sempre zero hora.....

Para fazer um teste inicial você pode executar um código simples:

while (true)
{
 Debug.Print("Horário Atual: " + DateTime.Now.ToString());
    Thread.Sleep(50000);
}

A saída desse código é só para o Debug e é mais ou menos assim:


Note que o horário é meio louco, agora são 17:25 de 2012. Não sei que hora é essa mas vamos lá se queremos um medidor que envie dados para a internet é conveniente que ele também tenha um ajuste de hora automático. Já pensou, toda vez que a placa desligar ter que ir até ela e corrigir a hora na "mão grande"...

A solução para o Netduino Plus é utilizar um servidor de tempo. O Time Server ou servidor de tempo (NIST) é um servidor que lê uma informação de tempo de um relógio de tempo real e distribui a informação pela internet através de um protocolo próprio chamado de Network Time Protocol (NTP), embora outros protocolos de tempo menos populares (ultrapassados) ainda estejam em uso.

O NTP é um protocolo baseado no UDP que tem uma finalidade muito especial de sincronização do relógio de um conjunto de computadores em redes de dados com latência variável. O NTP permite manter o relógio de um computador com a hora sempre certa e com grande exatidão. Originalmente idealizado por David L. Mills da Universidade do Delaware e ainda hoje mantido por si e por uma equipa de voluntários, o NTP foi utilizado pela primeira vez antes de 1985, sendo ainda hoje muito popular e um dos mais antigos protocolos da internet (veja mais detalhes na wikipédia). 

Exitem na internet uma série de servidores de tempo (NIST) na internet para capturar a hora certa e utilizar no sei código como referência, o site que eu peguei os IP's foi este: http://tf.nist.gov/tf-cgi/servers.cgi. Que são exatamente todos servidores no EUA, mas exitem outros pelo mundo a fora.


O código que eu fiz é bem simples. Trata-se de uma classe que quando inicializada atualiza o valor do tempo para a hora atual obtida através de um servidor da lista de servidores NIST da classe. O único parametro que deve ser passo para classe são os minutos de defasagem entre o valor da hora de referência em Greenwich para sua hora local, que no meu caso, Rio de Janeiro é -120 minutos ( -2 horas).

Esta é a classe:

using System.Net.Sockets;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using System.IO;
using System.Text;
using System;
using System.Net;
using Microsoft.SPOT.Net.NetworkInformation;


namespace RealTimeTest
{
           
    /// <summary>
    /// Autor: Victor Manuel
    /// Data: 11/02/2012
    /// 
    /// Descrição: Classe De serviços de sincronização de relógio
    /// para o NetduinoPlus
    /// 
    /// 
    /// Exemplo:
    /// 
    /// //Seta o IP da porta
    /// NetworkInterface.GetAllNetworkInterfaces()[0].EnableStaticIP("10.20.19.35", "255.255.255.0", "10.20.19.1");
    /// string[] dns = { "10.20.19.1", "200.222.122.133" };
    /// NetworkInterface.GetAllNetworkInterfaces()[0].EnableStaticDns(dns);
    /// System.Threading.Thread.Sleep(10000);
    /// 
    /// InternetTimeService nits = new InternetTimeService(-120);
    /// </summary>
    class InternetTimeService
    {
        private int TimeServerIndex = 0;
        private int OffSetMinutes = 0;


        /// <summary>
        /// System Synchronize Internal DateTime
        /// </summary>
        /// <param name="minutes">Time Zone Difference</param>
        public InternetTimeService(int minutes)
        {
            Debug.Print("InternetTimeService routine is running ...");
            OffSetMinutes = minutes;
            Utility.SetLocalTime(GetNetworkTime());
            Debug.GC(true);
        }

        /// <summary>
        /// NIST Internet Time Servers
        /// For server list access: http://tf.nist.gov/tf-cgi/servers.cgi
        /// </summary>
        public string[] InternetTimeServers = {"time.nist.gov", //  global address for all servers  Multiple locations 
                                               "nist1-ny.ustiming.org", //New York City, NY 
                                               "nist1.aol-va.symmetricom.com", //Reston, Virginia 
                                               "nist1-atl.ustiming.org ", //Atlanta, Georgia 
                                               "nist1-la.ustiming.org",  //Los Angeles, California 
                                               "time-nw.nist.gov", //Microsoft, Redmond, Washington 
                                               "utcnist.colorado.edu" //University of Colorado, Boulder 
                                               };
        


        /// <summary>
        /// Force to system synchronize internal DateTime
        /// </summary>
        public void ForceToUpdate()
        {
            Utility.SetLocalTime(GetNetworkTime());
            Debug.GC(true);
        }


        /// <summary>
        /// Method to query a NTP server and set the device date to the returned value
        /// </summary>
        /// <returns>Recived Server Time</returns>
        public DateTime GetNetworkTime()
        {
            while (true)
            {
                try
                {
                    Debug.Print("Conecting to:" + InternetTimeServers[TimeServerIndex].ToString());
                    IPEndPoint ep = new IPEndPoint(Dns.GetHostEntry(InternetTimeServers[TimeServerIndex].ToString()).AddressList[0], 123);

                    Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                    s.Connect(ep);

                    byte[] ntpData = new byte[48]; // RFC 2030
                    ntpData[0] = 0x1B;
                    for (int i = 1; i < 48; i++)
                        ntpData[i] = 0;

                    s.Send(ntpData);
                    s.ReceiveTimeout = 10000;
                    s.Receive(ntpData);

                    byte offsetTransmitTime = 40;
                    ulong intpart = 0;
                    ulong fractpart = 0;
                    for (int i = 0; i <= 3; i++)
                        intpart = 256 * intpart + ntpData[offsetTransmitTime + i];

                    for (int i = 4; i <= 7; i++)
                        fractpart = 256 * fractpart + ntpData[offsetTransmitTime + i];

                    ulong milliseconds = (intpart * 1000 + (fractpart * 1000) / 0x100000000L);

                    s.Close();

                    TimeSpan timeSpan = TimeSpan.FromTicks((long)milliseconds * TimeSpan.TicksPerMillisecond);

                    DateTime networkDateTime = (new DateTime(1900, 1, 1)) + timeSpan;
                    
                    Debug.Print("UTC: " + networkDateTime.ToString());

                    networkDateTime = (new DateTime(1900, 1, 1)) + timeSpan + TimeSpan.FromTicks((long)OffSetMinutes * TimeSpan.TicksPerMinute);

                    Debug.Print("LOCAL: " + networkDateTime.ToString());

                    return networkDateTime;
                }
                catch
                {
                    Debug.Print("Impossible to conect on " + InternetTimeServers[TimeServerIndex].ToString());
                    Debug.Print("try next time server..");
                    TimeServerIndex++;
                    if (TimeServerIndex == InternetTimeServers.Length)
                    {
                        Debug.Print("Impossible to access Internet Time Servers... ");
                        return DateTime.Now;
                    }

                }
            }
        }

    }
}
 
Este é o exemplo de utilização:

NetworkInterface.GetAllNetworkInterfaces()[0].EnableStaticIP("10.20.19.35", "255.255.255.0", "10.20.19.1");
string[] dns = { "10.20.19.1", "200.222.122.133" };
NetworkInterface.GetAllNetworkInterfaces()[0].EnableStaticDns(dns);
System.Threading.Thread.Sleep(10000);

InternetTimeService nits = new InternetTimeService(-120);
      
while (true)
{
    Debug.Print("Horário Atual: " + DateTime.Now.ToString());
    Thread.Sleep(50000);
}

Quando você mandar rodar aparecerá a seguinte mensagem na janela de depuração:

Espero que tenha ajudado mais com esse artigo sobre servidores NIST no Netduino.

domingo, 11 de novembro de 2012

Getting Started with the Internet of Things - Parte 2

 O Cosm é um serviço bem legal para ver suas medidas na internet. Um bom passo é ler a documentação disponível no próprio site que informa como funciona o envio de dados para a plataforma online.

O primeiro passo é criar uma conta no https://cosm.com/. O Cosm é um serviço gratuito para nós pequenos desenvolvedores assim você pode ter uma plataforma online gratuita para enviar a informação dos seus medidores a acessar de qualquer lugar.

Depois de cirada a conta você deverá fazer algumas configurações para enviar os dados. A primeira delas é criar uma chave. A chave (Key) é uma primeira camada de controle de permissão, parece que no Pachube antigo isso não existia. Deste novo modelo com chave de acesso você pode criar permissões distintas de acesso a conta no Cosm. Por exemplo, você pode ter uma chave que permite a criação de novas chaves mas só pode ser feita por um endereço de IP específico, e você pode ter outras chaves com permissões restritas apenas para envio de dados. Da mesma forma você pode ter um dispositivo cliente que mostra dados acessando o Cosm por uma chave de leitura apenas.

Para criar uma chave nova vá em Keys, logo abaixo do seu nome de login no canto superior direito. Você deve informar um Label de identificação da chave, você deve informar atmbém como ele vai atuar com os alimentadores, os privilégios da chave e se quiser outras opções avançadas como filtro de IP, numero de acessos e até data de expiração da chave. Recomendo para o primeiro teste colocar uma chave com acesso a todos os serviços, muito embora só vou usar nesse posto para alimentar dados.

A chave será um código enorme como este: woxZM8LeIHOE2-2r0XTcthj_8XqSAKxzMmoxUS8zL0I4UT0g.

Agora já temos uma chave de acesso e devemos incluir um dispositivo que vai enviar dados para o serviço, na verdade não é bem um dispositivo mas é uma espécie de "concertador" de dados que pode enviar diversas informações para o Cosm. Para isso vá em "Console", no canto superior direto logo abaixo do seu nome de login do Cosm.

A página aberta estará vazia, clique no botão azul chamado "+ Device/Feed" e aparcerá quatro opções na tela: Arduino, Current Cost, Twitter Stats e Somithing Else; Selecione "Something Else".

São quatro passos para configurar:
  1. Método de envio de dados: Os dados de alimentação podem ser enviados do dispositivo para o Cosm ou o Cosm pode tentar acessar os dados através de uma requisição. A segunda opção é muito complicada porque geralmente o Netduino vai ficar dentro de uma rede doméstica que é protegida por um firewall do roteador e da provedora de internet assim o melhor mesmo é fazer o envio dos dados da placa do Netduino Plus para o Cosm. Por isso selecione a opção "No, I will push data to Cosm";
  2. Título do Dispositivo: apenas dê um nome para o seu dispositivo que vai se conectar ao Cosm, não faz diferença para a programação;
  3. Tags: Os tag's são os identificadores dos dados que serão enviados: por exemplo: Temperatura, Humidade, Energia, Vazão etc... Coloque os separados por virgulas.
  4. A ultima opção é só para confirmar.
Assim que você confirmar a operação aparecerá um dispositivo na lista com um gráfico para cada tag de medição que você criou, isso mostra que está tudo certo, como não teve medida nenhuma estará tudo limpo. Clique sobre sobre o título do dispositivo, os dados vaõ ocupar a página toda e a URL da página será do tipo https://cosm.com/feeds/83197. Esse código final é o Feed ID (83197), guarde esse número.

Ainda se você clicar sobre o as configurações no cantor superior direito do medidor, em "Edit" você poderá ainda colocar o local onde está o medidor, adicionar novas tag's e mudar aquela configuração inicial também. Agora a parte do Cosm está pronta, vamos a programação.

Para iniciar a programação tenha em mãos a Key e o Feed ID. O Meu código está disponível aqui. Vão notar que deixei minha chave e os meus tag's, fiz isso porque quando eu estva começando não tinha nem ideia de como era a chave e o Feed ID e demorei um dia tentando entender como funcionava o sistema. De qualquer forma pode utilizá-los, eu deixo. O código é copiado de um post do Forum do Netduino com algumas modificações.

Na primeira parte eu fiz a configuração do IP estático e do DNS estático também porque o Oi Velox é um lixo tão grande que dá problema de DNS. Essa parte é a configuração da camada de rede que uma vez configura o acesso aos serviços de internet do .NETMF tornam-se disponíveis. Tem gente que configura isso pelo MFDeploy mas eu particularmente gosto de ver configurado no código.

Lembre-se de conectar o cabo de rede antes da alimentação da placa, o Netduino Plus ainda está com esse problema.

Outra coisa que merce atenção é que o NetworkInterface não está como pacote default do Netduino assim você deve ir no projeto em "References", com o botão direito clicar em "Add Reference", e adicionar o System.Http, depois adicionar a linha ao topo do seu código "using Microsoft.SPOT.Net.NetworkInformation;".

NetworkInterface.GetAllNetworkInterfaces()[0].EnableStaticIP("10.20.19.122", "255.255.255.0", "10.20.19.1");
string[] NetworkDns = { "10.20.19.1", "200.222.122.133" };
NetworkInterface.GetAllNetworkInterfaces()[0].EnableStaticDns(NetworkDns);

Uma vez conectada a interface de rede você pode iniciar o envio de dados. Para enviar os dados você deve se conectar ao serviço do Cosm através da função conect(). Essa função cria um socket que é nada mais do que uma "tomada" que designa uma usada para ligar o dispositivo (Netduino Plus) a um ponto final específico da rede designado por um endereço de rede, nesse caso a URI do Cosm: api.cosm.com.
 
A função conect() também tem um atributo de timeout, quando o tempo máximo é atingido ele retorna um socket vazio, isso é feito porque o Cosm pode estar indisponível por algum problema nas camadas de rede  ou até mesmo o serviço fora do ar e desse modo o código pode processar outra atitude como gravar no cartão microSD, por exemplo o dado lido.

static Socket Connect(string host, int timeout)
{
    // look up host's domain name, to find IP address(es)
    IPHostEntry hostEntry = Dns.GetHostEntry(host);
    // extract a returned address
    IPAddress hostAddress = hostEntry.AddressList[0];
    IPEndPoint remoteEndPoint = new IPEndPoint(hostAddress, 80);

    // connect!
    Debug.Print("connect...");
    var connection = new Socket(AddressFamily.InterNetwork,
        SocketType.Stream, ProtocolType.Tcp);
    connection.Connect(remoteEndPoint);
    connection.SetSocketOption(SocketOptionLevel.Tcp,
        SocketOptionName.NoDelay, true);
    connection.SendTimeout = timeout;
    return connection;
}

Se tudo ocorrer bem na rede de internet será possível criar um socket e barir a comunicação com o serviço do Cosm e enviar dados. O Envio de dados é feito pela função SendRequest(). esta função recebe a chave (key), o Feed ID o socket criado e a informação que será enviada no formato CSV (Comma-Separated Format), ou formato separado por virgulas onde será enviado no corpo da mensagem a informação no estilo: "tag,valor".

Toda mensagem enviada por internet tem uma URI de requisição (requestLine), um cabeçalho (header)e um conteúdo (content). a reqisição é o endereço de onde será enviada a mensagem com o método de envio que neste caso é o método "PUT" "/v2/feeds/seu feedid.csv HTTP/1.1" que se soma a URL do site e acessa o serviço específico de dados do tipo CSV utilizando o protocolo HTTP 1.1. O Header, ou cabeçalho da mensagem contem as informações necessárias ao direcionamento da mensagem para sua conta mediante a chave de acesso, o host name e o tamanho do conteúdo da mensagem. e por fim a mensagem em formato de texto csv.

static void SendRequest(Socket s, string apiKey, string feedId,
    string content)
{
    byte[] contentBuffer = Encoding.UTF8.GetBytes(content);
    const string CRLF = "\r\n";
    var requestLine =
        "PUT /v2/feeds/" + feedId + ".csv HTTP/1.1" + CRLF;
    byte[] requestLineBuffer = Encoding.UTF8.GetBytes(requestLine);
    var headers =
        "Host: api.cosm.com" + CRLF +
        "X-ApiKey: " + apiKey + CRLF +
        "Content-Type: text/csv" + CRLF +
        "Content-Length: " + contentBuffer.Length + CRLF +
        CRLF;
    byte[] headersBuffer = Encoding.UTF8.GetBytes(headers);
    s.Send(requestLineBuffer);
    s.Send(headersBuffer);
    s.Send(contentBuffer);
}

O serviço do Cosm também permite outros formatos como JASON e XML mas você pode implementar depois pois muda apenas a sintaxe da mensagem.

Depois de ter tudo construído em texto basta enviá-los através do socket que foi aberto. E o código funciona assim em Loop Infinito e manda um dado a cada 20 segundos, aproximadamente. No meu código eu pego um valor aleatório e envio para o servidor do Cosm.

public static void Main()
{
    NetworkInterface.GetAllNetworkInterfaces()[0].EnableStaticIP("10.20.19.122", "255.255.255.0", "10.20.19.1");
    string[] NetworkDns = { "10.20.19.1", "200.222.122.133" };
    NetworkInterface.GetAllNetworkInterfaces()[0].EnableStaticDns(NetworkDns);

    const string apiKey = "woxZM8LeIHOE2-2r0XTctHb_8XqSAKxzMmoxUS8zL0I4UT0g";
    const string feedId = "83197";
    Socket connection = null;
    while (true)   // main loop
    {
        Debug.Print("time: " + DateTime.Now);
        Debug.Print("memory available: " + Debug.GC(true));

        if (connection == null)   // create connection
        {
            try
            {
                connection = Connect("api.cosm.com",1000 );
            }
            catch
            {
                Debug.Print("connection error");
            }
        }

        if (connection != null)
        {
            try
            {
                Random rnd = new Random();
                double value = rnd.NextDouble();
                string sample = "voltage," + value.ToString("f");
                Debug.Print("new sample: " + sample);
                SendRequest(connection, apiKey, feedId, sample);
                sample = "number," + (rnd.NextDouble()).ToString("f");
                SendRequest(connection, apiKey, feedId, sample);
            }
            catch (SocketException)
            {
                connection.Close();
                connection = null;
            }
        }
System.Threading.Thread.Sleep(20000);
    }
}
Espero que tenha sido útil todas essas informações para quem pretende acessar o serviço do Cosm e mandar dados pela internet. Aproveito para dizer que gostaria que vocês comentassem os post's para que eu continue melhorando e colocando o assunto que for mais pertinente.


Se você quiser ver meus gráficos pode acessá-los através do site do Cosm

Para baixar o arquivo pronto do projeto com as funções clique aqui.

sexta-feira, 19 de outubro de 2012

Getting Started with the Internet of Things - Parte 1

    Muito embora eu tenha á publicado artigos relacionas aplicações do Netduino Plus envolvendo rede de internet uma das maiores referências nessa parte é o livro do Cuno Pfister - Getting Started with the Internet of Things. O livro trata do Netduino Plus e aplicações para internet de um jeito fácil e rápido. 
    Nesta série de artigos pretendo explorar o livro e mostrar um pouco do que o livro fala ampliando a discussão para aplicações em automação doméstica e monitoramento/medição. Para quem quiser comprar o Livro: O'REILLY  Amazon.com. Um apêndice disponibilizado pelo Chris Walker no site do Netduino: AQUI.

       O livro começa mesmo no capítulo II: Dispositivos funcionando como clientes HTTP. Trata-se de um capítulo inteiramente baseado  no "Pachube", um serviço na nuvem especialmente dedicado ao armazenamento de informações provenientes de dispositivos pendurados na rede em fase de desenvolvimento. Certamente você não encontrará mais esse nome pela rede, na verdade o serviço agora se chama Cosm, o livro é de 2011, ou seja, está velho...

      O .NET MF disponibiliza duas implementações para aplicações HTTP: (i) uma em alto nível para tratar requisições no espaço System.Net e (ii) outra em baixo nível para envio de Socket no espaço System.

Alguns conceitos

     Antes de iniciar propriamente no dito cujo, vale a oportunidade de revisar alguns conceitos sobre internet e protocolos. O livro começa nessa parte de uma maneira bem emblemática jogando as informações mínimas relevantes.
     Assim como ocorreu na comunicação serial diversos protocolos começaram a ganhar corpo com o advento da internet, iniciando-se no uso militar da década de 70 e 80 os protocolos passaram por uma longa evolução até a chegada de um "modelo ideal" que permitisse de modo bastante universal enviar quase todo o tipo de informação por ele: o protocolo TCP/IP.

   O TCP/IP é, na verdade, não apenas um protocolo mas sim um conjunto de protocolos de comunicação entre dispositivos em rede chamado muitas vezes de "pilha TCP/IP". TCP quer dizer Transmission Control Protocol, Protocolo de Controlo de Transmissão, e IP significa Internet Protocol,  Protocolo de Interconexão. Pode-se dizer que trata-se de camadas de tratamento de transporte de informação em alto nível (complicado!!???), onde cada camada é responsável por um grupo de tarefas, fornecendo um conjunto de serviços bem definidos para o protocolo da camada superior. As camadas mais altas estão logicamente mais perto do usuário (chamada camada de aplicação) e lidam com dados mais abstratos, confiando em protocolos de camadas mais baixas para tarefas de menor nível de abstração.


     O modelo OSI (modelo de topologia da internet) é um grupo de sete camadas que foi tomado como base para a criação do TCP/IP. O TCP/IP é convencionalmente dividido em 4 níveis básicos: Host/rede; Inter-rede; Transporte; e Aplicação, muito embora exista na internet o modo "novo" com 5 camadas, que retira o excesso do modelo OSI e melhora o modelo TCP/IP: Física; Enlace; Rede; Transporte; e Aplicação.

      Para não delongar muito a explicação sobre isso pode-se dizer que trata-se de uma solução prática para problemas de transmissão generalizada de dados.


      Há de se convir que as camadas mais "altas", como mostra o diagrama, são mais inteligíveis por parte de nós usuários, enquanto aquelas mais abaixo estão logicamente mais perto da transmissão física do dado (os bits's efetivamente transmitidos). Podemos entender isso como uma programação em camadas: cada camada serve de funções a camada mais acima.

      O que queremos de fato é uma abstração dos detalhes de transmissão bits através da ethernet. Por exemplo, quando o Firefox envia a página não a necessidade de se preocupar com a detecção de colisão de bits, a camada Física se preocupa com isso evitando assim ter de conhecer os detalhes de todas as aplicações e seus protocolos.

Essa topologia permite que camadas de cima forneçam serviços que as camadas de baixo não podem fornecer como exemplo temos o IP que é projetado para não ser confiável. Isso significa que toda a camada de transporte deve indicar se irá ou não fornecer confiabilidade e em qual nível.

O TCP (Transmission Control Protocol - Protocolo de Controle de Transmissão), é um protocolo orientado a conexões confiável que permite a entrega sem erros de um fluxo de bytes.

O UDP fornece integridade de dados (via um checksum) mas não fornece entrega garantida; já o TCP fornece tanto integridade dos dados quanto garantia de entrega (retransmitindo até que o destinatário receba o pacote).


Vamos agora fazer um breve apanhado das camadas de rede:

(i) Camada de aplicação:
        Trata-se da camada utilizada por 99% dos programas de rede para comunicação através de uma rede com outros programas. Códigos desenvolvidos nessa camada tendem a ser mais simples sendo que os dados são tratados no programa já obedecendo o formato da aplicação que quando necessários são codificados dentro do padrão de um protocolo.
        Serviços que suportam diretamente aplicações do usuário são tratados nessa camada são eles o HTTP (navegação na World Wide Web), FTP (transporte de arquivos), SMTP (envio de email), SSH (login remoto seguro), DNS (pesquisas nome <-> IP) e muitos outros.

     
(ii) Camada de Transporte

        Esta camada é responsável por resolver problemas como confiabilidade, integridade e a direção que o dado deve ser transmisito/recebido. O roteamento de dados está nessa camada também muito embora considerado parte da camada de rede.
     
(iii) Camada de Enlace
        A camada da pele enlace é parte do modelo TCP/IP  liga a ancoragem da aplicação/transporte com o hardware que fará a transmissão da informação. Podendo ser controlado tanto em software (device driver) para a placa de rede quanto em firmware. Responsável por atribuir aos dados um cabeçalho preparando os dados para transmissão. Da mesma forma, a camada de enlace recebe os dados, retira os header's adicionados e encaminhar os pacotes recebidos para a camada de rede.
        Veremos mais sobre essa camada quando implementamos dispositivos externos para comunicação como o mIP faz no Netduino que empacota as mensagens para o ENC28J60 e outros "drivers"  para a wifly shield.

(iv) Camada Física


        A camada física do Protocolo TCP/IP trata das características elétricas e mecânicas do meio, como tipos de conectores e cabos utilizado para estabelecer uma comunicação.

Com essa breve introdução já é possível continuar a entender o que está no .NET MF para aplicações pela internet.

Devaneando Aplicações

     Eu gosto sempre de firmar uma proposição inicial como objetivo de algum estudo, no nosso caso o livro já faz uma referência ao objetivo: enviar dados de temperatura de um sensor montado no Netduino Plus por internet.
     Como eu já vinha dizendo existem muitos protocolos por Ethernet naturalmente o livro trata apenas do TCP/IP - o que se alega em favor é a modularidade - como existem muitos dispositivos adaptados a esse tipo de protocolo torna-se mais abrangente uma solução em TCP/IP via HTTP por exemplo.
     O protocolo mais usado usando TCP/IP é o HTTP ( Hypertext Transfer Protocol ). Através do HTTP é possível enviar mensagens e receber pacotes em qualquer computador ou dispositivo conectado na rede, o que é uma vantagem, assim, focaremos nele.