Ajuda comunicação!!!

Software e Hardware para uC PIC

Moderadores: andre_luis, 51, guest2003, Renie

Ajuda comunicação!!!

Mensagempor daniel.sloczynski » 26 Jul 2011 10:29

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;
}



}









}
daniel.sloczynski
Bit
 
Mensagens: 47
Registrado em: 28 Abr 2011 09:13

Mensagempor RobL » 26 Jul 2011 11:30

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.
RobL
Dword
 
Mensagens: 1546
Registrado em: 20 Fev 2007 17:56

Mensagempor RobL » 26 Jul 2011 20:46

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().
RobL
Dword
 
Mensagens: 1546
Registrado em: 20 Fev 2007 17:56

Mensagempor daniel.sloczynski » 27 Jul 2011 13:14

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!
daniel.sloczynski
Bit
 
Mensagens: 47
Registrado em: 28 Abr 2011 09:13

Mensagempor RobL » 27 Jul 2011 14:32

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
Editado pela última vez por RobL em 27 Jul 2011 15:12, em um total de 1 vez.
RobL
Dword
 
Mensagens: 1546
Registrado em: 20 Fev 2007 17:56

Mensagempor RobL » 27 Jul 2011 15:18

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 ?
RobL
Dword
 
Mensagens: 1546
Registrado em: 20 Fev 2007 17:56

Mensagempor daniel.sloczynski » 27 Jul 2011 15:58

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!
daniel.sloczynski
Bit
 
Mensagens: 47
Registrado em: 28 Abr 2011 09:13

Mensagempor Djalma Toledo Rodrigues » 27 Jul 2011 19:48

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
Avatar do usuário
Djalma Toledo Rodrigues
Dword
 
Mensagens: 2334
Registrado em: 03 Ago 2008 13:22

Mensagempor daniel.sloczynski » 28 Jul 2011 17:43

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!
daniel.sloczynski
Bit
 
Mensagens: 47
Registrado em: 28 Abr 2011 09:13

Mensagempor RobL » 28 Jul 2011 19:24

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.
RobL
Dword
 
Mensagens: 1546
Registrado em: 20 Fev 2007 17:56


Voltar para PIC

Quem está online

Usuários navegando neste fórum: Nenhum usuário registrado e 1 visitante

cron

x