[2021][Julio][Problema 3]

[2021][Julio][Problema 3]

de Jose Agustin Bizio Piriz -
Número de respuestas: 1

Hice esta solucion para el modelado de la sierra en C, queria verificar si hacer una maquina de estados con la logica distribuida podia dar algun problema, mas que nada cuando se disparan las interrupciones, es mi solucion correcta/aceptable?


//maquina dedicada

//STATUS byte que contiene en los bits menos significativos el estado de los botoner

//son apretados simultaneamente si no difieren en mas de 150ms

//en el bit menos signitificativo de CONTROL se enciende o apaga la sierra

//la distancia al material a cortar no vale mas de TOL_MM

//el sensor interrumpe al procesador con la rutina tope, la distancia puede consultarse en DISTANCE

//en caso que la distancia varie fuera de la seguridad, debe encenderse el freno y la luz que debe titilar
//el freno se controla con el bit 2 de CONTROL y la luz con el 4

//hay un reloj de 100hz

#define APAGADA 0
#define PRENDIDA 1
#define FRENOMECANICO 2


char estado;
char estaBoton0Apretado;
char estaBoton1Apretado;
short tiempoBoton0Apretado;
short tiempoBoton1Apretado;
char seHaHechoTope;
short distPrimerTope;
char fueraDeRangoDeSeguridad;
short aControl;

void main() {
    //instalo interrupciones
    estado = APAGADA;
    OUT(CONTROL, 0);
    estaBoton0Apretado = 0;
    estaBoton1Apretado = 0;
    tiempoBoton0Apretado = 0;
    tiempoBoton1Apretado = 0;
    seHaHechoTope = 0;
    distPrimerTope = 0;
    fueraDeRangoDeSeguridad = 0;
    aControl = 0;

    enable();
    while(1) {
        estaBoton0Apretado = (in(STATUS) & 0x1 == 1);
        estaBoton1Apretado = (in(STATUS) & 0x2 == 2);

        switch (estado){
            case APAGADA:
                if(estaBoton0Apretado && estaBoton1Apretado && abs(tiempoBoton0Apretado - tiempoBoton1Apretado)*10 <= 150){
                    estado = PRENDIDA;
                    aControl = aControl | 0x1; //prendo motor
                    seHaHechoTope = 0;
                }
            break;
            case PRENDIDA:
                if(fueraDeRangoDeSeguridad){
                    estado = FRENOMECANICO;
                    aControl = ((aControl | 0x4) | 0x10); //prendo la alarma y el freno mecanico
                }else(!estaBoton0Apretado || !estaBoton1Apretado){
                    estado = APAGADA;
                    aControl = aControl & 0xFE; //apago motor
                }
            break;
            case FRENOMECANICO:
                if(!estaBoton0Apretado || !estaBoton1Apretado){
                    estado = APAGADA;
                    aControl = aControl & 0xFE; //apago motor
                    aControl = ((aControl & FB) & EF); //se apaga el bit de alarma y de freno mecanico
                }
            break;
        }

        OUT(CONTROL, aControl);

    }
}


//100 veces por segundo, cada 10ms
void timer(){

    if(estaBoton0Apretado)
        tiempoBoton0Apretado++;
    else
        tiempoBoton0Apretado = 0;

    if(estaBoton1Apretado)
        tiempoBoton1Apretado++;
    else
        tiempoBoton1Apretado = 0;
}

//cuando el protector de la sierra toca el material a cortar
void tope() {

    if(!seHaHechoTope) {
        distPrimerTope = in(DISTANCE);
    }else{
        if(abs(distPrimerTope - in(DISTANCE)) > TOL_MM)
            fueraDeRangoDeSeguridad = 1;
        else
            fueraDeRangoDeSeguridad = 0;
    }

}


En respuesta a Jose Agustin Bizio Piriz

Re: [2021][Julio][Problema 3]

de Federico Rivero -
Hola Agustín,

Solo quería aclarar que normalmente no corregimos soluciones enteras por el EVA. Habiendo dicho esto, con respecto a tu pregunta, en principio la solución puede ser correcta con la lógica en el main, en las interrupciones, o distribuída como en tu caso. Siempre que tenés lógica en el main tenés que tener cuidado que lo que se ejecuta en cada loop sea lo que querés. Un error muy común es manejar mal las condiciones de los if y que un código que se debería ejecutar una única vez, se ejecute continuamente, una vez en cada iteración del while.

Saludos,
Federico