Sensor con comunicación RS485

Buenas tardes a todos,

Estoy realizando un proyecto pero me estoy encontrando con diversos problemas. La idea principal es que tengo que comunicar un sensor con una placa Arduino Mega. Para que el sensor empiece a funcionar debo enviar una cadena de bytes, pero creo que no lo estoy haciendo viendo ya que no obtengo respuesta. Según el manual debo hacer esto (disculpar pero está en inglés):

The Model 864 Digital Altimeter communicates over a 2-wire differential RS-485 serial
data transmission line or optionally a half-duplex RS-232 data line. To interrogate the
head and receive echo data, a Switch Data Command string is sent via a serial command
program at a baud rate of 115200 bps, No Parity, 8 Data Bits and 1 Stop Bit. When the
Switch Data command is accepted, the head transmits, receives and sends its return data
back to the command program.

Mas especificamente, pone que la cadena debe empezar con unos bites y acabar con otros, como especifica:

The altimeter accepts up to 27 bytes of switch data from the serial interface and must see
the switch data header (2 bytes: 0xFE and 0x44 HEX) in order to process the switches.
The head will stop accepting switch data when it sees the termination byte (0xFD HEX).
The termination byte must be present for the head to process the switches.

Una vez el sensor aceptara el codigo, se deberia poner en funcionamiento y mandarme una respuesta (este punto ya lo miraremos mas adelante porque si no se enciende de poco me sirve).

El caso es que yo he conectado la Placa Mega junto con una placa RS485, he usado el puerto 0 para la comunicacion con el sensor (primero usé el puerto 1 para la comunicacion y el 0 para ver lo que enviaba mediante el ordenador, pero cambié al 0 para ver si el led RX se iluminaba, cosa que no ha pasado) y el PIN2 como interruptor para cambiar el estado de comunicacion de la placa RS485.

Os pego el código que he creado:

const int ledPin =  13;  // Led integrado en la placa
const int ReDePin =  2;  // HIGH = Emisor / LOW = Receptor

Aqui no tengo muy claro que tipo de variables usar, he probado con los dos tipos pero sigue sin funcionar.

//byte  interruptor[27]= {0xFE, 0x44, 0x1D, 5, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFD};
//static const unsigned char  interruptor[27]= {0xFE, 0x44, 0x1D, 5, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFD};


void setup()
{
 Serial.begin(115200); //Aqui inicio las caracteristicas de la comunicación
  pinMode(ledPin, OUTPUT);
  pinMode(ReDePin, OUTPUT);
}

void loop() 
{
 //RS485 en modo transmisor para enviar la  el activador del sensor
digitalWrite(ReDePin, HIGH);
digitalWrite(ledPin, HIGH);

Aqui tengo muchas dudas, uso serial.writte o serial.print para enviar los datos. Lo he probado de ambas maneras pero nunca obtengo respuesta.

//Serial.write (interruptor,26);


 for (int i=0; i<=26;i++)
 {
 //Serial.write(interruptor[i]);  //// 
 //Serial.write(interruptor[i],HEX);   ////
 }
Serial.flush();  
delay(1000);

La segunda parte ya la trataremos si solucionamos el envío de información.

Muchas gracias

Lo primero que debes tener claro al llegar a un foro es que todos tienen normas.
En este, los códigos se posteas de una manera y la que usaste no es la correcta.

Lee las Normas del foro.
Luego ve a More (abajo a la derecha), click, luego Modify y estas en modo EDICION.
**Selecciona todo el código y click en </> arriba del emoticon **

serial.print envía cadenas
serial.write envía bytes

Cuando pueda leer apropiadamente el código te contestaré por el resto, al menos yo.

Por otro lado... como no leíste las normas del foro, no usaste el recursos mas simple que alli se indica que es buscar en Google asi: Arduino RS485

Buenas surbyte,

Tienes toda la razón, entono el mea culpa porque no me leí las normas del foro y fuí directamente a escribir el post.

Respecto a buscar arduino RS485, ten por seguro que llevo días buscando por internet, mirando post de otra gente... Pero lo cierto es que no he encontrado lo que buscaba. He encontrado muchos ejemplos de comunicación entre dos arduinos con modulos RS485, o con algún sensor.. Pero yo me encuentro con un sensor que tiene 4 cables, dos de alimentación y dos de comunicación, por lo que he deducido que es una comunicación half duplex y a partir de ahi he ido cogiendo partes de codigo de los sitios que he encontrado.

Despues de tu respuesta, deduzco que tengo que usar Serial.print, no?

Muchas gracias.

Bien comencemos por lo básico.
Tu código es muy incompleto, llendo de lleno ahora a la comunicaición RS485.

Debes disponer de un pin que controle el flujo TX o RX.
Este pin hace la tarea

pinMode(ReDePin, OUTPUT);

Pero no veo que lo uses aunque tu código esta incompleto asi que es dificil entender que haces.
Luego pones información parcializada del dispositivo que quieres leer.
Normalmente deberías poner un enlace al manual para que nosotros confirmemos o no tu punto de vista.
Sino incurriremos en el mismo error sistemático aunque supongo que no es el caso.

IMAGENEX MODEL 864 PROGRAMMABLE DIGITAL ALTIMETER

Acá no dice cuales son los pines peri si que se alimenta con 22 a 32 VDC a 100mA
Tambien que la comunicación es RS485 half-duplex a 115.2 kbps
Hasta aca todo lo que ya has dicho asi que no aporto nada.

La info que muestras no pude hallarla.

Sería interesante que postearas el manual para leerlo y colaborar con tu proyecto.

Buenas surbyte,

Acabo de adjuntar el manual para que puedas echar un vistazo y sacar tus propias conclusiones.

Respecto al montaje, el sensor lo he alimentado con 24V, el + en el pin 4 y el menos en el pin 1. Para la comunicación con el modulo RS485, el A lo he metido con el Data + (pin 3) y el B con el Data - (pin 2).

El pin 2 lo he puesto como pin de control, conectado a los pines DE y RE (ambos puenteados para que cambie el modulo entre emisor y receptor). DI lo he conectado a TX y RO a RX del puerto serial 1 del Arduino MEGA (pines 18 y 19).

Esa ha sido la conexión de la placa junto con el sensor.

Ahora te adjunto el codigo que he creado solo para enviar la cadena de bits.

const int ledPin =  13;  // Led integrado para iluminarse en la placa
const int ReDePin =  2;  // HIGH = Driver / LOW = Receptor, es el pin de control que he usado conectado a la placa RS485


//Aqui no tengo claro si usar byte o static const unsigned char, he usado ambos metodos con igual resultado.
//byte  interruptor[27]= {0xFE, 0x44, 0x1D, 5, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFD};
static const unsigned char  interruptor[]= {0xFE, 0x44, 0x1D, 5, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFD};



void setup()
{
  Serial1.begin(115200); //Inicializo la velocidad de comunicación del puerto serie 1 (pines 18 y 19)
  Serial.setTimeout(100);//establecemos un tiempo de espera de 100ms
  //inicializamos los pines
  pinMode(ledPin, OUTPUT);
  pinMode(ReDePin, OUTPUT);
}

void loop() 
{
 //RS485 en modo transmisor para activar el sensor
 digitalWrite(ReDePin, HIGH);  //Aqui pongo el pin 2 en modo alto para poner el modulo RS485 en modo emisor
 digitalWrite(ledPin, HIGH); 

 for (int i=0; i<=26;i++) //Aqui intento mandar la cadena de bits mediante el puerto serie 1. He usado los dos metodos, serial1.write, serial1.print...
 {
  //Serial1.print(interruptor[i],HEX);
    Serial1.write(interruptor[i]);
 }
  Serial.flush();  
 delay(1000); 
 }

La parte para leer la respuesta del sensor aun no la he creado porque no soy capaz de activarlo.

Muchas gracias.

864 Manual.pdf (114 KB)

Lo tienes conectado al revés, A es Data- y B es Data+, ahí tienes el problema

Gracias Danicap.

Para realizar la conexión seguí la información que habia encontrado por internet y que me ponía esto:

The RS-485 differential line consists of two pins:
A aka '+' aka Data + (D+) aka TxD+/RxD+ aka non-inverting pin
B aka '-' aka Data - (D-) aka TxD-/RxD- aka inverting pin

Un saludo.

Eso es wikipedia jejeje no te fíes nunca de lo que leas ahí. Prueba a cambiar la polaridad y me dices a ver :wink:

Danicap:
Eso es wikipedia jejeje no te fíes nunca de lo que leas ahí. Prueba a cambiar la polaridad y me dices a ver :wink:

Jejeje, si tienes toda la razón, es de Wikipedia :frowning:

Como ya le dije ayer a surbyte, cuando eres nuevo en esto y miras mil paginas, foros, ideas (porque llevo días mirando muchos tutoriales y cosas varias).. Al final acabas creyendote todo.

Lo he cambiado pero sigue sin ir, supongo que la posición de los cables igual es solo uno de los muchos problemas que debe tener el código.

Gracias de todos modos!

Analizando el resto no veo así ningún fallo más de HW... tienes unidas las masas? la del sensor con la del arduíno? Si no hazlo que sin masas unidas no te va a funcionar.

Si esto sigue sin ir prueba a meterle un pequeño delay entre envios de bytes de unos 100ms para darle tiempo a procesar la info, no vaya a ser que lo estés saturando.

Un saludo!

Ya metí el delay(100) entre cada envio de bits.

Sigue sin ir, pero igual es tema de las masas como me comentas, el cable que lleva el sensor solo tiene 4 (2 de alimentación y 2 de datos). Hay un quinto pin en el sensor que deduzco que será tierra aunque el cable solo tiene 4.

Voy a ver si puedo conectarlo de alguna manera.

Gracias.

El de tierra no hace falta, supongo que estarás alimentando el sensor con una fuente y el arduíno con otra no? une las masas y solucionado.

Por lo que leo en el manual dice:

Head ID:
Standard: 0x1D
Optional: 0x11, 0x12, 0x13, 0x15, 0x15

Si no te funciona con las masas prueba con todas las ID si no hay manera de saber exactamente cual tiene, no vaya a ser que por lo que sea haya venido cambiada, no debería, pero puede pasar, no sería la primera vez

Danicap:
El de tierra no hace falta, supongo que estarás alimentando el sensor con una fuente y el arduíno con otra no? une las masas y solucionado.

El Arduino lo estoy alimentando desde el cable usb del ordenador mientras que el sensor lo alimento con una fuente de 24V. Saco un cable desde GND de arduino hasta el negativo de la fuente?

Gracias

El Arduino lo estoy alimentando desde el cable usb del ordenador mientras que el sensor lo alimento con una fuente de 24V. Saco un cable desde GND de arduino hasta el negativo de la fuente?

Si, une las masas, como dices saca un cable del GND del arduino y enchúfaselo al - de la fuente. No se me ocurre qué otra cosa pueda ser, salvo lo que te he comentado de las IDs...

Nada, seguimos sin que vaya. Hice todo lo que me aconsejaste pero sigue sin ir, el led TX se ilumina como si enviara los datos, pero no se si los recibe el sensor.

Un saludo.

Surbyte has podido echar un vistazo si esta bien o no lo que he hecho?

Gracias.

Buenos días,

He actualizado un poco el código, he probado a conectar los datos de las dos maneras posibles, he unido la masa del Mega con la fuente que alimenta al sensor y aun así sigo sin poder conectar. Creo que envío bien el comando para activar el sensor pero la respuesta siempre es -1 (No se recibe nada).

Me podría alguien confirmar que todo está bien?

const int ledPin =  13;  // Led integrado
const int ReDePin =  2;  // HIGH = Driver / LOW = Receptor
char incomingByte = 0;

const unsigned char  interruptor[]= {0xFE, 0x44, 0x12, 5, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFD};

void setup()
{
  Serial1.begin(115200); //Puerto serie 1 usado para comunicar con el sensor (18TX, 19RX)
  Serial.begin(9200); //Puerto serie para ver los datos que estoy escribiendo en el serie1
  Serial.setTimeout(100);//establecemos un tiempo de espera de 100ms
 
 //inicializamos los pines
  pinMode(ledPin, OUTPUT);
  pinMode(ReDePin, OUTPUT);
}

void loop() 
{
  //RS485 en modo transmisor, el activador del sensor
 digitalWrite(ReDePin, HIGH); //Pongo el pin 2 en modo alto para que el RS485 sea transmisor
 digitalWrite(ledPin, HIGH); 

 for (int i=0; i<=26; i++)
 {
  Serial1.print(interruptor[i],HEX); //Escribo el comando por el puerto 1
  Serial.print(interruptor[i],HEX); //Veo los datos que estoy escribiendo en el puerto 1 mediante el monitor serie
   delay(2.3); //Dejo un pequeño retraso sacado de un programa que tiene el fabricante
 
}
  Serial.flush();  //Limpio el buffer de salida

   //RS485 como receptor
  digitalWrite(ReDePin, LOW); //Pongo el pin 2 en estado bajo para activar el RS485 como receptor
  digitalWrite(ledPin, LOW); 


      //          // Aqui intento leer el dato que debería entrar por el puerto serie 1, que en este caso es 
                  siempre -1 (no recibe ningun tipo de dato)
            incomingByte = Serial1.read();

      //          // Aqui escribo lo que recibo, en este caso siempre -1
              Serial.print(" I received: ");
              Serial.println(incomingByte, DEC);
        }
           
 delay(1000); 
 }

Esto es lo que tengo el monitor serie todo el rato:

FE441250000300000A00000000000FD I received: -1
FE441250000300000A00000000000FD I received: -1
FE441250000300000A00000000000FD I received: -1
FE441250000300000A00000000000FD I received: -1
FE441250000300000A00000000000FD I received: -1

Gracias.

FE441250000300000A00000000000FD I received: -1
FE441250000300000A00000000000FD I received: -1
FE441250000300000A00000000000FD I received: -1
FE441250000300000A00000000000FD I received: -1
FE441250000300000A00000000000FD I received: -1

De momento ahi el 100 lo estas enviando mal, porque esta enviando un A,

Pon todos los valores en hexadecimal en la declaración

const unsigned char  interruptor[]= {0xFE, 0x44, 0x12, 5, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFD};

a ver si así manda bien el 100 => 0x64

Luego en el

delay(2.3);

No estoy seguro pero creo que ahi no puedes poner un float, pon 2 ó 3

Por lo demás no veo nada que esté mal....

Gracias Danicap,

Lo del 100 ha sido un fallo mio, modifique el codigo después de haberlo copiado en el mensaje. Ese parametro es unicamente para el delay en la respuesta del sensor.

Cambiado todo sigue igual, llegado a este punto y después de mucho mirar por internet y con vuestra ayuda me planteo que algo del sensor falla aunque es el segundo que pruebo.

Me ha dicho el fabricante que compre un adaptador rs485 a usb para conectar al ordenador y que una vez hecho esto pruebe un software que tienen ellos para ver si le sensor funciona correctamente.

Os habeis encontrado alguna vez algún sensor que no se pueda programar mediante Arduino? O cualquier sensor es completamente adaptable a este tipo de placas?

Muchas gracias.