# Comunicación RS-485 PIC C CCS



## colombia90 (Oct 13, 2015)

Buen día amigos del foro me dirijo a ustedes que son mi única ayuda en este momento ya que lo he intentado todo.
 es lo siguiente:

1. necesito realizar una comunicación entre un pic maestro y varios pic esclavos por medio de rs485 en ccs ya que este protocolo permite definir unos ID para cada pic y de esta forma se pregunta al pic la informacion deseada por su ID que lo identifica.
2. el rs485 es la comunicación que me sirve debido a sus características de distancia y que el ruido no la afecta.
por el momento solo quiero prender un led cuando mi pic esclavo reciva el dato de mi pic maestro.
3. estos codigos no me funcionan y no se porque.

este es el codigo del maestro:


```
#include <16f877a.h>
#fuses HS,NOWDT,NOPROTECT,PUT,NOBROWNOUT,NOLVP
#use delay(clock=4000000)
#use RS232(baud=9600,xmit=PIN_D1,rcv=PIN_D2,stream= PC)


#define  RS485_ID 0x20  //ID de identificacion en la red
#include <rs485.c>
#use standard_io(C)
#use standard_io(D)

#include <stdio.h>
#include <stdlib.h>
#include <input.c>
#byte port_a=5
#byte port_b=6
#byte port_e=9

int8 dato;
char data;
void main()
{   
    set_tris_a(0x00);
    set_tris_b(0xFF);
     set_tris_e(0x00);
     
     port_a=0x00;
     port_b=0x00;
     port_e=0x00;
     rs485_init();


  
  while(true)
            {

            data=getc(PC);//recibe dato que envia el pc por rs232
             
             if(data==\'1\') 
                                { 
                                dato=1;//dato que envio
                                output_high(PIN_D0);// pongo en alto para transmitir
                                delay_ms(30);
                                rs485_wait_for_bus(FALSE); 
                                rs485_send_message(0x40,8,dato); // linea que envia al pic que tiene el ID 0x40 y envia el dato #1
                                }
              
          }
}
```


Este seria el codigo del esclavo:


```
#include <16f877a.h>
#use delay(clock=4000000)
#fuses HS,NOWDT,NOPROTECT,PUT,NOBROWNOUT,NOLVP
#define  RS485_ID 0x40
#include <rs485.c>

#use standard_io(C)
#use standard_io(D)
#include <stdio.h>
#include <stdlib.h>

#byte port_a=5
#byte port_b=6
#byte port_e=9

int dato;


void main()
{   
     set_tris_a(0x00);
     set_tris_b(0x00);
     set_tris_e(0x00);
    
     port_a=0x00;
     port_b=0x00;
     port_e=0x00;
     rs485_init();
     output_low(pin_D0); // pongo en bajo para recibir
  while(true)
            {
                        if(rs485_get_message(dato,0))
                        {
                           output_high(pin_E0);
                           delay_ms(1500);
                           output_low(pin_E0);
                       
                        }
           
            }
      
}
```

voy a  subir imagenes de mi circuito. ...

este es la imagen de mi sistema


----------



## Gudino Roberto duberlin (Oct 13, 2015)

Hola,  que síntoma aparece?


----------



## colombia90 (Oct 13, 2015)

Bien, amigo. No me envía el dato y el esclavo no hace nada.

Sigo probando diferentes códigos y no me envía datos el maestro.


----------



## Gudino Roberto duberlin (Oct 13, 2015)

Hola, fijate en la sentencia if ( data==\'1\'), quizás haya un error. Porque utilizas  \' en lugar de ' ?
Además que pines utilizas en la transmisión de RS485?
Están configurados cómo salida?


----------



## colombia90 (Oct 13, 2015)

gudino, si yo lo tengo como lo dices '1' esta parte me funciona, y los pines estan declarados en la libreria que yo llamo arriba #include<rs485.c>. al momento de subir el codigo no subio del todo con los simbolos.


----------



## D@rkbytes (Oct 13, 2015)

Cuando no se envuelve el código con las etiquetas CODE o PHP, algunos navegadores colocan símbolos HTML.
Esto afecta el código y es por eso que se recomienda que el código sea envuelto antes de ser publicado.

Busca el ejemplo "ex_rs485.c" que viene incluido con PIC Compiler de CCS.
Se encuentra en la carpeta "Examples" en donde está instalado el compilador.
Es muy similar a lo que requieres y seguramente te servirá de orientación.


----------



## colombia90 (Oct 13, 2015)

gracias amigo d@rbytes por tu aporte, ya estuve analizando este ejemplo pero no me sirve porque lo que hace es convertir datos RS485 y los pone en línea de datos RS232.
yo necesito es declararle un id a cada pic16f877, para que cuando el maestro le envié un dato a un pic en especifico este pic haga la tarea y devuelva un dato de confirmación.


----------



## D@rkbytes (Oct 14, 2015)

Me parece que si te puede servir ese ejemplo ya que si existe comunicación RS-485 de PIC a PIC.
Obviamente tienes que realizar algunos cambios.

Sí se usa RS-232 como medio de comunicación entre usuario y microcontrolador, pero los datos ingresados del usuario por RS-232, son enviados por RS-485 hacia cada PIC.
Ese ejemplo es como un chat entre microcontroladores, por lo tanto ambos reciben y transmiten hacia un ID específico.

No tengo experiencia sobre éste protocolo, pero lo que necesitas es interceptar los datos RS-485.
Cuando un comando es válido, entonces se activa el Timer 1 y los datos RS-485 se reciben por interrupción externa, que en éste ejemplo es por RB0.

Adjunto el programa con simulación porque me pareció interesante el funcionamiento. 

El funcionamiento es el siguiente:
Al principio los  microcontroladores se deben identificar con algún ID.
Cada uno pedirá el ingreso de un ID de red y se valida presionando la tecla "Enter".
A continuación se escribe la letra "c" (Change Address) para ingresar el ID de destino.
Cuando ambos estén configurados, se envía en cualquiera de ellos el comando "*s*" (Sin comillas)
Si no se ha ingresado un ID de destino, el microcontrolador en cuestión lo pedirá.
En seguida aparecerá por la terminal RS-232, lo siguiente: *(ID):>
*(Donde ID será el identificador de destino)
Ésto quiere decir que el microcontrolador está listo para enviar datos.
Se escribe cualquier tipo de mensaje y se presiona la tecla "Enter"
Una vez enviados los datos, el microcontrolador queda nuevamente en espera de comandos.
En ambos microcontroladores se debe realizar el mismo procedimiento.

Los comandos están descritos en el programa y se obtienen por RS-232 al ingresar el comando "*h*".

Nota:
Programa compilado con PIC C Compiler de CCS v 5.048 (PCWHD) y simuladores ISIS v7.10 y v8.1 de Proteus.

Suerte.


----------



## colombia90 (Oct 14, 2015)

buen dia darkbytes, realice el circuito en proteus tal como esta en la foto y le cargue los archivos y me corrio pero no tuve comunicacion realice los pasos como tal me los explicaste en el foro pero solo pregunta los id les pongo el mismo pero no me deja escribir en los virtual terminal. aqui adjunto la imagen. 
agradesco su ayuda y aporte a este tema que es muy interesante ya que en la red hay varios con este mismo problema de comunicacion de rs485 con id.


----------



## D@rkbytes (Oct 14, 2015)

Te recomiendo que no realices otro diseño y mejor abras cualquiera de los dos que adjunté.
Esto es porque se tienen que configurar las resistencias del bus de enlace de forma diferente.
R3 debe ser digital, R4, R6, R7 y R8 deben excluirse, y R5 debe ser análoga.

Si tienes Proteus 8.0, y no puedes abrir el que adjunto, (8.1) puedes abrir el diseño v7.10.
Pero debes abrir proteus y en el menú File, seleccionas: "Open Project"
En la ventana de búsqueda que aparecerá, en las propiedades "Tipo" debes seleccionar "Design Files"
Con eso ya puedes abrir versiones anteriores a la 8.XX y cuando se guarden, se guardarán con el mismo nombre pero con la extensión ".pdsprj" y para la versión que tengas.

Nota:
Lo que se escribe no se ve, a menos que en la terminal se seleccione "Echo Typed Characters"
Una vez listo el mensaje, se debe presionar la tecla "Enter" para que se envíe.
Si se quiere seguir enviando mensajes, otra vez se debe enviar el comando "*s*"


----------



## colombia90 (Oct 14, 2015)

Bien amigo D@rkbytes. Que excelente ayuda, si me funcionó el chat ya con estos pasos que me explicó.

Tengo una pregunta. ¿Dónde se definen los pines que van conectados al max487?
Ya que yo revisé la librería RS485.c y tienen otros pines de conexión para el max con el PIC.
En el programa tampoco veo donde los definen debido a que yo quiero utilizar un PIC más grande como el 16F877A.

Otra pregunta. ¿En el montaje real, o sea físico qué resistencias entonces se usan cuando en proteus son digitales, en el caso de R8 y R6 que se debe hacer?
Eso sí no lo sabía. 

 Muchas gracias por su ayuda.


----------



## D@rkbytes (Oct 14, 2015)

colombia90 dijo:


> Tengo una pregunta. ¿Dónde se definen los pines que van conectados al max487?
> Ya que yo revisé la librería RS485.c y tienen otros pines de conexión para el max con el PIC.
> En el programa tampoco veo donde los definen debido a que yo quiero utilizar un PIC más grande como el 16F877A.


Se usan las definiciones de la librería RS485.C, pero para definir otros pines, se debe realizar la definición en la cabecera del programa y antes de incluir la librería.

Por ejemplo:
*#define* *RS485_RX_PIN PIN_C1
#define RS485_TX_PIN PIN_C2
#include <rs485.c>
*


colombia90 dijo:


> Otra pregunta. ¿En el montaje real, o sea físico qué resistencias entonces se usan cuando en proteus son digitales, en el caso de R8 y R6 que se debe hacer?
> Eso sí no lo sabía.


Las resistencias las puse basándome en un esquema que encontré.
No he realizado éste tipo de conexión, pero sé que es con cable trenzado.
Más información la puedes obtener aquí en el Foro o buscando en Google.


colombia90 dijo:


> Muchas gracias por su ayuda.


De nada. Suerte.


----------



## colombia90 (Oct 14, 2015)

Bien, amigo D@rkbytes. El código funciona muy bien en el PIC16F628A, pero al momento que cambio de PIC al 16F877A y armo el circuito en proteus con las resistencias análogas y digitales, y cargo el mismo código y conecto en los mismos pines, no funciona.
¿Usted sabe *por qué* será esta falla, si utilizo el mismo código?
Lo que cambio es la librería del PIC y armo el mismo circuito con los componentes.


----------



## D@rkbytes (Oct 14, 2015)

Seguramente conectaste algo mal.

Adjunto el mismo ejemplo funcionando, pero con 2 PIC16F877A.

PD: Únicamente modifiqué el programa y las conexiones para usar el módulo USART.
Antes:
*#use     rs232(baud=9600, xmit=PIN_B2, rcv=PIN_B1, stream=PC)
*Ahora:*
#use     rs232(UART1, stream=PC) *// Configuración por defecto: 9600, 8, N, 1

Ya en tu proyecto debes hacer pruebas con la definición de pines que quieras usar.


----------



## colombia90 (Oct 15, 2015)

BUENAS NOCHES 
AMIGO D@RKBYTES
muy agradecido por el circuito que me adjuntas funciono a la perfección y quedo en deuda ya que he avanzado el dia de hoy bastante en mi sistema.

Tengo una falla:
la verdad no entiendo porque cuando quiero cambiar para para trabajar con otro pic no me funciona en este caso es con el pic18f4685 como maestro y el pic16f877a como esclavo, te explico porque la insistencia de cambiar de pic's: 
Es porque el pic maestro me va a manejar muchas instrucciones que le llegan desde un computador y este pic maestro debe tener excelentes características como por ejemplo (96KB code,3328B data, 1024 EEPROM) como las tiene el pic 18f4685 ,y el pic16f877a ya se me lleno con pocas instrucciones y me quede corto intente de varias formas conectar mi nuevo pic maestro y no me funciona.

gracias si me puede ayudar a solucionar este inconveniente ya que es la única persona que me ha ayudado y muy buena su ayuda.

adjunto como va mi sistema.

esta es la imagen de como voy con mi sistema y yo se que les voy a ayudar a muchas personas a solucionar este tema de comunicación con rs485.



tengo otro inconveniente de que cuando el esclavo retorna datos al maestro no retorna el dato completo.
envia 0, y yo le estoy diciendo que envie 0,100. de pronto tiene idea del porque.



este es un video donde explico mi ultimo problema. para que me ayuden.


----------



## D@rkbytes (Oct 16, 2015)

Necesitas leer la hoja de datos del PIC18F4685 para elegir la palabra de configuración correcta, las características de los puertos y también de los registros.
Prácticamente todos los PIC de gama alta pueden ejecutar programas de PIC's de gama media, pero es necesario estudiar la hoja de datos para obtener la configuración adecuada.

Sobre el envío y recepción de datos; debe ser porque no se pueden enviar datos del tipo Float.
Prueba enviado sólo Bytes, y no valores con decimales.

¿Y ese vídeo con extensión .camrec, con qué se abre?
Mejor sube el vídeo en formato AVI, también comprimido dentro de un archivo .ZIP o .RAR


----------



## colombia90 (Oct 16, 2015)

Buenos dias 
aqui adjunto mi video.

como hago para capturar el dato que me envía el esclavo, ya que solo necesitaría compararlo con un if(datoesclavo==0) haga tal proceso.
pero es que el maestro lo captura en msg[32] y no se como convertir este dato.



para compararlo en un if()



otra pregunta estas resistencias que tienen los max487 se colocan solo al principio i al final de la red por lo que he leido, sera que me puedes confirmar si tiene conocimiento.

Necesitas leer la hoja de datos del PIC18F4685 para elegir la palabra de  configuración correcta, las características de los puertos y también de  los registros.

 no entiendo lo de la palabra correcta donde veo esta palabra, la  configuracion tengo la mismos pines que en el pic16f877a y no me  funciona, de casualidad no tienes un ejemplo con estos pic 18f4685 como  maestro y pic16f877a como esclavo que me ayudes.


----------



## D@rkbytes (Oct 16, 2015)

Necesitas estudiar bien sobre lo que quieres hacer para que adquieras más conocimientos.
Lo de la palabra de configuración, son los fuses que necesita el PIC para determinar el tipo de oscilador, la habilitación o no del Watch Dog Timer, la protección de código y datos, entre otras cosas más.
Busca sobre eso o consúltalo en la hoja de datos. (Configuration Word)

Y no, no tengo ejemplos con ese PIC, porque de hecho, esos que subí son los únicos y son los de CCS.


----------



## colombia90 (Oct 16, 2015)

aqui adjunto un video de lo que presenta mi pic 18f4685 cuando envio un dato. el pic muestra en osciloscopio una trama muy rara. en este video aparece es el pic 18f2620 es que estaba probando porque ya me daba por vencido con mi pic18f4685, entonces decidi probar con otro pero se me presento la misma falla con este otro pic. pero la idea es que me funcione con el pic18f4685 por sus exelentes caracteristicas de almacenamiento.



Bien listo voy a seguir probando haber hasta que logre que me funcione.


----------



## nelsonr (Oct 16, 2015)

hola  a todos  tengo una duda,  ya realice una comunicacion entre dos pic con la configuración
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
y los pases de datos los realizo con put() y los capturo con el get() todo esto en pic c.
La comunicación entre los pic  es buena. Pero ahí puntos en el programa justo después de un envío de datos que tengo delay para realizar un retardo como para darle tiempo  a uno de los pic para que realice la tarea  y estén sincronizado uno del otro.
Como quiero mejora esto, estoy en busca de la mejor practica para realizar una comunicación fluida entre pic sin ningún tipo de delay y me tope con la función I2C y realizando estudios a diferentes ejemplo en la web encontré  que ahí ocasiones que también tiene delay  y no se si esto es correcto

me pueden decir cual seria la mejor forma de manejar una comunicación entre pic  en PICc ?


----------



## colombia90 (Oct 16, 2015)

nelsonr dijo:


> hola  a todos  tengo una duda,  ya realice una comunicacion entre dos pic con la configuración
> #use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
> y los pases de datos los realizo con put() y los capturo con el get() todo esto en pic c.
> La comunicación entre los pic  es buena. Pero ahí puntos en el programa justo después de un envío de datos que tengo delay para realizar un retardo como para darle tiempo  a uno de los pic para que realice la tarea  y estén sincronizado uno del otro.
> ...


para mi me funciona mejor el rs232 y es mas facil de utilizar pero solo entre 2 pic's y tiene un alcance hasta de 20 metros con cable blindado.
el i2c solo tiene como maximo alcance de 6 metros y lo aturde mucho el ruido.
bien suerte.



bien amigo Darkbyte, ya me funciono con el pic18f4685 muy bien tenias toda la razon era de cuadra los #fuses, me queda solo un problema por resolver.

estoy en el inconveniente de que no se como capturar el dato que me envia el esclavo ya que es un vector int msg[32] y necesito compraralo en un if.


----------



## D@rkbytes (Oct 17, 2015)

colombia90 dijo:


> Estoy en el inconveniente de que no sé cómo capturar el dato que me envía el esclavo, ya que es un vector int msg[32] y necesito compararlo en un if.


Entonces en alguna parte de ese arreglo de 32 bytes debe estar lo que te interesa y envía el esclavo.
Sólo tú sabes cómo y qué es lo que estás enviando.


----------



## nelsonr (Nov 9, 2015)

hola en una trasmisión de datos tipo rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bi ts=8), si yo en un momento quiero trasmitir datos de tipo int y en otro punto de la programación necesito trasmitir  caracteres o incluso combinarlos como podría hacer esto.
Actualmente estoy enviando putc(Vln_Emisario) y recibiendo = getc() datos de tipo int8. Pero en un punto x de la programación me gustaría también mandar de un pic al otro datos tipo character.
como puedo resolver esto.
Gracias por todo .
Atte
Nelsonr


----------



## D@rkbytes (Nov 9, 2015)

Todo depende de la forma en que interpretes los que envías.

Es decir, si envías "A", lo interpretas como "A", y si envías 0x0A, lo debes interpretar como 0x0A

Ejemplo con caracteres (Byte como "Caracter"):

// Envío:
putc("A");

// Recepción:
dato = getc();
if(dato == "A")
// Código
...

Ejemplo con enteros (Byte como "Número entero"):

// Envío:
putc(0x0A);

// Recepción:
dato = getc();
if(dato == 0x0A)
// Código
...

O sea que no es lo mismo interpretar Bytes como Caracteres, que Bytes como Números enteros.


----------



## dcsalg (Nov 13, 2015)

Hola. Estoy utilizando el PIC18F46K22 y viene con dos puertos RS-232.
Uno lo quiero utilizar como RS-232 y el otro como RS-485.

Mi consulta. ¿Está bien cómo lo estoy configurando?

Muestro cómo lo tengo ahora.


```
#use rs232(baud=9600,parity=N,xmit=TX1,rcv=RX1,bits=8,stream=PORT1)

//port2
#define RS485_USE_EXT_INT TRUE
#define RS485_RX_PIN RX2
#define RS485_TX_PIN TX2
#define RS485_ENABLE_PIN RS_EN
//#define RS485_RX_ENABLE None
#define RS485_RX_BUFFER_SIZE 10
#define RS485_ID 10
#include <rs485.c>//NOTE: only one RS485 port is supported by the driver
```

Me salta un error en la librería rs485.c en la siguiente linea:

```
#use rs232(baud=9600, xmit=RS485_TX_PIN, rcv=RS485_RX_PIN, enable=RS485_ENABLE_PIN, bits=9, long_data, multi_master, errors, stream=RS485_CD)
```

No sé por qué.

//#define RS485_RX_ENABLE None
Esta línea la puse así pero no sé si está bien.

Lo que quiero es que con un pin me habilite a transmitir o recibir.
O sea, veo que muchos unen las patitas 2 y 3 del MAX 485 y depende si es 1 o 0, transmite o recibe, por lo que veo.

 Así que bueno, algo mal está, porque me sale error como puse en la línea de arriba de la librería.


----------



## dcsalg (Nov 15, 2015)

Hola, Lo que sucede que el codigo apenas lo comence a escribir ya me da error porque justo me lo da en la cabecera el ERROR.


```
#include <DomoK22.h>
//#use spi (MASTER, SPI2, ENABLE=PIN_D3, LOAD=PIN_D5, DIAGNOSTIC=PIN_D2, BAUD=9600, ENABLE_DELAY=10, DATA_HOLD=10, MODE=0, BITS=8, STREAM=SPI2)


#ZERO_RAM

void main()
{

   rs485_init();

   while(TRUE)
   {
   }
}
```
esto es lo unico que tengo en C siempre antes de comenzar a escribir el programa chequeo que compile lo basico aunque sea con las cabeceras #USE y demas y luego comienzo.


```
#include <18F46K22.h>
#device ADC=10

#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOPBADEN                 //PORTB pins are configured as digital I/O on RESET
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES PROTECT                  //Code protected from reads

#use delay(internal=16MHz)
#use FIXED_IO( A_outputs=PIN_A3 )
#use FIXED_IO( B_outputs=PIN_B3 )
#use FIXED_IO( C_outputs=PIN_C0 )
#use FIXED_IO( E_outputs=PIN_E2,PIN_E1,PIN_E0 )
/*#define RS   PIN_A0
#define RW   PIN_A1
#define EN   PIN_A2
#define BKL   PIN_A3
#define DTA4   PIN_A4
#define DTA5   PIN_A5
#define DTA6   PIN_A6
#define DTA7   PIN_A7*/
#define INT00   PIN_B0
#define INT01   PIN_B1
#define INT02   PIN_B2
#define RB3   PIN_B3
#define IN_RB4   PIN_B4
#define IN_RB5   PIN_B5
#define IN_RB6   PIN_B6
#define IN_RB7   PIN_B7
#define SPKR   PIN_C0
#define RS_EN   PIN_C1
#define ADC14   PIN_C2
#define I2C_CLK   PIN_C3
#define I2C_DTA   PIN_C4
#define STS   PIN_C5
#define TX1   PIN_C6
#define RX1   PIN_C7
#define SPI2_CL   PIN_D0
#define SPI2_DI   PIN_D1
#define SPI2_DG   PIN_D2
#define SPI2_EN   PIN_D3
#define SPI2_DO   PIN_D4
#define SPI2_LD   PIN_D5
#define TX2   PIN_D6
#define RX2   PIN_D7
#define RE0   PIN_E0
#define RE1   PIN_E1
#define RE2   PIN_E2
#define MCLR   PIN_E3

#use rs232(baud=9600,parity=N,xmit=TX1,rcv=RX1,bits=8,stream=PORT1)



//port2
#define RS485_USE_EXT_INT TRUE
#define RS485_RX_PIN RX2
#define RS485_TX_PIN TX2
#define RS485_ENABLE_PIN RS_EN
//#define RS485_RX_ENABLE None
#define RS485_RX_BUFFER_SIZE 10
#define RS485_ID 10
#include <rs485.c>//NOTE: only one RS485 port is supported by the driver


#use i2c(Master,Fast,sda=I2C_DTA,scl=I2C_CLK)//,force_hw)
```


eso es lo unico que tengo y me da el siguiente error

dentro de RS485.c del mismo CCS 

#use rs232(baud=9600, xmit=RS485_TX_PIN, rcv=RS485_RX_PIN, enable=RS485_ENABLE_PIN, bits=9, long_data, multi_master, errors, stream=RS485_CD)

error en esta linea y me pone el compilador

*** Error 100 "C:\Program Files (x86)\PICC\Drivers\rs485.c" Line 92(8,145): USE parameter value is out of range H/W USART can not multi master
1 Errors, 0 Warnings.
Build Failed.


es todo lo que tengo hasta ahora, pero si ya con esto no puedo compilar no puedo continuar programando lko que quiero hacer que es comunicarme con otros pic.


----------



## D@rkbytes (Nov 15, 2015)

El error que a mi me muestra, dice que "*H/W USART can not multi master*"
O sea que, USART por Hardware no puede ser Multi Maestro.

Entonces elimina la definición "*#define RS485_USE_EXT_INT TRUE*" que está en //port2


----------



## dcsalg (Nov 15, 2015)

Yo pensé que esa línea es para saber cuando algún PIC transmite algún dato y cuando éste lo recibe hace la interrupción.
¿Si elimino eso funciona igual la interrupción cuando llegue algún dato por la UART?

O sea: #int_RDA //Interrupción
¿UART Rx funciona?


----------



## D@rkbytes (Nov 15, 2015)

Debe mantenerse funcionando la interrupción, a menos que en alguna parte del programa se deshabilite.


----------



## dcsalg (Nov 15, 2015)

Voy a comenzar entonces manos a la obra. Voy primero eliminando esa línea que me dijiste esperó no aparezca el error y a partir de ahí comenzar. Muchas gracias ante otro error escribiré


----------



## dcsalg (Oct 11, 2016)

Hola Gente tanto tiempo, tengo problemas con el RS485, sigo sin entender y la verdad que no entiendo nada ya esto, yo estoy utilizando un pic18f14k50 como master y un pic16f887 como esclavo hice un programa tan sensillo como que envie un dato por ejemplo 0x0A y el receptor al recibir eso que encienda un led, y si envia por ejemplo 0x0B el receptor lo apaga, bueno conclusion no funciona, estoy usando las UART de los pic osea es por hardware y el receptor tendria que trabajar con interrupcion no me funciona, osea quiero unir los dos pines osea un pin del pic controle la transmision y la resepcion y tampoco funciona. no puedo creer que sea dificil lo que quiero hacer tan tonto soy para esto...

MASTER

```
#include <18F14K50.h>
#device ADC=10
#ignore_warnings  201, 216
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)

#use delay(internal=4MHz)
#define bt1   PIN_B0
#define bt2   PIN_B1
#define rx   PIN_B5
#define tx   PIN_B7
#define en   PIN_C4

#use  rs232(UART1, stream=pic1)

//port1
//#define RS485_RX_BUFFER_SIZE 8
#define RS485_USE_EXT_INT true
//#define RS485_ID 10

#define RS485_RX_PIN rx
#define RS485_TX_PIN tx
#define RS485_ENABLE_PIN en
//#define RS485_RX_ENABLE en
#define RS485_RX_BUFFER_SIZE 8
#define RS485_ID 10
#include <rs485.c>//NOTE: only one RS485 port is supported by the driver



void main()
{
   int   dest_id = 0;
   
   //port_b_pullups(0x03);

  
   RS485_init();
   delay_ms(1000);
   dest_id=12;
   
   

   while(TRUE)
   {
     // rs485_wait_for_bus(FALSE); 
      
      rs485_send_message(dest_id, 1, 0x0A);  
      delay_ms(2000);
      rs485_send_message(dest_id, 1, 0x0B);  
      delay_ms(2000);
   }

}
```

ESCLAVO

```
//#include <slave rs485.h>
// EN 0RX 1TX
#include <16F887.h>
#device ADC=10

#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES BORV21                   //Brownout reset at 2.1V

#use delay(internal=4MHz)
#use FIXED_IO( A_outputs=PIN_A0 )
#define led   PIN_A0
#define en   PIN_C5
#define tx   PIN_C6
#define rx   PIN_C7

#use  rs232(UART1, stream=pic1)

//port1
#define RS485_USE_EXT_INT TRUE
#define RS485_RX_PIN rx
#define RS485_TX_PIN tx
#define RS485_ENABLE_PIN en
//#define RS485_RX_ENABLE en
#define RS485_RX_BUFFER_SIZE 8
#define RS485_ID 12
#include <rs485.c>//NOTE: only one RS485 port is supported by the driver
int8 in_char = 0;

#INT_RDA
void serial_isr()
{
   in_char = fgetc(pic1);
}

void main()
{
   int data_received;
   
   enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);
   

   rs485_init(); 

   while(TRUE)
   {

      if(rs485_get_message(data_received, TRUE)) 
      //TODO: User Code
      if(data_received == 0x0A) 
            output_high(led); 

      else
            output_low(led); 

   }

}
```

no entiendo la verdad,
y si coloco #define RS485_USE_EXT_INT FALSE se pone peor millones de errores saltan,
no entiendo bien la comunicacion asi, yo utilizo rs232 utilizo los comandos put o get todo perfecto pero quiero utilizar rs485 

me pueden dar una mano, yel circuito en proteus seria los dos pic y los dos max487 utilizo pero ni siquiera puedo compilar estos programas..


----------



## D@rkbytes (Oct 12, 2016)

Pon atención a los errores del compilador.
En el programa "Master" muestra lo siguiente:


			
				CCS C Compiler dijo:
			
		

> "rs485.c" Line 92(8,145): USE parameter value is out of range   H/W USART can not multi master


Anteriormente ya te había mencionado sobre ese error.
Entonces, comenta o elimina;* #define RS485_USE_EXT_INT true

*Compilará, pero ahora mostrará lo siguiente:


			
				CCS C Compiler dijo:
			
		

> >>> Warning 240 "Master.c" Line 50(38,42): Pointer types do not match
> >>> Warning 240  "Master.c" Line 52(38,42): Pointer types do not match


Y eso es porque necesitas pasar los datos como punteros.
O sea, aquí:

```
rs485_send_message(dest_id, 1, 0x0A);  
      delay_ms(2000);
      rs485_send_message(dest_id, 1, 0x0B);  
      delay_ms(2000);
```
Posteriormente, en el programa "Esclavo" se hace lo mismo.
Después de eliminar o comentar la definición del problema, muestra lo siguiente:


			
				CCS C Compiler dijo:
			
		

> *** Error 92 "Esclavo.c" Line 33(1,2): Duplicate Interrupt function


Entonces se comenta o elimina la función duplicada y ya compilará.

```
[COLOR=DimGray]/*
#INT_RDA
void serial_isr()
{
   in_char = fgetc(pic1);
}
*/[/COLOR]
```



			
				CCS C Compiler dijo:
			
		

> 0 Errors,  2 Warnings.
> Build Successful.


Pero tendrás dos advertencias. La primera  es porque debes usar un puntero.
Eso lo harás colocando un * a lado derecho de la variable "data_received"
Así: *data_received
Y la segunda advertencia es porque la variable "in_char" quedó sin uso al eliminar la función duplicada.


----------



## dcsalg (Oct 12, 2016)

Si, justo estoy en eso, ya errores no tiene segun el compilador pero no me enciende el led aun del esclavo.

mira mi codigo

MAESTRO

```
#include <18F14K50.h>
#device ADC=10
#ignore_warnings  201, 216
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)

#use delay(internal=4MHz)
#define bt1   PIN_B0
#define bt2   PIN_B1
#define rx   PIN_B5
#define tx   PIN_B7
#define re   PIN_C4
#define de   PIN_C5

#use  rs232(UART1, stream=pic1)

//port1
//#define RS485_RX_BUFFER_SIZE 8
#define RS485_USE_EXT_INT false
//#define RS485_ID 10

#define RS485_RX_PIN rx
#define RS485_TX_PIN tx
#define RS485_ENABLE_PIN de
#define RS485_RX_ENABLE re
#define RS485_RX_BUFFER_SIZE 10

int8 OUR_RS485_ID = 10;
#define RS485_ID OUR_RS485_ID


#include <rs485.c>//NOTE: only one RS485 port is supported by the driver
//#include <driver_rs485.c>
void RS485send(char* s, int8 id)
{
   int8 size;

   for(size=0; s[size]!='\0'; ++size);

   rs485_wait_for_bus(FALSE);

   while(!rs485_send_message(id, size, s))
      delay_ms(OUR_RS485_ID);
}

void main()
{
   int   dest_id = 0;
   int a,b;
   a='a';
   b='b';
   //port_b_pullups(0x03);

  //output_high(en); 
  
   RS485_init();
   delay_ms(1000);
   dest_id=12;
   
   

   while(TRUE)
   {
      //rs485_wait_for_bus(FALSE); 
      RS485send(a, dest_id);
      
     // rs485_send_message(dest_id, 1, &a);  
      delay_ms(2000);
      RS485send(b, dest_id); 
      delay_ms(2000);
   }

}
```

ESCLAVO


```
#include <16F887.h>
#device ADC=10

#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES BORV21                   //Brownout reset at 2.1V

#use delay(internal=4MHz)
#use FIXED_IO( A_outputs=PIN_A0 )
#define led   PIN_A0
#define re   PIN_C4
#define de   PIN_C5
#define tx   PIN_C6
#define rx   PIN_C7

#use  rs232(UART1, stream=pic1)
//#use  rs232(UART1, stream=pic1)

//port1
#define RS485_USE_EXT_INT false
#define RS485_RX_PIN rx
#define RS485_TX_PIN tx
#define RS485_ENABLE_PIN de
#define RS485_RX_ENABLE re
#define RS485_RX_BUFFER_SIZE 8
#define RS485_ID 12


#include <rs485.c>//NOTE: only one RS485 port is supported by the driver




void main()
{
   int data_received;
   
  // enable_interrupts(INT_RDA);
  // enable_interrupts(GLOBAL);
   
 //  output_low(en); 
   rs485_init(); 

   while(TRUE)
   {

      if(rs485_get_message(data_received, false)) 
      delay_ms(500);
      //TODO: User Code
      if(data_received == 'a') 
           { output_high(led); delay_ms(599);}

      else
            output_low(led); 

   }

}
```

coloque en proteus para no grabar a cada rato los pic, 
decia coloque en proteus los dos picx los dos max y el led en el esclavo para que se encienda
cuando reciva un caracter A y que se apague cuando es B, un fracaso lo mio,

hay algo en el programa que por ser basico no lo estoy viendo


----------



## D@rkbytes (Oct 12, 2016)

Mira el programa del post #8 y modifícalo conforme a tus necesidades.
Ese está funcionando correctamente.


----------



## dcsalg (Oct 12, 2016)

D@rkbytes entiendo lo que decis, pero si te fijas es muy parecido yo justamente lo que copie de ese es los dos pines DE y RE porque los tenia unidos ahora cada uno esta con cada pin como se ve en el programa, lo unico que no utilice del post 08 son los char PCgetc(), PCgetInt() y otros mas que saque todo eso pórque yo no estoy ingresando nada, solo es usar el RS485send(a, dest_id); que seria el del post u el original   
 rs485_send_message(dest_id, 1, 'a');  si utilizo el de la libreria rs485, si envio el dato tendria que hacerlo, y para recibirlo utilizo como ves en mi programa ni siquiera aun estoy utilizando la interrupcion dentro del while del esclavo coloque el rs485_get_message(data_received, false) y tendria que recibirlo y con un ir como se observa en el programa enciendo o apago, bueno no lo hace, si queres te paso el programa y el proteus para que veas como se simula


----------



## D@rkbytes (Oct 13, 2016)

Me parece que tienes que seguir el protocolo del ejemplo "ex_rs485.c" y no así directamente como lo estás haciendo.
Fíjate cómo en ese ejemplo se van pasando los datos a funciones y posteriormente son enviados. 
Nota los arreglos pasados a punteros y su proceso.

Si entras en modo de depuración, podrás ver que no se están cumpliendo las condiciones en la función "rs485_get_message" de la librería "rs485.c"


----------



## dcsalg (Oct 13, 2016)

sabes que sucede que en el ejemplo de "ex_rs485.c" pasa por muchas funciones que lo veo hasta complicado. 
mi  programa esta la interrupcion por hardware por lo tanto ni siquiera me deja escribir 
#INT_RDA
void serial_isr()

como en el ejemplo de "ex_rs485.c" por la cantidad de errores que tira , eso es de seguro porque adentro de la libreria "rs485.c" debe estar siendo utilizado para la lectura de los datos cuando se recibe.

quiero creer y entender que "rs485_get_message" tiene que tener la capacidad de recibir el dato y almacenarlo en una variable, si por ejemplo declaro "INT msg[3];" como variable y lo utilizo en la funcion "rs485_get_message(msg, FALSE)" tiene que tener la capacidad de guardar en msg[0] la direccion destino, [1] el len que en mi caso es 1, y [2] el dato osea 0x0A , o 0x0B segun quiera, 

y con un if(msg[2]==0x0A) tendria que funcionar eso lo que no comprendo?

yo no tengo que utilizar ni GETC() ni nada de eso porque comprendo que la libreria ya me hace todo eso lo estoy probando asi y nada aun.
el ejemplo "ex_rs485.c" lo veo muy complicado, solo entendi quiero me parece que en la interrupcion timer1 se esta usando la funcion "rs485_get_message" y luego con un  printf y el msg[i+2] que no entendi bien, que es como colocar [2] porque el for cuando es 0 va al 2, y bueno decia con el printf muestra el dato en el display, porque el mio no lo hace eso?


```
#include <16F887.h>
#device ADC=10

#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES BORV21                   //Brownout reset at 2.1V

#use delay(internal=4MHz)
#use FIXED_IO( A_outputs=PIN_A0 )
#define led   PIN_A0
#define re   PIN_C4
#define de   PIN_C5
#define tx   PIN_C6
#define rx   PIN_C7

#use  rs232(UART1,enable=re, stream=pic1)
//#use  rs232(UART1, stream=pic1)

//port1
#define RS485_USE_EXT_INT false
#define RS485_RX_PIN rx
#define RS485_TX_PIN tx
#define RS485_ENABLE_PIN de
#define RS485_RX_ENABLE re
#define RS485_RX_BUFFER_SIZE 10
#define RS485_ID 12


#include <rs485.c>//NOTE: only one RS485 port is supported by the driver

int8 data_received[10];


void main()
{
   
   rs485_init(); 
 

   while(TRUE)
   {
            
          rs485_get_message(data_received, FALSE);

      
      if(data_received[2] == 0x0a)
           { output_high(led); delay_ms(400);}
     
      else
           { output_low(led);  delay_ms(400);}
           

   }

}
```


"rs485_get_message(data_received, FALSE);" lo estoy usando dentro del while otra cosa que me gustaria que sea por interrupcion que aun nose como lo hare. int_rda es el que se utiliza por interrupcion cuando se recibe pero bueno nose

osea las interrupciones en el ejemplo de "ex_rs485.c" las pueden utilizar porque tienen declarado #define RS485_USE_EXT_INT  TRUE

pero en mi caso es #define RS485_USE_EXT_INT FALSE


----------



## D@rkbytes (Oct 14, 2016)

Los datos si se tienen que pasar a un arreglo cómo puntero.
Modifiqué el programa del ejemplo "ex_rs485.c" para hacer Master/Slave y funciona, aunque los datos se acomodan en otra parte después de pasarlos a la función "RS485send".
No sé por qué, y para saberlo se tendría que estudiar mejor todo el proceso.

Tal vez con algunas modificaciones más, se pueda usar únicamente un int en vez de un arreglo.

Adjunto los programas.


----------



## dcsalg (Oct 15, 2016)

Estaba mirando lo que me enviaste y sos un GENIO!!!!!! pero ahora te pregunto algo desde mi ignorancia, porque utilizas "#define  RS485_USE_EXT_INT    TRUE"  osea porque TRUE y no en FALSE?
y lo segundo si el micro tiene UART incorporada porque no lo utilizas? osea si pongo FALSE tendria que utilizar la UART del micro?

Otra cosa que quise hacer para ir probando sobre tu programa si cambio de pin el RX, ahora esta en el RB0 pero si utilizo el #define RS485_RX_PIN       PIN_B2 por ejemplo , no enciende mas el led ahora lo declaro de nuevo RB0 si, eso tiene algo que ver con "clear_interrupt(INT_EXT);" y "enable_interrupts(INT_EXT);" que esta en la funcion "rcv_on"?


----------



## D@rkbytes (Oct 15, 2016)

No he estudiado bien la librería, lo que realicé lo hice por lógica de procesos.
Si te fijas, no completé los programas, el esclavo no responde, y el maestro no verifica.
Más que nada me interesaba que el esclavo validara la recepción comprobando el checksum.


dcsalg dijo:


> ¿Por qué  utilizas "#define  RS485_USE_EXT_INT    TRUE"  osea porque TRUE y no en  FALSE?


Porque usé la interrupción externa por RB0 para el pin de recepción. (Rx)


dcsalg dijo:


> Y lo segundo. ¿Si el micro tiene UART incorporada por qué no lo utilizas?
> O sea, ¿Si pongo FALSE, tendría que utilizar la UART del micro?


No, la librería lo hará por software y usando las terminales definidas, ya sea por usuario o las que tiene por defecto.
De ésta forma la librería se puede usar en dispositivos sin módulo USART y aparte lo libera en los que si tienen.


dcsalg dijo:


> Otra cosa que quise hacer para ir probando sobre tu programa, si cambio  de pin el RX, ahora está en el RB0, pero si utilizo el #define  RS485_RX_PIN       PIN_B2 por ejemplo, no enciende más el led, ahora lo  declaro de nuevo RB0 y sí.
> ¿Eso tiene algo que ver con  "clear_interrupt(INT_EXT);" y "enable_interrupts(INT_EXT);" que está en  la función "rcv_on"?


No, el que no responda a ese pin, debe ser porque no lo está tomando en cuenta.
La declaración sobre la definición de pines, debe estar antes de incluir la librería.


----------



## dcsalg (Oct 16, 2016)

una consulta yo veo que en el programa que enviaste pusiste msg[10] pregunto porque no manejo mucho string no es como un BASIC que podes tu nombre y lo envia C es mas rompe con eso y mucho no lo se, pero en deduccion veo que podes enviar 9 caracteres entiendo, entonces : el programa  que envia dice msg[0]='a' ; si quiero enviar dos letras ejemplo a1 pondria msg="a1", y con eso listo error el compilador no me tira calculo que esta bien, y en el caso receptor puse *msg="a1" porque si no coloco asterisco me da error, pero veo que no funciona , el receptor que enviaste pusiste msg[2]='a', pero si recibo dos letras como "a1" no me llega noto


----------



## D@rkbytes (Oct 16, 2016)

Por eso te mencioné que la función usa un arreglo pasado cómo puntero.
También dije que para usar un int y no un arreglo, se tendrían que realizar más modificaciones.

Ya tienes la base, sólo te resta modificar la librería.


----------



## dcsalg (Oct 20, 2016)

Hola aqui intente hacer una respuesta con lo que me enseñaste, con la unica modificacion que hice ahora que fue agregar dos leds en el receptor y cuando envio "L1ON" del master enciende el Led 1, "L2ON" enciende el led dos en el esclavo y "L3OFF" apaga los dos medio que me esta funcionando o quiero entender que la respuesta del esclavo hacia el master llega porque sino no me enviaria el otro dato pero noto que no me encienden los leds como quiero como que por momentos engancha y momentos no algo no me esta engranando ahi. 
 Siendo que lo que envia el master lo envia bien y en el esclavo estoy viendo como llega por ejemplo el "L1ON" 

lo raro que cuando uso el comando switch funciona o tiende a funcionar con el IF no en el esclavo eso.

MASTER

```
#include <16F818.h>
#device  *=16
#ignore_warnings  201, 216
#fuses   NOWDT
#use     delay(internal = 8MHz)  // Usar 20 MHz para montaje en físico.
#use     rs232(baud=9600, xmit=PIN_B2, rcv=PIN_B1, stream=PC)

#define  RS485_RX_BUFFER_SIZE 12
#define  RS485_USE_EXT_INT    TRUE


#define RS485_RX_PIN       PIN_B0   // Data receive pin
#define RS485_TX_PIN       PIN_B7   // Data transmit pin
#define RS485_ENABLE_PIN   PIN_B3   // Controls DE pin.  RX low, TX high.
#define RS485_RX_ENABLE    PIN_B2   // Controls RE pin.  Should keep low.



int8 OUR_RS485_ID = 0x10;
#define RS485_ID OUR_RS485_ID

#include <rs485.c>
#include <stdlib.h>

int1 flag_rs485=0;
int8 i;
char msg[10];
char dato[10];

#INT_TIMER1
void timer1_isr()
{
 //  int8 i;

   if(rs485_get_message(msg, FALSE))
   {
      flag_rs485 = 1;
       for(i=0; i < msg[1]; ++i)
         dato[i] = (msg[i+2]);
      //printf("\n\r%d: ", msg[0]);
      /*
      for(i=0; i < msg[1]; ++i)
         putc(msg[i+2]);
         printf("\n\r");
         */
   }
}


void clean_msg (void)
{
   for(i=0;i<sizeof(msg);i++)
   {
      msg[i] = 0x00;
      dato[i] = 0x00;
   }
}

void RS485send(char* s, int8 id)
{
   int8 size;

   for(size=0; s[size]!='\0'; ++size);

   rs485_wait_for_bus(FALSE);

   while(!rs485_send_message(id, size, s))
      delay_ms(OUR_RS485_ID);
           
}

int1 ask()
{
      if(flag_rs485)
      {
         disable_interrupts(INT_TIMER1);
         flag_rs485 = 0;
         
         if(msg[2] == '1')
            output_high(PIN_B4);         
         
         delay_ms(50);
         output_low(PIN_B4); 
         delay_ms(50);
         
         clean_msg();
        // rs485_wait_for_bus(FALSE);
         enable_interrupts(INT_TIMER1);
         delay_ms(100);      
         return true;
      }
}


void main()
{
   //int8 i;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
   //enable_interrupts(INT_RDA);
//   enable_interrupts(GLOBAL);
   rs485_init();
   enable_interrupts(INT_TIMER1);
   
   while (true)
   {
      //if(!input(PIN_A2))
      //{
      do
      {
         msg = "L1ON";
         RS485send(msg, 0x12);
         delay_ms(150); 
      }
      while(!ask());
      //   while(!input(PIN_A2));
      //}

     
      do
      {
         msg = "L2ON";
         RS485send(msg, 0x12);
         delay_ms(150); 
      }
      while(!ask());
      
      do
      {
         msg = "L3OFF";
         RS485send(msg, 0x12);
         delay_ms(150); 
      }
      while(!ask());
      

   }
}
```



ESCLAVO

```
#include <16F887.h>
#device  *=16
#ignore_warnings  201, 216
#fuses   NOWDT
#use     delay(internal = 8MHz)  // Usar 20 MHz para montaje en físico.

#define  RS485_RX_BUFFER_SIZE 12
#define  RS485_USE_EXT_INT    TRUE

#define RS485_RX_PIN       PIN_B0   // Data receive pin
#define RS485_TX_PIN       PIN_B1   // Data transmit pin
#define RS485_ENABLE_PIN   PIN_B7   // Controls DE pin.  RX low, TX high.
#define RS485_RX_ENABLE    PIN_B6   // Controls RE pin.  Should keep low.


int8 OUR_RS485_ID = 0x12;
#define RS485_ID OUR_RS485_ID


#include <rs485.c>
//#include <string.h>

int1 flag_rs485 = 0;
int8 i;
char msg[10];
char dato[10];

#INT_TIMER1
void timer1_isr()
{ 
   
   if(rs485_get_message(msg, FALSE))
   {
      flag_rs485 = 1;
 
      for(i=0; i < msg[1]; ++i)
         {dato[i] = (msg[i+2]);}

   }
}

void clean_msg (void)
{
   for(i=0;i<sizeof(msg);i++)
   {
      msg[i] = 0x00;
      dato[i] = 0x00;
   }
}

void RS485send(char* s, int8 id)
{
   int8 size;

   for(size=0; s[size]!='\0'; ++size);

   rs485_wait_for_bus(FALSE);

   while(!rs485_send_message(id, size, s))
      delay_ms(OUR_RS485_ID);
}

void main()
{  char* d;
   output_low(PIN_A0);
   
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
//   enable_interrupts(GLOBAL);
   rs485_init();
   enable_interrupts(INT_TIMER1);

   while (true)
   {
      if(flag_rs485)
      {
         disable_interrupts(INT_TIMER1);
         flag_rs485 = 0;

         //if(msg[2] == 'L'){
         //   switch(msg[3]){
         //      case '1': output_high(PIN_A0);
         //               break;
         //      case '2': output_high(PIN_A1); 
          //              break;
         //      case '3': output_low(PIN_A0); 
         //                output_low(PIN_A1); 
         //                break;
         //   }*/
            
            switch(dato){
               case "L1ON" :   output_high(PIN_A0);  break;
               case "L2ON" :   output_high(PIN_A1);   break;
               case "L3OFF" :   output_low(PIN_A0); output_low(PIN_A1);   break;
            }
//           if(dato=="L1ON")
//              output_high(PIN_A0);
//           if(dato=="L2ON")
//              output_high(PIN_A1);
//           if(dato=="L3OFF")
//               {output_low(PIN_A0); output_low(PIN_A1);}
           
           // }
         }
      
            delay_ms(300);
            clean_msg();
            enable_interrupts(INT_TIMER1);
            msg[0] = '1';
            RS485send(msg, 0x10);
   }
 }
```

la ASK se me ocurrio hacerlo asi y no saldria del DO hasta que no halla una respuesta capaz hay algo mas practico


> int1 ask()
> {
> if(flag_rs485)
> {
> ...





> do
> {
> msg = "L1ON";
> RS485send(msg, 0x12);
> ...


----------



## D@rkbytes (Oct 20, 2016)

Recuerda que es un arreglo, no puedes comparar de esa forma.
El arreglo tendrá lo siguiente:

Entonces es lógico que la comparación falle si haces...
case "L1ON" :   output_high(PIN_A0);  break;

Para eso tendrás que formatear la cadena usando strcpy y después la comparas con strcmp.


----------



## dcsalg (Oct 20, 2016)

Si observas msg guarda datos de longitud, dirección y dato, lo que hice es utilizar una variable dato donde almaceno el dato puro sin dirección ni longitud, es strcpy no copia string? Entonces la consulta teniendo la variable dato con el dato puro no alcanza? Strcmp compara string pero se puede usar por ejemplo if(strcmp(dato, "L1ON")==0) voy a probar la verdad no lo use eso pero creo que es algo así


----------



## dcsalg (Mar 3, 2017)

aqui subo el Zip con todo el contenido Quiero comunicar como decia varios modulos con un master donde se comunican por RS485, donde si preciono el switch de un modulo  que el master sepa que se preciono y se encendio tal salida de ese modulo como tambien el master si quiere apagar una salida de tal modulo lo pueda hacer, me explico? adjunto archivos hay dos carpetas de modulos porque aun estoy indeciso su utilizar un modelo u otro pero hago los dos modelos y despues decidire.


----------



## dcsalg (Mar 8, 2017)

HOLA Gente del foro, solucione una parte del problema pero sigo con inconvenientes!, tengo una central que seria el Master y varios modulos Esclavos, por razones de pruebas solo hice uno en proteus, entonces en el modulo Esclavo preciono el primer Boton, enciende una salida del modulo y le avisa a la central y puse un testigo que me avisa que se encendio una luz del modulo el testigo en el Master esta en PIN_A4 , (mas adelante escribira en un display por ahora solo gice eso para hacerlo mas rapido), pero bueno ahora al reves, preciono un Boton del MASTER o CENTRAL que entra por PIN_B7 (lo hago asi para probar, en realidad tendria que ser por bluetooth), y me tiene que encender o apar el pin_C0 del modulo 1.
la realidad no lo hace, es mas se me traba el modulo 1 y ya no me responde nada porque sucede eso? me podrian ayudar?, para mi se queda esperando o en algun loop o algo porque para que no responda. y cuando preciono en el modulo tampoco envia al master en pocas palabras no funciona mas.

Para probarlo adjunto un zip, haganlo correr y precionen el primer boton del MOdulo 1 y observen que se enciende PIN_C0 del modulo y PIN_A4 del master, pero preciono el boton 1 del Master y no enciende o apaga el PIN_C0 del modulo sino que ya tampoco funciona mas el modulo ni envia al master.


----------



## nelsonr (May 4, 2017)

Hola amigos después de haber realizado una comunicación exitosa en CCS compiler con  la configuración #use rs232 estoy profundizando en el caso para estar mas claro, les agradezco sus aportes,
Por ejemplo
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7,BITS=8,ERRORS, PARITY=N, stream=COM1)

Baud = 9600. De estas instrucción solo se que es la cantidad de bit por segundo que puedo trasmitir. 
Le agradezco que me corrijan o que aporten mas a este información.

Xmit,rcv es donde colo los pines de trasmisión Tx y Rx

Bits: entiendo que esto se usa para saber cuantos bits se envían en el bytes, y pueden ser configurados con 8,7,6 y 5.  
Entiendo que este tipo de transmisión se da en bytes. Por ende puedo deducir que puedo trasmitir hasta 1200 bytes por segundo ya que tengo definido que se trasmitan 9600 bits por segundo.
Le agradezco que me corrijan o que aporten mas a este información.

PARITY= N  *Los bits de paridad se utilizan como la forma más simple de*código para la detección de error.*
 Tengo entendido que hay dos tipo de paridad y para este caso yo indico que no utilizo este sistema de detección de errores.
Entiendo que el mismo solo se usa para transmisión.
Le agradezco que me corrijan o que aporten mas a este información.
N = No se utiliza paridad
E = Patidad Par
O = Paridad Impar.

ERRORS: De esta instrucción lo que conozco es que se usa para detectar errores de trasmisión y si en alguna interrupción que se este esperando el dato trasmitido existe por alguna razón un error y se cuelga la comunicación, esta función libera le ataco. Pero a subes esta instrucción nos permite usar una variable RS232_ERRORS de los cuales no conozco casi nada, solo se que se usan para apañar el mensaje de error para poder presentarlo en un lcd o algo así. 
#bit ninth_bit = RS232_ERRORS.7
#bit collision = RS232_ERRORS.6
Le agradezco que me corrijan o que aporten mas a este información.

Si puede hacer un ejemplo de como se usan las variables RS232_ERRORS y que significa .7 y .6 se los voy a agradecer.


----------



## D@rkbytes (May 4, 2017)

En la ayuda del compilador se encuentra todo lo que necesitas saber sobre *#USE* *RS232*.
Tan sólo presiona la tecla F1 y aparecerá.
Ahí verás un menú con varias pestañas, selecciona Índice y podrás realizar una búsqueda escrita o deslizante.
También puedes obtener información situando el cursor sobre alguna instrucción y después presionar la tecla F1.


----------



## dcsalg (Dic 24, 2017)

Hola, para no abrir otro foro, escribo aca estuve un tiempo probando el RS485, adjunto un archivo zip, deje un tiempo y retome estoy tratando de comunir 3 placas con un pic16f886, cada placa tiene 4 pulsadores y un led que corresponde a cada pulsador, y a su vez un dipswitch, donde si activo el pin 1 del dipswitch trasmite el boton 1 y asi sucecivamente. entonces si todos tienen la misma direccion recibiran esa informacion sino no. Entonces preciono por ejemplo el boton 1 y si tienen el mismo nombre las otras encienden el 1 me explico?. y si otra placa preciono el 1 y si estaban todas encendidas se apagan y si preciono en otra el 1 se encienden, no importa de donde porque todas se comunican. sea boton 1 o 2 o cualquiera. En fin el problema que en el proteus parece que funcionara aunq no me gusta mucho, y lo peor en vida real uno recibe el otro no, y si llego encender las 3 placas cuando preciono para apagar se apagan dos y la otra no es como que costara que las 3 reciban la misma informacion. y eso que pruebo con 3 nose que pasaria si pongo mas placas que esa es mi intencion no solo 3 pero en la vida real no se comunican bien porque es siempre algo se pierde no hacen todas lo mismo. adjunto zip. Gracias


----------



## D@rkbytes (Dic 24, 2017)

El problema tal vez se deba a que estás usando mal la función atoi(*string*).
Debes pasarle el valor con strcpy(_*dest*,* scr*_) y usar un arreglo sin datos, o como puntero.

En tu caso es más fácil transferir el dato a atoi como puntero, tan solo agrega un * a tu arreglo.
Por ejemplo:
char *msg[tope_array];

De esa forma, atoi comprenderá el dato y retornará un valor correcto, de otra forma, siempre retornará 0


----------



## dcsalg (Dic 24, 2017)

hola D@rkbytes, esa funcion es para otro metodo lee mas abajo del programa, esa que leiste es si recibo por bluetooth, el problema que tengo es cuando preciono el boton enciende el led de la placa esa y la que envia a otras y lo hace con otro if no con el atoi. con
asi envia

```
if(!input(KEY1)){disable_interrupts(INT_TIMER1); output_toggle(SAL1); envia_luz(1,input_state(SAL1),input(PC0)); while(!input(KEY1)); enable_interrupts(INT_TIMER1);}
```
envio a las otras placas y se recibe con un int_timer1

y los if son asi para selectar cual led


```
///// DATOS RECIVIDOS POR TECLA DE OTRO DISPOSITIVO
         IF((msg[0]==RS_ID)&&(msg[2]=='L'))
         { 
            switch (msg[3]) {
               case 1: output_bit(sal1,msg[4]); break;
               case 2: output_bit(sal2,msg[4]); break;
               case 3: output_bit(sal3,msg[4]); break;
               case 4: output_bit(sal4,msg[4]); break;
            }
         }
```

no hay atoi, por eso pregunto por favor que sucede que no reciben bien porfa, y me desconcierta
proteus funciona por eso subi el archivo y vida real recibe no todos capaz dos a veces los 3 o apan dos placas y la tercera no y no veo el error en el programa.


----------



## D@rkbytes (Dic 25, 2017)

Veo algunas cosas extrañas en tu programa que pueden ocasionar problemas.
Estar limpiando constantemente el array msg, hace que todo el tiempo se permanezca dentro del bucle de esa rutina.
Eso hace perder tiempo inútilmente.
Sería mejor limpiar el array después de cualquier uso.

Leer los datos usando un timer no lo veo buena opción y mucho menos como lo estás haciendo.
No estás recargando el timer 1 para un desborde establecido, sino que esperas su desborde por defecto.
Eso hará que se pierdan datos, porque no podrán ser leídos constantemente.

Te recomiendo que realices una depuración ICD para que mires los valores del array msg.
Ya que de esa forma podrás comprobar si en verdad estás obteniendo los valores que se esperan.
En tu simulación pude comprobar que tampoco estás realizando depuración y hacerlo es algo muy útil.


----------



## dcsalg (Dic 25, 2017)

Por las dudas Aclaro que no soy un esperto por las dudas, tengo un problemita no puedo hacer ICD y nunca hice eso si se puede hacer todo simulado para ver capaz si pero en vida real estoy usando cosas basicas, hasta mi programador, aqui adjunto otra modificacion del programa, pero lo que me da bronca que en proteus funciona. Me guio bastante con eso. son 3 placas conectados por un par telefonico con esos modulitos RS485 con los pic esos que ves en Proteus. Pero prende apaga bien por momentos falla uno placa luego vuelve a recibir y reacciona. Yo utilizo el Timer1 porque es como aprendi para recibir 
Estoy probando igual sacando como dijiste los clean_msg().
Utilice el SET_TIMER , pero no veo que los datos lleguen de manera confiable, como veras los envio varias veces para ver si se recibe. Pero Aun es Nulo los resultados igual. Voy a tratar de descansar y mañana seguire yo me guio con un ejemplo que me enviaste en este foro que conectaste dos pic y dos botones uno que enciende y o tro apaga a base de eso realice pero es increible que no me funcione con 3. 
Mi Grabador es un TMprog de paso para saber que utilizo y creo que no se puede hacer debugger con ese.
O el problema es la cantidad de datos?


----------



## dcsalg (Dic 31, 2017)

Sigo sin Lograrlo lo que hice ahora es tratado de Comprimir los datos osea enviar menos datos osea el receptor recibe menos msg, antes venia uno para uno con la direccion el otro la cantidad de datos otro que decia si es una luz, otro que decia cual y otro el estado encendido 1 o apagado 0. lo que hice ahora es unir estos dos ultimos a uno donde los primeros 4 bits dice cual es y los ultimos 4 el estado. pero sigue sin funcionar pense que enviando menos datos iban a recibir mejor pero siguen a veces sin recibir si o no , asique no va por ese lado y nose como hacerlo para que el dato llegue confiable, eh enviado mismos datos un par de veces por si no recibia en la primera pero veo que no funciona tampoco. no tienen un ejemplo de algo parecido a lo que quiero hacer de unir varias placas asi veo como funciona esa comunicacion. gracias  
nose si esta peor que antes o mejor 

hay una linea en la funcion envia_luz que dice as RS485send(dato,10);  eso lo puse porque hay otra placa que aun no la arme que recibe informacion de todas las placas de lo que estan haciendo, pero esa linea puede hacer que no se comuniquen entre ellas? pregunto porque es como enviar dato a una placa y la linea de abajo de esa envia a otra no creo que moleste eso o si? pero por favor si tienen algo que hayan echo capaz pueda ayudarme a ver porque nose me doy cuenta. Y es algo sencillo como pecionar un boton y encender el led


----------



## dcsalg (Ene 7, 2018)

Hola, aqui hay otra version del programa el circuito en proteus lo pueden utilizar de los otros zip que subi arriba y se le carga el programa este, lo que noto que en la Computadora y proteus funciona, Perooo, en la vida real entre dos placas funciona bien cuando coloco una tercera comienza el problema asiq nose si es problema de comunicacion?, si entre dos funciona perfecto y una tercera hace que funcione a veces si o no, capaz es problema del cable puede ser? hay algun secreto de como instalar los cables? Estoy utilizando los modilos RS485 de arduino esos chiquitos saben cuales digo? capaz hay que hacer alo que nose. Por eso hay alguna manera de conectarlos o algo que tenga que tener en cuenta? por ese mal funcionamiento. Gracias Y porfa ayudenme porque me escribi todo solo estos 3 me olvide aclarar nose si sirva los modulitos rs485 los alimento con 5v y los cables son par telefonicos


----------



## ricbevi (Ene 8, 2018)

Lamentablemente no programo en C pero he visto que usas velocidad de 9600, intenta bajar a 1200 que para la aplicación esa es mas que suficiente.
No se como estas usando el RX y TX, yo uso la UART incluida dentro del microcontrolador y al inicio de la emisión envió un carácter de control que hace que todos los que están "escuchando", sepan que habrá una emisión a continuación.
También cada integrante de la red tiene una identificación que debe ser emitida/recibida para individualizar los mensajes específicos. 
Ejemplo: A1, A2, A3,...A35.
Realice un control para 35 estaciones RS485 con el IC 75176 y lo probé en físico con 5 en simultaneo con cable UTP y funciona bien y envió mas información para ser mostrada en display en cada estación y comandar un tablero remoto con display grandes.
El lenguaje que use fue el Basic de Proton, lamentablemente como es un desarrollo comercial, no puedo compartir el software.


----------



## dcsalg (Ene 10, 2018)

Hola ricbevi,yo utilizo esos modulitos que se venden RS485 que son esos finitos que tienen para conectar do cables, sabes cuales digo no? y te comento yo no utilizo la UART del pic sino otros pines, y la recepcion cuando llega un mensaje hace una interrupcion por RB0 y comienza a leer, y utilizo par telefonico en la comunicacion y me pasa eso entre dos plaquetas todo perfecto pongo una tercera  y a veces anda otras no, y en PROTEUS funciona perfecto, por eso consulto  si es problema de cable, o son esas plaquetas cosas que no creo en internet hay infinidades de ejemplos con esas cosas y funcionan, o nose la verdad.


----------



## ricbevi (Ene 10, 2018)

Proteus es solo un simulador y da por echo cosas que en el "mundo real" no son así.
Un ejemplo de ello son los ruidos/interferencias que en el entorno virtual Proteus no los tiene en cuenta .
El cable para una red 485 ideal, no es un par telefónico y deberías como mínimo usar un UTP o STP, se a los módulos que te refieres, yo ese esquema los realice en la misma placa de circuito impreso de cada terminal.
Es importante usar los módulos internos que traen los micro-controladores a no ser que puedas mejorarlos externamente, no me parece el caso de la comunicación serie que te ocupa y esta resuelta de maravilla en casi todos los micro-controladores de los últimos tiempos.
Si seguís haciendo lo mismo y no atacas el problema donde radica, terminaras cansándote del proyecto.
Revisa las recomendaciones de los que te hemos tratado de ayudar y seguramente llegaras a buen puerto.
Saludos.

Ric.


----------



## dcsalg (Ene 12, 2018)

hola ricbevi, a ve si entendi vos decis que ataque por el lado de los cables entonces? a ver si mejora es asi? Te comento por las dudas que utilizo un cable par telefonico blindado de unos 60 o 70 cm no mas estoy probando todo en una mesa por eso nose si influye el ruido en esa distancias? 
Yo tengo esos modulos uno en cada extremo y tengo otro modulo ponele a mitad de camino de esa linea osea a unos 40 cm tengo un modulo en el medio, entonces uno en cada extremo y otro a mitad de camino, la pregunta es, Es necesario esa resistencia de 120 ohm utilizando esos modulos? y otro capaz tambien ayude el modulo que veo que tiene inconveniente es el que esta a mitad de camino no el de los extremos. Cuando logo que responde mas o menos , veo que los que estan a los extremos se comunican bastante bien, pero el que esta a la mitad no, si no se queda trabado en cendido no enciende, o pierdo el control un poco a veces el del medio suponiendo que quiero apagar el led del que me quedo encendido de la plaqueta que controla el modulo del medio como que me cuesta, el que tiene incoenvenientes es el del medio el que mas la sufre, pero porque? nose


----------



## ricbevi (Ene 12, 2018)

De mi intervención anterior...

SIC "*...he visto que usas velocidad de 9600, intenta bajar a 1200...*"

Las resistencias de terminación en las dos puntas de 120ohms son necesarias(no se si las culpables de que no te funcione a ti el sistema).

Las distancias que usas no son largas pero no tengo ni la mas pálida idea de que has echo tu en lo físico/real....conexiones, alimentación, etc, etc. 

Una cosa es el esquema, plano, etc. y otra muy distinta la construcción real y física en si.


----------



## dcsalg (Ene 28, 2018)

Tengo esas plaquetas que se venden de Arduino de RS485 con unas placas con los pic16f886 con par telefonico que no hay mas de un metro entre una laca y otra con una en el medio ningun secreto mas que eso, por eso preguno es necesario con esas plaquetas rs485 de arduino poner resistencias? porque son un circiuito completo esas plaquetas de arduino. y voy a probar a bajar la velocidad.


----------



## dcsalg (Feb 11, 2018)

Bueno probe eso de bajar la velocidad a 1200 y no corrigio nada y estoy probando todo a 1 metro las 3 plaquetas nose como hacer ya


----------



## Saint_ (Feb 14, 2018)

Hola dcsalg, veo que estas padeciendo con el problema este del rs485.
Por lo que leí en simulación esta funcionando todo.

Entonces ahora es cuestión de atacar al hardware, para esto se puede hacer lo siguiente:
Verificar que los módulos rs485 estén en buen estado.

Para esto nos olvidamos de todo el protocolo implementado (solo se cambia el programa, el circuito debe estar armado sin que le falte nada) y solo usamos el puerto serie.
Se elige un supuesto maestro y este envía una trama de datos cualquiera a los demás que serían los esclavos, los esclavos deberían recibir la misma información que envió le maestro, si alguno de los esclavos no recibe los datos correctamente entonces ya sabremos a quien centrar la atención.
Supongo que para verificar si recibió los datos se puede usar un lcd u otros puertos serie conectados a la pc.


----------



## dcsalg (Feb 18, 2018)

Hola Saint_ lo que sucede que no es que hay un maestro o un esclavo todos se comunican con todos, lomque utilizo son esos modulos de RS485 que se venden y lo que sucede que no siempre es el mismo el que responde segun como se le antoja a veces reacciona siempre uno o los 3 o a veces ni recibe entonces es como que me deja descolocado todo esto. tendra algo que ver porque no utilizo el RS232 de la plaqueta y utilizo por software? pero la realidad que no creo que sea eso la libreria de CCS esta bastante bien realizada, el problema es que si tengo 3 plaquetas, y transmito de la 1 la plaqueta 2 y 3 lo reciban y enciendan el led, como un repetidor de la 1 seria, y si se me ocurre apagar el led de la laqueta 2, que la plaqueta 1 y 3 lo apaguen, y si enciendo de la 3, que la plaqueta 1 y 2 enciendan, no resulta. Baje velocidad, la comunicacion esta a 1 metro entre plaquetas, y es cosa de no creer uno un par telefonico como puse antes para esta prueba que para un metro de distancia me va a servir como prueba y lo peor que como vi en su momento que funcionaba en la computadora construi las 3 plaquetas quedo lindo pero me pasa esto y me agarro una cosa adentro que no lo puedo creer porque le estoy haciendo de todo, nose ya porque lado viene el problema.


----------



## Saint_ (Feb 26, 2018)

Normalmente en I2C se usa un maestro y los demás son esclavos, lo que tu estás haciendo caería en multimaestro y es tiene sus detalles, en lo posible seria que trabajes en modo maestro-esclavo.


----------



## dcsalg (Mar 5, 2018)

Saint_ estoy usando RS485, no I2C.
Recién ahora comienzan a funcionar las plaquetas, lo que no entiendo es por qué tengo que resetar cada plaqueta con el boton de reset, si no, no funcionan.
O sea, conecto las plaquetas que son 3 y nada, presiono reset, esa comienza a funcionar, luego presiono el reset de la siguiente y así, si no presiono el reset, nada.
Es como si arrancara mal el programa, no sé. ¿Estará mal el orden de las líneas de código?


----------



## Saint_ (Mar 5, 2018)

dcsalg dijo:


> Saint_ estoy usando RS485 no I2C


Tienes razón, se me fue ese detalle, quise decir que en rs485 igual se usa la figura de maestro esclavo.

Por ahí me da la impresión de que como estas enviando los datos “todos contra todos”, tienes colisiones en el bus y eso justificaría el por qué recibes valores erróneos y de manera aleatoria.


----------



## dcsalg (Mar 6, 2018)

*Saint_ ¿Y* c*ó*mo hago eso de maestro esclavo? Porque en caso de I2C pones Master y los Otros Slave.
*Y* otra consulta*.* *¿S*i yo pre*s*iono una tecla en un esclavo para que encienda su led y quiero que encienda el led en el maestro, el esclavo no pasa ser master?
Porque el que env*í*a en este caso es el esclavo y no puedo estar interrogando con el maestro a todo momento los esclavos*.*
*C*reo porque esa linea tambi*é*n se usa para otras cosas, si*-*no estar*í*a todo el tiempo ocupada en interrogar*.*


----------



## Saint_ (Mar 6, 2018)

En realidad el maestro es que decide que va a hacer los esclavos.

En el caso de que si el en el esclavo se presiona una tecla y este enciende un led, se debería guardar el estado del led en alguna variable y cuando el maestro le pida información recién el esclavo le envié el dato esto implica que el maestro deberá interrogar periódicamente al o los esclavos,  los esclavos pueden estar haciendo sus tareas y solo enviar información cuando el maestro se los pida. Por eso en la trama RS485 normalmente se envía el id del que inicia la comunicación (este podría ser el maestro), el ID del destinatario (podría ser el esclavo), numero de bytes enviados, datos  y el ackt, de este modo se pueden detectas si hubo errores y si eso pasa entonces retransmitir.


----------



## dcsalg (Abr 26, 2018)

Disculpa que tarde en responder, voy a probar eso que me dijiste, tendría entonces que crear una central que valla chequeando esos módulos la macana que nose a que frecuencia puedo chequear? , una consulta trabaja así un sistema domotico? si hago conexión por rs485 y tengo módulos por la casa de 4 canales que es lo que fabrique con un pic cada modulo, que puedo encender con teclas eso lo guardo en una variable y la central recibe ese dato y si hay otro modulo que tendría que repetir por ejemplo un canal del modulo que tome la central se lo envía? nose si me explique bien? yo por ejemplo había pensado dos módulos con el mismo nombre si uno enciende enviaba el dato y si hay otro con el mismo nombre hacia lo mismo. De esta manera la central toma de uno y lo envía al otro. voy a probar. ojala me salga me va a llevar un tiempito porque tengo que hacer la central pero ojala funcione. Tendría que hacer que el modulo que almaceno la información una vez que la central lo lea cambie un estado de alguna bandera para que no repita eso de nuevo o no es necesario eso que opinas?


----------



## Saint_ (Abr 27, 2018)

dcsalg dijo:


> nose a que frecuencia puedo chequear?


yo creo que con 100ms es suficiente.


dcsalg dijo:


> si hago conexión por rs485 y tengo módulos por la casa de 4 canales que es lo que fabrique con un pic cada modulo, que puedo encender con teclas eso lo guardo en una variable y la central recibe ese dato y si hay otro modulo que tendría que repetir por ejemplo un canal del modulo que tome la central se lo envía?


Si un esclavo (tarjeta, modulo teclado o lo que sea) tiene que mandar información a otro esclavo, forzosamente el maestro tiene que leer la información del primer esclavo y luego enviársela al segundo esclavo.


dcsalg dijo:


> yo por ejemplo había pensado dos módulos con el mismo nombre si uno enciende enviaba el dato y si hay otro con el mismo nombre hacia lo mismo. De esta manera la central toma de uno y lo envía al otro.


No es buena idea que dos módulos tengan el mismo nombre, id o dirección a menos que ambos se comporten exactamente igual ...pero exactamente igual, de otro modo igual habría problemas en el bus de comunicaciones. En estos casos cada esclavo debería tener su propio nombre, id o dirección y todo controlado por el maestro


----------



## dcsalg (May 6, 2018)

sabes Mientras lo estoy haciendo me doy cuenta que no me convence algo, la central tiene un display que muestra la hora, tiene un teclado para configuracion, y si me pongo a chequear uno por uno, que aun no lo pude lograr, pierde tiempo en el chequeo desatendiendo lo demas, la cosa es que en todo caso la central escuche lo que los demas puedan enviar y no realizar un chequeo uno por uno no es alfo muy practico eso me parece. es como poner el despertador a las 4 de la mañana y estar despierto mirando la hora y cuando sean las 4 te levantas. Lo ideal es que haga sus cosas y cuando pasa algo en el modulo llame la atencion. pero ahi en este caso la central ya no es que chequea. por eso algo no comprendo de lo maestro y esclavo. en todo caso los modulos de 4 canales funcionen encendiendo las luces, si tenes una casa de dos pisos lo ideal es que en el piso de ariba pongas otro modulo, si se enciende la luz del frente de la casa planta baja lo que tiene que hacer es que el modulo de arriba dice ah encendio afuera de abajo yo voy hacer lo mismo afuera pero en el piso de arriba y enciende. entonces te queda todo el frente iluminado. Claro este ejemplo es sencillo con dos ahora imaginar con 3 o 4 modulos.


----------



## Saint_ (May 6, 2018)

dcsalg dijo:


> sabes Mientras lo estoy haciendo me doy cuenta que no me convence algo, la central tiene un display que muestra la hora, tiene un teclado para configuracion, y si me pongo a chequear uno por uno, que aun no lo pude lograr, pierde tiempo en el chequeo desatendiendo lo demas...


Todo depende de que tan bien se maneje los recursos del microcontrolador, por ejemplo (sumiendo que el microcontyrolador tiene 3 temporizadores, puerto serie harware...) al diplay se le asigna el temporizador 0, al teclado el temporizador 1, aún queda el temporizador 2 para que efectué la consulta a los esclavos y mediante la interrupción del puerto serie atender los datos enviados por los esclavos, todo está en que tan bien se distribuyan las tareas.


----------



## D@rkbytes (May 6, 2018)

Sí, por eso el microcontrolador dispone de varios periféricos, timers e interrupciones.
No es bueno ni conveniente hacer todo en el bucle principal del programa.


----------



## dcsalg (May 14, 2018)

Hola, ya voy adelantando pero tengo un problema ue nose como solucionarlo, tengo la central y dos modulos por ejemplo modulo 1 con direccion 0x20 y modulo dos con direccion 0x30.
Entonces enciendo la luz en el modulo 1, y la trama es se me ocurrio asi 0x4c 0x01  es un ejemplo ese el 0x4c es para que sepa que es una LUZ, el segundo que es 0x01 seria el estado de la luz osea un estado del pin de salida si es 0x00 luz apagada y si es 0x01 encendid, pero el inconveniente es, la cemtral escanea los modulos primero 0x20 y despues el 0x30, entonces vos encendes la luz del mosulo uno osea del 0x20 lee el estado y lo envia al modulo 0x30, osea la central envia 0x4c 0x01, pero si apago del modulo dos la luz cuando chequea el modulo 1 y ve que el modulo 2 esta apagado lo enciende de nuevo entonces no puedo apagarlo del dos se enciende y se apaga del uno y la cosa que se pueda hacer de ambos lados, como puedo solucionar eso? gracias


----------



## Saint_ (May 14, 2018)

Pues me imagino que en algún lugar de ti código tienes banderas que no se actualizan en cuanto se hace un cambio de estado por parte del maestro o de los esclavos. La solución no debería ser muy complicada pero depende de cómo este estructurado tus programas.


----------



## dcsalg (May 25, 2018)

Hola Estube haciendo el programa y es una cosa que no va, nada practico si la central tiene que chequear es engorroso, chequea los modulos que cual encendio la luz si hay una relacion con otro modulo le envia el dato para que lo encienda y lo mismo al contrario, si hay un modulo que tiene direccion 0x30 y otro con 0x20 chequea el primero si no tiene relaciones con otros modulos no hace nada, pero si tiene (como es l relacion hay que hacer un programa en el master que haga relaciones entre modulos) lee el modulo 0x30 luego lo envia el dao al 0x20, pero si no precionaste y encendiste la luz en ese chequea el 0x20 y si es asi lo envia al 0x30 para que lo copie, bueno eso ahora extendelo a unos 30 modulos y relaciones es no solo tedioso sino poco practico y no solo eso sino lo lento ques todo esto, no es mas facil que el odulo 0x30 le envie el dato al 0x20 y listo y lo mismo al reves con una copia al master para que sepa lo que hace. entonces es mucho mas rapido asi. el maestro sabe lo que sucede pero no administra, se envian los datos entre modulos. y como sabe la direccion del otro modulo el 0x30 por ejemplo por un dipswitch. pero la consulta no tendria que haber problemas con los datos que viajan en la linea , la libreria RS485 no esta preparada para chequear la linea cuando esta libre? cuando se usa el comando RS485send?bueno eso es lo que quise hacer desde un principio hace meses y es lo que no funciona bien


----------



## Saint_ (May 26, 2018)

Bueno, si prefieres trabajar en modo multimaestro y ya que la pregunta es más puntual. Te cometo que existe la función _rs485_wait_for_bus(tiempo_en_ms);_ que espera a que el bus este libre y la función _rs485_send_message(int to, int len, int* data);_ devuelve 1 si se envió los daros correctamente y 0 si hubo fallo.

Te convendría mucho darle una buena mirada a la librería que CCS trae para el RS4856.


----------



## tiaret4 (May 31, 2018)

He encontrado que el valor límite del cristal es 13.848833 MHz
más que este valor, la simulación será perturbada


----------

