Buscador

martes, 31 de octubre de 2017

Control acceso ordenador (login) mediante RFID


El link de descarga está al final del post.

En esta entrada aprenderemos cómo usar un arduino pro micro para permitirnos acceder a nuestra cuenta de usuario de nuestro ordenador.

Los materiales que usaremos:

· Arduino pro micro ( con un Arduino leonardo también te serviría )
· Módulo RFID-RC522
· Protoboard + cables
· Regulador de 3'3V  ( para el módulo RFID que funciona a menor tensión ).



Nota 1: La IDE de arduino me lo detecta como Leonardo, lo programé como tal y me funcionó correctamente.

Nota 2: Mi arduino pro micro no tiene regulador de 3'3V, si el tuyo lo lleva, no te hará falta el regulador de 3'3V que sale en la lista.








Diagrama de conexión

Necesitarás importar la libreria de RFID desde la IDE de Arduino. Abrimos nuestra IDE de Arduino y vamos a: Sketch -> Include library -> Manage libraries...


Se te abrirá una ventana como la anterior, en el buscador ( donde pone " Filter your search... " busca:   rc522  e instala la librería.


En mi caso ya la instalé por eso me sale inhabilitado el botón de instalación.

Una vez instalada la librería, ya podrás usar el código fuente ( te recomiendo reiniciar la IDE de Arduino ).

Notas: El arduino pro micro que usé, tenía que reconectarlo cada vez que subía el sketch para que me detectara el USB. Si al cargarlo ves que no te escribe el password, prueba a reconectarlo.









Descarga el código aquí





+info

domingo, 29 de octubre de 2017

Tutorial fabriación CPU desde 0: Módulo 01 - Clock, reset y FA

(En construcción)

Introducción


Empezamos una nueva serie donde crearemos paso a paso nuestra propia CPU, para ello nos valdremos de puertas lógicas y de algún que otro FPGA  y/o CPLD.

El motivo de usar FPGA y/o CPLD en vez de puertas lógicas será para mayor comodidad a la hora de crear algunas partes de la CPU ( por ejemplo,  si se quisieran añadir nuevas instrucciones o hacerlas más rápidas, con puertas lógicas sería un infierno ).

Nota: los FPGA y CPLD son, a grandes rasgos, circuitos que permiten programarles el comportamiento de elementos lógicos como una puerta AND, un multiplexor, etc. No funcionan igual que un procesador aunque pueden existir en el mercado algunas FPGA que integran procesadores. A diferencia de la programación convencional, para programar un FPGA o un CPLD, es necesario describir el hardware ( se le explica qué entradas y salidas tiene y cómo se comportarán ).

Es por ello que en estos tutoriales los partiremos en unos bloques, uno por cada módulo de la CPU. Dicha CPU estará compuesta de PCBs apiladas una encima la otra, formando una especie de "sandwich", conectándose entre sí. 

Dicho proyecto añadirá algunas partes que no son propias de una CPU, como por ejemplo, un bloque de fuente de alimentación y módulos de entrada/salida (I/O) como un teclado y una salida vga para tener "algo que funcione" y poderse mostrar cosas por pantalla.

En este proyecto no se busca crear un gran procesador ni tampoco el más eficiente, es por ello que los diseños mostrados son totalmente mejorables y toda sugerencia será bienvenida.


Información para nerds

F: 8MHz ( seguramente ampliable )
Bus de datos: 8 bits
Tipo de arquitectura: Von Neumann
Nº de IRQs externas: 8

Aclaraciones

Antes de entrar en materia, necesitamos explicar algunos conceptos de los procesadores. En la medida de lo posible, se intentará hacer de la forma más amena posible y si durante el transcurso de la nota aparecen nuevos términos, se intentarán explicar todos y cada uno de ellos. 
Por favor, si hay algo que no entiendas, déjamelo en los comentarios e intentaré añadirlo para futuros/as lectores/as.

Un procesador es un componente electrónico que, mediante instrucciones, se encarga de controlar los distintos módulos de un dispositivo, además de realizar algunas operaciones. Lo podríamos dividir en dos grupos:

· Realizar operaciones lógicas / matemáticas ( operaciones AND, OR, sumas, restas , etc ).
· Mover datos de una posición de memoria a otra.

Todo lo que ves en una pantalla como botones, sliders y demás, es información binaria, que mediante un código, interpreta esa información de una forma u otra. ¿Qué quiero decir con esto? por ejemplo, si guardamos en memoria el número 127, ese número puede ser una coordenada XY de un botón, una coordenada de tu mouse, el número de tecla que pulsaste, el resultado de una operación matemática que hiciste o que un programa hizo, el color de un pixel en pantalla, la munición restante de un personaje del videojuego que estás jugando, etc.

El procesador no es quien decide el uso de esos datos, éste simplemete obedece a un código dado, el programador/a ( o sea, nosotros :P ) es quien le explicará al procesador el uso de cada dato en memoria y cómo lo ha de gestionar ( comunicándose mediante las instrucciones en ensamblador ).

Todo ( y cuando digo todo, es todo todo ) es visto por un procesador como una posición de memoria. Desde las coordenadas XY de tu mouse hasta tu impresora, todo ha de ser direccionable desde memoria ( que has de poder acceder mediante una dirección de memoria ). Más adelante veremos que hay disponibles una serie de "trucos" o "herramientas" que nos facilitarán la vida para no tener que movernos siempre números.

Nota: la imagen no corresponde con la realidad, es un simple ejemplo
 
Esto que a priori puede parecer confuso, veremos que nos aporta una gran flexibilidad ( si añadimos un nuevo módulo, no hay que cambiar toda la CPU, simplemente indicarle qué uso tendrán las nuevas posiciones de memoria y seguir usando las mismas instrucciones de ensamblador, sin necesidad de crear unas nuevas ).

Pero entonces... ¿todo está en la ram?. No exactamente, aunque sea "direccionable" ( que podemos acceder mediante una dirección ) no implica necesariamente que se encuentre la memoria ram. Esto quiere decir que físicamente hay partes que no están conectadas a la memoria ram, pero por comodidad, a nivel lógico ( a la hora de programar ) se interpretan como tal. 

Cuando empecemos a crear algunos módulos de la cpu se verá mucho más claro este punto, pero es importante remarcar que, cuando se ve un mapa de memoria como el mostrado arriba, donde aparecen desde los gráficos de la gpu hasta la impresora, no necesariamente están todos en el mismo sitio físico, aunque a la hora de programar nos pueda parecer que es así.





Conceptos básicos necesarios para este módulo

Transistor:

A grandes rasgos ( y para no complicarlo más de lo necesario ), un transistor funciona como un interruptor, sólo que en vez de controlarse con el dedo, lo hace con una señal eléctrica. Está formado por tres pines y uno de ellos sería la señal de control, los otros dos se conectan o desconectan entre ellos, permitiendo pasar la señal eléctrica o bloqueándola.
 

Nota: el transistor usado en el ejemplo es conocido como transistor NPN

En la imagen anterior, podemos ver un 0 y un 1 a la izquierda del transistor, representan si hay señal o no. A partir de ahora, cuando veas un 0 de esa forma, es un 0 lógico, eso quiere decir que representa " no señal " ( apagado ) y el 1  representa " señal " ( encendido ).

Se usarán muy pocos transistores en la cpu, lo que sí usaremos, serán las puertas lógicas ( que están formadas a partir de transistores ) para reducir la complejidad, tamaño y precio ), pero es necesario entenderlos para poder comprender mejor el funcionamiento de las puertas lógicas.

 
Puertas lógicas and, or, not:

Las puertas lógicas son un conjunto de transistores que forman un circuito lógico, existen varios tipos, de momento sólo explicaremos las que usaremos en este ḿodulo. Nos permiten realizar operaciones booleanas de suma, negación, etc.

Como imagino que no te habrá quedado muy clara mi explicación anterior, pasaremos a ver algunos ejemplos:

Puerta AND:


 La puerta AND sólo da como resultado 1 cuando todas sus entradas son 1.
Nota: si nuestra CPU funciona a 5 voltios como nivel lógico, el 1 valdría 5v, pero si trabajase a 3'3V, el nivel lógico sería de 3'3V.

Puede que ahora no le veas mucha utilidad, pero en un futuro verás como sí. Mediante puertas lógicas podremos crear circuitos que necesitemos para que, al cumplirse ciertas condiciones, dé como resultado una serie de salidas que necesitamos.

Nota 1: para crear circuitos lógicos medianamente complejos, es muy útil aprender a crear mapas de karnaugh. Nos permitirán de forma simple, generar las puertas lógicas que necesitamos mediante las entradas que queremos y las salidas que buscamos.

Nota 2: La puerta AND no está limitada a dos entradas, hay puertas and de 4 y más entradas.
 

Puerta OR:


La puerta OR nos dará como resultado un 1 siempre y cuando alguna de sus estradas esté activa (  no importa la combinación, si una de sus entradas se activa, la salida también se activará ).

Nota 1: "1 OR 1" no da 2 porque no funciona igual que la suma a la que estamos acostumbrados. Si lo prefieres, cambia los 1 y 0 por " true " y " false ".

Nota 2: Como ocurre con la puerta AND, la puerta OR tampoco está limitada a 2 entradas.


Puerta NOT:


Esta última puerta es bastante simple, su función es invertir la señal lógica. Las puertas NOT sólo tienen una entrada, si se quiere una NOT de varias entradas, podría usarse una NAND ( de momento no la explicaremos ).



Nota: Se anima al lector/a a investigar sobre cómo se crea una puerta lógica a partir de transistores para ver la relación que hay entre ambos.




Cristal de cuarzo:

El cristal de cuarzo es un componente electrónico que nos dará una frecuencia de trabajo para nuestra CPU. Podríamos entrar en detalles mucho más técnicos sobre éstos pero no nos será muy necesario para nuestro proyecto, con entender que al aplicarle una tensión, nos oscilará a una frecuencia ( la llevan escrita en el encapsulado ) nos es suficiente por ahora.

Más adelante veremos que, mediante unos circuitos llamados contadores ( se crean con puertas lógicas ), podremos ir contando los " ticks " del reloj y así, poder realizar las operaciones correspondientes.

Distintos encapsulados de cristal de cuarzo




Registros:

Los registros son pequeñas memorias donde dejamos datos temporalmente. Por ejemplo, un registro que use nuestra CPU para dejar el resultado de una operación matemática. Hay varios tipos de registros y algunos, como comentamos anteriormente, no están de forma física unidos entre sí. Algunos tipos de registros podrían ser:

· Propósito general: Te permiten guardar el dato que quieras, desde un número de una operación a una dirección de memoria.

· Específicos: Los puede usar la CPU para indicar estados de partes específicas ( posición de el resultado de una operación ( si fue negativa, cero, etc.), siguiente instrucción a ejecutar,  etc).

Nota: cuando creemos nuestra CPU, también crearemos los registros, que nos permitirán interactuar con nuestra CPU. Normalmente, el tamaño de un registro ( medido en bits ) es igual que la arquitectura de la CPU. La nuestra será de 8 bits, eso quiere decir que nuestros registros tendrán un tamaño de 8 bits.


Sistema binario:

No quiero meter mucha teoría con el sistema binario, os enseñaré una forma muy rápida que uso para calcular los números sin necesidad de usar divisiones u otro sistema que implique "demasiado cálculo". El sistema binario es otra forma de representar los números, pero a diferencia del sistema decimal ( diez ), en el binario se usan dos dígitos.




En la imagen anterior, puede verse una forma de calcular el número binario, simplemente se suman los valores en azul donde hay el digito 1. En el primer ejemplo, 2 + 16 se sumó así porque si vemos los números en azul ( potencias de dos ) y después los unos de color verde, coinciden con el  2 y el 16 en azul. El resto de posiciones ( 1, 4, 8, 32 y 64 )  al tener ceros, no se suman.


 En el sistema binario por ejemplo, el número 3 sería 11  y para pasar al número 4, añadimos un nuevo dígito ( 100 ), si probáis estos dos números con la tabla superior, veréis como coinciden. Los ceros de la izquierda no son importantes pero los de la derecha son totalmente necesarios.

Nota: Es muy importante que se domine el sistema binario de forma fluida, nos será muy útil más adelante para la creación de algunos módulos de la CPU ( tampoco es necesario saber hacer divisiones o raices cuadradas en binario, pero sí saber pasar de binario a decimal y viceversa ).
 

Multiplexor:

Un multiplexor está compuesto de puertas lógicas ( como mostraremos a continuación ) y es un componente con muchas entradas, una salida y unos pines de control ( para seleccionar la entrada ). Podríamos imaginarlo como un selector:



El número en binario que le demos a los pines de control, nos conectará la entrada con la salida ( ignorad hacia dónde apuntan las flechas, la dirección sería opuesta ).

Nota: Sólo puede conectar una entrada con una salida.



Entrando en materia

El procesador que haremos, constará de varios módulos, en este punto sólo se numerarán pero no se explicarán ( se harán en cada entrada correspondiende a dicho módulo ).

· FA
· Clock
· Reset
· Unidad de control ( UC )
· IRQs ( interrupciones )
· Entradas / Salidas ( I/O )
· ALU
· Stack
· Registros

No os preocupéis por no entender qué significado tienen los puntos anteriores, sólo con saber que existen nos vale por ahora. En esta entrada hablaremos del clock, reset y la FA.






Clock:


El sistema de clock, contará con opción de usar un clock interno o externo:




En el dibujo anterior, podemos ver que consta de tres entradas: 
· Señal clock interno ( U4, pin 3 ).
· Registro "Extern_Intern" ( nos permitirá seleccionar mediante instrucciones de ensamblador si queremos usar el reloj interno o externo ).
· Señal clock externo ( U3B, pin 4/5 ).

Lo que vemos en el dibujo anterior es un multiplexor que tiene 2 entradas , 1 pin de control y una salida:

- control = 0 --> clock interno
- control = 1 --> clock externo

El reloj interno será de 8MHz. Aunque parezca poco comparado con nuestros procesadores ( de varios GHz ) nos servirá para este proyecto. Hemos de recordar que no buscamos competir contra intel :P

Nota: El componente U4 es un cristal de cuarzo,  que nos da una frecuencia fija de 8MHz.


Reset:




Este circuito nos permitirá resetear toda la CPU justo en el instante que se alimenta. ¿Por qué se hace esto?, para asegurarnos que conocemos en qué estado empiezan los distintos módulos, de lo contrario podría ocurrir que un registro quede con una carga residual y no haya el dato que nos pensamos que contiene ( por ejemplo, el contador de programa y empezar en una instrucción equivocada ).

El pin " Reg_RST " es un pin que irá conectado a un registro especial, que nos permitirá resetear la CPU por software.

El componente J2 ( donde pone Reset ) es un conector para el pulsador de reset. El componente R5 junto al componente C8 permiten el reset inicial de forma automática. El condensador ( C8 ) tardará un tiempo en cargarse, mediante la resistencia (R5) que tiene en serie y su propia capacidad se ajusta el tiempo de carga. Durante dicho tiempo, el pin 2 del componente U3A ( este componente tendría que empezar a sonarte ya ;) ) lo tendrá a 0, generando en la salida un 0 lógico. 

Nota 1: La señal de reset es negada, eso quiere decir que " se activa " mediante un 0 lógico. Por lo tanto, para resetear nuestra CPU, aplicaremos un 0 lógico.

Nota 2: Vcc y GND son los dos terminales de alimentación, en este caso, Vcc valdrá 3.3V. Nuestra CPU funcionará internamente a 3.3V y externamente a 5V.

FA:

La fuente de alimentación contiene varios circuitos, empecemos con el de control:



En la imagen anterior podemos ver un circuito que nos permite apagar la CPU mediante software ( Registro_FA_On_Off ) al aplicarle un 0 lógico. El componente J1 es donde va el pulsador para encender la CPU, éste activa el transistor Q2 ( éste se conoce como MOSFET, es un poco distinto al NPN, se controla mediante tensión y no corriente ). A mano derecha podemos ver una etiqueta llamada IRQ_On_Off, cuando el botón sea pulsado, dará un 1 lógico en ese pin, pudiendo detectar así la CPU si alguien pulsó el botón ( usado cuando se pida por hardware apagar la CPU ).

Nota 1: Este módulo (FA) no se integra en las CPUs comerciales, se gestiona de otras formas.

Nota 2: La CPU se alimentará con un transformador de 12 voltios, conectado en la etiqueta " 12V_input ".





En la imagen anterior, podemos ver dos reguladores, uno que transforma los 12 voltios a 5 y el otro a 3'3 voltios. Los usaremos para alimentar los dos bloques de la CPU. La interna funcionará con 3.3v y la externa con 5v.

Nota 1: Los reguladores anteriores son conmutados, eso quiere decir que no tienen tantas pérdidas a la hora de transformar la energía, podríamos imaginarlo como un interruptor que se cierra y abre tan rápido que sólo deja pasar la tensión que quiere. Hay otras formas de regular la tensión,  como la forma lineal, que normalmente se usa un transistor de potencia para limitar la tensión , disipando dicho componente el resto de energía que no se use.

Nota 2: Para más información, buscar sobre fuentes lineales y fuentes conmutadas.




Puntos pendientes:
· Diseñar y fabricar PCB
· Soldar componentes y debuggear PCB

+info

sábado, 17 de septiembre de 2016

Conexión directa por ethernet a Banana Pro

En esta ocasión explicaré cómo conectarse a nuestra Banana Pro sin necesidad de internet. Usaremos una conexión directa entre el conector ethernet de nuestro ordenador y el que lleva incorporado nuestra Banana Pro.

El sistema que usaré en mi máquina es Ubuntu 16.X y el de mi Banana Pro es Ubuntu 14.X.

Primero configuraremos el ethernet de nuestro ordenador, para ello nos vamos a " System settings " ( supongo que en castellano será algo parecido a " herramientas del sistema ") , una vez ahí, entramos en " network " y accedemos a la opción por cable.




Una vez ahí, buscamos " opciones " o un botón con un nombre parecido en la esquina derecha inferior:



Nos vamos a la pestaña " general " y seleccionamos la opción de conectarse cuando esté disponible.




Seguidamente, pasamos a la pestaña de la configuración de IPV4, donde cambiaremos a " shared to other computers " ( algo parecido a "compartido con otros ordenadores "):





En este punto conectaremos nuestra Banana Pro y ordenador mediante un cable ethernet y encenderemos nuestra Banana Pro, esperamos un par de minutos a que el sistema inicie y seguidamente intentaremos conectarnos mediante SSH.

Para ello, pulsa  ctrl + alt+ t ( abrir una terminal)  y prueba de realizar una conexión. Normalmente el usuario es " bananapi" y el host " lemaker ".


ssh bananapi@lemaker.local


Si todo ha ido bien, veremos algo parecido a esto:


Le escribimos el siguiente password:

bananapi

Y ya estaremos conectados !



Próximamente enseñaré cómo conectar un SATA ( también cómo hacernos nuestro propio cable de alimentación SATA) y que arranque el sistema desde éste. Puede que, aunque no tan seguro, enseñe cómo compilar u-boot desde el código fuente original y cómo montar nuestro propio sistema operativo desde el código fuente.

saludos!


+info

jueves, 22 de octubre de 2015

Guardar estado pulsado de LED en memoria EEPROM interna de Arduino ( petición de Meta)

Muy buenas a tod@s, os adjunto un código sugerido por un visitante de este blog que consiste en crear una combinación binaria con pulsadores ( 4 pulsadores, un nibble ) y con un quinto botón (botón de guardar) que permite almacenar el dato en la EEPROM de nuestro Arduino. De esa forma, aunque se vaya la luz quedará grabada una copia de la combinación hecha.


/*
  Guarda en la EEPROM la combinación de los pulsadores BOTON_1 ~~ BOTON_4  al pulsar el botón " BOTON_GUARDAR "
*/

#include <eeprom.h>

//-----------------------defines --------------------------------------------------------------------------------------------------------
#define BOTON_GUARDAR 2 // se ponen en define para ahorrar memoria. 
                        //Si se usases variables, perderías unos 9~18 bytes de memoria (en función del tipo de variable)

#define LED_1 3
#define LED_2 4
#define LED_3 5
#define LED_4 6

#define BOTON_1 7
#define BOTON_2 8
#define BOTON_3 9
#define BOTON_4 10



#define POISICION_DE_MEMORIA_ESTADO_LED 0

//-----------------------variables globales ----------------------------------------------------------------------------------------------
byte dato_entrada = 0;

//-----------------------funciones -------------------------------------------------------------------------------------------------------
void setup() 
{
  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(BOTON_GUARDAR), ISR_guardar_dato, RISING);

  pinMode(BOTON_1,INPUT);
  pinMode(BOTON_2,INPUT);
  pinMode(BOTON_3,INPUT);
  pinMode(BOTON_4,INPUT);
  
  pinMode(LED_1,OUTPUT);
  pinMode(LED_2,OUTPUT);
  pinMode(LED_3,OUTPUT);
  pinMode(LED_4,OUTPUT);
  
 lee_EEPROM_y_muestra_dato();
}

void loop() 
{

}

void ISR_guardar_dato()
{
  leer_pulsadores_y_guardar_en_variable();
  actualiza_estado_de_los_LED();
  actualizar_dato_de_la_EEPROM();
}

void lee_EEPROM_y_muestra_dato() // lee el dato de la EEPROM y actualiza los LED en función del dato
{
  dato_entrada = EEPROM.read(POISICION_DE_MEMORIA_ESTADO_LED);
  actualiza_estado_de_los_LED();
}

void actualizar_dato_de_la_EEPROM() // regrabamos el valor del dato que hay en la EEPROM
{
  EEPROM.write(POISICION_DE_MEMORIA_ESTADO_LED, dato_entrada);
}

void actualiza_estado_de_los_LED() // leemos la EEPROM y actualizamos los LED en función del dato
{  
  digitalWrite(LED_1, ( (dato_entrada >>3) & 0x01 ) ); // pintamos cada led con su bit correspondiente
  digitalWrite(LED_2, ( (dato_entrada >>2) & 0x01 ) );
  digitalWrite(LED_3, ( (dato_entrada >>1) & 0x01 ) );
  digitalWrite(LED_4, ( (dato_entrada >>0) & 0x01 ) );      
}


void leer_pulsadores_y_guardar_en_variable()
{
  byte temp = digitalRead(BOTON_1); // X000
  
  if(temp == 1) {  dato_entrada |= (1 << 3); }// el 3 es porque lo guardaremos en el bit 3 de la variable (guardamos 1 ) 
  else          {  dato_entrada &= ~(1 << 3); }// el 3 es porque lo guardaremos en el bit 3 de la variable ( guardamos 0 ) 
  
  temp = digitalRead(BOTON_2); // 0X00
  
  if(temp == 1) {  dato_entrada |= (1 << 2); }// el 2 es porque lo guardaremos en el bit 2 de la variable (guardamos 1 ) 
  else          {  dato_entrada &= ~(1 << 2); }// el 2 es porque lo guardaremos en el bit 2 de la variable ( guardamos 0 )  
  
  temp = digitalRead(BOTON_3); // 00X0
  
  if(temp == 1) {  dato_entrada |= (1 << 1); }// el 1 es porque lo guardaremos en el bit 1 de la variable (guardamos 1 )
  else          {  dato_entrada &= ~(1 << 1); }// el 1 es porque lo guardaremos en el bit 1 de la variable ( guardamos 0 )  
  
  temp = digitalRead(BOTON_4); // 000X
  
  if(temp == 1) {  dato_entrada |= (1 << 0); } // aqui no desplazamos, porque lo dejamos en el bit 0, donde nos encontramos
  else          {  dato_entrada &= ~(1 << 0); } 
}




Un saludo!
+info
-