quarta-feira, 15 de abril de 2015

Tutorial comunicação serial, node.js e gráficos em tempo real via socket.

Com o surgimento do Arduino, foi possível ampliar as aplicações de eletrônica e robótica em geral com a rápida adesão e criação de bibliotecas e módulos específicos e fáceis de manusear. Tratando-se de software, o Node.js tornou-se muito popular com o surgimento de milhares de pacotes e a possibilidade de estabelecer conexões com várias linguagens, tipos de bancos de dados e inúmeras tecnologias. Dentre elas, a comunicação serial, padrão usado na maioria dos projetos de sistemas microcontrolados.
Estabelecendo a conexão via serial de seu sistema embarcado com o Node.js torna possível expandir a sua aplicação uma vez que o node implementa um servidor web. Você pode facilmente utilizar as milhares de APIs web disponíveis além de hospedar seu sistema em um servidor e fornecer acesso por smartphones, tablets e demais dispositivos que se conectam à rede mundial de computadores.
Esse tutorial tem como objetivo explicar como estabelecer a comunicação serial entre seu sistema microcontrolado (não necessariamente Arduino, mas qualquer um que implemente comunicação serial) e o Node.js, além de utilizar uma biblioteca em JavaScript para plotar gráficos em tempo real utilizando uma página web.

Primeiro passo, é preciso instalar o Node.js em sua máquina, basta acessar o site https://nodejs.org/download/ e seguir para a seção de downloads. 
A instalação segue um fluxo tranquilo em Windows e Mac. No Windows, você precisa adicionar o caminho do executável do node para a variável de ambiente do sistema PATH para poder executá-lo do terminal do Windows. Isso pode ser feito em painel de controle, configurações avançadas.

Se está usando ambiente GNU/Linux, basta baixar o arquivo compactado com o código-fonte, extrair os dados para uma pasta qualquer, em seguida, acesse a pasta e digite os comandos:

./configure 
make
#make install 

Se você encontrou algum erro nessa parte, certifique-se de ter instalado o pacote build-essential que contém os compiladores necessários para gerar o executável do node. O comando make pode demorar mais de 5 minutos porque ele está compilando o sistema e isso demora mesmo. Lembre-se que o terceiro comando deve ser feito com privilégios de administrador (sudo), uma vez que ele copia o arquivo para a pasta bin do sistema.

Pronto, node.js já está instalado em sua máquina. Junto com ele, existe o npm (node package manager) que é o gerenciador de pacotes do node. A partir do qual é possível instalar pacotes para as mais variadas aplicações (acesse esse link para conferir do que estou falando: https://www.npmjs.com/).

Vamos inicialmente criar um diretório para organizar nosso app (geralmente os projetos em node são chamados de app - aplicação). Abre um terminal e navegue até o diretório. Feito isso, digite o seguinte comando:

npm install express

Esse é o primeiro pacote que vamos instalar. Verifique que após a instalação, um subdiretório foi criado: node_modules. Todos os módulos que você instalar ficarão localizados dentro dessa pasta. A menos que use a opção -g em que o módulo é instalado globalmente no diretório do node no seu sistema (opção usada quando vamos instalar o socket.io - algumas vezes ele dá problema e exige que seja instalado globalmente).

http://expressjs.com/ esse pacote é interessante porque ele é um framework que encapsula muitas funções do node para você e permite um desenvolvimento mais fluido para seu app. Para maiores informações, acesse a página dele.

Agora digite o seguinte comando:

npm install serialport

Esse módulo é o responsável em estabelecer a comunicação serial com o node. Maiores detalhes aqui: https://www.npmjs.com/package/serialport .

Por fim:

npm install socket.io

Já que temos nossos pacotes básicos, vamos criar um arquivo chamado server.js dentro do nosso diretório de trabalho. Esse é o arquivo principal de nossa aplicação. Vamos iniciar a codificação. Primeiro requisite os seguintes arquivos (semelhante ao include do C e require do PHP):

var app      = require('express')();
var express = require('express');

Essas variáveis irão armazenar objetos que utilizaremos mais adiante. Em seguida vamos utilizar um diretório para servir arquivos públicos como arquivos .css e .js.

app.use(express.static(__dirname + '/public'));

Definimos executando o método use do app que instanciamos mais adiante. Eu separei o arquivo express para justamente poder utilizar a chamada express.static acima. Agora crie também um diretório chamado public na pasta do projeto. Iremos adicionar alguns arquivos mais na frente no tutorial.

O próximo passo é criar o nosso servidor http e instanciar o socket.

var http = require('http').Server(app);
var io = require('socket.io')(http);

Feito isso, temos o nosso servidor e o socket prontos para serem usados. Agora definimos rotas para o servidor web responder às requisições dos usuários com a seguinte linha:

app.get('/', function(req, res) {
  res.sendfile('index.html');
});

A função de callback aceita dois parâmetros, uma requisição e uma resposta. Isso quer dizer que, quando o usuário requisitar o endereço raiz da nossa aplicação "/", o node vai retornar uma página chamada index.html que depois criaremos.

Agora vamos criar a variável do socket:

var mySocket;

Registramos o socket quando a conexão é estabelecida da seguinte maneira:

io.on('connection', function(socket) {
  mySocket = socket;
  console.log('a user connected');
  socket.on('disconnect', function() {
      mySerialPort.close(function(err) {
          if (err) console.log("Error at disconnect event: " + err);
          console.log('port closed');
      });
  });
});

Registramos eventos usando o método on. Quando o usuário emitir um sinal para fechar a conexão, o nosso socket irá encerrar a comunicação (on 'disconnect').

Vamos definir agora a porta serial:

var serialport = require("serialport");
var SerialPort = serialport.SerialPort;

Em seguida instanciamos o objeto com as configurações:

var mySerialPort = new SerialPort("/dev/ttyACM0", {
    baudrate: 115200,
    parser: serialport.parsers.readline("\n")
  });

Observe que é preciso dizer a porta serial onde seu microcontrolador está conectado. No Debian ela foi reconhecida como /dev/ttyACM0, mas no Windows será COMx e no Mac como /dev/tty.usbmodemx. Certifique-se de colocar o caminho correto do seu dispositivo. Definimos também a taxa de transmissão dos dados e escolhemos um parser para a serial. Ele vai ler linhas e reconhecer quando houver mudança de linha "\n". Isso pode ser encontrado na documentação do serialport.

Agora vamos criar eventos para a nossa porta serial.

Quando ela for aberta corretamente, vamos indicar uma mensagem para o usuário:

mySerialPort.on("open", function() {
    console.log("Port Open");
});

Veja que em cada evento, existe uma callback relacionada como ele a qual é executada quando o evento é disparado.

Um evento especial chamado 'data' é quando os dados chegam na porta serial. Vamos implementar a leitura dos dados que chegam:

mySerialPort.on("data", function(data) {
  console.log('data received: ' + data); // apenas debug
  io.emit('serialData', {
    dado: parseFloat(data)
  });

});


Observe que o socket já foi incluído dentro do evento, e, quando os dados chegam, já emitimos um evento via socket para que o usuário que está acessando a página veja o resultado. O evento 'serialData' foi criado por mim e esse nome será utilizado posteriormente na página index.html para gerenciar a chegada de novos dados pelo socket. Eu configurei o Arduino para de tempos em tempos enviar um número ponto flutuante (float) pela serial.

Por fim, vamos iniciar o nosso servidor:

http.listen(3000, function() {
  console.log('listening on *:3000');
});

Esse comando faz com que o servidor esteja ligado e funcione na porta 3000.

Vamos agora implementar o nosso index.html. Primeiramente, vamos acessar a página da biblioteca Chart.js que vamos utilizar para plotar os gráficos. Crie um diretório js dentro da pasta public do projeto. Acesse a página http://www.chartjs.org/ e clique em download. Quando abrir o repositório do github, clique no arquivo Chart.js, depois na opção Raw e salve o arquivo dentro do diretório public/js de sua aplicação.

Estarei utilizando gráfico de linhas e, para maiores informações, acesse a documentação dele aqui: http://www.chartjs.org/docs/ .

Vamos criar nosso index.html. Basicamente configuramos o socket, instanciamos o Chartjs, configuramos alguns parâmetros e tratamos os eventos do socket para que os dados sejam plotados. Definimos um canvas, que é o lugar onde o gráfico será plotado. No meu caso, usei algumas configurações globais e coloquei dentro do diretório js também, o arquivo está em logo abaixo.

// Conteúdo do arquivo ChartConfig.js

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
Chart.defaults.global = {
    // Boolean - Whether to animate the chart
    animation: false,

    // Number - Number of animation steps
    animationSteps: 0,

    // String - Animation easing effect
    animationEasing: "easeOutQuart",

    // Boolean - If we should show the scale at all
    showScale: true,

    // Boolean - If we want to override with a hard coded scale
    scaleOverride: false,

    // ** Required if scaleOverride is true **
    // Number - The number of steps in a hard coded scale
    scaleSteps: null,
    // Number - The value jump in the hard coded scale
    scaleStepWidth: null,
    // Number - The scale starting value
    scaleStartValue: null,

    // String - Colour of the scale line
    scaleLineColor: "rgba(0,0,0,.1)",

    // Number - Pixel width of the scale line
    scaleLineWidth: 1,

    // Boolean - Whether to show labels on the scale
    scaleShowLabels: true,

    // Interpolated JS string - can access value
    scaleLabel: "<%=value%>",

    // Boolean - Whether the scale should stick to integers, not floats even if drawing space is there
    scaleIntegersOnly: true,

    // Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value
    scaleBeginAtZero: false,

    // String - Scale label font declaration for the scale label
    scaleFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",

    // Number - Scale label font size in pixels
    scaleFontSize: 12,

    // String - Scale label font weight style
    scaleFontStyle: "normal",

    // String - Scale label font colour
    scaleFontColor: "#666",

    // Boolean - whether or not the chart should be responsive and resize when the browser does.
    responsive: true,

    // Boolean - whether to maintain the starting aspect ratio or not when responsive, if set to false, will take up entire container
    maintainAspectRatio: true,

    // Boolean - Determines whether to draw tooltips on the canvas or not
    showTooltips: false,

    // Function - Determines whether to execute the customTooltips function instead of drawing the built in tooltips (See [Advanced - External Tooltips](#advanced-usage-custom-tooltips))
    customTooltips: false,

    // Array - Array of string names to attach tooltip events
    tooltipEvents: ["mousemove", "touchstart", "touchmove"],

    // String - Tooltip background colour
    tooltipFillColor: "rgba(0,0,0,0.8)",

    // String - Tooltip label font declaration for the scale label
    tooltipFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",

    // Number - Tooltip label font size in pixels
    tooltipFontSize: 14,

    // String - Tooltip font weight style
    tooltipFontStyle: "normal",

    // String - Tooltip label font colour
    tooltipFontColor: "#fff",

    // String - Tooltip title font declaration for the scale label
    tooltipTitleFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",

    // Number - Tooltip title font size in pixels
    tooltipTitleFontSize: 14,

    // String - Tooltip title font weight style
    tooltipTitleFontStyle: "bold",

    // String - Tooltip title font colour
    tooltipTitleFontColor: "#fff",

    // Number - pixel width of padding around tooltip text
    tooltipYPadding: 10,

    // Number - pixel width of padding around tooltip text
    tooltipXPadding: 10,

    // Number - Size of the caret on the tooltip
    tooltipCaretSize: 8,

    // Number - Pixel radius of the tooltip border
    tooltipCornerRadius: 6,

    // Number - Pixel offset from point x to tooltip edge
    tooltipXOffset: 10,

    // String - Template string for single tooltips
    tooltipTemplate: "<%if (label){%><%=label%>: <%}%><%= value %>",

    // String - Template string for multiple tooltips
    multiTooltipTemplate: "<%= value %>",

    // Function - Will fire on animation progression.
    onAnimationProgress: function() {},

    // Function - Will fire on animation completion.
    onAnimationComplete: function() {}
  }

// fim do arquivo ChartConfig.js

Aqui começa o index.html:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8" />
  <title>Realtime plot</title>
  <script src="/socket.io/socket.io.js"></script>
</head>

<body>
  <canvas id="meusDados" width="900" height="400"></canvas>
  <script src="js/Chart.js"></script>
  <script src="js/ChartConfig.js"></script>
  <script language="javascript">
  // conjunto de dados vazio
  var formatoDados = {
    labels: [],
    datasets: [{
      fillColor: "rgba(172,194,132,0.4)",
      strokeColor: "#ACC26D",
      pointColor: "#fff",
      pointStrokeColor: "#9DB86D",
      data: []
    }]
  };
  var meusDados = document.getElementById("meusDados").getContext("2d");
  var myChart = new Chart(meusDados).Line(formatoDados);
  </script>
  <script>
  var socket = io();
  var cont = 1;
  var valores = [];
  socket.on('serialData', function(res) {
    
    if (cont > 81) {
      myChart.removeData();
      //socket.disconnect();
      //console.log("serialport closed");
    }

    myChart.addData([res.dado], cont++);

    //console.log(res.dado);
  });
  </script>
</body>

</html>

Observe que, após instanciar o objeto do socket, eu verifico o evento que foi criado no servidor 'serialData' e efetuo a leitura desse valor através de uma callback. Observe que ele chega em forma de objeto e precisamos acessar o campo 'dado' para obter o valor desejado. 

Utilizo a variável cont para servir como eixo das abscissas, os dados provenientes da serial comporão o eixo das ordenadas. Inicialmente o conjunto de dados é vazio e ele é preenchido com os dados da serial. Por motivos de visualização, eu decidi remover o conjunto de dados quando o contador for maior do que 81, caso contrário, se o fluxo de dados for muito grande, você poderá perceber travamentos no seu browser.

Pronto, o seu aplicativo está pronto para receber dados da serial e plotar em tempo real.

Execute o seguinte comando para iniciar o servidor node em terminal:

node server.js

Você verá uma mensagem indicando que o servidor está "escutando" na porta 3000.
Para verificar o funcionamento, abra um navegador e digite o endereço http://localhost:3000

Algumas melhorias ainda precisam ser feitas na utilização da biblioteca Chart.js. Se o fluxo de chegada de dados for grande, pode ser que o sistema trave. É preciso ter um maior controle disso e evitar que ocorre estouro de buffer pelo uso exagerado de memória.

Todo esse processo foi feito em videoaulas e você acompanhá-las pelos links abaixo:


Parte 1: https://www.youtube.com/watch?v=LNtmLapUSzw



Parte 2: https://www.youtube.com/watch?v=ewMkFQ6surQ

Parte 3: https://www.youtube.com/watch?v=d_SoD0iE54Y



Qualquer dúvida, pode comentar nos vídeos que eu responderei.

Um abraço,

Bruno Pinho


domingo, 10 de novembro de 2013

Python

Iae galera, tudo beleza?
Hoje venho fazer uma postagem sobre uma linguagem de programação que está sendo usada bastante e que possui uma estrutura boa de se aprender, o python.

Estou cursando uma disciplinal na faculdade que a maioria dos trabalhos usa python e eu nunca havia programado nela antes. Não há mistério, python é uma linguagem interpretada, não precisa compilar, basta colocar os comandos para ver imediatamente o resultado, ou então criar um script para executar uma lista deles.

Para quem usa Linux não vai ter dificuldade alguma porque geralmente o interpretador já vem por padrão na distribuição e basta digitar python na linha de comando. Caso contrário, há instaladores na página oficial.

Primeira coisa a citar, python não precisa declarar tipo de variável, é dinâmico. Ora é inteiro, ora vetor ou até mesmo string, fica a seu cargo. Uma variável pode mudar sua representação no decorrer do programa, embora não seja uma boa prática.

Python possuem milhares de módulos e te permite fazer desde gráficos até interfaces bonitas com botões, etc.


Manipulação de strings e vetores são fáceis e há métodos padrões para te auxiliar. Eu comecei a elaborar uma série de tutorias e espero que te ajude a compreender melhor.
Aqui está o link: http://youtu.be/af09RGQoMGM
Tenha uma boa introdução e boa sorte!
Abraço,
Bruno Pinho

segunda-feira, 23 de janeiro de 2012

Compilador MiniJava


Desde quando comecei meus estudos de computação e aprendi a primeira linguagem de programação, C, eu tenho a curiosidade de entender o funcionamento de um compilador.

Ficava fascinado pelo fato de um programa transformar um arquivo texto contendo construções da linguagem, em outro arquivo contendo código que uma máquina consegue compreender preservando a semântica, ou seja, seu significado. Esse é o processo de compilação.

Para iniciantes, isso fica um pouco abstrato porque o foco inicial é aprender a programar e não como funciona um compilador.
Finalmente, no meu 7° período de curso (bem que poderia ser antes!) tive a oportunidade de, não só entender todo esse processo de compilação, mas também construir um compilador seguindo as etapas de projeto. Cursei a disciplina Compiladores ministrada pelo professor Marcus Ramos o qual agradeço a paciência e disponibilidade para tirar dúvidas e compartilhar seu conhecimento, o que possibilitou a realização desse trabalho!

A linguagem usada para a construção foi MiniJava. Ela é uma versão reduzida do Java. Possui apenas construções simples e comandos básicos como if, while, System.out.println(), permite criação de métodos e atributos de classe e possui apenas tipos int, boolean, objeto e vetor de int.

Como nosso tempo foi curto (pouco menos de 2 meses, porque antes tivemos que ver a teoria que envolve a construção de compiladores), algumas decisões de projeto tiveram de ser tomadas para que pelo menos algo de cada etapa (análise sintática, análise de contexto e geração de código) pudesse ser feito.

A análise sintática consiste em reconhecer os símbolos (tokens) a partir da leitura de um arquivo texto de entrada e verificar se eles respeitam as regras gramaticais da linguagem fonte (no caso foi usada uma BNF estendida que pode ser encontrada aqui).

Na semântica, já com os tokens corretamente reconhecidos, o programa é verificado se está correto agora observando o significado das construções. Basicamente acontece a identificação (reconhecimento de variáveis e métodos) e vinculação (vincula cada uso de variável com sua declaração). Possíveis erros são facilmente identificados e mensagens exatas podem ser emitidas nessas etapas.

E, por fim, geração de código. Com o programa bem escrito e com o significado correto perante as regras da linguagem, as instruções podem ser traduzidas passo a passo para linguagem de máquina. Gerando o PUSH para reservar espaço para variáveis, STORE para guardar valores, LOAD para carregar valor de um registrador, JUMP para desvios, dentre outras. Essas são algumas básicas, cada máquina possui seu conjunto de instruções.

No nosso caso, o código de máquina foi gerado com base em uma máquina abstrata usada a partir do livro base da disciplina (link dele aqui), o TAM (Triangle Abstract Machine).

Aqui nesse link você encontra o arquivo compactado contendo o executável do compilador em bytecode juntamente com uma classe de exemplo. Também há um manual explicando como que instala e usa o compilador! Fique à vontade para testar e comentar.

Um abraço,
Bruno Pinho.

sexta-feira, 13 de janeiro de 2012

Dropbox no Debian Squeeze



Recentemente instalei o dropbox no Debian Squeeze e ele não funcionava de modo algum. Usei os pacotes .deb do site oficial tanto para Ubuntu quanto Debian e todos davam o mesmo problema: não encontrava um arquivo 'dropbox' no diretório /home/user/.dropbox-dist/ sendo que ele estava lá.

Tentei instalar pelo codigo fonte, compilei tudo mas não funcionou também. Mesmo erro. Depois de tanto procurar, resolvi tentar uma dica do site do dropbox mas o download falhava. Ate que encontrei uns arquivos compactados. Fiz o donwload versão x86 (versão 64 bits) deles e extraí para a minha pasta home. Entrei no diretório .dropbox-dist e executei o daemon do dropbox: ./dropboxd

A partir daí ele baixou uns arquivos de instalação e pude usá-lo normalmente. Para criar o atalho, pode ser na mão, mas se já tiver a versão instalada a partir do .deb, basta apagar o diretorio .dropbox-dist e substituí-lo pelo baixado do site como fiz acima. Pronto, agora o seu dropbox funciona tranquilamente no Squeeze!

Depois de vasculhar e tentar sem sucesso inúmeras vezes pelo .deb, consegui resolver o problema.
Espero que tenha ajudado!

3DSP? Nunca mais!


Placa wireless 3DSP
Hoje venho compartilhar com vocês, usuários de notebook MUB (Microboard Ultimate Black) da Microboard que vem com a placa de conexão wireless 3dsp de fabricação chinesa, o fim dos meus problemas com a rede sem fio. Recentemente instalei o Windows Seven e, ao instalar o driver da dita placa e usá-lo, volta e meia dava a famosa tela azul. Não sei por que isso, mas o problema era por conta da placa. Sempre a usei no Xp e sempre funcionou bem, não tenho do que reclamar. No entanto, eu gosto de usar Linux e na versão open source dos drivers o negócio é um pouco complicado.

Eu tenho a preferencia pela distro Debian. Mas eu tinha uma barreira que impedia de usá-lo. Os drivers não funcionavam corretamente. Para compilar era um trabalho e tinha que renomear uns diretórios e mesmo assim não funcionava. Quando pensava estar tudo ok, a placa não tinha um bom desempenho. Instabilidade na conexão e superaquecimento do meu note são só 2 problemas que listo... Só havia uma distribuição Linux em que os drivers funcionavam corretamente: Ubuntu. Você baixava o pacote .deb e instalava numa boa. Só que eles tinham limitação de versão do kernel e, sempre na próxima versão do Ubuntu que sair e tiver uma atualização do lernel, o drive pára de funcionar. Então teria que e esperar sair o pacote pré-compilado para a próxima versão do Ubuntu. Ou seja, sempre ficava dependendo do pessoal desenvolver o próximo pacote para a versão... Isso não é uma coisa boa!

Mas há o código fonte, você poderia compilar e resolver o problema... Não! Simplesmente esse código fonte só funcionava também no Ubuntu. Tentei inúmeras vezes instalar no Debian mas aí aparecia a famosa frase dessa placa quando abria o seu gerenciador: “no valid wireless device”.

Então, já cansado de ficar limitado a usar ao o Ubuntu,  abdiquei do bluetooth (só para lembrar, a 3dsp possui wireless e bluetooth na mesma placa) e a troquei. Antes de tudo, precisava pesquisar quais placas teriam suporte no Linux ou pelo menos drivers que funcionassem. Isso pode ser visto para o Debian aqui. Achei duas placas de nome no mercado que teria suporte no Linux: atheros e rtl. Não achei atheros com preço acessível. Então parti para a rtl. Mas possuem 3 versões. Eu optei pela rtl8187b da azurewave. Além de ter suporte, possui drivers open source. E, para nossa alegria, o Debian Squeeze já possui módulo para essas placas: rtl8187. Bastava então instalá-lo e carregar. 

Placa RTL8187B da Azurewave
Comprei a placa Minipci no valor de 39 reais. Abri o notebook e fiz apenas trocar pela 3dsp reconectando os cabos da antena da mesma maneira que estavam. Liguei o notebook e pronto. Tanto o Windows quanto o Linux reconheceram automaticamente o driver. Fiquei surpreso já que tinha separado os drivers.. Mas o importante é que agora tenho a liberdade de escolher qualquer distribuição Linux porque essa placa tem suporte em muitas versões do kernel e o código fonte esta disponível para instalação manual. E, na pior das hipóteses, pode usá-la com o ndiswrapper. A 3dsp não funcionava com o ndiswrapper porque não possui o arquivo necessário.    

Então, para aqueles que ainda têm dor de cabeça com essa placa, segue mais uma experiência de alguém que resolveu trocá-la para ter melhor desempenho e liberdade com seu notebook MUB!

quinta-feira, 22 de setembro de 2011

Vídeo - Comando fork() no Linux

Bem pessoal, segue abaixo uma vídeo-aula que fiz explicando como se cria processos no ambiente linux usando o comando fork().


domingo, 11 de setembro de 2011

O que são Microcontroladores?


Alguém já ouviu falar em microcontrolador e ficou se perguntando o que é e para que serve? Pois é, imagine um computador em miniatura que possui um conjunto reduzido de instruções mas que é capaz de controlar inúmeras coisas como a temperatura do seu forno microondas, a temperatura de um dado ambiente e até acionar motores! O objetivo é criar um dispositivo que seja semelhante ao chip de processador usado em seu notebook ou desktop mas seja projetado para aplicações específicas e que exija bem menos potência para funcionar. Foi então que surgiu o PIC (Programmable Interface Controller ou controlador de interface programável) fabricado pela Microchip. Dentro desta "pastilha" preta cheia de pinos acima, há inúmeros módulos, por assim dizer, que possuem características importantes para o funcionamento do conjunto.

Aí dentro encontramos diversos dispositivos de entrada e saída e periféricos. Ou seja, encontramos um conversor Analógico/Digital, memória, uma CPU para processar os dados, dentre outros. O conversor serve para obter dados provenientes de sensores e convertê-lo para um sistema que seja fácil do computador interpretar. Os dados que estão na natureza possuem muitas vezes natureza analógica, ou seja, sinais contínuos no tempo. Os computadores só entendem 0 e 1, então é preciso converter esse sinal contínuo em uma sequência de zeros e uns!!
A memória é usada para guardar o programa que a gente faz usando a linguagem C, por exemplo, dentro do chip para ele poder ser executado, e, ao ser desligado, o seu conteúdo não seja perdido!
E também uma memória volátil, aquela que os dados são perdidos quando tiramos a alimentação (energia).

O uso desses componentes pequenos está cada vez mais comum hoje em dia já que sistemas específicos e projetos direcionados são cada vez mais necessários. Você aí, se tiver uma fazendo e quer que a sua irrigação seja monitorada 24horas por dia para que não haja prejuízos, com certeza você pode "encomendar" um sistema desse de um Engenheiro por exemplo. Ele vai desenvolver o programa e adquirir os sensores corretos para monitorar e quem sabe, se for preciso, acionar alguma coisa. Ele vai fazer uma plaquinha que vai conter lá o elemento principal para fazer todo o gerenciamento do sistema, o Microcontrolador! Um sistema desses você pode encontrar por aí, garanto que não vai ser fácil, e pior, talvez não seja 100% adequado para o seu problema. Então é por isso que sua aplicabilidade é muito grande. Já que cada situação possui suas características que precisam ser desenvolvidas especificamente para cada cliente.

Esse chip também possuem pinos usados para enviar sinais para serem interpretados por um computador via comunicação usb ou serial. Então além de monitorar a sua fazenda, ele ainda pode enviar os dados para serem salvos em HD e analisados depois, e por aí a imaginação ajuda bastante nessas horas, colocar tudo em banco de dados, criar gráficos, analisar em qual época do ano tal fenômeno é mais presente, onde é preciso aumentar ou diminuir a quantidade de água e etc!
Bem é isso, espero que tenham entendido um pouco do que expliquei!

quinta-feira, 8 de setembro de 2011

Comando fork() - Sistemas Operacionais

Pessoal, resolvi postar algo sobre o uso do comando fork() em ambiente Linux de programação.
Quando damos o comando fork() em um programa escrito em C no Linux, ele vai criar uma cópia exata a partir do ponto em que o comando é executado e dois processos executam ao mesmo tempo, o processo pai (aquele que chama o comando fork() ) e o processo filho (o que foi gerada pela chamada do fork() ).
Um programa simples que usa o fork() pode ser visto logo abaixo:

#include < stdio.h >
#include < stdlib.h >
#include < sys/types.h >
#include < sys/wait.h >
#include < unistd.h >

int main ()
{
pid_t filho;
filho = fork(); //aqui criamos o processo filho
if ( filho == 0 ) { //execução do filho
printf ("Sou o filho executando...\n");
_exit(0);
}
else { //execução do pai
printf ("Sou o pai executando.\n");
}
exit(0);
}

Uma maior explicação dos cabeçalhos incluídos nesse programa pode ser encontrado nas entradas de manual do linux, como "man fork". Você pode encontrar descrições detalhadas de cada função.
Podemos ver que quando damos um comando fork() um valor de retorno é atribuído à variável filho. No processo pai, esse valor é diferente de zero, no processo filho, é igual a zero. Observe que o que estiver abaixo do comando fork() é replicado para outro processo, então tanto o processo pai quanto o filho irão executar o que vier abaixo, por isso precisamos testar com o "if" o que cada um deve executar. Então se o valor da variável filho é igual a zero, então quer dizer que é o trecho de código que o filho deve executar, caso contrário, será o do pai. Dessa forma, temos dois processos executando, sendo que um foi gerado pelo outro! A ideia é fazer com que os dois executem e realizem tarefas de modo mais rápido, sendo que cada tarefa é atribuída para cada um realizar separadamente, com isso pode-se obter ganho de desempenho!
Espero que tenham gostado!