3.1. Ejemplo comunicación serie microPLC
En el siguiente ejemplo realizaremos un sencillo programa para controlar nuestro microPLC a través de una consola de comandos. Cargamos un menú interno en el microPLC, que permite controlar las funciones programadas mediante un terminal serie, a través de la RS-232. En el ejemplo controlamos las salidas por relé mediante unos comandos de control, pero se puede realizar el control y la parametrización de cualquier aplicación, así como la visualización o la medida de variables del microPLC.
Comunicación RS-232 para el microPLC
El control se realiza mediante el envío de un frame formado por un comando y un parámetro según se muestra en la siguiente tabla:
Frame: <Comando><parámetro><cr>
Comando:
Parámetro:
El siguiente código muestra un sencillo programa para realizar el control de los relés del microPLC a través de cualquier terminal serie.
/*
* Control de salidas de Relé para el microPLC - arduino
*
* Descripción: Control de los relés de salida de la placa microPLC mediante códigos enviados
* desde el terminal serie. Mediante RS-232 con el adaptador USB del arduino.
*
* Autor: Rafa Aranda
* Fecha: 13-12-2013
* Versión: 1.0
*/
// Asignación de Pins a Salidas digitales
#define Out_1 6
#define Out_2 7
#define Out_3 8
#define Out_4 9
// Pins de entrada (están ordenados de forma decreciente por necesidades del PCB)
#define In_1 5
#define In_2 4
#define In_3 3
#define In_4 2
// Librerías
#include "microPLC.h"
#include <string.h>
// Funciones prototipo
void getInputs(void);
void setOutputs(void);
void Menu(void);
unsigned char GetCode(void);
void Cmd(void);
// Variables globales
//Definición de las variables de trabajo
m4bits s; // Entradas del MicroPLC
m4bits k; // Salidas del MicroPLC
// Comunicaciones serie
char buff[16]; // Buffer de datos
char code[16]; // Buffer de comando
char dat[2]; // Carácter temporal
/* setup
* Tareas iniciales de preparación
*/
void setup()
{
// Iniciar las comunicaciones en serie
Serial.begin(9600);
// Establecer los pins de salida de los relés
pinMode(Out_1, OUTPUT);
pinMode(Out_2, OUTPUT);
pinMode(Out_3, OUTPUT);
pinMode(Out_4, OUTPUT);
// Establecer los pins de entradas digitales optoacopladas
pinMode(In_1, INPUT);
pinMode(In_2, INPUT);
pinMode(In_3, INPUT);
pinMode(In_4, INPUT);
// Preparar las variables
strcpy(buff, "");
strcpy(dat, "");
// Mostrar el menu de información
Menu();
}
/* loop
* Programa principal
*/
void loop() {
getInputs(); // Leer las entradas digitales
//-------- Ciclo --------
// Si se ha recibido algún carácter
if (Serial.available()){
// Leer los caracteres recibidos
if(GetCode()>0){
Cmd(); // Analizar el comando
}
}
//------------------------
setOutputs(); // Activar las salidas
delay(1); // CicloScan + 1ms, retardo para anti-rebotes
}
/* Menu
* Información con los comandos programados
*/
void Menu(void){
Serial.println("Frame: <cmd><parametro> ");
Serial.println("cmd: <p>Paro");
Serial.println(" <m> Marcha");
Serial.println("parametro: <1..4> Rele");
}
/* GetCode
* Guarda en el buffer de comandos los caracteres recibido hasta obtener un CR
*/
unsigned char GetCode(void){
dat[0] = Serial.read(); // Leer el carácter del buffer de recepción
Serial.write(dat[0]); // Realizar eco de los datos recibidos
if(dat[0] == 10){ // Omitir el carácter de control LF
return 0;
}
if(dat[0] == 13){ // Si CR
strcpy(code, buff); // Validar el comando
strcpy(buff, "");
return strlen(code);
}else{
strcat(buff, dat);
}
return 0;
}
/* Cmd
* Analizar el comando y ejecutar la acción correspondiente
*/
void Cmd(void){
if(!strcmp(code, "m1")){
k._1=1;
Serial.println("k1=1");
}else if(!strcmp(code, "m2")){
k._2=1;
Serial.println("k2=1");
}else if(!strcmp(code, "m3")){
k._3=1;
Serial.println("k3=1");
}else if(!strcmp(code, "m4")){
k._4=1;
Serial.println("k4=1");
}else if(!strcmp(code, "p1")){
k._1=0;
Serial.println("k1=0");
}else if(!strcmp(code, "p2")){
k._2=0;
Serial.println("k2=0");
}else if(!strcmp(code, "p3")){
k._3=0;
Serial.println("k3=0");
}else if(!strcmp(code, "p4")){
k._4=0;
Serial.println("k4=0");
}else{
Menu();
}
}
/* GetInputs
* Lee el estado de la entrada indicada en el parámetro y lo asigna invertido a las variables de trabajo
*/
void getInputs(void){
s._1=!digitalRead(In_1);
s._2=!digitalRead(In_2);
s._3=!digitalRead(In_3);
s._4=!digitalRead(In_4);
}
/* setOutputs
* Asigna el estado de las variables de trabajo a las salidas digitales
*/
void setOutputs(void){
digitalWrite(Out_1, k._1);
digitalWrite(Out_2, k._2);
digitalWrite(Out_3, k._3);
digitalWrite(Out_4, k._4);
}