SIPIU

Participantes:

Renata de Camillo Corrêa Bernardes

Resumo do projeto:

Sistema de Identificação de Problemas de Infraestrutura Urbana

Descrição do projeto:

   Grandes centros urbanos apresentam inúmeros problemas de infraestrutura, os quais influenciam diretamente na  qualidade de vida de sua população. Levando em conta agilizar a identificação  e  localização de  problemas, o SIPIU,  busca identificar,  localizar e cadastrar diversos  problemas de infraestrutura  urbana em  prol de agilizar seus reparos. Dentre os problemas os mais comuns estão: vazamentos de água e esgoto, buracos e imperfeições no asfalto e calçadas, terrenos baldios irregulares e entulho em locais proibidos.

   Pensando em mapear as cidades de modo eficiente, seria necessário pessoas que percorrem longas distâncias durante seu turno de trabalho. Os garis, que atuam profissionalmente na limpeza das vias públicas, se adequariam a essa categoria. A cidade de São Paulo possui 13 mil profissionais nesse ramo, que percorrem 7.8 quilômetros de vias por dia.

  O hardware seria  acoplado nos carrinhos  utilizados por  esses profissionais, de modo que ao identificar um problema, ele através de chaves e botões ativaria o GPS e escolheria a categoria do problema. Esses dados são enviados para a nuvem, onde os responsáveis pelos reparos teriam acesso rapidamente e podem pensar em medidas para realizar as ações necessárias.

   Dentro do conceito de IoT (internet das coisas) os garis com seus coletores de dados (carrinhos) gerariam uma grande quantidade de dados relevantes que seriam transmitidos diretamente a nuvem em um portal IoT que armazenaria esses dados para um sistema de analise que geraria automaticamente ordens de serviço para os órgãos competentes equacionarem os problemas reportados. A integração dos sistemas facilita também a geração de relatórios de eficiência da solução dos problemas e se eles foram efetivamente equacionados. Utilizando algoritmos de “machine learning” essa massa de dados históricos pode preditar ações futuras (por exemplo no mês de maio há uma incidência nos últimos 3 anos de aumento de buracos nas vias em 40%) e seus devidos orçamentos.

Overview do projeto:

Contato:[email protected]

A apresentação a seguir introduz e explicita todos os conceitos do projeto e sua relevância e colaboração no âmbito social, clique na imagem para acessar.

prezi

Histórico do desenvolvimento:

Diagrama de blocos inicial do sistema a ser desenvolvido:

duagramadeblocos

Essa semana o kit chegou e comecei a planejar e dar os primeiros passos do projeto. O primeiro a ser feito é estudar as possibilidades de comunicação entre a OM13070: LPCXpresso4337, que possui duas seriais, e os módulos 3G e GPS.  E começar a desenvolver o código e fazer vários testes para ir adequando as necessidades.

Carreguei todo o ambiente da IDE LPCXpresso v8.2.0 no Windows 8 e rodei o programa para piscar o led. Funcionou perfeitamente! Usei como referência o artigo do Embarcados: Primeiros Passos com a LCPXpresso4337.

Continuando os testes iniciais, conectei a placa  OM13082: LPC General Purpose Shield na placa OM13070: LPCXpresso4337, com ela é possível realizar várias funções. A que eu achei mais interessante foi utilizar o LCD, com ele posso fazer vários testes e printar alguns resultados ou parâmetros importantes  para o projeto.

whatsapp-image-2016-09-09-at-21-54-47

Pensando na instalação do sistema nos carrinhos dos garis, fui em busca de maiores informações e das dimensões para que fosse possível começar a desenvolver um modelo do que virá a ser o protótipo.

img_20160908_094740329_hdr

Essa semana foram feitos diversos testes com o GPS e o Modem 3G! A próxima etapa é fazer com que eles se comuniquem com a OM13070: LPCXpresso4337. E também integrá-los com a plataforma IoT!

O teste com o GPS JN3 foi um sucesso, foram transmitidos as localizações corretas e com isso facilita a passagem dos dados para o microcontrolador.

GPStelit

Fiz um diagrama de blocos funcional para ajudar na hora de programar.

diagramafuncional

A comunicação entre a  OM13070: LPCXpresso4337 e os módulos 3G e GPS é serial. O código da OM13070: LPCXpresso4337 foi feito na plataforma mbed, onde já foi feita a comunicação serial entre ele e os módulos. O próximo passo é fazer a interface com o usuário, onde ele escolherá o tipo de problema que encontrou e acionará a comunicação.

img_20161009_155842091

Já o Modem 3G, foi programado em  Phyton para receber uma string com os dados a serem transmitidos e conectar-se ao DeviceWise, a plataforma IoT  aonde os dados são tratados, aonde fica fácil acompanhar os dados coletados.

Como os dados ficam centrados na plataforma IoT, é possível pegá-los facilmente e expô-los em uma plataforma. Está sendo desenvolvido um site responsivo, utilizando HTML, CSS e Javascript, onde será possível ter de forma fácil e rápida os últimos dados coletados, o problema encontrado, latitude, longitude, sua localização no mapa e a data da coleta, assim, o usuário poderá encaminhar as informações para o órgão responsável.

 

 

 

Foi desenvolvido o esquema 3D do protótipo do SIPIU, nele é possível observar a posição que o sistema ficaria no carrinho e a interface do usuário, por meio de dois push bottons para selecionar a opção do problema e outro que serviria de confirmação. O esquema foi desenvolvido no programa SketchUp.

O código para a LPCXpresso4337  está quase pronto! Usando o display e o joystick é possível selecionar o problema que o usuário encontrou. Assim, quando ele seleciona o problema, é lido na entrada serial, a string que vem do GPS indicando sua localização exata. Com isso, é enviado para o Modem 3G um string com o status, problema em questão, junto com a string do GPS. O código encontra-se no tópico software abaixo.

Fiz um vídeo mostrando o funcionamento e a interface do sistema:

O site do SIPIU ficou pronto! Nele é possível ver na página home o último dado enviado, e sua localização no mapa. Na página histórico é possível consultar a tabela com outros dados coletados.


site1

site2

site3


Business Plan

Desenvolvi o plano de negócios, definindo as características e estratégias do SIPIU. Nele contém também o estudo da sua viabilidade, onde foi calculado, de forma aproximada, os custos para implementação do sistema. Para acessar o Business Plan clique aqui.

business

Como parte da documentação,  estratégia de negócio e divulgação, desenvolvi um catálogo que explica de forma rápida sobre o sistema. O catálogo pode ser acessado aqui.

folder


Evolução do sistema

Com a instalação no Brasil da Rede SIGFOX uma rede mundial de LPWAN focada em IoT,  o sistema SIPIU pode ser alterado facilmente para operar nessa rede.

A grande vantagem está no fato de redução de custo do hardware e do custo de operação do sistema. Outra grande vantagem é o baixo consumo de energia , fazendo com que  equipamento opere com a mesma bateria por 1 a 2 anos.

Para o estudo utilizamos o componente da NXP para essa finalidade: OL2385.

sigfox1

sipiu2


Desafios encontrados durante o desenvolvimento

Os principais desafios encontrados durante o desenvolvimento do SIPIU, foram:

  • integração do hardware e a comunicação entre os equipamentos;
  • programação web, principalmente na parte de Javascript;
  • patentear o projeto, não consegui informações adequadas até agora.

Hardware:

   O hardware é constituído pelo microcontrolador, que no caso será utilizada a placa OM13070: LPCXpresso4337 Development Board da NXP:

placanxp

Placa OM13082: LPC General Purpose Shield da NXP:

OM13082_main_visul

Modem 3G DD3G – 910 da Duodigit:

modem3g

GPS JN3 da Telit:

gps

Será utilizada comunicação serial entre o módulo 3G e o processador NXP, comunicação serial/SPI entre o módulo GPS e o processador NXP. O painel seria de fácil utilização, onde as chaves seriam numeradas e identificadas de acordo com cada tipo de problema observado.

Esquema elétrico da montagem do hardware:

esquematico

Software/Firmware:

O Código da placa   OM13070: LPCXpresso4337  está sendo contruído na plataforma mbed. Ela é bem fácil de ser usada, basta escolher o tipo de hardware a ser utilizado, e ao compilar o código obtem-se um arquivo em binário que é passado diretamente para a placa. Para isso utilizei como base o artigo Primeiros passos com a placa LPCXpresso4337 no mbed.

O código encontra-se abaixo, utilizou-se as bibliotecas para o display e o joystick, configurações para a comunicação serial.

#include "mbed.h"
#include "ST7567.h"
#include "PCAL9555.h"
 
ST7567 lcd(D11, D13, D12, D9, D10);            				 // mosi, sclk, reset, A0, nCS
Serial pc(USBTX, USBRX);                       				 //configura a comunicação serial
Serial micro(TX, RX);										//confira a entrada de dado do GPS
PCAL9555    gpio_exp(SDA, SCL);								// configura o joystick
GpioBusIn   joystick(gpio_exp, X0_0, X0_1, X0_2, X0_3, X0_4); 
 
int selectionArrow (char,int);				//funcao que posiciona a seta 
void lcdStart();							//funcao que inicializa o lcd

enum key_num {                          //configuracoes do joystick
    Key_Up     = (1 << X0_4),
    Key_Down   = (1 << X0_0),
    Key_Center = (1 << X0_1),
};

int main()
{
    int mainState = 18;                 // posicao inicial da seta
    char direction; 					//variavel se define se a seta sobe ou desce
    char gps[80], location[80];
    
    
    lcd.set_contrast(0x35);             //configura contraste do Display
    lcd.cls();                          //Limpa Display
    lcdStart();							//inicializa o display

    micro.format(8, Serial::None, 1);  //configuracoes da comunicacao serial com o GPS
    micro.baud(4800);
    pc.format(8, Serial::None, 1);
    pc.baud(9600);   
 
  
    while(true) {                               // loop principal
            
        int keys = joystick.read();				//leitura do joystick
        int state;								//armazena a posicao
        
        if ((keys & Key_Up) == 0){				//se a seta de selecao subir
            direction = 'U';					
            state = selectionArrow(direction,mainState);	//chama a funcao para movimentar a flecha
            mainState = state;								//retorna a posicao atual
        }
        if ((keys & Key_Down) == 0){			//se a seta de selecao descer
            direction = 'D';
            state = selectionArrow(direction,mainState);	//chama a funcao para movimentar a flecha
            mainState = state;								//retorna a posicao atual
        }          
                 
        if (micro.readable()) {  		//recebe a string da localizacao  do problema
          location= micro.scanf(gps);            
           break;
        }
            
        if ((keys & Key_Center) == 0){  //quando o usuario da enter na opcao desejada
            
            switch (mainState){    //dependendo da opção envia para o modem 3G uma string diferente
                
               case 18 : 
                   pc.printf("1#%c", location);    
                   break;
                    
                case 34 : 
                    pc.printf("2#%c", location);     
                    break;    
                
                case 50 : 
                    pc.printf("3#%c", location);    
                    break;
            }
            
            
            lcd.cls();                         		//limpa o display
            lcd.locate(0, 34);                     //Posiciona na terceira linha
            lcd.printf("TRANSMITINDO DADOS...");  
            wait(20); 								//delay de 20 segundos para dar o tempo de transmissao
            
            lcd.cls();								//limpa o display
            lcd.locate(16, 34);                     //Posiciona na terceira linha
            lcd.printf("DADOS ENVIADOS");
            wait(2);
            
            
            lcdStart();				//funcao que inicializa o lcd
            
        }
       wait(0.2);
    }
}

int selectionArrow(char key, int actualState){ 		//funcao que posiciona a flecha de acordo com a opcao do usuario
    if (key == 'U') {								//para subir
        if (actualState > 18){
            lcd.locate(0, actualState);
            lcd.printf("  ");
            actualState -= 16;
            lcd.locate(0, actualState);                
            lcd.printf(">>");            
            return  actualState;
        }
    }
    if (key == 'D') {							//ou para descer
        if (actualState >= 18 && actualState < 50){
            lcd.locate(0, actualState);
            lcd.printf("  ");
            actualState += 16;
            lcd.locate(0, actualState);                
            lcd.printf(">>");   
            return  actualState;
        }    
    }
    return actualState;
}

void lcdStart () {
    lcd.locate(0, 1);                        //posiciona na primeira linha
    lcd.printf("SELECIONE O PROBLEMA");      //Escreve mensagem na primeira linha
    lcd.locate(16, 18);                     //Posiciona a segunda linha
    lcd.printf("BURACO NO ASFALTO");        //Escreve mensagem na segunda linha
    lcd.locate(16, 34);                     //Posiciona a terceira linha
    lcd.printf("VAZAMENTO DE AGUA");        //Escreve mensagem na terceira linha
    lcd.locate(16, 50);                     //Posiciona a quarta linha
    lcd.printf("ENTULHO");                  //Escreve mensagem na quarta linha
    
    lcd.locate(0, 18);                      //Posiciona a segunda linha
    lcd.printf(">>");                       //Escreve a seta na segunda linha
}

O Modem 3G foi programado em Python, ou seja, foi configurado para receber uma string com todos os dados necessários e os mesmos são enviados para a plataforma IoT.

Esse primeiro código inicializa o Modem, e o prepara para identificar qual operadora o simcard que foi inserido pertence. Depois faz passo a passo a conexão e o envio do dado, e vai informando o processo.

import time
import SER
import MDM
import GPIO
import DW_send
import binascii


print 'Import OKrn'
SER.send('Rodando')



def Config_Oper(): #Busca a operadora e configura APN 
 print 'CONFIG_APN'
 print 'Get Operadorarn'
 
 res=''
 res = MDM.send('AT#LSCRIPTr', 2) 
 res = MDM_receive(2) 
 res = res.upper() 
 print res
 tesc = res.find ('CONFIG_APN.PY') 
 if (tesc==-1): 
 print 'apn defalt'
 res=''
 res = MDM.send('AT+COPS?r', 2)
 res = MDM_receive(2) 
 res = res.upper() 
 print res
 ip='zap.vivo.com.br' 
 usr='vivo' 
 psw='vivo' 
 tes = res.find ('VIVO') 
 if (tes == -1):
 ip='claro.com.br' 
 usr='claro' 
 psw='claro' 
 tes = res.find ('CLARO') 
 if (tes == -1):
 ip='tim.br' 
 usr='tim' 
 psw='tim' 
 tes = res.find ('TIM') 
 if (tes == -1):
 ip='oi.com.br' 
 usr='oi' 
 psw='oi' 
 tes = res.find ('OI') 
 if (tes == -1):
 op1 = 0 
 print 'Operadora desconhecida'
 if (tesc!=-1): 
 print 'arquivo apn'
 import CONFIG_APN
 ip,usr,psw = CONFIG_APN.config()
 if(ip==''):
 res = MDM.send('AT#REBOOTr', 2) 
 return (ip,usr,psw) 
 

def MDM_receive(timeout): # Recebe resposta dos comandos AT
 res = ''
 start = time.time()
 while (time.time() - start < timeout):
 res = res + MDM.read()
 return res
 


def Conect(ip, usr, psw): # Faz a conexão e ganha um endereço de IP 
 tent=0
 con=1

 print 'configure PDP context with APN %s, username %s, password %s' % (ip, usr, psw)
 res=''
 res = MDM.send('AT+CGDCONT=1,"IP","' + ip + '"r', 2) 
 res = MDM_receive(2)
 res = res.find ('OK')
 if (res == -1):
 print 'error setting PDP contextr'
 
 if (usr != ''):
 print 'set GPRS usernamer' 
 res=''
 res = MDM.send('AT#USERID="'+ usr + '"r', 2)
 res = MDM_receive(2)
 res = res.find ('OK')
 if (res == -1):
 print 'error setting GPRS usernamer' 

 if (psw != ''):
 print 'set GPRS passwordr' 
 res=''
 res = MDM.send('AT#PASSW="'+ psw + '"r', 2)
 res = MDM_receive(2)
 res = res.find ('OK')
 if (res == -1):
 print 'error setting GPRS passwordr' 

 print 'activate GPRS contextr'
 
 while(tent<=20)&(con==1): 
 print 'iniciando tentativa ' + str(tent) + ' ...'
 res=''
 res = MDM.send('AT#GPRS?r',2) 
 res = MDM_receive(2)
 res = res.upper()
 print res
 tes = res.find ('#GPRS: 0')
 tes1 = res.find ('#GPRS: 1')
 tes2 = res.find ('#GPRS: 2')
 print tes
 print tes1
 print tes2
 
 if(tes==2): 
 res=''
 res = MDM.send('AT#GPRS=1r',2)
 res = MDM_receive(4)
 print res
 res = res.find ('OK')
 if(res==2):
 print 'conectado'
 if (res == -1):
 print res
 con=1
 print 'Impossivel conectarr'
 if(tes1==2): 
 con=0
 
 if(tes2==2): 
 res=''
 res = MDM.send('AT#GPRS=0r',2)
 res = MDM_receive(4)
 res = res.find ('OK')
 con=1
 if(tent==20)&(con==1):
 res=''
 res = MDM.send('AT#LSCRIPTr', 2)
 res = MDM_receive(2)
 res = res.upper()
 print res
 tesc = res.find ('CONFIG_APN.PY')
 if(tesc!=-1):
 res=''
 res = MDM.send('AT#DSCRIPT="CONFIG_APN.py"r', 2)
 res = MDM_receive(2)
 res = res.upper()
 print res
 tesc = res.find ('OK')
 if(tesc==2):
 res = MDM.send('AT#REBOOTr', 2)
 
 tent=tent+1 
 print 'all settings doner'
 return con

print 'SIPIU_INICIO'
 
op1 = 0
sim1 = 0
tent1 = 0
ok = 0
repete = 0 
 
while((sim1==0)&(tent1<=20)):
 print 'iniciando tentativa ' + str(tent1) + ' ...'
 
 res = MDM.send('AT+CREG=0,0r', 2) 
 res = MDM_receive(2)
 res = res.upper()
 print res
 
 print 'Get Operadorarn'
 
 res = MDM.send('AT+CPIN?r', 2) 
 res = MDM_receive(2)
 res = res.upper()
 print res
 
 
 
 tes = res.find ('ERROR')
 if (tes == -1):
 
 print 'Aguardando registrorn'
 
 res = MDM.send('AT+CREG?r', 2) 
 res = MDM_receive(2)
 res = res.upper()
 print res
 
 tes = res.find ('+CREG: 0,1') 
 print tes
 if (tes == 2):
 print 'Registrado'
 sim1=1
 
 ip,usr,psw = Config_Oper()
 print 'APN'
 print ip
 print 'User'
 print usr
 print 'Password'
 print psw
 
 
 tent1=tent1+1 
 #print op1
 
if(sim1==1):
 
 ok=Conect(ip, usr, psw)
 print 'Chama DW Send'
 sim1=DW_send.DW_connect()
 

if(sim1==0): 
 print 'Nao foi possivel conectar' 
print 'Doner'
print ok


while(repete<=10):
 MDM.send('AT#DWCONN?r', 0);
 res = MDM_receive(1);
 res = res.upper()
 tes = res.find ('#DWCONN: 1,2')
 repete=repete+1
 if (tes==2):
 
 print 'Modem ja conectado no DW'
 conect = 1
 print 'Enviando Dados...'
 DW_send.Status_reg1()
 
 if (repete==10):
 sim1=DW_send.DW_connect()
 repete=0
 if (tes!=2):
 
 print 'Nao foi possivel enviar Dados'
 res = MDM.send('AT#REBOOTr', 2) 

O segundo código faz a conexão do Modem com a plataforma IoT, o Devicewise. Nele são inseridos as informações necessárias para fazer login na plataforma e poder ser feita a comunicação.

import time
import SER
import MDM
import binascii


#################################
APP_TOKEN = # inserir aqui o app token
SER.set_speed('9600','8N1')
#################################

def MDM_receive(timeout): # Recebe respostas de comandos AT
 res = ''
 start = time.time()
 while (time.time() - start < timeout):
 res = res + MDM.read()
 return res
 
def SER_receive(timeout): # Recebe respostas da Serial
 res = ''
 fora = '0'
 start = time.time()
 while (fora=='0'):
 res = res + SER.read()
 if(res[:-1].endswith('x0d')):
 fora='1'
 SER.send(res)
 return res
 
def DW_connect(): #Conecta no DeviceWise
 sim1=0
 tent=0
 MDM.send('AT#DWCFG=open-api.devicewise.com,0,' + APP_TOKEN + 'r', 0)
 res = MDM_receive(5)
 res = res.upper()
 tes = res.find ('OK')
 if(tes!=(-1)):
 print 'APP_TOKEN_OK1'
 MDM.send('AT#DWCONN?r', 0)
 res = MDM_receive(5)
 res = res.upper()
 print res
 tes = res.find ('#DWCONN: 1,2')
 if (tes==2):
 print 'Modem ja conectado no DW'
 sim1=1
 if (tes!=2):
 MDM.send('AT#DWCONN=0r', 0)
 res = MDM_receive(5);
 res = res.upper()
 tes = res.find ('#DWCONN: 0,0')
 if (tes==2):
 print 'Tentando reconectar'
 DW_connect()
 
 while (sim1==0 & tent<=10):
 print 'APP_TOKEN_OK2'
 MDM.send('AT#DWCONN=1r', 0)
 res = MDM_receive(5)
 print res
 res = res.upper()
 tes = res.find ('OK')
 if(tes!=(-1)):
 
 sim1=0
 tent=tent+1
 if(tes!=(-1)):
 print 'DW_connect_OK'
 sim1=1
 return sim1


def gravalog(msg): #Envio de LOG para o DW.
 MDM.read()
 MDM.send('AT#DWSEND=0,log.publish,msg,' + str(msg) + 'r', 0)
 time.sleep(2)
#Fim do bloco gravalog.



def Status_reg1(): # Aguarda receber evento e coordenadas

 SER.send('*')
 a = SER_receive(10)
 print a
 cord=a.split('#')
 if (a!=''):
 print 'dado da resposta'
 print a
 MDM.send('AT#DWSEND=0,property.publish,key,Status,value,' + str(cord[0]) + 'r', 0)
 res = MDM_receive(20)
 print res
 print 'dado enviado'
 MDM.send('AT#DWSEND=0,property.publish,key,Latitude,value,' + str(cord[1]) + 'r', 0)
 res = MDM_receive(20)
 print res
 print 'dado enviado'
 MDM.send('AT#DWSEND=0,property.publish,key,Longitude,value,' + str(cord[2]) + 'r', 0)
 res = MDM_receive(20)
 print res
 print 'dado enviado' 
 if (a==''):
 print 'Sem resposta do medidor'
		

Com o Modem conectado ao Devicewise, podemos observar os dados coletados e sua evolução, e a situação do modem. Nela também é possível fazer alterações remotas.

dd11

 

Através da plataforma IoT é possível referenciar o site, que está sendo desenvolvido, com todos os dados coletados, e que gera a localização exata em um mapa dinâmico.

Todos os códigos encontram-se no meu perfil do Github.

Referências:

1 – http://www.embarcados.com.br/primeiros-passos-com-lpcxpresso4337/

2 – http://www.embarcados.com.br/lpcxpresso4337-no-mbed/

3 – https://cloud.m2mair.com/app/login

4 – http://www.nxp.com/

5 – http://duodigit.com.br/

6 – http://www.telit.com/

7 – http://www.sketchup.com/pt-BR/download

8 – https://www.mbed.com/en/

9 – https://www.sigfox.com/

10 – http://www.nxp.com/documents/leaflet/OL2385LWPWRLF.pdf

11 – https://github.com/renatadecamillo/SIPIU