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:

; 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:

; 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.

Saludos.
Me puse a estudiar un poco, el Arduino nos permite trabajar un poco menos complicado de los que planteas. Pero si es posible reducir códigos y hacer un sketch como el que planteas, así que hice el mio.

Pero hago énfasis en que solo es de prueba, lo desarrolle para el UNO, en el mega es mas facil pues saco directamente por el Puerto A u otro que tenga libre los 8 pines

const byte valorD[]= { B10000111,B10001011,B01000011,B10010011,B01000011,B01000011,B01000011,B00100011};
const byte valorB[]= { B11111001,B11111001,B11111100,B11111100,B11111100,B11111100,B11111100,B11111100};
byte entrada=0;
/*
98765432
01  100001	(Configuración 0. Estado "Vacio").
01  100010	(Configuración 1. Estado "Llenandose").
00  010000	(Configuración 2. Estado "Alarma").
00  100100	(Configuración 3. Estado "Lleno").
00  010000	(Configuración 4. Estado "Alarma").
00  010000	(Configuración 5. Estado "Alarma").
00  010000	(Configuración 6. Estado "Alarma").
00  001000	(Configuración 7. Estado "Rebose").
*/
void setup() {
  /* Lo pines 0 y 1 del puerto D se dejan para comunicación Serial y evitar colisiones*/
  DDRD = B11111110; 
  DDRB = B00000011; // Los pines de entrada son 2,3 y 4 del puerto B, 0 y 1 son de salida.
}

void loop(){
    entrada =((~PINB&B00011100)>>2);
    PORTB = valorB[entrada];
    PORTD = valorD[entrada];    
}

Hola:

Graicas por el ejemplo.

Me cuesta un poco interpretarlo. La diferencia del primer ejemplo que puse con el segundo en asm de un PIC. Es que el segundo está bien para display de 7 segmentos y el ejemplo del agua si no hay más datos o otras funciones por medios.

Si quieres hacer otras funciones a parte de lo que está establecido en el dibujo de arriba, a parte de cumplir estas funciones, puedo añador en las configuraciones de cada dirección por ejemplo un tiempo o otra función de lo que sea. Para que lo sepas.

Trabajo con Arduino UNO r3.

Fíjate que este ejemplo, el de arriba, tiene tres sensores que hace de alarma, y siete de salidas, cinco para Leds y otras dos para motores bomba de agua.

Por eso me cuesta entender tu código.

Gracias de nuevo por la ayuda.

Hola.
Hay varias formas de implementar lo que dices. En el caso que propones, la solución de max_saeta está muy bien, ya que sencillamente devuelven dos valores en función de otro.
Sin embargo, igual me equivoco, creo que lo que tú estás buscando se corresponde a las funciones switch-case.
Ejemplo:

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;
      }

¿Es eso lo que buscabas?

Muchas gracias, es lo que buscaba.

No entiendo la parte de PORT B. Eso no es para Arduino UNO. ¿Verdad?

Lo demás es lo que buscaba. XD XD XD XD XD XD XD XD.

Ahora comprendo mejor. Voy hacer pruebas.

Gracias de nuevo por la ayuda.

Hola.
He puesto PORTB como ejemplo, al igual que podría haber puesto PORTA. Creo que ambos existen en el UNO. Arduino, al igual que PIC, también permite manipulación directa de puertos. De hecho las instrucciones de manejo de pines, generalmente más recomendables, pues evitan posibles errores nuestros al trabajar con puertos completos, internamente son convertidas a instrucciones de puerto.

Saludos

El código que colocaste primero es un asambler muy limpio por eso quise hacerlo también y evitar retardo por las instrucciones básica de arduino. Me ayudo mucho pues aprendio a usar instrucciones directas para puerto del AVR, en este caso, el Atmega328p, que usa el UNO.

Para aclarar el UNO "NO" tiene puerto A solo B, C y D.

Y si, ademas de los nombres comunes de los pines, PORTB se usa en arduino, en case del arduino UNO. PORTD maneja desde el pin digital 0 al pin digital 7 y PORTB maneja los pines del 8 al 13. Es decir solo se usan los seis bits menos significativos. En el caso del PORTD los bit 0 y 1 se usan para comunicación serial, ese es el motivo por el cual hay dos arreglos de bytes en mi sketch, para no usa estos pines del puerto D.

El puerto C, en el arduino UNO, maneja las seis entradas analógicas, pero también se pueden configurar como entradas o salidas digitales.
t

Ahora con respecto al funcionamiento del sketch, hace lo mismo que planteas en tus códigos y dibujo, ya que tienes tres entradas colocadas en los pines 10,11 y 12, que serian los sensores. Como en tu código es RA0, RA1 y RA2.

Las salidas que en tu código usas el puerto B del PIC6F84A, aquí se conecta desde el pin digital 2 al pin digital 9.

max_saeta:
Para aclarar el UNO "NO" tiene puerto A solo B, C y D.

Cierto... Sorry. Es lo que tiene contestar sin revisar el pinout, y mira que esa información estaba en el propio vínculo que puse :blush:

Hola:

Gracias por comentar. Me han dejado la cosas claras.
http://www.atmel.com/images/Atmel-8271-8-bit-AVR-Microcontroller-ATmega48A-48PA-88A-88PA-168A-168PA-328-328P_datasheet_Complete.pdf

Este circuito lo quería de base, en realidad estoy haciendo otra cosa con el LCD en Arduino, ya que trabajar con muchos mensajes con PIC no cabe y necesito usar tabla que pase de las 256 bytes y en C esto no ocurre.

Pueden descargar el pdf que lo explica aquí de que hablo.

Lo que quiero hacer para ustedes es una tontería, solo mostrar mensajes por un LCD 20x4 o el 16x2 cuando una PlayStation 2 Fat abre la bandeja, la cierrra, gira el motor, detectar disco dentro de ella, cuando graba datos en la Memory Card y más cosas.

Con Arduino se hace mucho más fácil.

Un saludo.

Saludo.