COMANDOS HEXADECIMALES SOBRE RS485

Hola Amigos

Actualmente estoy tratando de hacer un sensor de niveles de liquido con 3 sensores que responden a comandos HEXADECIMALES sobre RS485

Basicamente tengo 3 sensores y un ARDUINO UNO con el shield de DFRObot conectados a la red 485.

Mi ARDUINO tendra la direccion 01 de la red y mis sensores 02,03 y 04 respectivamente.

Para preguntarle a los sensores por su data debo enviar el siguiente comando en HEXADECIMAL:

[prefijo pregunta para sensor] [direccion del sensor] [comando de pregunta de nivel] [checksum]

0x31 0x02 0x06 0x39 //Para sensor 2 el prefijo siempre es 31h y el comando siempre es 06h
0x31 0x03 0x06 0xFD //Para sensor 3
0x31 0x04 0x06 0x93 //Para sensor 4

Luego de esto cada sensor me debe responder algo similar a esto:

[prefijo respuesta sensor] [direccion sensor] [comando respondido] [temperatura °C] [nivel 1byte] [nivel 2byte] [frecuencia1byte] [frecuencia2byte] [checksum]

un ejemplo seria:

3E 02 06 1C 1D 0A E2 05 C4 //el prefijo respuesta siempre sera 3Eh

Tengo un primer sketch y aun no lo pruebo, pero tengo muchas dudas si le voy a enviar bien los comandos a las sondas(digo en hexadecimal) y si los estoy recibiendo bien tmb.

alguien podria ayudarme con la revision?

//Primer sketch de comunicacion con las sondas


int tka = 4;//Estos pines van a ser controlados externamente para saber por cual sonda pregunta el arduino
int tkb = 7;
int tkc = 8;
int EN = 2;  //RS485 shield Enable terminal, High for Send , Low for Receive 
byte data[8];
byte cont;


#define  myaddress     01


void setup() {
  
    Serial.begin(9600);
    pinMode(tka,INPUT);
    pinMode(tkb,INPUT);
    pinMode(tkc,INPUT);
    pinMode(EN,OUTPUT);
    digitalWrite(EN,LOW);
}

void loop()
{
  
  if (digitalRead(4)==HIGH){
    Serial.flush();     
    //(byte prefix,byte address,byte command,byte checksum)
    //Voy a Enviar (0x31, 0x02, 0x06, 0x39)
    sendCMD(49,2,6,57);
    //DESPUES DE ESTO DEBERIA PONER EN==LOW, PARA RECIBIR LA RESPUESTA DE LA SONDA, POR EL MOMENTO LO VOY A HACER SIN VERIFICAR EL CHECKSUM.
    //OSEA EN BRUTO DEBERIA RECIBIR ALGO SIMILAR A: 0x3E, 0x02, 0x06, 0x1C, 0x1D, 0x0A, 0xE2, 0x05, 0xC4
    //Siempre va a tener el mismo tamaño 9 bytes (byte prefix, byte address, byte command, byte tempe, byte lvl1, byte lvl2, byte freq1, byte frec2, byte checksum)
    receiveINFO();
    
  }
 if (digitalRead(7)==HIGH){
    Serial.flush();     
    //(byte prefix,byte address,byte command,byte checksum)
    //Voy a Enviar (0x31, 0x02, 0x06, 0xFD)
    sendCMD(49,3,6,253); 
    receiveINFO();
   
 }
    
if (digitalRead(8)==HIGH){
    Serial.flush();     
    //(byte prefix,byte address,byte command,byte checksum)
    //Voy a Enviar (0x31, 0x02, 0x06, 0x93)
    sendCMD(49,4,6,147); 
    receiveINFO();
}
 

}

//Funciones

byte receiveINFO()
{
  byte byte_receive;
  byte conteo=0;
  
  while(Serial.available())
  {
    byte_receive=Serial.read();
    if (byte_receive==62)
    {
      while(conteo<=9)
      {
        data[cont]==byte_receive;
        cont=cont+1;
      }
    }
  }
}

void sendCMD(byte prefix,byte address,byte command,byte checksum)
{
  
  
  digitalWrite(EN,HIGH);
  delay(1);

  Serial.print(prefix,HEX);
  Serial.print(address,HEX);
  Serial.print(command,HEX);
  Serial.print(checksum,HEX);
  digitalWrite(EN,LOW);

  
  
}

SondasRS485.ino (2.04 KB)

Algunas preguntas ¿Donde estas conectando el modulo? como utilizas serial.begin() deben estar conectado en los pines 0 y 1 , en otro caso deberías utilizar la librería SoftwareSerial.h . ¿Cual es el datasheet del sensor? utilizas sendCMD, pero no hay ninguna librería declarada.

Hola Peter muchas gracias por responder:

Claro que el Shield esta conectado a 0 y 1. aqui el datasheet del shield.

el de los sensores es este:

http://omnicomm-online.com/downloads/Integration-Manual-Omnicomm-LLS.pdf

sendCMD es una funcion que yo cree, si miras en las funciones en la parte de abajo del sketch. o sendCMD es una palabra dedicada de el lenguaje arduino? si es asi entonces lo corrijo.

Denuevo mil gracias por cualquier ayuda que puedas darme.

Estan bien enviados los comandos entonces?

ups perdon no coloque el link del shield.

http://www.dfrobot.com/wiki/index.php/RS485_Shield

PeterKantTropus:
Algunas preguntas
¿Donde estas conectando el modulo? como utilizas serial.begin() deben estar conectado en los pines 0 y 1 , en otro caso deberías utilizar la librería SoftwareSerial.h .
¿Cual es el datasheet del sensor?
utilizas sendCMD, pero no hay ninguna librería declarada.

Gracias por responder

aca tienes una buena página con ejemplos que puedes usar

Libreria RS485

Es similar a al tuya, usa SofwareSerial que ha sido reemplazado por NewSoftwareSerial.

Aca otro buen artículo

Muchas gracias

De hecho el mio esta basado en el de Igor.

Pero no se si lo tengo correcto o no.

O sea si alguien pudiera revisar y ver si hice bien las cosas...soy bastante newbie

Mi mayor duda es si si estoy enviando bien el comando a los sensores (hexadecimal)

Luce bien. Hasta donde vi. LO que hago en esos casos es armar un segundo Max485 y con algun programa de prueba para la PC leo la trama enviada. OJo que la pc tiene niveles rs232 o sea +-12V y tienes que usar un max232 para convertirlos a TTL y luego le max485. Hay mucha documentación sobre eso. Asi verás la trama enviada en la PC y podras contestarle tambien. Muchos de esso programas son Modbus monitors.

Excelente idea....has usado algun software en especial?

por cierto en algun post (creo que en el de igor) veo que cogieron un arduino uno(no smd) y le quitaron el atmega y asi se conectaron a la red que tal te parece esa idea?

Hola Estoy probando el sketch en el monitor serial de arduino y con un cable enviado a los 5 voltios del arduino para habilitar el envio de informacion.

Pero al hacer el puente por 1sg el programa envia muchisimas veces el comando. Osea como la velocidad del puerto es mucho mas rapida que mis dedos el Arduino envia todos los comandos que puede durante ese lapso de tiempo, como puedo hacer para que envie SOLO una vez y ya no mas? asi el PIN habilitador aun se encuentre en ALTO?

Alguien me puede ayudar?

No se si son pulsadores o qué pero primero deberías evitar posibles rebotes.
Basicamente lo que debes hacer es :
cread una variable statusTka

bool statusTka=false;
unsigned int valortka;

y luego 

valortka = digitalRead(tka);

if (valortka ==HIGH && !statusTka ){
    statusTka != statusTka;   // esto invierte el estado de statusTka cada vez que digitalRead(tka) == HIGH (de nuevo, no olvides los posibles rebotes=)
    //................
    // lo que sigue   
}

// resto del códgio
if (statusTka) {// si es 1 entonces envia los comandos RS485
    // envias tus comandos RS485
   if (valortka == LOW) {
       statusTka = false; // con este se ejecuta una sola vez
   }
}

esto es para uno de tus interruptores, deberías repetirlo para os otros 2.

sendCMD es una funcion que yo cree, si miras en las funciones en la parte de abajo del sketch. o sendCMD es una palabra dedicada de el lenguaje arduino? si es asi entonces lo corrijo.

Es que soy de la vieja escuela y las funciones las declaro primero y a veces no leo lo que sigue después de void loop :grin:

Yo utilizo el siguiente codigo para detectar el llamado flanco ascendente

     valor_actual= digitalRead() ;  
    if (valor_anterior==0 && valor_actual==1){
       // codigo a ejecutar
       }  
    valor_anterior= digitalRead() ;

y este para el descendente

     valor_actual= digitalRead() ;  
    if (valor_anterior==1 && valor_actual==0){
       // codigo a ejecutar
       }  
    valor_anterior= digitalRead() ;

Muchisimas gracias a ambos, voy a mirar como ajusto sus ideas a mi sketch y cuando lo tenga listo…lo comparto aca.

Hola AMIGOS

Les cuento usando el codigo de surbyte no me funciono nada…SURBYTE…no se que hice mal

ahi te lo envio.

a ver si puedes ayudarme…mil gracias por todo el apoyo que me has dado hasta el momento.

//Primer sketch de comunicacion con las sondas


int tka = 4;//Estos pines van a ser controlados externamente para saber por cual sonda pregunta el arduino
int tkb = 7;
int tkc = 8;
int EN = 2;  //RS485 shield Enable terminal, High for Send , Low for Receive 
byte data[8];
byte cont;

bool statusTKA=false;
bool statusTKB=false;
bool statusTKC=false;
unsigned int valortka;
unsigned int valortkb;
unsigned int valortkc;




#define  myaddress     01


void setup() {
  
    Serial.begin(9600);
    pinMode(tka,INPUT);
    pinMode(tkb,INPUT);
    pinMode(tkc,INPUT);
    pinMode(EN,OUTPUT);
    digitalWrite(EN,LOW);
}

void loop()
{
  valortka=digitalRead(tka);
  if (valortka==HIGH && !statusTKA)
  {
    statusTKA != statusTKA;
  }
  if (statusTKA)
  {
    Serial.flush();     
    sendCMD(49,2,6,57);
    if (valortka==LOW)
    {
      statusTKA=false;
    }
    receiveINFO();
  }
    
   
   
    valortkb=digitalRead(tkb);
  if (valortkb==HIGH && !statusTKB)
  {
    statusTKB != statusTKB;
  }
  if (statusTKB)
  {
    Serial.flush();     
    sendCMD(49,3,6,253);
    if (valortka==LOW)
    {
      statusTKB=false;
    }
    receiveINFO();
  } 
   
    
    
    
   valortkc=digitalRead(tkc);
  if (valortkc==HIGH && !statusTKC)
  {
    statusTKC != statusTKC;
  }
  if (statusTKC)
  {
    Serial.flush();     
    sendCMD(49,4,6,147);
    if (valortkc==LOW)
    {
      statusTKC=false;
    }
    receiveINFO();
  }   
    
    
  }
 

//Funciones

byte receiveINFO()
{
  byte byte_receive;
  byte conteo=0;
  
  while(Serial.available())
  {
    byte_receive=Serial.read();
    if (byte_receive==62)
    {
      while(conteo<=7)
      {
        data[cont]==byte_receive;
        cont=cont+1;
      }
    }
  }
}

void sendCMD(byte prefix,byte address,byte command,byte checksum)
{
  
  
  digitalWrite(EN,HIGH);
  delay(1);

  Serial.print(prefix,HEX);
  Serial.print(address,HEX);
  Serial.print(command,HEX);
  Serial.print(checksum,HEX);
  digitalWrite(EN,LOW);

  
  
}

Con el codigo de PeterKantTropus, me envia muy bien una vez, pero despues no puedo volver a enviar nunca mas.

Peter que me sugieres para poder volver a enviar?

AH Y POR CIERTO SURBYTE SI SON UNOS PULSADORES LOS QUE USO.

//Primer sketch de comunicacion con las sondas


int tka = 4;//Estos pines van a ser controlados externamente para saber por cual sonda pregunta el arduino
int tkb = 7;
int tkc = 8;
int EN = 2;  //RS485 shield Enable terminal, High for Send , Low for Receive 
unsigned int valor_actualA;
unsigned int valor_actualB;
unsigned int valor_actualC;
unsigned int valor_anteriorA;
unsigned int valor_anteriorB;
unsigned int valor_anteriorC;
byte data[8];
byte cont;


#define  myaddress     01


void setup() {
  
    Serial.begin(9600);
    pinMode(tka,INPUT);
    pinMode(tkb,INPUT);
    pinMode(tkc,INPUT);
    pinMode(EN,OUTPUT);
    digitalWrite(EN,LOW);
    valor_anteriorA==LOW;
    valor_anteriorB==LOW;
    valor_anteriorC==LOW;
    
}

void loop()
{
  valor_actualA=digitalRead(4);
  if (valor_anteriorA==LOW && valor_actualA==HIGH)
  {
    
  //if (digitalRead(4)==HIGH){
    //Serial.flush();     
    //(byte prefix,byte address,byte command,byte checksum)
    //Voy a Enviar (0x31, 0x02, 0x06, 0x39)
    sendCMD(49,2,6,57);
    valor_anteriorA=digitalRead(4);
    //DESPUES DE ESTO DEBERIA PONER EN==LOW, PARA RECIBIR LA RESPUESTA DE LA SONDA, POR EL MOMENTO LO VOY A HACER SIN VERIFICAR EL CHECKSUM.
    //OSEA EN BRUTO DEBERIA RECIBIR ALGO SIMILAR A: 0x3E, 0x02, 0x06, 0x1C, 0x1D, 0x0A, 0xE2, 0x05, 0xC4
    //Siempre va a tener el mismo tamaño 9 bytes (byte prefix, byte address, byte command, byte tempe, byte lvl1, byte lvl2, byte freq1, byte frec2, byte checksum)
    receiveINFO();
    
  }
  valor_actualB=digitalRead(7);
  if (valor_anteriorB==LOW && valor_actualB==HIGH)
  {
    
  //if (digitalRead(4)==HIGH){
    //Serial.flush();     
    //(byte prefix,byte address,byte command,byte checksum)
    //Voy a Enviar (0x31, 0x02, 0x06, 0x39)
    sendCMD(49,3,6,253);
    valor_anteriorB=digitalRead(7);
    //DESPUES DE ESTO DEBERIA PONER EN==LOW, PARA RECIBIR LA RESPUESTA DE LA SONDA, POR EL MOMENTO LO VOY A HACER SIN VERIFICAR EL CHECKSUM.
    //OSEA EN BRUTO DEBERIA RECIBIR ALGO SIMILAR A: 0x3E, 0x02, 0x06, 0x1C, 0x1D, 0x0A, 0xE2, 0x05, 0xC4
    //Siempre va a tener el mismo tamaño 9 bytes (byte prefix, byte address, byte command, byte tempe, byte lvl1, byte lvl2, byte freq1, byte frec2, byte checksum)
    receiveINFO();
  }
  valor_actualC=digitalRead(8);
  if (valor_anteriorC==LOW && valor_actualC==HIGH)
  {
    
  //if (digitalRead(4)==HIGH){
    //Serial.flush();     
    //(byte prefix,byte address,byte command,byte checksum)
    //Voy a Enviar (0x31, 0x02, 0x06, 0x39)
    sendCMD(49,4,6,147);
    valor_anteriorC=digitalRead(8);
    //DESPUES DE ESTO DEBERIA PONER EN==LOW, PARA RECIBIR LA RESPUESTA DE LA SONDA, POR EL MOMENTO LO VOY A HACER SIN VERIFICAR EL CHECKSUM.
    //OSEA EN BRUTO DEBERIA RECIBIR ALGO SIMILAR A: 0x3E, 0x02, 0x06, 0x1C, 0x1D, 0x0A, 0xE2, 0x05, 0xC4
    //Siempre va a tener el mismo tamaño 9 bytes (byte prefix, byte address, byte command, byte tempe, byte lvl1, byte lvl2, byte freq1, byte frec2, byte checksum)
    receiveINFO();
  
  }
 //if (digitalRead(7)==HIGH){
 //   Serial.flush();     
    //(byte prefix,byte address,byte command,byte checksum)
    //Voy a Enviar (0x31, 0x02, 0x06, 0xFD)
  //  sendCMD(49,3,6,253); 
    //receiveINFO();
   
// }
    
//if (digitalRead(8)==HIGH){
   /// Serial.flush();     
    //(byte prefix,byte address,byte command,byte checksum)
    //Voy a Enviar (0x31, 0x02, 0x06, 0x93)
  //  sendCMD(49,4,6,147); 
  //  receiveINFO();
//}
 

}

//Funciones

byte receiveINFO()
{
  byte byte_receive;
  byte conteo=0;
  
  while(Serial.available())
  {
    byte_receive=Serial.read();
    if (byte_receive==62)
    {
      while(conteo<=7)
      {
        data[cont]==byte_receive;
        cont=cont+1;
      }
    }
  }
}

void sendCMD(byte prefix,byte address,byte command,byte checksum)
{
  
  
  digitalWrite(EN,HIGH);
  delay(1);

  Serial.print(prefix,HEX);
  Serial.print(address,HEX);
  Serial.print(command,HEX);
  Serial.print(checksum,HEX);
  digitalWrite(EN,LOW);

  
  
}

Amigos tengo un gran problema

conecto el ARDUINO(O VARIOS QUE TENGO) Con el sketch cargado y con solo acercarle los dedos este comienza a enviar informacion como loco....que puede pasar?

tienes las entradas al aire, sinresistencias pull down o pull up.

Hola surbyte

Tienes toda la razon, gracias por hacerme caer en cuenta de esa bestialidad, mil disculpas por la ignorancia.

A proposito...viste el codigo que implemente con tu ayuda? que hice mal? no me envia nada

El PeterKant, me funciona, pero envia una unica vez.

Lo que yo pretendo es al pulsar envie una vez nada mas no importa lo que dure el pulso, pero si vuelvo a pulsar envie nuevamente.

Chicos disculpen la ignorancia, pero cada dia voy mejorando y estoy seguro que no volvere a caer en errores comunes, pero como ven aun soy bastante newbe.

De cuanto me sugieres las resistencias a tierra?