Autor Tópico: Modbus RTU com PIC  (Lida 4906 vezes)

Description:

0 Membros e 2 Visitantes estão vendo este tópico.

Offline EduardoGrieger

  • Novato
  • *
  • Posts: 7
  • Sexo: Masculino
  • GUIA CNC BRASIL
  • Cidade - UF: Sertãozinho - SP
  • Nome:: Eduardo Grieger
  • Profissão: Engenheiro de Aplicações
Modbus RTU com PIC
« Online: 19 de Outubro de 2017, 08:44 »
Olá pessoal, preciso de uma ajuda para desenvolver uma lógica de comunicação Modbus RTU entre um microcontrolador PIC e um supervisório.


Minha arquitetura é a seguinte:


Tenho um microcontrolador 16F877A e o mesmo terá que comunicar via modbus  RTU com um sistema de supervisório indusoft. A comunicação precisa ser Modbus por conta da distância que o microcontrolador ficará do PC. Entre o PC e o microcontrolador tenho um conversor TTL/RS485.


Estou usando o compilador MikroC Pro para desenvolver a lógica do microcontrolador.


Desde já agradeço a atenção de todos.

Offline minilathe

  • How to ask questions - The Smart Way...
  • Moderadores
  • CNCMASTER
  • ******
  • Posts: 4295
  • Sexo: Masculino
  • http://science-lakes.com/article43-html.html
  • Cidade - UF: Rio de Janeiro - RJ
  • Nome:: Gil Pinheiro
  • Profissão: Engenheiro e professor universitário
Re:Modbus RTU com PIC
« Resposta #1 Online: 19 de Outubro de 2017, 09:02 »
Você quer desenvolver um Slave ou Master Modbus?
Quais funções Modbus pretende usar?

Offline EduardoGrieger

  • Novato
  • *
  • Posts: 7
  • Sexo: Masculino
  • GUIA CNC BRASIL
  • Cidade - UF: Sertãozinho - SP
  • Nome:: Eduardo Grieger
  • Profissão: Engenheiro de Aplicações
Re:Modbus RTU com PIC
« Resposta #2 Online: 19 de Outubro de 2017, 10:23 »
Olá Minilathe,


Eu quero desenvolver um Slave Modbus RTU, onde o SCADA deverá trocar dados com ele.


As funções que preciso é:


Ler dados do microcontrolador, boolenas e inteiras;
Escrever dados no microcontrolador, booleanas e inteiras;

Offline minilathe

  • How to ask questions - The Smart Way...
  • Moderadores
  • CNCMASTER
  • ******
  • Posts: 4295
  • Sexo: Masculino
  • http://science-lakes.com/article43-html.html
  • Cidade - UF: Rio de Janeiro - RJ
  • Nome:: Gil Pinheiro
  • Profissão: Engenheiro e professor universitário
Re:Modbus RTU com PIC
« Resposta #3 Online: 19 de Outubro de 2017, 11:40 »
Há vários anos criei um Master para um pic similar a este seu (com menos pinos). O Slave é um pouquinho mais complicado, seria conveniente usar interrupção, para a correta detecção da mensagem de requisição.

Offline EduardoGrieger

  • Novato
  • *
  • Posts: 7
  • Sexo: Masculino
  • GUIA CNC BRASIL
  • Cidade - UF: Sertãozinho - SP
  • Nome:: Eduardo Grieger
  • Profissão: Engenheiro de Aplicações
Re:Modbus RTU com PIC
« Resposta #4 Online: 19 de Outubro de 2017, 12:01 »
No compilador MikroC tem um exemplo de comunicação mestre e escrava via RS485 mas não sei se é modbus, ou seja, não sei identificar se é modbus ou não. Segue abaixo o exemplo:


PIC Master Code:



char dat[10];                          // buffer for receving/sending messages
char i,j;


sbit  rs485_rxtx_pin  at RC2_bit;               // set transcieve pin
sbit  rs485_rxtx_pin_dire ction at TRISC2_bit;   // set transcieve pin direction


// Interrupt routine
void interrupt() {
  RS485Master_Receive(dat);
}


void main(){
  long cnt = 0;


  ANSEL  = 0;                          // Configure AN pins as digital I/O
  ANSELH = 0;


  PORTB  = 0;
  PORTD  = 0;
  TRISB  = 0;
  TRISD  = 0;




  UART1_Init(9600);                    // initialize UART1 module
  Delay_ms(100);


  RS485Master_Init();                  // initialize MCU as Master
  dat[0] = 0xAA;
  dat[1] = 0xF0;
  dat[2] = 0x0F;
  dat[4] = 0;                          // ensure that message received flag is 0
  dat[5] = 0;                          // ensure that error flag is 0
  dat[6] = 0;


  RS485Master_Send(dat,1,160);




  PIE1.RCIE = 1;                     // enable interrupt on UART1 receive
  PIE2.TXIE = 0;                     // disable interrupt on UART1 transmit
  INTCON.PEIE = 1;                   // enable peripheral interrupts
  INTCON.GIE = 1;                    // enable all interrupts


  while (1){
                                       // upon completed valid message receiving
                                       //   data[4] is set to 255
    cnt++;
    if (dat[5])  {                     // if an error detected, signal it
      PORTD = 0xAA;                    //   by setting portd to 0xAA
    }
    if (dat[4]) {                      // if message received successfully
      cnt = 0;
      dat[4] = 0;                      // clear message received flag
      j = dat[3];
      for (i = 1; i <= dat[3]; i++) {  // show data on PORTB
        PORTB = dat[i-1];
      }                                // increment received dat[0]
      dat[0] = dat[0]+1;               // send back to master
      Delay_ms(1);
      RS485Master_Send(dat,1,160);


    }
   if (cnt > 100000) {
      PORTD ++;
      cnt = 0;
      RS485Master_Send(dat,1,160);
      if (PORTD > 10)                  // if sending failed 10 times
        RS485Master_Send(dat,1,50);    //   send message on broadcast address
     }
  }
                                       //   function to be properly linked.
}






PIC Slave Code:



char dat[9];             // buffer for receving/sending messages
char i,j;


sbit  rs485_rxtx_pin at RC2_bit;             // set transcieve pin
sbit  rs485_rxtx_pin_dire ction at TRISC2_bit;   // set transcieve pin direction


// Interrupt routine
void interrupt() {
 RS485Slave_Receive(dat);
}


void main() {
  long cnt = 0;
  //ANSEL  = 0;                        // Configure AN pins as digital I/O
  //ANSELH = 0;


  PORTB = 0;
  PORTD = 0;
  TRISB = 0;
  TRISD = 0;




  UART1_Init(9600);                  // initialize UART1 module
  Delay_ms(100);
  RS485Slave_Init(160);              // Intialize MCU as slave, address 160


  dat[4] = 0;                        // ensure that message received flag is 0
  dat[5] = 0;                        // ensure that message received flag is 0
  dat[6] = 0;                        // ensure that error flag is 0


  PIE1.RCIE = 1;                     // enable interrupt on UART1 receive
  PIE2.TXIE = 0;                     // disable interrupt on UART1 transmit
  INTCON.PEIE = 1;                   // enable peripheral interrupts
  INTCON.GIE = 1;                    // enable all interrupts


  while (1) {
    if (dat[5])  {                   // if an error detected, signal it by
      PORTD = 0xAA;                  //   setting portd to 0xAA
      dat[5] = 0;
    }
    if (dat[4]) {                    // upon completed valid message receive
      cnt++;
      dat[4] = 0;                    //   data[4] is set to 0xFF
      j = dat[3];
      for (i = 1; i <= dat[3];i++){
          PORTB = dat[i-1];
      }
      if (cnt>=100){                   // besteira, conta de 1 até 7 a cada 100 ciclos
        dat[0] = dat[0]+1;             // increment received dat[0]
        cnt=0;
        if(dat[0] > 7) {
          dat[0] = 0;
        }
      }
      Delay_ms(1);
      RS485Slave_Send(dat,1);        //   and send it back to master
    }
  }
}


Nesses códigos comunica PIC com PIC, não sei se dá pra aproveitar alguma coisa porque não sei se está usando protocolo Modbus RTU.

Offline minilathe

  • How to ask questions - The Smart Way...
  • Moderadores
  • CNCMASTER
  • ******
  • Posts: 4295
  • Sexo: Masculino
  • http://science-lakes.com/article43-html.html
  • Cidade - UF: Rio de Janeiro - RJ
  • Nome:: Gil Pinheiro
  • Profissão: Engenheiro e professor universitário
Re:Modbus RTU com PIC
« Resposta #5 Online: 20 de Outubro de 2017, 10:53 »
Faltaram as funções RS485Slave_Receive, RS485Slave_Send e RS485Slave_Init.

Offline EduardoGrieger

  • Novato
  • *
  • Posts: 7
  • Sexo: Masculino
  • GUIA CNC BRASIL
  • Cidade - UF: Sertãozinho - SP
  • Nome:: Eduardo Grieger
  • Profissão: Engenheiro de Aplicações
Re:Modbus RTU com PIC
« Resposta #6 Online: 20 de Outubro de 2017, 16:00 »
Olá Minilathe,


Acho que não entendi sua resposta. As funções que você comentou eu coloquei em negrito no código abaixo:




PIC Slave Code:[/size]char dat[9];             // buffer for receving/sending messageschar i,j;sbit  rs485_rxtx_pin at RC2_bit;             // set transcieve pinsbit  rs485_rxtx_pin_dire ction at TRISC2_bit;   // set transcieve pin direction// Interrupt routinevoid interrupt() { RS485Slave_Receive(dat);}void main() {  long cnt = 0;  //ANSEL  = 0;                        // Configure AN pins as digital I/O  //ANSELH = 0;  PORTB = 0;  PORTD = 0;  TRISB = 0;  TRISD = 0;  UART1_Init(9600);                  // initialize UART1 module  Delay_ms(100); RS485Slave_Init(160);              // Intialize MCU as slave, address 160  dat[4] = 0;                        // ensure that message received flag is 0  dat[5] = 0;                        // ensure that message received flag is 0  dat[6] = 0;                        // ensure that error flag is 0  PIE1.RCIE = 1;                     // enable interrupt on UART1 receive  PIE2.TXIE = 0;                     // disable interrupt on UART1 transmit  INTCON.PEIE = 1;                   // enable peripheral interrupts  INTCON.GIE = 1;                    // enable all interrupts  while (1) {    if (dat[5])  {                   // if an error detected, signal it by      PORTD = 0xAA;                  //   setting portd to 0xAA      dat[5] = 0;    }    if (dat[4]) {                    // upon completed valid message receive      cnt++;      dat[4] = 0;                    //   data[4] is set to 0xFF      j = dat[3];      for (i = 1; i <= dat[3];i++){          PORTB = dat[i-1];      }      if (cnt>=100){                   // besteira, conta de 1 até 7 a cada 100 ciclos        dat[0] = dat[0]+1;             // increment received dat[0]        cnt=0;        if(dat[0] > 7) {          dat[0] = 0;        }      }      Delay_ms(1);      RS485Slave_Send(dat,1);        //   and send it back to master    }  }}

Offline EduardoGrieger

  • Novato
  • *
  • Posts: 7
  • Sexo: Masculino
  • GUIA CNC BRASIL
  • Cidade - UF: Sertãozinho - SP
  • Nome:: Eduardo Grieger
  • Profissão: Engenheiro de Aplicações
Re:Modbus RTU com PIC
« Resposta #7 Online: 20 de Outubro de 2017, 16:02 »
Olá Minilathe,


Acho que não entendi sua resposta. As funções que você comentou eu coloquei em negrito no código abaixo:




char dat[9];             // buffer for receving/sending messages
char i,j;




sbit  rs485_rxtx_pin at RC2_bit;             // set transcieve pin
sbit  rs485_rxtx_pin_dire ction at TRISC2_bit;   // set transcieve pin direction




// Interrupt routine
void interrupt() {
 RS485Slave_Receive(dat);
}




void main() {
  long cnt = 0;
  //ANSEL  = 0;                        // Configure AN pins as digital I/O
  //ANSELH = 0;




  PORTB = 0;
  PORTD = 0;
  TRISB = 0;
  TRISD = 0;








  UART1_Init(9600);                  // initialize UART1 module
  Delay_ms(100);
  RS485Slave_Init(160);              // Intialize MCU as slave, address 160




  dat[4] = 0;                        // ensure that message received flag is 0
  dat[5] = 0;                        // ensure that message received flag is 0
  dat[6] = 0;                        // ensure that error flag is 0




  PIE1.RCIE = 1;                     // enable interrupt on UART1 receive
  PIE2.TXIE = 0;                     // disable interrupt on UART1 transmit
  INTCON.PEIE = 1;                   // enable peripheral interrupts
  INTCON.GIE = 1;                    // enable all interrupts




  while (1) {
    if (dat[5])  {                   // if an error detected, signal it by
      PORTD = 0xAA;                  //   setting portd to 0xAA
      dat[5] = 0;
    }
    if (dat[4]) {                    // upon completed valid message receive
      cnt++;
      dat[4] = 0;                    //   data[4] is set to 0xFF
      j = dat[3];
      for (i = 1; i <= dat[3];i++){
          PORTB = dat[i-1];
      }
      if (cnt>=100){                   // besteira, conta de 1 até 7 a cada 100 ciclos
        dat[0] = dat[0]+1;             // increment received dat[0]
        cnt=0;
        if(dat[0] > 7) {
          dat[0] = 0;
        }
      }
      Delay_ms(1);
      RS485Slave_Send(dat,1);        //   and send it back to master
    }
  }
}

Offline minilathe

  • How to ask questions - The Smart Way...
  • Moderadores
  • CNCMASTER
  • ******
  • Posts: 4295
  • Sexo: Masculino
  • http://science-lakes.com/article43-html.html
  • Cidade - UF: Rio de Janeiro - RJ
  • Nome:: Gil Pinheiro
  • Profissão: Engenheiro e professor universitário
Re:Modbus RTU com PIC
« Resposta #8 Online: 20 de Outubro de 2017, 21:19 »
Não... seu programa apenas chama essas rotinas.  As menções feitas são chamadas e não declarações. Ok?

Por exemplo, a linha

      RS485Slave_Send(dat,1);        //   and send it back to master

Aparece apenas uma vez (na chamada). Onde está a respectiva declaração?

O mesmo se aplica às outras funções.
« Última modificação: 20 de Outubro de 2017, 23:53 por minilathe »

Offline EduardoGrieger

  • Novato
  • *
  • Posts: 7
  • Sexo: Masculino
  • GUIA CNC BRASIL
  • Cidade - UF: Sertãozinho - SP
  • Nome:: Eduardo Grieger
  • Profissão: Engenheiro de Aplicações
Re:Modbus RTU com PIC
« Resposta #9 Online: 24 de Outubro de 2017, 22:52 »
Essas rotinas são da biblioteca do MikroC. Eu não sei o que essa rotina faz por é fechado pra visualização, abaixo segue o link da biblioteca:


https://download.mikroe.com/documents/compilers/mikroc/pic/help/rs-485_library.htm

Offline minilathe

  • How to ask questions - The Smart Way...
  • Moderadores
  • CNCMASTER
  • ******
  • Posts: 4295
  • Sexo: Masculino
  • http://science-lakes.com/article43-html.html
  • Cidade - UF: Rio de Janeiro - RJ
  • Nome:: Gil Pinheiro
  • Profissão: Engenheiro e professor universitário
Re:Modbus RTU com PIC
« Resposta #10 Online: 25 de Outubro de 2017, 09:33 »
Essas rotinas são da biblioteca do MikroC. Eu não sei o que essa rotina faz por é fechado pra visualização, abaixo segue o link da biblioteca:


https://download.mikroe.com/documents/compilers/mikroc/pic/help/rs-485_library.htm

Você pode usar o exemplo que você postou juntamente com as rotinas de sua biblioteca. Pode tentar obter o código fonte dessas rotinas, se precisar consertar alguma coisa.

Offline EduardoGrieger

  • Novato
  • *
  • Posts: 7
  • Sexo: Masculino
  • GUIA CNC BRASIL
  • Cidade - UF: Sertãozinho - SP
  • Nome:: Eduardo Grieger
  • Profissão: Engenheiro de Aplicações
Re:Modbus RTU com PIC
« Resposta #11 Online: 28 de Outubro de 2017, 00:17 »
Em uma pesquisa na internet achei um trabalho de conclusão de curso onde um cara desenvolveu uma lógica usando protocolo modbus. Peguei esse código abri no meu compilador que foi o mesmo onde o criador desenvolveu, simulei no protheus mas não deu certo. Não sei se foi por conta do protheus, porque tive que virtualizar a porta COM e usar o COMPIN do protheus. Vou tentar simular na real com PIC e depois posto aqui o resultado.

Offline minilathe

  • How to ask questions - The Smart Way...
  • Moderadores
  • CNCMASTER
  • ******
  • Posts: 4295
  • Sexo: Masculino
  • http://science-lakes.com/article43-html.html
  • Cidade - UF: Rio de Janeiro - RJ
  • Nome:: Gil Pinheiro
  • Profissão: Engenheiro e professor universitário
Re:Modbus RTU com PIC
« Resposta #12 Online: 28 de Outubro de 2017, 06:51 »
Já usei a porta serial no Proteus com PIC sem problemas. Considere que, se você está implementando um Master Modbus, deveria estar recebendo as mensagens de requisição num monitor de serial, dentro do Proteus. Como não há um Slave ativo, a comunicação não possuirá respostas. E dependendo do programa, pode tentar comunicar algumas vezes e parar.

 

/** * */