Si además quieres enviarnos un Artículo para el Blog y redes sociales, pulsa el siguiente botón:
Buenas,
estoy trabajando en un proyecto donde necesito conectar una bateria de PICs 18F2550 en serie. La última debe recibir los datos de las anteriores. La duda es si es viable realizarlo con RS232 o con USB. Entiendo que con RS232 podría utilizar TX->RX entre 2 PICs (la primera pareja), y luego usar el puerto TX de la segunda PIC hacia el RX de la tercera PIC, y así sucesivamente. La distancia entre PICs es de 2 metros. No sé si el ruido puede hacer que se lean carateres erróneos.
Por otro lado, veis viable la conexión en serie mediante USB?. Supongo que no podía usar en una comunicación D+ -> D+ y entre la segunda y tercera PIC D- -> D- o sí?¿
Bueno, pues cualqueir sugerencia es bien acogida.
Gracias.
Saludos
Bueno,
pues tengo compilada la función de holding_registers. Sacado de http://www.pinguino.org.ve/wiki/index.php?title=Usuario:Rasm4 " onclick="window.open(this.href);return false;
Voy a ver si puedo hacer una prueba para comunicar el Pinguino con el PC. En cualqueir caso, voy a intentar adquirir 2 MAX485 para conectar ambos PICs por serial.
#include <stdlib.h>
#define TIMEOUT 1000 // 1 second
#define BAUDRATE 9600 // Defina la rata de baudios
#define MAX_READ_REGS 20 // se limita a 20 registros por transaccion
#define MAX_WRITE_REGS 20 // se limita a 20 registros por transaccion
#define MAX_RESPONSE_LENGTH 46
#define PRESET_QUERY_SIZE 46
#define PORT_ERROR -5
int read_holding_registers(int slave, int start_addr, uint8_t count, int *dest)
{
int function = 0x03; /* Function: Read Holding Registers */
int ret;
unsigned char packet[REQUEST_QUERY_SIZE + CHECKSUM_SIZE];
if (count > MAX_READ_REGS) {
count = MAX_READ_REGS;
}
build_request_packet(slave, function, start_addr, count, packet);
if (send_query(packet, REQUEST_QUERY_SIZE + CHECKSUM_SIZE) > -1) {
ret = read_reg_response(dest, packet);
}
else {
ret = -1;
}
return (ret);
}
Le he echado una ojeada a esa librería, y bueno, no me parece de la mejor calidad.
Tampoco me queda claro el tipo de acceso que hace al puerto serie subyacente. Ni si usa interrupciones, ni que temporizador usa.
Tampoco me deja clara la estructura del programa, ni de las rutinas, ni de la relación entre archivos.
Ni me gusta que sean librerías.
Vamos, que si no te va, allá tu.
Lo que intuyo es que hay muchas llamadas entre rutinas que acaban accediendo directamente al puerto serie por polling, de tal manera que las funciones son síncronas, bloqueando la CPU mientras comunicas y desperdiciando preciosos ciclos de procesador en waits.
La estructura es caótica y la indentación, como poco pobre. La ayuda es poco válida, en mi opinión, aunque yo no la uso mucho.
Y lo peor, si vas a aprender a partir de aquí, que te pillen confesado.
En mi muy torcida y enrevesada opinión, esta librería (como la mayoría de librerías que he leído), está escrita por alguien que no programa muy bien ni sabe que es un microcontrolador. Huele a proyecto final de carrera o a aficionado novato o pogramador de micros con muy poca experiencia o pocos conocimientos.
Bueno pues...si que me das ánimos pa seguir adelante. En cualquier caso, aparte del "performance" que le pueda faltar . ¿ Qué opciones me propones para arrancar ?
Saludos y gracias.
Los pasos, en mi opinión son los siguientes:
Dado que para desarrollar no necesitas, en un principio el RS-485, mientras este te llega y aprendes a conectarlo, puedes usar un puerto serie cualquiera que tengas.
Sobre eso, empieza por hacer las rutinas de transmisión y recepción por el puerto serie, por interrupciones.
Después, que dichas rutinas te envíen un buffer y te reciban otro buffer, por el puerto serie, utilizando interrupciones. Necesitarás flags para saber si estás todavía transmitiendo o no.
Aprende a utilizar le temporizador: necesitas uno para detectar el time-out de fin de trama.
Envía y transmite tramas del pinguino al PC y viceversa, sin importar mucho el contenido, pero utilizando la transmisión por búffer y la recepción con el timeout del timer para detectar que has recibido una trama completa.
Con eso, tienes la capa de HW más o menos lista. De ahí al RS-485 es sólo añadir el manejo del semi-dúplex: añadir un par de líneas donde pasar de Rx a Tx y viceversa, en las rutinas que ya tendrás.
Sobre eso, hay que hacer la capa de ModBus propiamente dicha. Es relativamente sencilla. Empieza por hacer el CRC por tablas, más rápido y eficiente que el que tienes en la librería, aunque este también te valdría (quizás es la rutina mejor implementada...).
Las tramas suelen tener una estructura más o menos fija: utiliza structs, por ejemplo, como tipo Union. Aprende a meter y sacar datos de ellas. Una función para manejar cada tipo de transacción (la 3 y la 16, por ejemplo) suele ser lo típico, junto a una rutina 'principal' que controle si has recibido una trama, si la trama es para tí (comprobación de dirección), si es válida (check de CRC), y en caso afirmativo, ejecutar la transacción requerida. En total cinco funciones: la de procesado de ModBus (o principal), una para el CRC, otra para contestar que no ha ido bien (transacción errónea o datos erróneos o error de dirección), y una para cada tipo de transacción. Recuerda que desde el micro como esclavo, sólo transmites como consecuencia o respuesta a una petición por parte del maestro.
En el lado del PC creo recordar que hay herramientas más o menos desarrolladas o que simplifican el desarrollo. C# Express, gratuito, es un buen punto de partida.
ok, muchas gracias por la información. Voy a intentar empezar como me has indicado. Sólo una pregunta. ¿ Es factible que utilice en mi caso la comunicación por broadcast, es decir que todos los slaves contesten a la vez con la lectura a petición del master, o es mejor que el master pregunte a todos y cada uno unidireccionalmente ? ¿ Pierdo alguna funcionalidad al utilizar broadcast ?
Gracias de nuevo.