Haz una pregunta
  Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos » Arduino y Raspberry Pi
Foros Registrarse ¿Olvidaste tu contraseña?

Temas similares

10/09/2014 #1

Avatar de Meta

Tabla de la verdad con Arduino
Buenas:

Se hacer tabla de la verdad con ensamblador de los microcontroladores PIC, pero no de Arduino. Los códigos en asm de los PIC pongo algunos ejemplos.


Ver zoom.

Ejemplo 1:
Código:
; Controla el nivel de un depósito de líquido. Utiliza (entre paréntesis las líneas del
; microcontrolador a la que se han conectado):
; -    Tres sondas detectoras: SV, Sonda de Vacío (RA0); SLL, Sonda de LLenado (RA1);
;    SR, Sonda de Rebose (RA2).
; -    Dos bombas de agua: B1 (RB5), B2 (RB6).
; - Cinco indicadores: Vacio (RB0), Llenandose (RB1), Lleno (RB2), Rebose (RB3),
;    Alarma (RB4).
;
; Su funcionamiento: 
; -    Cuando ninguna de las sondas está mojada se entiende que el depósito está vacío y
;    se accionarán las dos bombas. El indicador "Vacio" se iluminará .
; -    Cuando el nivel del líquido toque la sonda de vacío "SV" seguirá llenándose el
;     depósito con las dos bombas. El indicador "Llenandose" se ilumina.
; -    Cuando el nivel del líquido toca la sonda de llenado "SLL", para la bomba B2, quedando
;    B1 activada en modo mantenimiento. El indicador "Lleno" se ilumina.
; -    Si el nivel del líquido moja la sonda de rebose "SR" se apaga también la bomba B1,
;    quedando las dos bombas fuera de servicio. El indicador "Rebose" se enciende.
; -    Cuando se produce un fallo o mal funcionamiento en las sondas de entrada (por
;    ejemplo que se active la sonda de rebose y no active la de vacío) se paran
;    las dos bombas. El indicador "Alarma" se ilumina.
;
; Según el enunciado del problema, teniendo en cuenta las conexiones citadas y poniendo la
; salida no utilizada (RB7) siempre a cero, la tabla de verdad resultante es:
;
; RA2.. RA0 | RB7 ...          ... RB0
; ------------|--------------------------------
;  0   0   0  |  0   1   1   0   0   0   0   1    (Configuración 0. Estado "Vacio").
;  0   0   1  |  0   1   1   0   0   0   1   0    (Configuración 1. Estado "Llenandose").
;  0   1   0  |  0   0   0   1   0   0   0   0    (Configuración 2. Estado "Alarma").
;  0   1   1  |  0   0   1   0   0   1   0   0    (Configuración 3. Estado "Lleno").
;  1   0   0  |  0   0   0   1   0   0   0   0    (Configuración 4. Estado "Alarma").
;  1   0   1  |  0   0   0   1   0   0   0   0    (Configuración 5. Estado "Alarma").
;  1   1   0  |  0   0   0   1   0   0   0   0    (Configuración 6. Estado "Alarma").
;  1   1   1  |  0   0   0   0   1   0   0   0    (Configuración 7. Estado "Rebose").
;
; ZONA DE DATOS **********************************************************************

    LIST        P=16F84A
    INCLUDE        <P16F84A.INC>
    __CONFIG    _CP_OFF &  _WDT_OFF & _PWRTE_ON & _XT_OSC

; ZONA DE CÓDIGOS ********************************************************************

    ORG     0                    ; El programa comienza en la dirección 0.
Inicio
    clrf    PORTB                ; Debe estar a cero cuando el puerto se configure como salida.
    bsf        STATUS,RP0            ; Acceso al Banco 1.
    clrf    TRISB                ; Las líneas del Puerto B se configuran como salida.
    movlw    b'00011111'            ; Las 5 líneas del Puerto A se configuran como entrada.
    movwf    TRISA
    bcf        STATUS,RP0            ; Acceso al Banco 0.
Principal
    movf    PORTA,W                ; Lee los sensores.
    andlw    b'00000111'            ; Máscara para quedarse con el valor de los sensores.
    addwf    PCL,F                ; Salta a la configuración adecuada.
    goto    Configuracion0
    goto    Configuracion1
    goto    Configuracion2
    goto    Configuracion3
    goto    Configuracion4
    goto    Configuracion5
    goto    Configuracion6
    goto    Configuracion7
Configuracion0
    movlw     b'01100001'            ; Estado "Vacio" (configuración 0).
    goto    ActivaSalida
Configuracion1
    movlw     b'01100010'            ; Estado "Llenándose" (configuración 1).
    goto    ActivaSalida
Configuracion2
    movlw     b'00010000'            ; Estado "Alarma" (configuración 2).
    goto    ActivaSalida
Configuracion3
    movlw     b'00100100'            ; Estado "Lleno" (configuración 3).
    goto    ActivaSalida
Configuracion4
    movlw     b'00010000'            ; Estado "Alarma" (configuración 4).
    goto    ActivaSalida
Configuracion5
    movlw     b'00010000'            ; Estado "Alarma" (configuración 5).
    goto    ActivaSalida
Configuracion6
    movlw     b'00010000'            ; Estado "Alarma" (configuración 6).
    goto    ActivaSalida
Configuracion7
    movlw     b'00001000'            ; Estado "Rebose" (configuración 7).
ActivaSalida
    movwf    PORTB                ; Visualiza por el puerto de salida.
    goto     Principal

    END
Ejemplo 2:
Código:
; ZONA DE DATOS **********************************************************************

    LIST        P=16F84A
    INCLUDE        <P16F84A.INC>
    __CONFIG    _CP_OFF &  _WDT_OFF & _PWRTE_ON & _XT_OSC

; ZONA DE CÓDIGOS ********************************************************************

    ORG     0                    ; El programa comienza en la dirección 0.
Inicio
    bsf        STATUS,RP0            ; Acceso al Banco 1.
    clrf    TRISB                ; Las líneas del Puerto B se configuran como salida.
    movlw    b'00011111'            ; Las 5 líneas del Puerto A se configuran como entrada.
    movwf    TRISA
    bcf        STATUS,RP0            ; Acceso al Banco 0.
Principal
    movf    PORTA,W                ; Lee los sensores.
    andlw    b'00000111'            ; Máscara para quedarse con valor de sensores.
    call    Estado
    movwf    PORTB                ; Resultado se visualiza por el puerto de salida.
    goto     Principal

; Subrutina "Estado" --------------------------------------------------------------------
;
Estado
    addwf    PCL,F
    retlw    b'01100001'            ; Entrada "Vacio".
    retlw    b'01100010'            ; Estado "Llenándose".
    retlw    b'00010000'            ; Estado "Alarma".
    retlw    b'00100100'            ; Estado "Lleno".
    retlw    b'00010000'            ; Estado "Alarma".
    retlw    b'00010000'            ; Estado "Alarma".
    retlw    b'00010000'            ; Estado "Alarma".
    retlw    b'00001000'            ; Estado "Rebose".

    END
En resumen, lo que tengo en asm, quiero saber como se hace en C de Arduino de la forma más elegante como este indicado arriba.

Un cordial saludo.
12/09/2014 #2

Avatar de JoaquinFerrero

Lo normal en esos casos, de querer obtener un valor a partir de otro, es usando un arreglo.
12/09/2014 #3

Avatar de Scooter

En arduino también se puede leer un puerto de golpe y hacer lo mismo que en asm.
Otra posibilidad es hacer el maxterms o minterms de la ecuación y pasarlo a código tal cual solo cambiando la sintaxis and es &, or es | etc

Edito y aclaro:
Los operadores son and &&, or || y not !

Ejemplo de tabla cualquiera:
CBA S
000 1
001 0
010 0
011 0
100 0
101 1
110 1
111 0
La función lógica sale: S=(/c·/b·/a)+(c·/b·a)+(c·b·/a)

Eso pasado a arduino sería
(pseudocódigo, hay que arregla mayúsculas etc etc para que funcione)
Hay que definir las variables como boolean
loop{
C=digitalread(x);
B=digitalread(xx);
A=digitalread(xxx);
digitalwrite(S,(C!||B!||A!)&&(C||B!||A)&&(C||B||A! ))
}

Nota: Esto no lo he probado, pero debería de funcionar
13/09/2014 #4

Avatar de JoaquinFerrero

Usando arreglos (arrays) sería algo así (no probado):

Código PHP:
/* Entradas */
#define S_REBOSE  B00000001
#define S_LLENO   B00000010
#define S_VACIO   B00000100

/* Salidas */
#define VACIO     B00000001
#define LLENANDO  B00000010
#define LLENO     B00000100
#define REBOSE    B00001000
#define ALARMA    B00010000
#define BOMBA1    B00100000
#define BOMBA2    B01000000

char tabla[] = {
  
/* B000 : vacío    */  BOMBA2|BOMBA1|VACIO,    
  
/* B001 : llenando */  BOMBA2|BOMBA1|LLENANDO,
  
/* B010 : alarma   */  ALARMA,
  
/* B011 : lleno    */  BOMBA1|LLENO,    
  
/* B100 : alarma   */  ALARMA,
  
/* B101 : alarma   */  ALARMA,
  
/* B110 : alarma   */  ALARMA,
  
/* B111 : rebose   */  REBOSE
};

void setup() {
  
/* entradas */
  
DDRB &= ~(S_REBOSE S_LLENO S_VACIO);

  
/* salidas */
  
DDRD  VACIO
        
LLENANDO
        
LLENO
        
REBOSE
        
ALARMA
        
BOMBA1
        
BOMBA2
        
;
}

void loop() {
  
PORTD tablaPORTB ];  /* el valor del puerto B */
                           /* apunta al valor del puerto D */
                           /* que deseamos */
  
delay(1000);

Como ves, el programa está escrito para que sea muy fácil su mantenimiento y actualización. No hay que aprenderse los bits, ya que solo usamos nombres.

(Tengo una duda con respecto a la línea que inicializa el puerto B, que no sé si hace bien la operación matemática. Lo miro más tarde y reedito el mensaje.)
13/09/2014 #5

Avatar de Meta

Buenas:

Graicas por la aportaciones.

Este parece muy cómodo.

Código:
byte entrada=PORTB & B111;
      switch (entrada){
            case B000:
                  Serial.println("Vacio");
                  // resto de comandos, incluyendo llamadas a funciones
                  break;
            case B001:
                  Serial.println("Llenando");
                  break;
            case B011:
                  Serial.println("Lleno");
                  break;
            case B111:
                  Serial.println("Rebose");
                  break;
            default:     // esto se ejecutaría en el resto de casos. 
                  Serial.println("Alarma");
                  break;
      }
Cómo de actualizar y si quieres tambiñen puede incluir otras funciones por medio.

Saludo.
13/09/2014 #6

Avatar de JoaquinFerrero

Depende de lo que necesites: si solo necesitas saber el valor de respuesta a una determinada entrada, te vale con usar un arreglo o una fórmula matemática como te comentaba Scooter. Pero si necesitas realizar más operaciones, entonces sí que debes usar el switch().
13/09/2014 #7

Avatar de Scooter

El problema es que hay que poner 256 "cases". Habría que ver el caso concreto para ver cual es el método mas eficiente.
13/09/2014 #8

Avatar de Meta

Sólo se pondrá la cantidad de "cases" que realmente vayas a usar. No los 256, entonces te entra depresión.
13/09/2014 #9

Avatar de JoaquinFerrero

Afortunadamente, contamos con los ordenadores, para simplificar el trabajo de generar los 256 casos:

Código:
perl -e 'printf("\t\tcase B%08b:\n", $_) for 0 .. 255'
Esta línea genera 256 líneas así:
Código:
                case B00000000:
                case B00000001:
                case B00000010:
                case B00000011:
                case B00000100:
Para el caso que nos ocupa, son solo 8 casos:
Código:
perl -e 'printf("\t\tcase B%03b:\n", $_) for 0 .. 7'
También hay que recordar que se pueden agrupar los casos, si tienen un comportamiento similar:
Código:
                case B0100:
                case B0101:
                case B0110:
            /* casos de la alarma */
            ...
Finalmente, existe la opción 'default', que se encargará de todos los casos no contemplados.
Código:
		default:
13/09/2014 #10

Avatar de Scooter

Tomes el camino que tomes en vez de poner la tabla sin mas primero se puede simplificar, para ello hay programas, y poner la función simplificada.
Respuesta
¿Tienes una mejor respuesta a este tema? ¿Quieres hacerle una pregunta a nuestra comunidad y sus expertos? Registrate

Buscar más temas sobre:
Lupa Arduino y Raspberry Pi

Cerrar
Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos » Arduino y Raspberry Pi

Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO ©2011, Crawlability, Inc.