Após ter visto um artigo sobre o Raspberry PI na atmosfera com o projecto Pi in the Sky, decidi, porque não experimentar ? No projeto eles usam uma placa de telemetria para dar informações sobre temperatura, pressão , etc.. Como não tenho acesso a nenhuma placa dessas, porque não fazer o mesmo, mas com componentes disponiveis no mercado? Então, começou a nascer este projeto.
English version
Em primeiro lugar, como localizar o Raspberry PI por GPS.
Material
Raspberry PI B/B+ (usei ambos)
2 GPSs (embora só seja necessário 1, experimentei com os dois)
GPS Receiver – EM-406A SiRF III (20 Channel) – Já não é fabricado
GY-NEO6MV2 Flight Controller GPS Module For Arduino EEPROM MWC APM 2.5
Ligações
Para ligar o(s) GPS(s) ao Raspberry PI precisamos de usar o GPIO. A tabela seguinte mostra os PINs para a versão B onde ligar o GPS.
Raspberry PIN | GPS PIN |
---|---|
2 – 5v | VIN/VCC |
6 – GND | GND |
8 – TX | RX |
10 – RX | TX |
Nota: Reparar que o TX e o RX trocam quando se ligam ao GPS: RX -> TX e TX -> RX
Aqui fica o Pinout do Raspberry PI versão B
GPS GY-NEO6Mv2
Ligação do GPS GY-NEO6Mv2 ao PI
Algumas imagens das ligações do GPS ao Raspberry PI versão B
GPS EM-406A
Para ligar o GPS EM-406A precisei de comprar um cabo JST SH Jumper 6 – de 6 pins para encaixar no GPS – embora só sejam necessários 4 pins.
Esquema das ligações do GPS EM-406A
Neste caso, o GPS EM-406A foi ligado a um Raspberry PI B+. Os PINs no GPS são ambos os mesmos e as ligações iguais. A unica coisa que muda é o GPIO do RPI B+.
Ligar o PI e efetuar login
Assim que tiverem uma prompt, é necessário alterar umas configurações para que a UART esteja disponivel para o GPS, uma vez que é usada para permiter ligar-se a um terminal e autenticar-se.
Editar o ficheiro /boot/cmdline.txt e alterar:
1 |
dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait |
para
1 |
dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait |
Depois, editar o ficheiro inittab para comentar uma linha para que não seja lançada uma consola na ligação serie:
Comentar a seguinte linha (deverá ser a ultima):
1 |
#T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100 |
Após estas alterações, efetuar reboot ao PI
1 |
sudo reboot |
Assim que possivel, instalar as aplicações para o GPS
1 |
sudo apt-get install gpsd gpsd-clients |
Executar o gpsd
1 |
gsudo gpsd /dev/ttyAMA0 -F /var/run/gpsd.sock |
Executar o cliente e esperar que o GPS funcione
1 |
cgps -s |
E ao final de alguns segundos (talvez mais – sair do cgps e voltar a entrar) devem conseguir sinal.
Poupar energia
Podem-se poupar cerca de 20mA (mais ou menos) desligando a saída PAL/HDMI (partindo do principio que não vamos usar) .
Para tal, basta adicionar a linha seguinte ao arranque (Geralmente adicionando a linha ao ficheiro /etc/rc.local)
1 |
/opt/vc/bin/tvservice -off |
dica via http://www.daveakerman.com/?page_id=1294
Atualizar um mapa com a posição corrente do Raspberry PI
Não serve de nada ter um GPS ligado ao PI se não for para criar uns pontos e uns trilhos com ele.
Criar um mapa com as coordenadas GPS
Agora que já temos os módulos de python para o GPS, vamos usar para reportar as coordenadas.
Como vai o PI fazer isto? Bem, a minha solução foi, com um servidor web, a aplicação em Python coloca as coordenadas num diretório especifico e a aplicação web a correr num outro computador (ou no PI – mais à frente esta solução) vai aceder ao PI e ler esse ficheiro com as coordenadas, que posteriormente vai coloca no mapa.
Instalar um servidor web para partilhar as coordenadas.
1 |
sudo apt-get install nginx |
Configurar o nginx
É a primeira vez que trabalho com o nginx. Decidi instala-lo porque consome menos recursos que o apache.
Por questões de segurança, alteramos o porto do nginx. Em vez do 80, vamos usar o 2121 (por exemplo).
1 |
sudo vi /etc/nginx/sites-available/default |
Alterar a linha de
1 |
#listen 80; |
para
1 |
listen 2121; |
Alterar o document_root
Na linha que diz root, alteramos para
1 |
root /home/pi/gps/www; |
Nota: Não esquecer de criar as diretorias gps/www
1 |
mkdir -p gps/www |
Uma vez que o nginx corre com o grupo www-data, vamos adicionar o pi ao grupo para que a diretoria configurada em cima seja acessivel pelo nginx.
1 |
sudo gpasswd -a pi www-data |
Nota: Para que fique ativo, têm que terminar a sessão e voltar a entrar
Alterar as permissões para que qualquer ficheiro criado seja lido pelo grupo porque qualquer ficheiro criado pertencerá ao grupo www-data – (setgid)
1 |
chmod g+s www |
Reiniciar o nginx
1 |
sudo /etc/init.d/nginx restart |
Nota: Não esquercer que, se configurado como em cima, têm que aceder usando
1 |
http://<rpi_ip>:2121/ |
Código
PI
Instalar o módulo de Python gpxpy
1 2 3 4 |
git clone https://github.com/tkrajina/gpxpy.git cd gpxpy sudo python setup.py build sudo python setup.py install |
Todo o código para este projeto encontra-se na minha conta do bitbucket.
A diretoria rpi contém um ficheiro chamado gpswww.py .Este ficheiro é colocado no Raspberry PI, onde desejarem – mas têm que posteriormente criar uma diretoria chamada www no mesmo nível – é nesta diretoria que este script vai colocar o ficheiro – chamado coords.txt – que contém as coordenadas naquele momento.
Para o executar, nada mais simples que:
1 |
sudo python gpswww.py |
Antes de o executar, tenham a certeza que o GPS está bem ligado e a funcionar. Podem usar os examplos em cima, com o comando cgps -s
Para mais informações sobre os módulos de Python do gpsd, basta visitar a página.
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 |
# Feiticeir0 - Bruno Santos (feiticeir0@whatgeek.com.pt) # date: 10.12.2014 # # Python script para guardar as coordenadas # correntes num ficheiro para ser lido via script em PHP # de um computador remoto from sys import argv import gps import gpxpy import gpxpy.gpx #Listen on port 2947 of gpsd session = gps.gps("localhost", "2947") session.stream(gps.WATCH_ENABLE | gps.WATCH_NEWSTYLE) while True: try: report = session.next() # wait for a 'TPV' report and display the current time # to see all report data, uncomment the line below #print report if report['class'] == 'TPV': # Abrir ficheiro para guardar as coordenadas coords = open ("www/coords.txt","w") coords.write(str(report.lat)) coords.write(","); coords.write(str(report.lon)) coords.close() except KeyError: pass except KeyboardInterrupt: quit() except StopIteration: session = None print "GPSD has terminated" |
Computador
No computador que vai mostrar os mapas, é necessário um servidor web (com suporte PHP) e acesso à internet para que possa mostrar os mapas.
No bitbucket encontram-se os ficheiros necessários.
Só é necessário alterar 2 linhas, uma em cada um dos seguintes ficheiros:
– getcoords.php : alterar a linha $rpi_host para o IP do vosso PI
– pingPHP.php : alterar a linha $host novamente com o IP do vosso PI
Atualização: Com a nova versão, não é preciso alterar ficheiros nenhuns, bastando para isso colocar o IP do RPI na caixa para o efeito e pressionar “Track”
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 |
<!DOCTYPE html> <html> <head> <title>RPI Tracking</title> <meta charset="utf-8"> <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css"/> <style> #map { margin-left: auto; margin-right: auto; width: 1500px; height: 900px; float: right; } input[type="button"] { border: 1px solid #b5c1d5; background-color: #94aecf; color: white; height: 28px; border-radius: 3px; width: 100px; } </style> <script src="https://code.jquery.com/jquery-2.1.1.js"></script> </head> <body> <div id="map"></div> <script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet.js"></script> <script> var map = L.map('map').setView([39.823006667, -7.490308333], 14); mapLink = '<a href="http://openstreetmap.org">OpenStreetMap</a>'; L.tileLayer ('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© ' + mapLink + ' Contributors', maxZoom: 18, }).addTo(map); var ongoing = 1; $(document).ready(function() { $('#startTrack').click(function() { if (ongoing == 1) { startTrackingRPI(); ongoing = 0; /*$(this).css('background-color','#d79d9c'); $(this).attr('value','Stop');*/ } /* else { ongoing = 1; $(this).css('background-color','#94aecf'); $(this).attr('value','Track'); }*/ }); function startTrackingRPI() { var oldlon = 0.00; //define old coords var oldlat = 0.00; //define old coords //get status from robot //get IP Address var ip = $('#ip').val(); // red offline - green online function getStatus() { //new image if (!ip.length == 0) { //alert (ip); var online = 'images/online.png'; var offline = 'images/offline.png'; //gerar url $.post ('pingPHP.php',{ip:ip},processaDados); function processaDados (data) { //alert ('data ' + data); if (data == 1) $('#status').attr('src',online); else $('#status').attr('src',offline); } } } // 3s em 3s verifica setInterval(getStatus,3000); //colocar marcador function getCoords() { $.post('getcoords.php',{ip:ip},processCoords); function processCoords(data) { $('#coordstoput').val(data); //TODO: Verificar se dados devolvidos sao validos //TODO: Verificar se nao houver conectividade, nao tentar inserir marcador var coords = data.split(","); //verificar se sao iguais as que ja temos //para nao colocar marcadores no mesmo local if ((coords[0] != oldlon) && (coords[1] != oldlat)) { //se sao diferentes, inserir marcador // insert a new marker var marker = L.marker([coords[0],coords[1]]).addTo(map); //atribuir estas coordenadas antigas oldlon = coords[0]; oldlat = coords[1]; } } } // 4s em 4s verifica coordenadas - diminir para aumentar detalhe do mapa setInterval(getCoords,4000); var newCoord = getCoords(); //Marker //var marker = L.marker([39.823366667, -7.490128333]).addTo(map); }; }); </script> <!-- <textarea id="coordstoput" rows="2" cols="30"></textarea> --> <img src="images/offline.png" id="status" style="vertical-align:middle;"> <input type="text" size="15" maxlenght="15" placeholder="RPI Endereço IP" name="ip" id="ip"> <input type="button" value="Track" id="startTrack"> </body> </html> |
Seguindamente, os ficheiros auxiliares:
1 2 3 4 5 6 7 |
<?php $host = $_POST['ip']; if (!$socket = @fsockopen($host,2121)) echo 0; else echo 1; ?> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<?php $rpi_host = $_POST['ip']; $port = ":2121"; $url = $rpi_host.$port.'/coords.txt'; $ch = curl_init(); $timeout = 5; curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout); $data = curl_exec($ch); curl_close($ch); //return preg_replace("/\r|\n/", "", $data); echo preg_replace("/\r|\n/", "", $data); ?> |
E está tudo configurado.
NOTA IMPORTANTE: Pode parecer que o mapa não está a atualizar, mas a verdade é que está. Façam zoom out com o rato e coloquem o mapa no local onde estão. Como é necessário colocar coordenadas iniciais ao criar o mapa, coloquei as de Castelo Branco (a minha cidade). Será uma questão a alterar na próxima versão. (Obrigado Nuno Oliveira)
Num browser, executem o ficheiro RPITracking.html e fiquem à espera que marca a posição do vosso PI.
Nesta versão eu optei por usar marcadores em vez de uma linha. Noto que, ao final de algum tempo, começa a ficar um pouco confuso – mas irei alterar isso numa futura versão para colocar uma linha em vez de marcadores.
Aqui fica o resultado de uma experiencia que fiz hoje de manhã (Imagem da versão anterior)
Usar o PI para mostrar o mapa (em atualização)
Em vez de usar outro computador para ir buscar as coordenadas ao RPI e mostrar no mapa, podemos usar antes o RPI para fazer tudo – acedendo a ele via browser –
Alterar o nginx
Instalar o PHP
1 |
sudo apt-get install php5-fpm |
A seguir, editar o ficheiro /etc/nginx/sites-available/default
1 |
sudo vi /etc/nginx/sites-available/default |
e descomentar as seguintes linhas:
1 2 3 4 5 6 7 8 |
location ~ .php$ { fastcgi_split_path_info ^(.+.php)(/.+)$; # # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini # fastcgi_pass 127.0.0.1:9000; fastcgi_pass unix:/var/run/php5-fpm.sock; fastcgi_index index.php; include fastcgi_params; } |
Guardar e recarregar o nginx
1 |
sudo /etc/init.d/nginx reload |
Para funcionar, os ficheiros que colocaram no PC, coloquem no PI – alterando o IP nos ficheiros indicados para o do PI e devem ter a funcionar o mapa dentro do PI. Conforme configuraram o root no nginx, é nesse local que devem colocar os ficheiros. Uma nota neste caso, e uma vez que está tudo no mesmo local, não havia necessidade de usar o curl – no PHP – para ir buscar as coordenadas, mas mal também não faz e funcionará sem problemas.
Mobilidade do PI
Para que isto tudo funcione, é necessário que o PI funcione com baterias.
No meu caso, estou a usar baterias lipo para alimentar o PI – com duração de cerca de 2h e 30m – não é muito, mas para já é o suficiente.
O material que uso é (Foi nesta loja de comprei) :
– Lithium Ion Polymer Battery – 3.7v 1200mAh
– PowerBoost 500 Basic – 5V USB Boost @ 500mA from 1.8V+ (para aumentar os 3.7v da bateria para os 5v do PI)
– USB/DC Lithium Polymer battery charger 5-12V (3.7/4.2v cells) (para carregar as baterias)
Com um cabo mini-usb ligam isto tudo ao PI. Eu acredito que não seja a forma mais eficiente de alimentar o PI, mas após alguns dias de leitura foi o que arranjei. Não sou expert em eletrónica – se houver alguem aí que tenha uma forma mais eficiente de alimentar o PI – faça favor de dizer alguma coisa !
Antes de ter resolvido ficar assim – testei com pilhas AA de 1.5v – um adaptador de 6 pilhas AA de 1.5v e um Pololu 5v Step-up/Step-down voltage regulator 5v para controlar a voltagem (6 * 1.5v = 9v). No entanto, não sei o que fiz mal, mas só durava cerca de 40m – além de pesar imenso…

NOTA: Este projeto (para já) tem a atenuante que, no computador onde estejam a ver a localização do PI tenha que estar ligado à Internet para poder ir buscar os mapas. Tem também outra atenuante que, tanto o PI como o computador têm que estar ligados na mesma rede (ou se preferirem, via internet – com DNS dinamico é possivel conseguir isto) – Essencialmente têm que ter conetividade. Para alterar isto, brevemente (assim que chegarem) quero testar isto com o Xbee ! Os modelos que mandei vir têm alcance de 1,5km – Isto deve ser interessante. Atualizações para essa altura.
Espero que gostem. Algum erro e/ou omissão, avisem.
Post muito bom!
Parabéns pelo artigo, muito bom! Gostaria somente de uma ajuda, se caso eu precisasse armazenar os locais em um arquivo, tipo txt por exemplo, para abrir depois e não precisar de conexão com a internet, seria possível? Obrigado!
Olá Aieser !
Obrigado pelo comentário.
É possível sim.
Eu só usei assim para visualizar em “tempo real” a progressão do RPI.
Pode-se guardar as coordenadas num ficheiro (no RPI) e posteriormente abrir o ficheiro e colocar num mapa.
Envolve um pouco de programação, mas por exemplo:
No lado do RPI, basta alterar as linhas do codigo que guarda as coordenadas para que acrescente em vez de escrever por cima (alterando a linha de abertura e fecho do ficheiro para o inicio e fim respetivamente.
No caso depois do HTML, basta abrir usando jquery ou PHP para ler o ficheiro e colocar num mapa…
Se quiseres, posso acrescentar aqui ao tutorial! Só preciso de alguns dias !
Seria ótimo ter um tutorial sobre isso! Obrigado pela resposta, e parabéns mais uma vez pela iniciativa!
Amigo, vc comprou seu módulo num site gringo? Demorou muito pra chegar??
Olá Suellen !
Foi comprado na banggood.com . Tipicamente entre 3 semenas a 1 mês. !
AH, você só conseguiu esses resultados usando os dois módulos???
è que estou fazendo um projeto maluco e preciso usar o módulo gps, mas oq comprei veio quebrado
Sim, tanto um como o outro funcionaram bem !
Poxa, me manda um email falando mais sobre isso??
Tenho que colocar um GPS no meu raspberry 3 pra entregar o projeto do TCC mas estou enfrentando problemas…
Na verdade, o projeto original era com o Arduino Mega, mas aí eu quis fazer por fora no rasp.
Resumindo: No Mega, o GPS não deu sinal de vida. Minha companheira de TCC disse que ele simplesmente não acende o ledzinho. Ou não recebe a corrente, ou ele queimou (ou ja veio queimado) :/
Então, vou ter que comprar outro módulo e tentar fazer no Rasp (tenho noção nenhuma de eletrônica kkkk)
Aí agora vou me meter a fazer no rasp…
Entra em contato comigo, que te dou mais detalhes do que queremos fazer 🙂
OIá, fiz esse tutorial com meu rasp 3 e um GY-NEO6MV2. Eu consigo ver os dados do gps com o comando cgps -s mas estou com um problema ao rodar o script gpswww.py. As coordenadas são escritas somente uma vez no coords.txt. Elas deveriam ser incrementadas, correto? Tem alguma permissão especial para a pasta www?
Obrigado!
Olá Bruno.
Obrigado. As coordenadas no ficheiro coords.txt são sempre escritas por cima – não são incrementadas. As permissões são de escrita para o utilizador do nginx.
(os comandos seguintes estão no post)
Adicionar o utilizador PI ao grupo (partindo do principio que o www-data é o grupo do nginx):
sudo gpasswd -a pi www-data
E dar permissões na pasta:
chmod g+s www
Olá, fiz os procedimentos no meu raspberry pi 3, o arquivo inittab não tem nada, a antena de gps até pisca mas com o comando “cgps -s” não aparece nada e o comando anterior não funciona, pode me ajudar?