Página 1 de 1

Ajuda comunicação!!!

MensagemEnviado: 26 Jul 2011 10:29
por daniel.sloczynski
Olá amigos!

Venho pedir ajuda a alguém mais experiente.
Estou tentando implementar a comunicação modbus rtu com um inversor de frequencia, ondeo pic é o master.

Mando o telegrama, mas o inversor nem pisca o led indicando que está enviando uma resposta de volta.
Já testei ligando no hyperterminal, ele manda certo, e calcula o crc certo... Será algo relacionado a algum delay que está faltando?



Segue o código abaixo para alguém que estiver disposto a me ajudar.


#include <18F4620.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=16000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7)
#include "stdio.h"
#include "LCD_4B.c"


//////////////////////////////////////////declaração das variaveis///////////////////////////////////



unsigned char buf_485[30];
unsigned char CRC_bytes[2];//cria um vetor para armazenar o valor do crc
char flag=0;

///////////////////////////////////////////////funçoes usadas/////////////////////////////////////////

void Calculo_CRC(unsigned int num_of_char,unsigned char *ptr_num)//,register unsigned int checksum) checksum = 0XFFFF
{
char i,j;//variaveis local
long checksum = 0XFFFF;//resultado do crc
for (i=0; i < num_of_char; i++)
{
checksum ^= *ptr_num; // executa uma operação ex or (XOR)
ptr_num++; // pega proximo caracter da sequencia(rotaciona uma unidade a direita no vetor)
for (j=0; j < 8; j++) // checa os 8 bits do caracter
{
if ((checksum & 0x01) == 0) // se LSB bit = 0
{
checksum >>= 1;//apenas rotaciona o bit sem nenhum tratamento
}
else
{
checksum = (checksum >> 1) ^ 0XA001;//rotaciona o bit e faz um ou logico(OR) com 0XA001
}
}
}
CRC_bytes[0]=checksum;
CRC_bytes[1]=checksum>>8;

}

/////////////////////////////////////////////////////////////////////////////////////////////////////
void main()



{


lcd_ini();


while(1)

{
if (!input(pin_a2)&&flag==0)
{



buf_485[0] = 0x01; // Endereço do Slave
buf_485[1] = 0x03; // Função MODBUS: Read Input Register
buf_485[2] = 0x00; // Registro inicial para ler (MSB)
buf_485[3] = 0x02; // Registro inicial para ler (LSB)
buf_485[4] = 0x00; // Total de registros para ler (MSB)
buf_485[5] = 0x02; // Total de registros para ler (LSB)
Calculo_CRC(6, buf_485); //coloquei a quantidade-1,pois a contagem
buf_485[6] = CRC_bytes[0]; // CRC (LSB)
buf_485[7] = CRC_bytes[1]; // CRC (MSB)
delay_us(3000);
printf("%X%X%X%X%X%X",buf_485[0],buf_485[1],buf_485[2],buf_485[3],buf_485[4],buf_485[5]);
printf("%X%X", buf_485[6],buf_485[7]);
delay_us(6000);
flag=1;
}


if(!input(pin_a3))

{
flag=0;
}



}









}

MensagemEnviado: 26 Jul 2011 11:30
por RobL
Seu CRC está com os bytes invertidos no buffer.
O CRC_Hi vai primeiro, depois o CRC_Low.

Inverta o byte do CRC na sua função printf().

Se houver qualquer atraso maior que 1,5bit, durante a TX, o telegrama será ignorado. Note que a funcao de envio foi dividida em duas. Isto não deve gerar este atrso em 9.600bps mas fique atento. Não deve haver uma interrupção, durante a TX que gere esse gap. Portanto, para teste, retire a interrupção, durante as suas funções printf().

O CRC tem que ser calculado, no seu exemplo, desde o ítem 0 a 5 do seu buffer, ou seja, 6 bytes. Como seu loop foi inicializado com zero deverá sair ao testar o valor 6 (que seria o sétimo byte).

Salvo se o servo não devolve código de erro, deveria lhe retornar algo.

Como não lhe devolve erro, cabe lembrar:
Com o hiperterminal você está enviando sinal RS232 (+12 e -12V)
Com o PIC deve sair RS232 também. Tem lá o conversor ?
O baud rate deve ser o mesmo.

MensagemEnviado: 26 Jul 2011 20:46
por RobL
Dando outra olhada, parece que sua função trata o sinal para RS232.
Como você coloca o nome do buffer como char buf_485[30], será que você está de fato com um conversor RS485 na saída do PIC (ou RS232) ?
A dúvida é que você testou com o PC através do hyperterminal (RS232). A não ser que tenha convertido RS232 para RS485.

Se estiver usando RS485, quem está controlando o sinal habilita TX, habilita RX ?
Ou está somente transmitindo, sem receber ?
Apesar do padrão elétrico RS-485 não ser definido como half duplex, normalmente é usado como tal. Neste caso tem que ter o sinal para habilitar tx e ao final de tx habilitar rx.
Hummm! Acho que é o seu char_flag quem faz o papel da direção no RS-485.

Outra sugestão:
Você pode estar com mais um problema, pois deve estar usando RS-485.

Note que a UART é um periférico e após jogar um byte para dentro dela, ela vai continuar a transmitir seu byte independente de seu programa.
Porém (isto é muito importante), seu programa não pode mudar o sinal de direção ainda. O sinal TX/RX(suponho seu char_flag) não pode mudar antes de 10bits a 9600 bps, após sua segunda printf(crc) retornar. Se mudar, corta a tx, apesar da UART continuar enviando os bits do último byte.
Para teste, mude a direção para RX após 20 bits a 9600 bps e ajuste esse tempo em função do seu programa e seu hardware (capacitâncias).

Olha, dividir o buffer em 2 printf() eu não entendi a finalidade e pode causar problema, caso entre uma interrupção, após o retorno da primeira printf().

MensagemEnviado: 27 Jul 2011 13:14
por daniel.sloczynski
Galera, é o seguinte...

Primeiramente obrigado pelo interesse em tentar me ajudar.

Eu tenho um conversor RS232/RS485 e na placa onde está o pic tenho um max232 para converter os níveis de ttl(pic) para rs232... No hardware não existe problema. É o próprio conversor quem se encarrega de fazer este controle de TX e RX (por hardware).


O problema é mesmo no software... Na verdade é meio grosseiro(eu pelo menos acho) utilizar o printf para mandar os dados, mas foi esse o jeito que me ocorreu. Sei que existe outras maneiras, mas não sei como fazer.

E outra, se o printf funcionar, que comando eu uso para ler a uart do pic e ver se ele recebeu algo de volta?


Creio eu que seja problema relacionado a estrutura do telegrama.

No padrão modbus-rtu o telegrama é

|START BIT|B0|B1|B2|B3|B4|B5|B6|B7|STOP BIT|STOP BIT|


Uso dois stop bits pq não tô usando paridade.

Mas na real essa é a estrututa que o telegrama deveria ter.
Mas como faço no softrware para ter certeza que ele tá gerando esse start bit, e depois os dois stop bit?

Caso não tiver isso a mensagem é ignorada pelo inversor.
Creio que é esse o meu problema.


Talvez agora, que eu me expliquei melhor, alguém possa me dar uma ajuda, hehehe.


Abraço!

MensagemEnviado: 27 Jul 2011 14:32
por RobL
Errei. No LRC (com ele "L") é que a ordem do byte é Hi primeiro e Low depois.
No CRC a ordem do seu buffer está correta. Verifique no protocolo se é isso mesmo.

Baixe este programa, do link abaixo, ligue o seu PIC no PC e mande o seu telegrama para o Mbus.exe .
Verifique seu telegrama no programa. Assim ficará mais fácil. O programa é free.

http://www.modbus.pl/download/zxy66/v19/Mtester.zip

MensagemEnviado: 27 Jul 2011 15:18
por RobL
Respondendo a sua pergunta sobre os stop bits.
Quem gera eles é a UART, conforme configuração. Isto deve estar sendo feito pela sua função rs232.

Você tem certeza qual a configuração do seu servo (inversor) se um ou dois stop bits ?

MensagemEnviado: 27 Jul 2011 15:58
por daniel.sloczynski
Quanto ao CRC, está certo, segundo o manual do inversor.


Primeiro low, depois high.


E dos dois stopbits também tenho certeza.




Acho que essa função não tá mandado os caracteres realmente em hexadecimal como tem que ser.

Só não sei o pq.


Vou dar uma olhada nas configurações da uart pra ver se tem dois stop...


Abraço!

MensagemEnviado: 27 Jul 2011 19:48
por Djalma Toledo Rodrigues
daniel.sloczynski escreveu: ...
Acho que essa função não tá mandado os caracteres realmente em hexadecimal como tem que ser.


Hexad ou ASCII ?


DJ

MensagemEnviado: 28 Jul 2011 17:43
por daniel.sloczynski
Dando um feedback pra galera....


Resolvi o problema da comunicação.


Configurei a uart no braço mesmo, sem essa diretiva do "#use rs232"
e escambal.


Meu cálculo pra crc está sendo, desse jeito nas coxa mesmo, sem precisar da tabela.
O inversor respondendo aos comandos do pic...

Não sabem a minha alegria ao ver aquele led de tx do inversor piscar, depois de quase uma semana tentando fazer funcionar.



Agora estou criando minhas próprias funções, conforme eu preciso na comunicação com o inversor.

Se pintar alguma dúvida volto aqui e peço ajuda pra galera.


Agradeço aos que tentaram me ajudar.


Abraços!

MensagemEnviado: 28 Jul 2011 19:24
por RobL
Meu cálculo pra crc está sendo, desse jeito nas coxa mesmo, sem precisar da tabela.


Não há nada de errado com seu cálculo de CRC em termos de qualidade.
Com a tabela, gasta-se muita flash, devido ao grande número de constantes. Calculando em run time, gasta-se processamento e tempo. É apenas questão de opção em função do que se tem e quer.

Essa "macro" deveria estar gerando código em ASCII.

Bom que resolveu.