Ir ao conteúdo
  • Cadastre-se

Tutorial : Introdução ao uso de PIC´s em BASIC com o PIC Simulator IDE - Parte 1/2


Posts recomendados

Ola a todos,

Bem pessoal conheci, e ainda conhecendo o mundo da programação de micro controladores pic usando pic Simulator (PSI) através deste fórum e lendo a apostila do prof. Paulo “pena que ele abandonou os PICs”,mas infelizmente não evolui muito neste período.

Mas ainda nao desisti, desenvolvi um projeto para automatizar uma bomba d água que abastece o sistema de caixas aqui de casa, acredito que para a maioria aqui seja algo simples, mas para mim foi uma evolução e tanto.

Vou postar o código e tentar descrever o projeto, e o motivo deste post.

O sistema e basicamente uma comunicação serial via módulos de RF 433MHZ entre dois pic, sendo que o Transmissor faz a leitura de três sensores "duas bóias magnéticas e um eletrodo”, instaladas na caixa d água, e envia para o receptor que se encarrega de fazer o trabalho pesado, tenho o sistema instalado e funcionando já a um bom tempo, mas às vezes acontecem algumas interferências (Rf) que faz com que o sistema funcione de forma errada.

Modifiquei o código para tentar melhorar isto, ainda não testei na pratica, na simulação (Proteus) funcionou ok, a modificação foi criar uma constante que chamei de "ID" e enviar junto com os dados (variáveis "sensor "), e comparar com uma constante “ID" no receptor, se as constantes forem diferentes entre-se o sistema e bloqueado ou desativado.

Gostaria da opinião e ajuda de vocês para saber se e isto mesmo? Ou tem uma melhor forma de resolver isto, para tornar o sistema mais confiável.

 

Obs. Se alguém se interessar só pedir que posto os desenhos.

 

Codigo transmissor.

'TRANSMISSOR RF433Mhz "SERIAL v1.0"
'PIC16F628A CLOCK INTERNO 4 MHZ
Define CONF_WORD = 0x3f38
AllDigital
Define CLOCK_FREQUENCY = 4
TRISA = 00000111b  'Bits 0 ao 2 entada p/ sensores
TRISB = 00000000b  'Leds_Bits 5,6,7
PORTA = 0
PORTB = 0
Define SEROUT_DELAYUS = 2000
CMCON = 0x07
OPTION_REG.7 = 0x00
Dim sensor As Byte
Dim n As Byte
Const id = 211
Symbol serial_tx = PORTB.2  'Saida p/ modulo RF 433MHZ "Serial"
Symbol led_sp = PORTB.5
Symbol led_sc = PORTB.6
Symbol led_sv = PORTB.7
'-----------------------------------------------------
'******** Inicializaçao *********
For n = 0 To 4
Toggle led_sp
Toggle led_sc
Toggle led_sv
WaitMs 300
Next n
'------------------------------------------------------
'********* Inicio Programa ********
inicio: 'Transmissao
sensor = PORTA And 00000111b
WaitMs 50
SeroutInv serial_tx, 600, id, sensor
led_sp = Not PORTA.0  'SP
led_sc = Not PORTA.1  'SC
led_sv = Not PORTA.2  'SV
Goto inicio

 

Codigo receptor.

'RECPTOR RF433Mhz "SERIAL v1.0"
'PIC16f628a oscilador interno 4MHZ
Define CONF_WORD = 0x3f38
Define CLOCK_FREQUENCY = 4
AllDigital
CMCON = 0x07
OPTION_REG.7 = 0x00
TRISB = 00000010b
PORTB = 0
Symbol serial_rx = PORTB.1  'Entrada p/receptor Modulo RF "Serial"
Symbol buzzer = PORTB.6  'Saida para alarme "Buzer"
Symbol rele = PORTB.7  'Saida para rele "Bomba d'agua"
Symbol led_sp = PORTB.3  'Leds sensores
Symbol led_sc = PORTB.4  '"""" """"""""
Symbol led_sv = PORTB.5  '"""" """"""""
Symbol erro_com = PORTB.0  'Led erro de comunicaçao
Dim n As Byte
Dim valor As Byte
Dim flag_sv As Bit
Dim id As Byte  'Teste id
id = 0
valor = 0
flag_sv = 0
erro_com = 0  'Teste id
'***************************************************
'"So pra facilitar a vida"
'Binario __ decimal
'sensors<=>valor
'SP = sensor de caida (Proteçao contra falha, falta de agua no poço etc...)
'SC = nivel maximo
'SV = nivel minimo
'sp,sc,sv
'0  0  0  = 0
'0  0  1  = 1
'0  1  0  = 2
'0  1  1  = 3
'1  0  0  = 4
'1  0  1  = 5
'1  1  0  = 6
'1  1  1  = 7
'*****************************************************
For n = 0 To 3  'Pisca "leds_Inicializaço"
Toggle led_sp
Toggle led_sc
Toggle led_sv
WaitMs 300
Next n
Goto inicio
'*****************************************************
End                                               
'--------------------------------------------------------------------------
'**********INICIO_PROGRAMA **********
inicio:'Recepcao
Gosub receber  'Receber leirura da serial
While valor = 4
Goto inicio
Wend
Gosub sensores  'Verifica sensores
Goto inicio
'--------------------------------------------------------------------------
sensores:
If valor = 7 And flag_sv = 0 Then Gosub liga
If valor = 7 And flag_sv = 1 Then Gosub alarme
If valor = 6 And flag_sv = 1 Then Gosub alarme
If valor = 0 Then Gosub desliga
Return                                            
'-------------------------------------------------------------
liga:
rele = 1  'Liga rele "Motor Bomba"
flag_sv = 1
WaitMs 5000  'Tempo ate começar a cair agua na caixa(+-45 SEGUNDOS)
Gosub receber
If valor = 6 Then
flag_sv = 0
Else
flag_sv = 1
Endif
Return                                            
'----------------------------------------------------------------
desliga:
buzzer = 0  'Desativa alarme
rele = 0  'Desliga rele
flag_sv = 0  'Zera flag_sv
Return                                            
'----------------------------------------------------------------
alarme:
rele = 0  'Desativa rele (bomba d`agua)
Toggle buzzer  'Toca_alarme sonoro
Toggle led_sp  'Pisca Leds
Toggle led_sc  '- "     "
Toggle led_sv  '- "     "
WaitMs 400
Goto alarme
'-----------------------------------------------------------------
receber:  'Serial
SerinInv serial_rx, 600, id, valor  '*******Teste id
led_sv = Not valor.0  'led = inverso do bit_0 da variavel valor
led_sc = Not valor.1  'led = inverso do bit_1 da variavel valor
led_sp = Not valor.2  'led = inverso do bit_2 da variavel valor
If id <> 211 Then  'Se houver falha de comunicaçao
buzzer = 0  'Desativa alarme
rele = 0  'Desliga rele
flag_sv = 0  'Zera flag_sv
'------------------------------------------------------------------
For n = 0 To 5
Toggle erro_com  'Pisca Led  erro_com
WaitMs 100
Next n
'------------------------------------------------------------------
WaitMs 200
Goto receber
Else
Endif
Return

 

ABS.

jfeliciano

Link para o comentário
Compartilhar em outros sites

@jfeliciano,

 

Nossa ainda tenho saudades do PSI.... mas eu tive de abandonar o PSI, pois ele não permitia comunicações mais avançada como o I2C, SPI, etc.....

 

A escolha pelo Bascom eliminou todos esses gargalos, mas como ele só rodacom os AVR's, tive de mudar . Mas como já disse várias vezes, ainda bem que mudei !!!!!

 

Bom, quanto ao seu problema, que tal voce sempre enviar um byte extra, por exemplo, caso voce esteja transmitindo apenas um byte, envie um segundo byte, com os bits individuais invertidos ?

 

Assim voce compara o primeiro com o segundo, e caso não sejam exatamente invertidos, voce descarta essa recepção por erro !!!

 

Caso esteja enviando mais de um byte, por exemplo, 3 bytes, envie sempre um quarto byte, cujo valor é a soma dos tres primeiros ?  Assim quando receber seus bytes, faça a soma na recepção dos tres primeiros e compare com o valor do quarto ?

 

Essa técnica se chama Checksum, e é uma técnica simples mas ajuda muito a diminuir os erros ou interferências !

 

Paulo

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Paulo, muito obrigado pela resposta.

Quem sabe um dia tambem tente brincar com os avrs,mas ainda tenho muito que aprender com os pics, ate ganhei um arduino UNO de um amigo ,mas por enquato esta na gaveta.

Nao sei se voce deu uma olhada no meu programa, mas eu fiz uma modificaçao que nao testei na pratica, so simulei, onde estou enviando um byte ( constante ), e na sequencia envio os bytes com os dados ( 3 bits que podem variar de 0 a 7), e na recepçao verifico se a constante recebida e igual outra no receptor, se for diferente inibe o sistema. nao sei se na pratica vai funcionar.

Seria posivel voce postar um exemplo pratico do que voce disse?,pois nao entendi muito bem com fazer, ja que meus dados muda de valor frequentemente (0 a 7).

 

Grato.

jfeliciano

Link para o comentário
Compartilhar em outros sites

jfeliciano, seria melhor colocar o trecho do codico do que ele todo ficaria mais fácil de entender.

 

Eu ja fiz o Modbus usando PIC Basic, no receptor nao usei Checksum, fiz um sistema bem simples de contagem de bits.

 

Você pode fazer o seguinte, vou descrever em passos

 Acredito que você tenha feito uma interrupção para dados na porta, foi isso?

 

Faça um pacote de 4 bits

 

Vou tentar fazer pseudo-codico

 

Variáveis

Port.x "porta que recebe os dados"

contador_a

contador_b

Dado_a

​Dado_b

​Dado_c

​Dado_d

 

Inicio

contador_a = 0

contador_b = 1

 

 

port.x (recebe dado na porta, primeiro bit do pacote)

 

interrupção

 

contador_a= contador_a +1

 

se contador_a = 1

Dado_a = port.x

Contador_b = 1

se contador_a = 2

Dado_b = port.x

se contador_a = 3

Dado_c = port.x

se contador_a = 4

Dado_d = port.x

contador_b = 0

Fim da interrupção

 

Main:

 

Se contador_b = 0 e contador_a = 4

'trata os dados"

contador_a = 0

Fim Se

 

se contador_b = 50

contador_b = 0

contador_a = 0

Fim se

 

contador_b = contador_b + 1

Fim Main

 

Espero que entenda o codico acima

você tem um tempo de 50 ciclos para receber 4 bits que inicia quando recebe o primeiro bit

O pacote só sera valido se receber 4 bits em um tempo menor que 50 ciclos, caso receba um numero menor que 4 o contador_a é zerado em 50 ciclos e descarta o pacote.

Link para o comentário
Compartilhar em outros sites

Rafael.luc, obrigado pela resposta.

Desculpe pelo tamanho do texto, e que ainda estou meio perdido com a nova cara do forum.

Nao usei interupcao, apenas criei loops , que fica o tempo todo enviando e recebendo dados,

Ate porque so sei mesmo o fijao com arros kakakak....,nao sei como seria sua ideia porque meus dados pode mudar em poucos minutos ou demorar um dia ou mais para mudar.

 

Abs

jfeliciano

Link para o comentário
Compartilhar em outros sites

jfeliciano, nao conheço nada sobre RF, mas em comunicação entre dois PICs o dado recebido na porta é de alta prioridade deve usar  interrupção para nao perder o dado.

Loop de ficar dando um "Scan" na porta é usado para leitura, geralmente é usado para atualizar um valor no LCD ou algo assim.

Link para o comentário
Compartilhar em outros sites

jfeliciano, nao conheço nada sobre RF, mas em comunicação entre dois PICs o dado recebido na porta é de alta prioridade deve usar  interrupção para nao perder o dado.

Loop de ficar dando um "Scan" na porta é usado para leitura, geralmente é usado para atualizar um valor no LCD ou algo assim.

Rafael.luc, como falei nao sou um expert na arte de programar, mas o que sei e que o sistema funcIona ja ha um bom tempo sem problemas ,apenas ocasionalmente ( raramente) sofre com alguma interferencia na parte do RF,o que faz com que o sistema fique louco,por isso gostaria de tornar o sitema mais confiavel.

Obs. destaquei com cores diferente a parte importante do codigo para facilitar o entendimento.

Att.

jfeliciano

Link para o comentário
Compartilhar em outros sites

Esqueça meu codico, tive fazer por bit o você fez foi armazenar o valor em um Byte.

 

Pelo que vi você recebe o valor do RF na variavel id, seria melhor fazer isso

 

Main (exemplo)

 

SerinInv serial_rx, 600, id "Essa função SerinInv ativa um loop internamente ate ler o ultimo bit

 

Se id = 101

aciona_1

 

 

Se id = 102

aciona_2

 

 

Se id = 103

aciona_3

 

Se id < 101 e id > 103 e id > 0

erro

 

id = 0 "coloque no final do main

 

Fim 

Link para o comentário
Compartilhar em outros sites

Acho que ainda não consegui ser claro na explicação.

Este código postado já foi modificado e testado apenas na simulação, mostrou funcionar na forma desejada.

Gostaria de uma opinião se isto e valido na pratica, ou tem forma melhor de fazer.

A modificação foi que acrescentei uma constante "ID" com o valor ( 211) escolhido ao acaso, e enviado serialmente com a variável "sensor" (leitura dos sensores ligado ao PortA .BITs 0,1,2) , e recebido em "ID", e também " sensor" que e guardado na variável "valor" , se o valor de "ID " recebido for (211) o programa executa normalmente, caso contrario o sistema será inibido ou desativado se já estiver  em execução, e sinaliza com um LED ligado no PortB.0  "led erro_com"

Acredito que desta forma seria muito difícil uma interferência (lixo) conseguir gerar exatamente uma “ID” com o valor (211)-binário -11010011, e se faltar também comunicação (falta de luz no transmissor, por exemplo. etc...) o sistema também se comportaria da mesma forma.

Não sei se falei besteira, mas se falei corrijam-me, por favor.

 

Att.

jfeliciano

Link para o comentário
Compartilhar em outros sites

Checksum como é implementado é bastante complicado devido as operações envolvidas.

 

No seu caso que tem apenas 3 bits (um byte), eu faria da seguinte forma, como você esta enviando 2 bytes, sendo o segundo um byte verificador.

 

No Byte de dados, você faz uma mascara inversa, cuja o resultado você armazena numa variável.  O primeiro byte você envia sem mascara e o segundo é a mascara inversa do primeiro byte.

No receptor você pega o primeiro byte e aplica mascara inversa e depois compara com o segundo byte recebido, se for igual não ouve corrupção de dados.

 

É fácil de fazer, vou tentar fazer um pseudo codico

 

variáveis:

byte_dado

byte_verificador

 

byte_verificador = mascara(byte_dado)

 

Envia serial byte_dado, byte_verificador

 

No receptor

 

variáveis:

byte_dado

byte_verificador

Byte_masc

 

Recebe serial byte_dado, byte_verificador

byte_masc = mascara(byte_dado)

 

se (byte_masc = byte_verificador)

trata os dados

senao

erro

 

 

Procure por mascara de bits no manual, faz algum tempo que nao programo 

Link para o comentário
Compartilhar em outros sites

Checksum como é implementado é bastante complicado devido as operações envolvidas.

 

No seu caso que tem apenas 3 bits (um byte), eu faria da seguinte forma, como você esta enviando 2 bytes, sendo o segundo um byte verificador.

 

No Byte de dados, você faz uma mascara inversa, cuja o resultado você armazena numa variável.  O primeiro byte você envia sem mascara e o segundo é a mascara inversa do primeiro byte.

No receptor você pega o primeiro byte e aplica mascara inversa e depois compara com o segundo byte recebido, se for igual não ouve corrupção de dados.

 

É fácil de fazer, vou tentar fazer um pseudo codico

 

variáveis:

byte_dado

byte_verificador

 

byte_verificador = mascara(byte_dado)

 

Envia serial byte_dado, byte_verificador

 

No receptor

 

variáveis:

byte_dado

byte_verificador

Byte_masc

 

Recebe serial byte_dado, byte_verificador

byte_masc = mascara(byte_dado)

 

se (byte_masc = byte_verificador)

trata os dados

senao

erro

 

 

Procure por mascara de bits no manual, faz algum tempo que nao programo 

Caramba!!!!! :huh:  isto esta cada vez mais confuso para mim, nao estou conseguindo captar este lance da mascara :confused:,Acho o  manual do PSI e meio pobre.

Link para o comentário
Compartilhar em outros sites

Use a funcao ShiftLeft ou ShiftRight

 

 

variáveis:

byte_dado

byte_verificador

 

byte_verificador = ShiftRight(byte_dado, 1)

Envia serial byte_dado, byte_verificador

 

No receptor

 

variáveis:

byte_dado

byte_verificador

Byte_masc

 

Recebe serial byte_dado, byte_verificador

byte_masc = ShiftRight(byte_dado, 1)

 

se (byte_masc = byte_verificador)

trata os dados

senao

erro

Link para o comentário
Compartilhar em outros sites

Use a funcao ShiftLeft ou ShiftRight

 

 

variáveis:

byte_dado

byte_verificador

 

byte_verificador = ShiftRight(byte_dado, 1)

Envia serial byte_dado, byte_verificador

 

No receptor

 

variáveis:

byte_dado

byte_verificador

Byte_masc

 

Recebe serial byte_dado, byte_verificador

byte_masc = ShiftRight(byte_dado, 1)

 

se (byte_masc = byte_verificador)

trata os dados

senao

erro

Mas neste caso o que vai acontecer quando byte_dado for =0 ?

Link para o comentário
Compartilhar em outros sites

Acho que pra fazer desta forma teria que acrescenta mais um bit ao byte_dados(3-bits) ,veja na tabela abaixo, pois 001 tambem e um dado valido(util).

Mas se for usar 4 bits talvez tenha que refazer todo o programa.

 

'SP = sensor de caida (Proteçao contra falha, falta de agua no poço etc...)
'SC = nivel maximo
'SV = nivel minimo
'sp,sc,sv
' 0   0   0  = 0
' 0   0   1  = 1
' 0   1   0  = 2
' 0   1   1  = 3
' 1   0   0  = 4
' 1   0   1  = 5
' 1   1   0  = 6
' 1   1   1  = 7

'*****************************************************

EDIT.

Veja esta outra ideia que tive, acho que ficou melhor que a primeira, o que voce  acha ?.....

 

TRANSMISSOR......
Variaveis,
Dim sensor As Byte
Dim id As Byte
inicio:
sensor = PORTA And 00000111b
id = sensor + 211
SeroutInv serial_tx, 600, sensor, id
GOTO inicio
*******************************************************
RECEPTOR.....
Variaveis,
Dim valor As Byte
Dim id As Byte  'Teste id
Dim id_rx As Byte
id = 0
id_rx = 0
valor = 0
'-------------------------------------------------------
receber:  'Serial
SerinInv serial_rx, 600, valor, id
id_rx = valor + 211
SE id_rx <> id  >>ERRO  'Se houver falha de comunicaçao
Senao >> CONTINUA.....

Link para o comentário
Compartilhar em outros sites

Para evitar o problema do zero poderia fazer isso

 

 

Recebe serial byte_dado, byte_verificador

byte_masc = ShiftRight(byte_dado, 1)

 

se (byte_masc = byte_verificador)

trata os dados

senao

erro

 

Se byte_dado = 001

byte_dado = 002

senao

byte_dado = 001

 

//Nao zera a variavel byte_masc ela deve permanecer com ultimo valor da operação.


No seu codico

 

TRANSMISSOR......
Variaveis,
Dim sensor As Byte
Dim id As Byte
inicio:
sensor = PORTA And 00000111b
id = sensor + 211 ( voce nao pode somar, se a soma for maior que 255 ID vai zerar porque é maior que um byte, ou seja, maior que 3 bits)

Por isso coloquei ShiftRight  que só muda a posição dos bits dando outro valor e o resultado sempre sempre sera em 3 bits.

Link para o comentário
Compartilhar em outros sites

Mas você levou em consideração que quem define o valar da variável dados (sensor) e os sensores instalado na caixa, e que este valor nuca vai ultrapassar o valor 7(111)?

E sempre tenho que zerar as variáveis auxiliares (id & id_rx).

 

Sim esta certo, confundi com valor total do Byte que é 255

Link para o comentário
Compartilhar em outros sites

Estou achando meio complicado e recompor a variável dados (sensor), na recepção depois de fazer o deslocamento (Shift) dos Bits,por que ela precisa ser  exatamente o valor dos sensores.

voce vai decompor e armazenar em outra variável  a variável dados (sensor) iria permanecer no mesmo valor que foi recebido, ou seja, não seria alterado.

 

Mas pode fazer com soma como havia feito, o que importa é faça uma operacao

Link para o comentário
Compartilhar em outros sites

Visitante
Este tópico está impedido de receber novas respostas.

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

Ebook grátis: Aprenda a ler resistores e capacitores!

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!