fbpx

Expresate

Si además quieres enviarnos un Artículo para el Blog y redes sociales, pulsa el siguiente botón:

Desincronización en...
 
Avisos
Vaciar todo

Desincronización en transmisión serie

33 Respuestas
6 Usuarios
0 Reactions
19 K Visitas
xyvy
Respuestas: 50
 XyVy
Topic starter
(@xyvy)
Trusted Member
Registrado: hace 16 años

Hola Señores, tengo un problema y pregunto sobre este tema por si me podéis echar un cable con alguna sugerencia.

Resulta que tengo un PIC 16F876a que me controla unos motores mediantes relés y a su vez el PIC es controlado por un PC mediante una comunicación serie, el problema que tengo es que tras varias transmisiones entre PIC y PC, parece que el PIC pierde el norte y no contesta más....

Para que os hagáis una idea, desde el PC siempre transmito 3 bytes con los comandos, y siempre espero 2 bytes de respuesta del PIC que informan de la operación realizada, algunos comandos implican retardos, pero estos retardos se realizan posteriormente a contestar al PC por parte del PIC, y antes de volver a enviarle una orden al PIC me espero un ratito... el caso es que tras varias transmisiones ya no recibo nada del PIC.

Hay que tener en cuenta que uso una rutina enganchada al Timer0, para que el PIC haga otras tareas referentes a los fines de carrera de los motores.

He probado en comunicarme mediante puerto serie, con la aplicación que tengo desarrollada en C, como mediante con el Hyperterminal y en los dos casos sucede lo mismo, el PIC parece no seguir contestando, lo curioso es que a veces sucede antes y otras veces despues.

Alguna idea de porque, pues necesito controlar el PIC desde el PC y ya descarte i2c pues también tenía problemas.

Ciao y gracias.

Responder
32 respuestas
xyvy
Respuestas: 50
 XyVy
Topic starter
(@xyvy)
Trusted Member
Registrado: hace 16 años

Por si sirve de algo os pego el programa.

Tiene una rutina que examina periodicamente los fines de carrera de los dos motores y el programa principal que atiende los comandos del PC. El control de los motores se realiza con 2 relés por motor.

#include <16F876A>

#device adc=8

#FUSES NOWDT //No Watch Dog Timer
#FUSES XT //Crystal osc <4mhz> 1 Hz (1s)
// 125 -> 2 Hz (500ms)
// 62 -> 4 Hz (250ms)
// 50 -> 5 Hz (200 ms)
// 31 -> 8 Hz (125ms)
// 16 -> 16 Hz (62ms)

#define RETARDO 50
int contador=RETARDO;

#define RELE1 PIN_A0
#define RELE2 PIN_A1
#define RELE3 PIN_A2
#define RELE4 PIN_A3

int activo1, activo2, activo3, activo4;
int pulsado1, pulsado2, pulsado3, pulsado4;
int oactivo1, oactivo2, oactivo3, oactivo4;
int opulsado1, opulsado2, opulsado3, opulsado4;

#define INI_SWITCH1 PIN_B5 // Interruptor 1, Inicio del stirrer
#define FIN_SWITCH1 PIN_B4 // Interruptor 1, Fin del stirrer
#define INI_SWITCH2 PIN_B6 // Interruptor 2, Inicio del stirrer
#define FIN_SWITCH2 PIN_B7 // Interruptor 2, Fin del stirrer

#define ON '1'
#define OFF '0'

char estado_motor1;
char estado_motor2;

int es_simulacion;

void StopMotor1()
{
estado_motor1=OFF;

output_low(PIN_B1);
output_low(RELE1);
output_high(PIN_B2);
delay_ms(5);
}

void StopMotor2()
{
estado_motor2=OFF;

output_low(PIN_B1);
output_low(RELE3);
output_high(PIN_B2);
delay_ms(5);
}

void StopMotores()
{
estado_motor1=OFF;
estado_motor2=OFF;
StopMotor1();
StopMotor2();
}

void MueveMotor1(BYTE dato)
{
output_high(PIN_B1);
output_low(PIN_B2);
output_low(RELE1);
delay_ms(10);
if (dato>=128) {
output_low(RELE2);
} else {
output_high(RELE2);
}
delay_ms(5);
output_high(RELE1);

estado_motor1=ON;
}

void MueveMotor2(BYTE dato)
{
output_high(PIN_B1);

output_low(PIN_B2);
output_low(RELE3);
delay_ms(10);
if (dato>=128) {
output_low(RELE4);
} else {
output_high(RELE4);
}
delay_ms(5);
output_high(RELE3);

estado_motor2=ON;
}

void MueveMotores(BYTE dato)
{
output_high(PIN_B1);
output_low(PIN_B2);

output_low(RELE1);
output_low(RELE3);
delay_ms(10);
if (dato>=128) {
output_low(RELE2);
output_low(RELE4);
} else {
output_high(RELE2);
output_high(RELE4);
}
delay_ms(5);
output_high(RELE1);
output_high(RELE3);

estado_motor1=ON;
estado_motor2=ON;
}

void InicioMotor1()
{
output_high(PIN_B1);
output_low(PIN_B2);
output_low(RELE1);
delay_ms(10);

output_low(RELE2);

delay_ms(5);
output_high(RELE1);

estado_motor1=ON;
}

void InicioMotor2()
{
output_high(PIN_B1);

output_low(PIN_B2);
output_low(RELE3);
delay_ms(10);

output_low(RELE4);

delay_ms(5);
output_high(RELE3);

estado_motor2=ON;
}

void InicioMotores()
{
output_high(PIN_B1);
output_low(PIN_B2);

output_low(RELE1);
output_low(RELE3);
delay_ms(10);

output_low(RELE2);
output_low(RELE4);

delay_ms(5);
output_high(RELE1);
output_high(RELE3);

estado_motor1=ON;
estado_motor2=ON;
}

void FinMotor1()
{
output_high(PIN_B1);
output_low(PIN_B2);
output_low(RELE1);
delay_ms(10);

output_high(RELE2);

delay_ms(5);
output_high(RELE1);

estado_motor1=ON;
}

void FinMotor2()
{
output_high(PIN_B1);

output_low(PIN_B2);
output_low(RELE3);
delay_ms(10);

output_high(RELE4);

delay_ms(5);
output_high(RELE3);

estado_motor2=ON;
}

void FinMotores()
{
output_high(PIN_B1);
output_low(PIN_B2);

output_low(RELE1);
output_low(RELE3);
delay_ms(10);

output_high(RELE2);
output_high(RELE4);

delay_ms(5);
output_high(RELE1);
output_high(RELE3);

estado_motor1=ON;
estado_motor2=ON;
}

void inicializa()
{
output_high(PIN_B2);
StopMotor1();
StopMotor2();
output_low(PIN_B2);
}

// Rutina de atención a la interrupción sirve unicamente para hablar i2c como esclavo
// y atender por tanto peticiones desde el PC
#INT_TIMER0
void timer1interrupt()
{
set_timer0(6);
contador--;
if (contador==0) {
contador=RETARDO;
oactivo1=activo1;
oactivo2=activo2;
oactivo3=activo3;
oactivo4=activo4;

//output_toggle(PIN_B1);
activo1=input(INI_SWITCH1);
activo2=input(FIN_SWITCH1);
activo3=input(INI_SWITCH2);
activo4=input(FIN_SWITCH2);

// EJE 1 (MOTOR 1)
if (!pulsado1 && !pulsado2 && activo1 && activo2) {
StopMotor1();
pulsado1=1;
pulsado2=1;
} else {
if ((activo1) && (!pulsado1)) {
StopMotor1();
delay_ms(5);
pulsado1=1;
// Las siguientes lineas son para simular inicio-fin del eje
if (es_simulacion) {
FinMotor1();
}
}

if ((activo2) && (!pulsado2)) {
StopMotor1();
delay_ms(5);
pulsado2=1;
// Las siguientes lineas son para simular inicio-fin del eje
if (es_simulacion) {
InicioMotor1();
}
}
}
// EJE 2 (MOTOR 2)
if (!pulsado3 && !pulsado4 && activo3 && activo4) {
StopMotor2();
pulsado3=1;
pulsado4=1;
} else {
if ((activo3) && (!pulsado3)) {
StopMotor2();
delay_ms(5);
pulsado3=1;
// Las siguientes lineas son para simular inicio-fin del eje
if (es_simulacion) {
FinMotor2();
}
}

if ((activo4) && (!pulsado4)) {
StopMotor2();
delay_ms(5);
pulsado4=1;

// Siguiente linea es para simular inicio-fin del eje
// Las siguientes lineas son para simular inicio-fin del eje
if (es_simulacion) {
InicioMotor2();
}
}
}
delay_ms(30);

activo1=input(INI_SWITCH1);
activo2=input(FIN_SWITCH1);
activo3=input(INI_SWITCH2);
activo4=input(FIN_SWITCH2);

opulsado1=pulsado1;
opulsado2=pulsado2;
opulsado3=pulsado3;
opulsado4=pulsado4;
if (!activo1) {
pulsado1=0;
}
if (!activo2) {
pulsado2=0;
}
if (!activo3) {
pulsado3=0;
}
if (!activo4) {
pulsado4=0;
}
delay_ms(20);
}
}

void main()
{
char data;
int pulsado=0;
char sw=0;
BYTE comando;
BYTE dato1;
BYTE dato2;
char msg[5];
int16 tiempo;

port_b=0;

output_high(PIN_B1);
output_low(RELE1);
output_low(RELE2);
output_low(RELE3);
output_low(RELE4);
sw=0;
pulsado=0;
delay_ms(2000);

StopMotores();

// Inicialiamos los pulsados a 0 (no pulsados)
pulsado1=0;
pulsado2=0;
pulsado3=0;
pulsado4=0;

es_simulacion=0;

tiempo=20;

delay_ms(tiempo*100);

setup_counters(RTCC_INTERNAL, RTCC_DIV_16);
set_timer0(6);

enable_interrupts(GLOBAL);
enable_interrupts(INT_TIMER0);

output_high(PIN_B1);
output_low(PIN_B2);
delay_ms(tiempo*100);

output_high(PIN_B2);
output_low(PIN_B1);
delay_ms(tiempo*100);
output_low(PIN_B2);

while (1) {
do {
comando=getchar();
} while (!es_comando(comando));
dato1=getchar();
dato2=getchar();

switch(comando) {
case INIT: StopMotores();
printf("ix");
break;
case CONSULTA_MOTOR1:
printf("c%c", estado_motor1);
break;
case CONSULTA_MOTOR2:
printf("c%c", estado_motor2);
break;
case MUEVE_MOTOR1:
tiempo=dato2;
MueveMotor1(dato1);
printf("m%c", dato1);
delay_ms(tiempo*100);
StopMotor1();
break;
case MUEVE_MOTOR2:
tiempo=dato2;
MueveMotor2(dato1);
printf("m%c", dato1);
delay_ms(tiempo*100);
StopMotor2();
break;
case MUEVE_MOTORES:
tiempo=dato2;
MueveMotores(dato1);
printf("ma");
delay_ms(tiempo*100);
StopMotores();
break;
case STOP_MOTOR1:
StopMotor1();
printf("s1");
break;
case STOP_MOTOR2:
StopMotor2();
printf("s2");
break;
case STOP_MOTORES:
StopMotores();
printf("sa");
break;
case INTERRUPTOR1:
if (input(INI_SWITCH1)) {
printf("1A");
} else {
printf("0B",);
}
break;
case INTERRUPTOR2: if (input(FIN_SWITCH1)) {
printf("1A");
} else {
printf("0B");
}
break;
case INTERRUPTOR3: if (input(INI_SWITCH2)) {
printf("1A");
} else {
printf("0B");
}
break;
case INTERRUPTOR4: if (input(FIN_SWITCH2)) {
printf("1A");
} else {
printf("0B");
}
break;

case VERSION: printf("v1");
break;

case INICIO_MOTOR1:
InicioMotor1();
printf("i1");
break;
case INICIO_MOTOR2:
InicioMotor2();
printf("i2");
break;

case INICIO_MOTORES:
InicioMotor1();
printf("ia");
break;

case FIN_MOTOR1:
FinMotor1();
printf("f1");
break;

case FIN_MOTOR2:
FinMotor2();
printf("f2");
break;

case FIN_MOTORES:
FinMotores();
printf("fa");
break;

case SET_SIMULACION:
if (dato1=='1') {
es_simulacion=1;
printf("x1");
} else {
es_simulacion=0;
printf("x0");
}
break;
case GET_SIMULACION:
if (es_simulacion) {
printf("x1");
} else {
printf("x0");
}
break;

default: StopMotores();
printf("er");
}
}
}

Obviamente alguna variable no sirve para nada y es de códigos que he ido problando y que no había quitado...

Si por ejemplo envío varias veces el mismo comando: INICIO_MOTOR1 en un número indeterminado de veces ya no contesta a ningún comando.

Ciao.

Responder
xyvy
Respuestas: 50
 XyVy
Topic starter
(@xyvy)
Trusted Member
Registrado: hace 16 años

Podría tener algo que ver con que no he conectado la tierra del puerto serie, con la tierra que usa el PIC ?

Ciao.

Responder
xyvy
Respuestas: 50
 XyVy
Topic starter
(@xyvy)
Trusted Member
Registrado: hace 16 años

He conectado el PIN5 del puerto serie a la tierra del circuito, pero nada sigue haciendo lo mismo... que podría ser?

Responder
dragonet80
Respuestas: 1328
(@dragonet80)
Ardero
Registrado: hace 17 años

Sin haberme mirado nada el código, te digo que lo que tú comentas de las tierras, deberías tenerlas conectadas. Siempre tiene que haber una referencia entre diferentes "aparatos" para que puedan comunicarse correctamente.

Quizá el problema que tú describes no esté ahí. Pero corrige eso y vuelve a probar.

Responder
Página 1 / 7
Compartir: