sábado, 23 de junho de 2012

Algumas considerações sobre consumo de energia

Hoje tem-se falado muito a respeito do desperdício eletrônico, a alguns anos atrás lembro-me de ter lido uma série de artigos sobre o tema na revista ELEKTOR sobre esse tema e agora usando o Netduino percebo cada vez mais que existe uma necessidade real de se analisar o consumo dos dispositivos.

Muito embora o Netduino Plus tenha o formado do Arduino, ele traz muitas vantagens em relação a plataforma antiga: em termos de hardware tem-se o cardão microSD na placa para armazenamento, foco dos últimos post's, e a comunicação por internet também na própria placa. Em termos de software também exite uma evolução enorme uma vez que o Netduino usa linguagem orientada a objeto e a plataforma Visual Studio  através do .NET Microframework. As vantagens de migrar as soluções embarcadas para a orientação a objeto tornam a programação mais rápida e limpa. Lembro-me das dificuldades que tinha quando tentava, como o dsPIC33F, executar múltiplas tarefas como escrita na EPROM externa, comunicação Serial e o controle propriamente dito etc.

Mas não só de coisas boas o Netduino é feito. Alguns tropeços no desenvolvimento do hardware deixam a placa para trás em termos de desempenho - poucas portas IO disponíveis são um tremendo limite quando se deseja construir aplicações específicas. Além disso, o chip da DAVICOM permite o chamado PoE  (Power over Ethernet) mas, lamentavelmente, essa funcionalidade não está implementada. 


O Netduino deve ser compreendido como uma nova linha em termos do desenvolvimento de dispositivos embarcados - um plataforma sem sistema operacional que permite o gerenciamento multitarefa do processador e um desenvolvimento de código rápido. Essa característica do Netduino torna-o ideal para desenvolvimento rápido de protótipos e até mesmo participação em projetos específicos em soluções personalizadas.


Aqui nesse post trago uma abordagem do Netduino Plus quanto ao consumo de energia. Os testes realizados são relativamente simples e analise dos resultados idem.


Sabe-se que o Netduino utiliza reguladores lineares para ajusto nível de tensão fornecido e demandado pelos periféricos. Nesse ponto será feita algumas considerações (aproximações), a primeira delas é considerar todos os elementos como grande consumo sendo alimentados pelo 3.3V para as estimativas de potência consumida efetiva, mas a diante esse conceito ficará mais claro. Feito isso foi feito três testes com códigos diferentes a fim de avaliar o consumo de energia da placa, o resultado está sendo apresentado na tabela abaixo:


Sem processamento (sleep infinito pelo código)
Processando contas simples continuamente (adição, subtração, divisão e multiplicação)
Processando da escrita no  Cartão SD
45 mA
55,4 mA
65,5 mA

Deveria ter realizado mais testes, mas para esse momento já está razoável. Note que o Netduino Plus sem executar nenhum código consome 45mA, isso significa que alimentando através de uma Bateria Alcalina Duracell AAAA 9V 320mAh, seria possível manter a placa ligada por pouco mais de 7h e lendo e escrevendo no cartão SD esse tempo seria reduzido para 4,9 horas. A pergunta que pode ser feita agora é o que isso significa de fato. 

Uma durabilidade de 5horas suprida por uma bateria é muito baixa tendo em vista que não foi utilizado nenhum dispositivo de acionamento (ou medição), até mesmo para um simples dispositivo de medição necessitaria de uma autonomia de dias. Veja por exemplo, o caso do medidor de nível de caixa d'água uma boa autonomia seria de 6 meses ou mais! Dito isso porque ninguém gostaria de ter o desconforto de se lembrar que o dispositivo que monitora o nível da caixa d'água foi desligado por falta de energia e parou de armazenar os dados.

Esse consumo, podemos dizer até exagerado deve-se em especial a camada de código do bootloader do Netduino que por si só consome boa parte da memória e da energia da placa. 

Vale lembrar ainda do tempo de inicialização do bootloader ser elevado quando comparado as soluções escritas em C no Arduino/PIC e afins que demoram não mais de um segundo para inciar o código. Netduino Chega a demorar um minuto para iniciar suas atividades.

O custo do regulador linear
 
Pode-se analisar ainda  o caso do consumo dos reguladores lineares. Nesse ponto cabe uma análise do ponto de vista da energia. Aproximando o consumo para 3,3V e 65mA temos uma potência efetivamente consumida de 0,214 W - Considerando uma aplicação com bateria de 9V - temos um consumo efetivo da placa de 0,585 W. A diferença é a energia dissipado no regulador linear que ajusta a tensão para os 3,3V. 

Duas conclusões podem ser tomadas:
1ª - Usando uma alimentação de 9V, 63,3% da energia é desperdiçada nos reguladores lineares da placa. Como uma
Bateria Alcalina Duracell AAAA 9V 320mAh custa em média R$15,00. R$10,00 são jogados fora nos reguladores, um pecado...


2º - Usar 4 pilhas em série terá o mesmo efeito em durabilidade uma vez que a placa usa reguladores lineares. Utilizando a Duracell Plus Power de 2500 mAh custa R$12,00 (4 pilhas) e terá um rendimento efetivo de 45% e uma durabilidade de 8,12 horas.


Muito deve-se analisar para chegar em uma solução ideal em termos de custo benefício na construção desse tipo de solução embarcada. No caso do registrado de nível para caixa d'água 8,12 horas ainda parece algo bem distante da realidade (mesmo usando a pilha tipo D "bujão" 108horas - 3,6 meses).

Tenho um amigo que vai utilizar uma placa dessas que sobe linux para uma aplicação com reconhecimento de imagem para controlar um carrinho automaticamente. Pelo que me foi relatado a placa consome 2A quando está processando e adicionando os motores e acessórios o conjunto terá um consumo violento de energia; como me comprometi a fazer o carrinho antes de construí-lo farei a análise de energia vs. autonomia para dimensionar um tamanho da bateria que o carrinho irá utilizar, esse post foi apenas uma análise prévia para o que está por vir.



Mais a frente, em um outro post farei uma análise mais completa do consumo do Netduino Plus utilizando o osciloscópio para ter uma ideia mais ampla dos picos de consumo de energia. Farei também com outros periféricos conectados as portas IO porque isso muda um pouco a dinâmica da placa. espero que tenha sido esclarecedor o post quando a questão do consumo do Netduino Plus.

segunda-feira, 18 de junho de 2012

Escrevedo no Cartão SD - Parte 2

No primeiro artigo sobre a escrita no cartão SD foi visto um código básico para escrever no cartão SD na forma de arquivo sem preocupações adicionais com a segurança da escrita, que para uma solução mais robusta, é necessária. Por trata-se de um elemento móvel e intercambiável, o cartão SD pode ser removido indiscriminadamente, muito embora os leitores desse bolg jamais tenham feito isso, espero. Além disso, o cartão pode ser danificado.

Em todos os casos faz-se necessária uma validação de o cartão SD está realmente inserido no soquete. Pesquisando nas decentralizadas informações do site do Netduino consegui encontrar na wiki um artigo sobre isso: http://wiki.netduino.com/Detecting-the-presence-of-an-SD-Card.ashx


_________________________________________________________________________________________________using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.IO;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.NetduinoPlus;

namespace SD_Card_Example_2
{
    public class Program
    {
        //Inicialização do código
       public static void Main()
        {
            //Inicializa o Led e o Botão da placa
            InputPort bord_button = new InputPort(Pins.ONBOARD_SW1, false,
                                        Port.ResistorMode.Disabled);
            //Cria a Data Atual
            DateTime CurrentDate = new DateTime(2012, 06, 17, 14, 08, 00);
            Int32 InterruptTime = 10000;

            //Criando o Evento periódico de tempo que chama a função LightCheckProcessEvents
            //para escrever no cartão a condição de luz e o tempo
            AutoResetEvent autoEvent = new AutoResetEvent(false);
            LightCheck LightCheckObject = new LightCheck(CurrentDate, InterruptTime);
            TimerCallback LightCheckCallBack = LightCheckObject.LightCheckProcessEvents;
            Timer LightCheckTimer = new System.Threading.Timer(LightCheckCallBack, autoEvent, InterruptTime, InterruptTime);

           //Inifinito!
           Thread.Sleep(Timeout.Infinite);
       }
    }

    public class LightCheck
    {
       
        private static System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
           
        //Cria o pino de interrução
        private static InterruptPort sdCardStatusPort = new InterruptPort((Cpu.Pin)57, false,
                                                                    Port.ResistorMode.PullUp,
                                                                    Port.InterruptMode.InterruptEdgeBoth);

        // Global
        Boolean SDCardIsOk = true;
        DateTime InternalDate;
        Int32 InternalInterruptTime;
        OutputPort bord_led = new OutputPort(Pins.ONBOARD_LED, false);
        InputPort bord_ldr = new InputPort(Pins.GPIO_PIN_D0, false, Port.ResistorMode.Disabled);

        ///


        /// Contrutor, passa a data corrente paa inicio dos registros
        ///

        /// Data Atual
        /// Tempo da Interrupção em milisegundos
        public LightCheck(DateTime date, Int32 InterruptTime)
        {
            InternalDate = date;
            InternalInterruptTime = InterruptTime;
               
            //Cria o chamado do pino de interrupção quando o Cartão SD é movido
            sdCardStatusPort.OnInterrupt += sdCardStatusPort_OnInterrupt;
        }

        ///


        /// Processa os eventos basenados na interrupção periódica
        ///

        /// Objeto que Chama
        public void LightCheckProcessEvents(object o)
        {
            //quando chama aumenta o tempo
            InternalDate = InternalDate.AddMilliseconds((double)InternalInterruptTime);

            //Se o cartão Sd está acessível então:
            if (sdCardStatusPort.Read() == false)
            {
                //Acessa o Cartão SD e cria/acessa (cria se não existir ainda) um arquivo
                //chamdo "fileTest.txt" onde os dados serão salvos
                FileStream log_file = new FileStream(@"\SD\light.txt", FileMode.Append);

                //Cria uma mensagem de teste que será escrita toda a vez que o botão for
                //precionado na placa do netduino
                string msg = InternalDate.ToString("G") + "\t" + bord_ldr.Read().ToString() + "\n";

                //Escreve o dado no arquivo
                log_file.Write(encoding.GetBytes(msg), 0, msg.Length);

                //Fecha o acesso ao cartão
                log_file.Flush();
                log_file.Close();
                log_file.Dispose();

                //Pisca o Led 10x para comprovar que o o dado foi escrito mesmo.
                Int16 i = 0;
                bord_led.Write(false);
                for (i = 0; i < 10; i++)
                {
                    bord_led.Write(!bord_led.Read());
                    Thread.Sleep(100);
                }
            }

        }

        ///


        /// Interrupção de Remoção do Cartão SD
        ///

        /// ?
        /// ?
        /// Momento em que o cartão foi removido
        public void sdCardStatusPort_OnInterrupt(uint data1, uint data2, DateTime time)
        {

            //Se o cartão foi removido
            if (sdCardStatusPort.Read() == true)
            {
                SDCardIsOk = false;
                //Pisca o Led Infinitamente enquanto o cartão estiver fora da placa
                while (sdCardStatusPort.Read() == true)
                {
                    bord_led.Write(!bord_led.Read());
                    Thread.Sleep(200);
                }


            }
            else
            {
                SDCardIsOk= true;
            }

            bord_led.Write(false);
        }
    }
}
_________________________________________________________________________________________________

Esse código ainda não possuí todos os melhoramentos que se deve, mas já é um inicio, em relação ao código final da primeira parte desse artigo sobre escrita no cartão SD; esse software faz o LED da placa piscar continuamente se o cartão SD for removido ajudando a identificar o problema, não fiz a opção por continuar a salvar os dados, tão somente deixei de aquistá-los.

domingo, 17 de junho de 2012

Escrevedo no Cartão SD - Parte 1


No trabalho temos alguns registradores de qualidade de energia, são medidores bem avançados capazes de medir até o 31º harmônico além de medir a tensão, corrente, potência etc.. O único problema são os ridículos 2 MB de memória disponível para armazenar os dados das leituras efetuadas o que nos leva a um triste exercício de reflexão sobre quantas amostras temos que tomar para otimizar os 2MB de memória.

Pois bem, mês passado coloquei o medidor em um cliente para 7 dias de medição. Infelizmente cometi um erro confundindo-me 10 minutos com 10 segundos e com isso perdi uma semana de medição porque a memória do medidor acabou e só pude colher dados durante as 12horas inicias.
Esse episódio me fez pensar em como são engessadas essas tecnologias nacionais em termos de armazenamento e esse medidor custou o preço simbólico de R$ 5.700,00. Bom, lamentos a parte vamos ao que interessa de fato - o armazenamento no cartão SD do Netduino Plus.

Armazenar dados é uma coisa importante para qualquer aplicação que se tenha em vista, em especial quando se deseja monitorar alguma coisa. Meu foco aqui será ater-se a escrita no cartão SD por isso, pretendo implementar um projeto simples: monitorar um sensor de luz do sol  se está escuro ou claro aberta ou fechada. Muito embora seja simples apresentarei com isso um evento de escrita no cartão SD acionado por um sensor externo, o que é bem interessante.

Vamos então ao primeiro passo da brincadeira, atualizar o Netduino Plus. Eu atualizei o meu para o 4.2 RC5 que tem uma classe chama "StorageDevice.MountSD" que não tinha no 4.1, por isso tenha certeza que está rodando o .NET Micro Framework4.2.

Eu fiz um código exemplo, que a pesar de simplificado, ajuda a entender algumas coisas sobre o cartão SD. Lembre-se que você deve adicionar nas referências do projeto SecretLabs.NETMF.IO . Feito isso o restante é copiar o código.
__________________________________________________________________________________________
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.IO;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.NetduinoPlus;

namespace SD_Card_Example_01
{
    public class Program
    {
        //Isso é para codificação UTF8, não sei como funciona ao certo.
        private static System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
        public static void Main()
        {
            //Inicializa o Led e o Botão da placa
            OutputPort bord_led = new OutputPort(Pins.ONBOARD_LED, false);
            InputPort bord_button = new InputPort(Pins.ONBOARD_SW1, false, Port.ResistorMode.Disabled);
           

            while (true)
            {
                //Sempre que o botão for precionado faça:
                if (bord_button.Read())
                {
                    //Acessa o Cartão SD e cria/acessa (cria se não existir ainda)                            // um arquivo
                    //chamdo "fileTest.txt" onde os dados serão salvos
                    FileStream log_file = new FileStream(@"\SD\fileTest.txt",
                                                                     FileMode.Append);

                    //Cria uma mensagem de teste que será escrita toda a vez
                    //precionado na placa do netduino
                    string msg = "Isso é um teste do cartão SD! ";

                    //Escreve o dado no arquivo
                    log_file.Write(encoding.GetBytes(msg), 0, msg.Length);

                    //Fecha o acesso ao cartão
                    log_file.Flush();
                    log_file.Close();
                    log_file.Dispose();

                    //Pisca o Led 10x para comprovar que o o dado foi escrito mesmo.
                    Int16 i = 0;
                    for (i = 0; i < 10; i++)
                    {
                        bord_led.Write(!bord_led.Read());
                        Thread.Sleep(100);
                    }

                    //Dorme um pouco só por garantia
                    Thread.Sleep(100);
                }
            }
            Thread.Sleep(Timeout.Infinite);
        }
__________________________________________________________________________________________

 Este é um código simplificado que eu reuni através do post's no fórum do Netduino. Debugando o código algumas centenas de vezes é possível ver o Led piscando cada vez que o botão da placa é pressionado.

Desligando a placa do Netduino e conectando o cartão SD no computador , pode-se abrir o arquivo com o bloco de notas e verá o resultado, as mensagens escritas em sequência.


 Nesse primeiro exemplo não me preocupei muito com tabulação e a forma com que os dados serão interpretados depois, o importante é constatar quão simples foi o código e o universo de possibilidades que o cartão pode trazer. Em um primeiro momento a escrita sequencial dos dados, com um tempo de amostragem fixo pode ser um primeiro passo para a aquisição de dados. Além dessa função é possível, também, ler um arquivo simples de configuração tal como os tradicionais *.ini do Windows que utilizam a sintaxe "variável=valor;". Muitas outras formas de usar o cartão SD podem ser elaboradas e utilizadas na prática como salvar uma página de HTML e usar o Netduino Plus como Host de página.


Aqui vale uma breve explicação quanto aos Cartões SD de grande capacidade e o chinas (cartões fake). Comprei um cartão de 2Gb  da Kingston por R$5,00 aqui no rio meses atrás para usar no Netduino, como na época estava focado em outros projetos um amigo meu iniciou os testes e constatou que o cartão não era reconhecido pela placa do Netduino Plus. Logo depois de alguns post trocados no forum do Netduino verificou-se que o cartão era um Kingston falso e não tinha comunicação SPI.  Os cartões SD possuem três padrões de comunicação SDIO1, SDIO3, e SPI - a SPI não é obrigatória nos cartões SD de grande capacidade (acima de 1Gb) assim muito cartões SD não tem essa comunicação por isso é importante ter atenção na hora de comprar o cartão SD compatível com o Netduino,a além da limitação de capacidade de 2Gb ainda tem a limitação da comunicação.

Teste com os cartões originais da Sony e SanDisk e da Kingston de 2Gb e tudo saiu bem.

Mudando o foco um pouco para a aplicação, o sensor de luz do tipo LDR (Light Dependent Resistors) tem uma resistência de 60,0 kΩ - Sem Luz e 1,0 kΩ - Com Luz do Dia  uma faixa bem ampla. Alimentando o sensor diretamente com 3,0V com um resistor de aterramento de  5k tem-se uma tensão de de 2,50V quando o LDR for excitado com luz e 0,23V no inverso (sem luz incidindo) o que é razoável analisando pelo datasheet esses níveis lógicos alto e baixo.


A foto mostra o LDR montado para o teste junto com Netduino Plus. O teste foi bem simples e código ficou um pouco mais elaborado para controlar o tempo através de uma interrupção periódica, fiz isso para deixar essa medição independente de outras tarefas que futuramente pretendo implementar. De modo geral o código e bem simples de entender - uma classe separada foi criada para manipular a checagem da luz (LightCheck) essa classe tem as variáveis internas: o tempo de interrupção e a data atual, ambas passadas do código principal através do construtor. Uma vez construída e  atribuido o evento ao LightCheckProcessEvents a função é executada independentemente.

__________________________________________________________________________________________ namespace SD_Card_Example_01
{
    public class Program
    {
        //Inicialização do código
        public static void Main()
        {
            //Inicializa o Led e o Botão da placa
            InputPort bord_button = new InputPort(Pins.ONBOARD_SW1, false,
                                     Port.ResistorMode.Disabled);
            //Cria a Data Atual
            DateTime CurrentDate = new DateTime(2012, 06, 17, 12, 02, 00);
            Int16  InterruptTime = 1000;

            //Criando o Evento periódico de tempo que chama a função LightCheckProcessEvents
            //para escrever no cartão a condição de luz e o tempo
            AutoResetEvent autoEvent = new AutoResetEvent(false);
            LightCheck LightCheckObject = new LightCheck(CurrentDate, InterruptTime);
            TimerCallback LightCheckCallBack= LightCheckObject.LightCheckProcessEvents;
            Timer LightCheckTimer = new System.Threading.Timer(LightCheckCallBack, autoEvent, InterruptTime, InterruptTime);

            Thread.Sleep(Timeout.Infinite);
        }
    }

    public class LightCheck
    {
        private static System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();

        // Global
        DateTime InternalDate;
        Int16 InternalInterruptTime;
        OutputPort bord_led = new OutputPort(Pins.ONBOARD_LED, false);
        InputPort  bord_ldr = new InputPort(Pins.GPIO_PIN_D0, false, Port.ResistorMode.Disabled);

        ///

        /// Contrutor, passa a data corrente paa inicio dos registros
        ///

        /// Data Atual
        /// Tempo da Interrupção em milisegundos
        public LightCheck(DateTime date, Int16 InterruptTime)
        {
            InternalDate = date;
            InternalInterruptTime = InterruptTime;
        }

        ///

        /// Processa os eventos basenados na interrupção periódica
        ///

        /// Objeto que Chama
        public void LightCheckProcessEvents( object o )
        {
            //quando chama aumenta o tempo
            InternalDate.AddMilliseconds(InternalInterruptTime);

            //Acessa o Cartão SD e cria/acessa (cria se não existir ainda) um arquivo
            //chamdo "fileTest.txt" onde os dados serão salvos
            FileStream log_file = new FileStream(@"\SD\light.txt", FileMode.Append);

            //Cria uma mensagem de teste que será escrita toda a vez que o botão for
            //precionado na placa do netduino
            string msg = InternalDate.ToString("G") + "\t" +
                                   bord_ldr.Read().ToString() + "\n";

            //Escreve o dado no arquivo
            log_file.Write(encoding.GetBytes(msg), 0, msg.Length);

            //Fecha o acesso ao cartão
            log_file.Flush();
            log_file.Close();
            log_file.Dispose();

            //Pisca o Led 10x para comprovar que o o dado foi escrito mesmo.
            Int16 i = 0;
            for(i = 0; i < 10; i++)
            {
                bord_led.Write(!bord_led.Read());
                Thread.Sleep(100);
            }
        }
    }
} __________________________________________________________________________________________

O resultado disso é uma execução continuada e periódica do código, onde a data é incrementada e a mensagem é escrita dizendo se o ambiente estava iluminado ou não. Nesse código o tempo de interrupção é de 10 segundos, baixo devido ao teste, acredito que a cada 60s seja uma amostragem boa.
 

A conclusão desse tópico é que podemo escrever no Cartão SD com muita facilidade utilizando o Netduino Plus o que faz dele uma plataforma muito mais poderosa e rápida de se programar se comparado com os tradicionais Arduíno e outras famílias de placas de desenvolvimento. No próximo tópico será discutida leitura do cartão SD onde será possível ler a data de partida do cartão SD.