Pages: [1] 2   Go Down
Author Topic: Problema com comunicação RS485 Master / Slave  (Read 1977 times)
0 Members and 1 Guest are viewing this topic.
Aracaju, SE, Brasil
Offline Offline
Sr. Member
****
Karma: 4
Posts: 323
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Olá,

Já postei a dúvida no fórum Network, Protocols and Devices, mas como estão demorando um pouco para entender, posso ter um pouco de dificuldade em entender a resposta em inglês, e o pessoal do fórum em português são muito prestativos, decidi postar aqui também.

Resumindo: consigo fazer a comunicação Master -> Slave utilizando as funções do Nick Gammon, mas não consigo enviar o feedback. Tenho um loop no Master que fica aguardando a resposta, mas o Master fica parado neste loop.

Seguem os códigos:

Master:
Code:
#include "RS485_protocol.h"
//#include <NewSoftSerial.h>

const byte ENABLE_PIN = 4;
const byte LED_PIN = 13;
int led;
byte msg[2];

// callback routines

void fWrite (const byte what)
{
  Serial.write (what);  
}

int fAvailable ()
{
  return Serial.available ();  
}

int fRead ()
{
  return Serial.read ();  
}

void setup ()
{
  Serial.begin (28800);
  pinMode (ENABLE_PIN, OUTPUT);  // driver output enable
  pinMode (LED_PIN, OUTPUT);  // built-in LED
  led = 0;
}  // end of setup

void loop ()
{

  if (led == 0)
    memcpy (msg, (byte[]){1,1}, sizeof msg);  // device 1, turn on
  else if (led == 1)
    memcpy (msg, (byte[]){2,1}, sizeof msg);  // device 2, turn on
  else if (led == 2)
    memcpy (msg, (byte[]){1,0}, sizeof msg);  // device 1, turn off
  else if (led == 3) {
    memcpy (msg, (byte[]){2,0}, sizeof msg);  // device 2, turn off
    led = -1;
  }

  led++;

  // send to slave  
  digitalWrite (ENABLE_PIN, HIGH);  // enable sending
  sendMsg (fWrite, msg, sizeof msg);

  while (!(UCSR0A & (1 << UDRE0)))  // Wait for empty transmit buffer
    UCSR0A |= 1 << TXC0;  // mark transmission not complete
  while (!(UCSR0A & (1 << TXC0)));   // Wait for the transmission to complete
  
  digitalWrite (ENABLE_PIN, LOW);  // disable sending

  // receive response  
  byte buf [10];
  byte received = recvMsg (fAvailable, fRead, buf, sizeof buf);

  digitalWrite (LED_PIN, received == 0);  // turn on LED if error   */

  delay (500);

}  // end of loop

Slave 1:
Code:
#include "RS485_protocol.h"

const byte ENABLE_PIN = 4;
const byte LED_PIN = 13;
const byte ERROR_PIN = 9;
const byte SLAVE_NUMBER = 1;
const byte GREEN_PIN = 8;

void fWrite (const byte what)
{
  Serial.print (what);  
}
  
int fAvailable ()
{
  return Serial.available ();  
}

int fRead ()
{
  return Serial.read ();  
}
  
void setup()
{
  Serial.begin (28800);
  pinMode (ENABLE_PIN, OUTPUT);  // driver output enable
  pinMode (ERROR_PIN, OUTPUT);
  pinMode (GREEN_PIN, OUTPUT);
  pinMode (LED_PIN, OUTPUT);
  digitalWrite (ENABLE_PIN, LOW);
}

void loop()
{
  byte buf [20];
  
  byte received = recvMsg (fAvailable, fRead, buf, sizeof (buf) - 1);
  
  if (received)
    {
    digitalWrite (ERROR_PIN, LOW);
    if (buf [0] != SLAVE_NUMBER) {
      digitalWrite (GREEN_PIN, HIGH);
      return;  // not my device
    }
    digitalWrite (GREEN_PIN, LOW);
    digitalWrite (LED_PIN, buf[1]);  // set light level

    byte msg [] = {
       0,  // device 0 (master)
       3,  // turn light on command received
    };
    
    delay (1);  // give the master a moment to prepare to receive
    digitalWrite (ENABLE_PIN, HIGH);  // enable sending
    sendMsg (fWrite, msg, sizeof msg);
    
    while (!(UCSR0A & (1 << UDRE0)))  // Wait for empty transmit buffer
        UCSR0A |= 1 << TXC0;  // mark transmission not complete
    while (!(UCSR0A & (1 << TXC0)));   // Wait for the transmission to complete
    
    digitalWrite (ENABLE_PIN, LOW);  // disable sending
    
    
   }  else { // if nothing received
     digitalWrite (ERROR_PIN, HIGH);
   }  // end receive if
  
}  // end of loop

No Master, o LED fica sempre aceso (indicando erro na leitura), e no Slave, o LED de erro acende entre comandos bem sucedidos.

Alguma idéia?
Logged

'round the world...
Offline Offline
Faraday Member
**
Karma: 42
Posts: 3219
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

De onde tiraste este código?

Eu posso estar errado, mas olhando assim de repente parece que envias 2 bytes e tentas ler 20...
Logged

Eu não sou o teu criado. Se respondo no fórum é para ajudar todos mediante a minha disponibilidade e disposição. Responder por mensagem pessoal iria contra o propósito do fórum e por isso evito-o.
Se realmente pretendes que eu te ajude por mensagem pessoal, então podemos chegar a um acordo e contrato onde me pagas pela ajuda que eu fornecer e poderás então definir os termos de confidencialidade do meu serviço. De forma contrária toda e qualquer ajuda que eu der tem de ser visível a todos os participantes do fórum (será boa ideia, veres o significado da palavra fórum).
Nota também que eu não me responsabilizo por parvoíces escritas neste espaço pelo que se vais seguir algo dito por mim, entende que o farás por tua conta e risco.

Dito isto, mensagens pessoais só se forem pessoais, ou seja, se já interagimos de alguma forma no passado ou se me pretendes convidar para uma churrascada com cerveja (paga por ti, obviamente).

Aracaju, SE, Brasil
Offline Offline
Sr. Member
****
Karma: 4
Posts: 323
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

De onde tiraste este código?

Eu posso estar errado, mas olhando assim de repente parece que envias 2 bytes e tentas ler 20...

Do mesmo site que peguei a biblioteca: http://www.gammon.com.au/forum/?id=11428

Você não está errado, mas não acredito que isso seja problema, pois o master também envia 2 bytes e o slave tenta ler 20 e pega os 2 bytes tranquilamente.
Logged

'round the world...
Offline Offline
Faraday Member
**
Karma: 42
Posts: 3219
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Pergunta idiota...

Estás a usar um Uno ou 2009?
Logged

Eu não sou o teu criado. Se respondo no fórum é para ajudar todos mediante a minha disponibilidade e disposição. Responder por mensagem pessoal iria contra o propósito do fórum e por isso evito-o.
Se realmente pretendes que eu te ajude por mensagem pessoal, então podemos chegar a um acordo e contrato onde me pagas pela ajuda que eu fornecer e poderás então definir os termos de confidencialidade do meu serviço. De forma contrária toda e qualquer ajuda que eu der tem de ser visível a todos os participantes do fórum (será boa ideia, veres o significado da palavra fórum).
Nota também que eu não me responsabilizo por parvoíces escritas neste espaço pelo que se vais seguir algo dito por mim, entende que o farás por tua conta e risco.

Dito isto, mensagens pessoais só se forem pessoais, ou seja, se já interagimos de alguma forma no passado ou se me pretendes convidar para uma churrascada com cerveja (paga por ti, obviamente).

Aracaju, SE, Brasil
Offline Offline
Sr. Member
****
Karma: 4
Posts: 323
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Uno (master) e um ATMega328p na protoboard funcionando com os 8 MHz internos.
Logged

'round the world...
Offline Offline
Faraday Member
**
Karma: 42
Posts: 3219
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Um problema que eu vejo é que o Uno tem dois chips ligados aos pinos 0 e 1 (que suponho seja o que estás a usar).

É sempre uma possibilidade que o chip que faz a traducão entre USB e TTL esteja a estragar isto.

Experimenta com a NewSoftSerial, como o Gammon tem no seu site e vê o resultado. Se tiveres a oportunidade de usar dois chips em vez da placa do Arduino seria o ideal pois tiravas a limpo que não tinhas problemas de ligacão.

O hardware está de acordo com o que ele tem no site dele?
Logged

Eu não sou o teu criado. Se respondo no fórum é para ajudar todos mediante a minha disponibilidade e disposição. Responder por mensagem pessoal iria contra o propósito do fórum e por isso evito-o.
Se realmente pretendes que eu te ajude por mensagem pessoal, então podemos chegar a um acordo e contrato onde me pagas pela ajuda que eu fornecer e poderás então definir os termos de confidencialidade do meu serviço. De forma contrária toda e qualquer ajuda que eu der tem de ser visível a todos os participantes do fórum (será boa ideia, veres o significado da palavra fórum).
Nota também que eu não me responsabilizo por parvoíces escritas neste espaço pelo que se vais seguir algo dito por mim, entende que o farás por tua conta e risco.

Dito isto, mensagens pessoais só se forem pessoais, ou seja, se já interagimos de alguma forma no passado ou se me pretendes convidar para uma churrascada com cerveja (paga por ti, obviamente).

Aracaju, SE, Brasil
Offline Offline
Sr. Member
****
Karma: 4
Posts: 323
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hum... agora entendi o motivo do NewSoftSerial... alimentar o Uno pela porta DC ao invés do USB pode resolver?

De qualquer forma, vou tentar trocar de portas. Mas acho que o problema é de sincronização, algo assim.

Sobre o hardware, só não coloquei os resistores, mas como por enquanto está tudo na protoboard, está tranquilo.
Logged

'round the world...
Offline Offline
Faraday Member
**
Karma: 42
Posts: 3219
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Existe um motivo pelo qual as resistências estão lá...

Alimientar pela porta DC não ajuda porque o outro chip continua activo.
Logged

Eu não sou o teu criado. Se respondo no fórum é para ajudar todos mediante a minha disponibilidade e disposição. Responder por mensagem pessoal iria contra o propósito do fórum e por isso evito-o.
Se realmente pretendes que eu te ajude por mensagem pessoal, então podemos chegar a um acordo e contrato onde me pagas pela ajuda que eu fornecer e poderás então definir os termos de confidencialidade do meu serviço. De forma contrária toda e qualquer ajuda que eu der tem de ser visível a todos os participantes do fórum (será boa ideia, veres o significado da palavra fórum).
Nota também que eu não me responsabilizo por parvoíces escritas neste espaço pelo que se vais seguir algo dito por mim, entende que o farás por tua conta e risco.

Dito isto, mensagens pessoais só se forem pessoais, ou seja, se já interagimos de alguma forma no passado ou se me pretendes convidar para uma churrascada com cerveja (paga por ti, obviamente).

Aracaju, SE, Brasil
Offline Offline
Sr. Member
****
Karma: 4
Posts: 323
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Existe, melhorar o sinal para longas distâncias, aumentando a diferença entre as linhas A e B. Mas na protoboard, não precisa, até onde eu li e entendi. Inclusive, no datasheet nem fala nessas resistências entre as linhas e  o ground/5v, apenas em uma resistência entre as linhas A e B.
Logged

Offline Offline
Jr. Member
**
Karma: 1
Posts: 75
3ª Idade ... in the house
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Boas,

A ver o teu esquema sem ver o código, vejo que lhe faltam as 2 resistências fim de linha que normalmente são de 120 ohm.

E para mais RS485 não é nenhum protocolo "soft" mas sim hard

aqui te deixo alguns links que pesquisei em tempos para comunicar com uma carta de entrada/saídas via rs485 ( vê os meus antigos posts)

http://arduino-info.wikispaces.com/RS485-Brick

http://real2electronics.blogspot.fr/2009/09/buses-de-campo-para-arduino-rs485.html

Cumprimentos

Zé tretas
Logged

Arduino Mega 2560
Arduino Nano
Arduino UNO Rev3
Raspberry PI Model B
EasyPIC v4

'round the world...
Offline Offline
Faraday Member
**
Karma: 42
Posts: 3219
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Existe, melhorar o sinal para longas distâncias, aumentando a diferença entre as linhas A e B. Mas na protoboard, não precisa, até onde eu li e entendi. Inclusive, no datasheet nem fala nessas resistências entre as linhas e  o ground/5v, apenas em uma resistência entre as linhas A e B.

Ok... tu obviamente sabes o que está errado no sistema logo não me parece que te consiga ajudar muito mais.
Logged

Eu não sou o teu criado. Se respondo no fórum é para ajudar todos mediante a minha disponibilidade e disposição. Responder por mensagem pessoal iria contra o propósito do fórum e por isso evito-o.
Se realmente pretendes que eu te ajude por mensagem pessoal, então podemos chegar a um acordo e contrato onde me pagas pela ajuda que eu fornecer e poderás então definir os termos de confidencialidade do meu serviço. De forma contrária toda e qualquer ajuda que eu der tem de ser visível a todos os participantes do fórum (será boa ideia, veres o significado da palavra fórum).
Nota também que eu não me responsabilizo por parvoíces escritas neste espaço pelo que se vais seguir algo dito por mim, entende que o farás por tua conta e risco.

Dito isto, mensagens pessoais só se forem pessoais, ou seja, se já interagimos de alguma forma no passado ou se me pretendes convidar para uma churrascada com cerveja (paga por ti, obviamente).

Aracaju, SE, Brasil
Offline Offline
Sr. Member
****
Karma: 4
Posts: 323
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

É, acho que era algum problema de timing... enfim, acabei deixando a biblioteca do Nick Gammon de lado e desenvolvi a minha própria, com base no protocolo que encontrei neste link.

Depois de alguns ajustes, já estou conseguindo comunicar os arduinos pelo RS495, com uma comunicação bem robusta (com o protocolo tenho acesso a MUITOS comandos, agora só preciso definir os comandos de acordo com o design da minha rede), utilização relativamente simples, e rápida o suficiente para minha necessidade, sem precisar fazer delay para não ter problema de sincronia (estou conseguindo enviar um comando após o outro, sem delay entre eles, e todos os comandos estão sendo entendidos).

Ah, e não estou com resistores entre as pernas A e B dos MAX485. Como falei, uma vez que eles estão no protoboard, não precisam desse artifício. Pelo o que eu entendi, esses resistores ajudam a melhorar o sinal para longas distâncias, para aumentar a diferença entre a linha A e B, melhorando assim o sinal (pelo menos foi assim que eu entendi, depois testo em um sistema real, com maiores distâncias, onde o sinal pode sofrer interferências).
Logged

Portugal
Offline Offline
Edison Member
*
Karma: 37
Posts: 1534
Pretending you know everything then you will learn nothing.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ola a uns tempos também andei a brincar com o RS485 e desenvolvi uma pequena lib para o que eu queria. Nao está terminada e deve ter coisas menos correctas mas funciona para o meu fim.Tem coisas que podem ser melhor optimizadas, nao estou a implementar ACK dos slaves inda ,nem tempos de timeout de resposta dos slaves ...
Digamos que a deixei ficar assim por falta de tempo e ter o projecto na gaveta à espera de ser sacado fora.
No entanto pode te dar uma visão do que fiz e fazer melhor do que fiz.
Também falta me depois colocar isso tudo dentro de uma class c++ para ser possível instanciar um objecto


* RS485.h (0.46 KB - downloaded 14 times.)
* RS485.cpp (2.8 KB - downloaded 14 times.)
« Last Edit: April 29, 2013, 03:32:42 am by HugoPT » Logged

Debian,Mint,Ubuntu
Arduino Mega 2560
Arduino Nano
Arduino Duemilanove
MAC OS Montain Lion
Raspberry PI Model B


Aracaju, SE, Brasil
Offline Offline
Sr. Member
****
Karma: 4
Posts: 323
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ola a uns tempos também andei a brincar com o RS485 e desenvolvi uma pequena lib para o que eu queria. Nao está terminada e deve ter coisas menos correctas mas funciona para o meu fim.Tem coisas que podem ser melhor optimizadas, nao estou a implementar ACK dos slaves inda ,nem tempos de timeout de resposta dos slaves ...
Digamos que a deixei ficar assim por falta de tempo e ter o projecto na gaveta à espera de ser sacado fora.
No entanto pode te dar uma visão do que fiz e fazer melhor do que fiz.
Também falta me depois colocar isso tudo dentro de uma class c++ para ser possível instanciar um objecto



Então, fiz como você, mas já implementei o ACK dos slaves e coloquei dentro de um classe. Uma diferença que percebi pelo o .h que você passou é que utilizo um protocolo fechado, onde cada comando tem 15 bytes, e me parece que sua biblioteca deixa isso aberto.

A noite envio minha lib para vocês darem uma olhada.
Logged

Aracaju, SE, Brasil
Offline Offline
Sr. Member
****
Karma: 4
Posts: 323
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Demorou, mas segue minha biblioteca para comunição RS485.

Como dito anteriormente, o protocolo utilizado é o descrito neste link.

No construtor é informado o id do dispositivo, um pointer para o Stream (&Serial, ou um SoftwareSerial) e o pino de controle envio/leitura do RS485.

Depois é só enviar a mensagem pelos métodos sendENQ, sendACK e sendNAK, de acordo com o que se deseja. Para receber a mensagem, deve-se ficar aguardando a mensagem (waitForMessage(long)), e depois verificar se houve atualização na mensagem (updated()). Só será recebida a mensagem se ela foi destinada ao dispositivo.

Via de regra, o master tem id 1 e os slaves quaisquer outros ids. O master envia comando para o slave, e aguarda resposta do mesmo, confirmando que a mensagem foi recebida (ACK). Os slaves sempre ficam aguardando comando, e quando recebem respondem dizendo que entenderam o comando (ACK) ou que não entenderam (NAK). Nessa resposta pode estar a informação desejada pelo master.

* MasterSlaveFuji.h (1.16 KB - downloaded 33 times.)
* MasterSlaveFuji.cpp (5.91 KB - downloaded 38 times.)
Logged

Pages: [1] 2   Go Up
Jump to: