Por alguna razón no viene instalada por defecto ninguna interfaz de video en las ultimas versiones de Matlab. Para resolver esto solo hay que escribir en la consola supportPackageInstaller e instalar el siguiente paquete:
Con esto podrás adquirir la imagen de tu webcam sin problemas después de reiniciar Matlab.
viernes, 23 de octubre de 2015
lunes, 28 de septiembre de 2015
Interrupciones externas en Raspberry Pi con Python
A partir de la versión 0.5.6 de la librería RPi.GPIO es posible utilizar rutinas de interrupción externas. Como los usuarios de microcontroladores experimentados deben saber, una rutina de interrupción permite ejecutar una o una serie de instrucciones sin perder tiempo en bucles de lectura. Es decir que si el procesador se encuentra ejecutando una tarea, éste pausará el proceso en curso y ejecutará la rutina de interrupción ante un flanco de subida o bajada ocurrido en un pin GPIO. Si no has comprado tu Raspberry recientemente y no has actualizado su software es recomendable hacerlo:
sudo apt-get update
sudo apt-get upgrade #(Esto podría tardar hasta más de una hora)
El siguiente código es un ejemplo sencillo sobre el uso de interrupciones. Tenemos dos rutinas de interrupción CuentaA() y CuentaB() asociadas a GPIO23 y GPIO24 respectivamente. Cada una incrementan una variable de conteo y muestran el resultado en consola. El programa se detiene cuando el contador A es mayor o igual a 5. Para más detalles sobre interrupciones pueden revisar la documentación de la librería RPi.GPIO. Para evitar el el efecto de rebote se utilizan capacitores de entre 22 o 10 uF conectados en paralelo con las resistencias pulldown de 10K como se muestra en el circuito [aunque también puede utilizarse un debounce vía software agregando el argumento bouncetime=200 a la función add_event_detect()]:
import RPi.GPIO as GPIO
import os
contaA = 0
contaB = 0
#Setup
GPIO.setmode(GPIO.BCM)
GPIO.setup(23,GPIO.IN)
GPIO.setup(24,GPIO.IN)
#Callbacks
def CuentaA(channel):
global contaA
contaA += 1
os.system("clear")
print "Contador A: ", contaA
print "Contador B: ", contaB
def CuentaB(channel):
global contaB
contaB += 1
os.system("clear")
print "Contador A: ", contaA
print "Contador B: ", contaB
#Interrupciones
GPIO.add_event_detect(23, GPIO.RISING, callback = CuentaA)
GPIO.add_event_detect(24, GPIO.RISING, callback = CuentaB)
print "Contador A: ", contaA
print "Contador B: ", contaB
#Bucle principal
while(contaA < 5):
pass
GPIO.cleanup()
sudo apt-get update
sudo apt-get upgrade #(Esto podría tardar hasta más de una hora)
El siguiente código es un ejemplo sencillo sobre el uso de interrupciones. Tenemos dos rutinas de interrupción CuentaA() y CuentaB() asociadas a GPIO23 y GPIO24 respectivamente. Cada una incrementan una variable de conteo y muestran el resultado en consola. El programa se detiene cuando el contador A es mayor o igual a 5. Para más detalles sobre interrupciones pueden revisar la documentación de la librería RPi.GPIO. Para evitar el el efecto de rebote se utilizan capacitores de entre 22 o 10 uF conectados en paralelo con las resistencias pulldown de 10K como se muestra en el circuito [aunque también puede utilizarse un debounce vía software agregando el argumento bouncetime=200 a la función add_event_detect()]:
import RPi.GPIO as GPIO
import os
contaA = 0
contaB = 0
#Setup
GPIO.setmode(GPIO.BCM)
GPIO.setup(23,GPIO.IN)
GPIO.setup(24,GPIO.IN)
#Callbacks
def CuentaA(channel):
global contaA
contaA += 1
os.system("clear")
print "Contador A: ", contaA
print "Contador B: ", contaB
def CuentaB(channel):
global contaB
contaB += 1
os.system("clear")
print "Contador A: ", contaA
print "Contador B: ", contaB
#Interrupciones
GPIO.add_event_detect(23, GPIO.RISING, callback = CuentaA)
GPIO.add_event_detect(24, GPIO.RISING, callback = CuentaB)
print "Contador A: ", contaA
print "Contador B: ", contaB
#Bucle principal
while(contaA < 5):
pass
GPIO.cleanup()
sábado, 19 de septiembre de 2015
jueves, 17 de septiembre de 2015
Filtro de Notch de 60 Hz
Debido a la restricción de los valores comerciales para los resistores y capacitores, este circuito tiene una frecuencia central de 58.94 Hz. Sin embargo, como se puede ver en una simulación, se tiene una atenuación de -34 dB (un factor de de 0.0004) para la componente de 60 Hz.
Para más detalles sobre este tipo de filtros pueden consultar éste artículo.
Para más detalles sobre este tipo de filtros pueden consultar éste artículo.
Etiquetas:
Electrónica,
Instrumentación Biomédica
domingo, 13 de septiembre de 2015
Circuito para electrocardiografía (ECG/EKG)
En este video utilizan un circuito con ganancia de 100 con buenos resultados (el cual no funcionó en mi caso), lo que me hace sospechar que existen varios factores que afectan el voltaje de entrada. Posiblemente este circuito no funcionará en condiciones diferentes por lo que recomiendo experimentar con diferentes valores de ganancia.
Un segundo circuito que también funciona muy bien es una modificación del que pueden encontrar en The Biosignal How-To:
Etiquetas:
Electrónica,
Instrumentación Biomédica
miércoles, 29 de julio de 2015
“Que nadie trate de deducir quién fui
de todo lo que hice y todo lo que dije.
Había un obstáculo que deformaba
mis acciones y mi modo de vivir.
Había un obstáculo que me detenía
muchas veces cuando iba a hablar.
Por medio de mis acciones más inadvertidas
y mis escritos más velados,
sólo por medio de estas cosas podré ser comprendido.
Pero quizá no valga la pena dedicar
tanto interés y tantos esfuerzos a descubrir quién soy.
Más adelante –en una sociedad más perfecta-
otro, hecho exactamente como yo,
sin duda aparecerá y actuará con libertad.”
— Cosas escondidas, Constantino Cavafis.
domingo, 19 de julio de 2015
Comunicación serial con Arduino y Scilab
Recuerda instalar Serial Communication Toolbox primero con Module Manager.
Programa en Scilab
h=openserial("/dev/ttyACM0","9600,n,8,1"); // *
xpause(1e06); // retardo (aprox. 1 sec)
writeserial(h,char(1)) // envía 1(uint8)
xpause(1e06) // retardo (aprox. 1 sec)
writeserial(h,char(0)) // envía 0 (uint8)
closeserial(h);
* En Windows se debe sustituir "/dev/ttyACM0" por el número (sin comillas) de COM. Por ejemplo, para el COM5 quedaría: h=openserial(5,"9600,n,8,1");
Probamos la comunicación con un programa simple en Arduino dónde el led del puerto 13 encienda enviando un 1 y apagándolo con un 0.
Programa de prueba en Arduino
Programa en Scilab
h=openserial("/dev/ttyACM0","9600,n,8,1"); // *
xpause(1e06); // retardo (aprox. 1 sec)
writeserial(h,char(1)) // envía 1(uint8)
xpause(1e06) // retardo (aprox. 1 sec)
writeserial(h,char(0)) // envía 0 (uint8)
closeserial(h);
* En Windows se debe sustituir "/dev/ttyACM0" por el número (sin comillas) de COM. Por ejemplo, para el COM5 quedaría: h=openserial(5,"9600,n,8,1");
Probamos la comunicación con un programa simple en Arduino dónde el led del puerto 13 encienda enviando un 1 y apagándolo con un 0.
Programa de prueba en Arduino
void setup() { Serial.begin(9600); pinMode(13, OUTPUT); digitalWrite(13,LOW); } void loop() { while (Serial.available() > 0) { int lectura = Serial.read(); if (lectura == 1){digitalWrite(13,HIGH);} else if(lectura == 0){digitalWrite(13,LOW);} } }Como ejercicio, se puede escribir un programa dónde se envíe un valor PWM (0-255) desde Scilab hacía un led conectado a la tarjeta.
Etiquetas:
Arduino,
Linux,
Programación,
Scilab
miércoles, 15 de julio de 2015
Comunicación SPI con un DAC en VHDL
De la hoja de especificaciones, tenemos el siguiente diagrama de tiempos:
Los periodos que nos interesan son t5, que es el periodo mínimo entre datos ( el tiempo mínimo que el FPGA debe esperar para enviar el siguiente dato de manera que el DAC pueda reaccionar) y t3 y t4 que nos indican que SCK debe tener un duty cycle de 50% con un periodo T = t3+t4. En la página 4 de la hoja podemos encontrar que los tiempos mínimos requeridos son: t5 = 100 ns y una frecuencia para SCK de 10 Mhz. Los periodos t1 y t2 nos indican una especificación igual de importante. Indican que el flanco de subida de SCK debe ocurrir justo a la mitad del bit enviado. Entendiendo estas restricciones, podemos ahora comenzar a escribir nuestro programa. Nuestra entidad deberá tener 2 entradas: clk y un reset, y 3 salidas: SCK, CD y datos:
La implementación estará formada por los siguientes bloques elementales:
- Divisor de frecuencia (50 a 10 MHz)
- Divisor de frecuencia para reloj de CS
- Memoria ROM
- Registro PISO (Parallel Input Serial Output)
- Generador de reloj SCK
Memoria ROM
Los datos almacenados por esta memoria deben tener la estructura especificada por el fabricante (pag. 8), que en este caso es la siguiente:
A3A2A1A0D9D8D7D6D5D4D3D2D1D0X1X0
Control Datos Don't Care
Para este ejemplo debemos enviar la mitad del voltaje de referencia al canal A y actualizar su salida, por lo que los valores para el código de control deben ser "1001" (ver tabla de la pag. 9). Se crean entonces las siguientes señales que serán usadas en la memoria ROM:
type rom is array(0 to 2) of std_logic_vector(15 downto 0);
constant control: std_logic_vector(3 downto 0):="1001";
constant dc: std_logic_vector(1 downto 0):= "00"; -- Bits don't care constant myrom: rom
:=( control&"0111111111"&dc,
control&"0111111111"&dc,
control&"0111111111"&dc);
La razón de implementar una memoria ROM como un arreglo de varios elementos para un ejemplo tan simple es para que pueda ser modificada fácilmente para hacer cosas más interesantes como enviar una función triangular o cosenoidal (en cuyo caso habrá que incrementar el tamaño del array a entre 50 o 100 elementos). Otro detalle que debo mencionar es que, como se verá en el programa completo, el incremento de la dirección se hace con el reloj CS. Esto se hace a modo de tener el bit-rate máximo. Se puede agregar un nuevo divisor a una frecuencia más baja para cambiar el dato si así lo desean.
Registro PISO
Este registro serializará los datos recibidos de la salida de la memoria ROM y los enviará de forma síncrona en cada flanco de bajada* del reloj secundario de 10 MHz. La serialización únicamente se efectuará después de recibir un flanco de subida del reloj CS.
*Esto de modo que se cumpla la especificación de los tiempos t1 y t2, así SCK deberá estar en fase con el reloj secundario.
Generador de reloj SCK
Este reloj deberá tener una frecuencia de 10 MHz pero requiere cumplir una condición: debe activarse durante el siguiente flanco de subida del reloj secundario (10 MHz) después del flanco de bajada del pulso CS. Esto se logra mediante una implementación if síncrona normal. Sin embargo, dado que no es posible implementar físicamente una instrucción en flanco de bajada inmediatamente después de un flanco de subida ("bad synchronous description") se recuré a un truco combinacional para generar el reloj SCK que puede verse en el programa completo.
Teniendo el programa listo, así luce en simulación con ISim:
(Click para agrandar)
Programa completo
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
entity DAC_SPI is
port(
clk : in std_logic; -- 50 MHz
reset : in std_logic;
CS : out std_logic;
SCK : out std_logic; -- 10 MHz
datos : out std_logic); -- Salida serial
end entity;
architecture rtl of DAC_SPI is
-- Señales
-- Divisor
signal count: integer :=1;
signal clk_10: std_logic:='0';
-- ROM
signal address: integer range 0 to 2;
type rom is array(0 to 2) of std_logic_vector(15 downto 0);
constant control: std_logic_vector(3 downto 0):="1001"; -- Cargar y actualizar canal A
constant dc: std_logic_vector(1 downto 0):= "00"; -- Bits don't care
constant myrom: rom
:=( control&"0111111111"&dc,
control&"0111111111"&dc,
control&"0111111111"&dc);
signal rom_out: std_logic_vector(15 downto 0):=(others=>'0');
signal clk_cs: std_logic:='0';
-- PISO
signal temp: std_logic_vector(15 downto 0):= (others =>'0');
signal t: std_logic;
-- Otros
signal a: integer range 0 to 18 :=1;
signal sck_t: std_logic;
--
begin
-- Divisor de frecuencia (10 MHz)
process(clk) begin
if(clk'event and clk='1') then
count <=count+1;
if(count = 5) then -- dónde count = frec de reloj / frec deseada
clk_10 <= not clk_10;
count <=1;
end if;
end if;
end process;
--
-- PISO
process (clk_10,rom_out,clk_cs)begin
if (CLK_10'event and CLK_10='0') then
if (clk_cs='1') then
temp(15 downto 0) <= rom_out(15 downto 0);
else
t <= temp(15);
temp(15 downto 1) <= temp(14 downto 0);
temp(0) <= '0';
end if;
end if;
end process;
datos <= t;
--
-- SCK
process(clk_10,clk_cs) begin
if (clk_10'event and clk_10 = '1') then
if(clk_cs='0')then
SCK_t <= '1';
else
SCK_t <= '0';
end if;
end if;
end process;
SCK <= (sck_t) and (clk_10) and not(clk_cs);
--
-- Divisor de frecuencia para CLK_CS
process(clk_10) begin
if(clk_10'event and clk_10='1') then
a <=a+1;
if(a = 17) then
clk_cs <= '1';
a <=0;
else
clk_cs <= '0';
end if;
end if;
end process;
--
-- ROM
process(clk_cs,reset) begin
if reset = '1' then
address <= 0;
elsif( clk_cs'event and clk_cs = '1' ) then
if address < 2 then
address <= address + 1;
else
address <= 0;
end if;
rom_out <= myrom(address);
end if;
end process;
-- CS
CS <= clk_cs;
--
end rtl;
martes, 14 de julio de 2015
New Horizons finalmente en Plutón
Imagen de Plutón a 766000 kilómetros de distancia tomada por la New Horizons
16 horas antes del encuentro (NASA/APL-JHU/SwRI).
9 años había esperado para ver esta fotografía y ha valido totalmente la espera. Un símbolo de lo lejos que puede llegar la inventiva humana.
"A la espera de los datos del encuentro, hoy ya vivimos en un mundo que
sabe qué aspecto tiene Plutón. A partir de ahora, cuando queramos hablar
de Plutón o de un objeto del cinturón de Kuiper ya no usaremos borrosas
imágenes del telescopio Hubble o pinturas de artistas, porque al fin
tenemos imágenes reales obtenidas por un artefacto humano que hemos
mandado a los límites del sistema solar."
lunes, 13 de julio de 2015
Simulando circuitos con ngspice
Ngspice es un simulador de circuitos gratuito y de código abierto desarrollado por el CAD Group de la Universidad de California, Berkeley. Si ya están familiarizados con otros programas basados en SPICE no debe ser mayor problema aprender a usarlo. Por otro lado, si están acostumbrado a las comodidades de programas como Multisim o Proteus hay algunas cosas que deben saber para empezar. La forma de trabajar con ngspice es la siguiente:
Es necesario crear un directorio en donde estén guardados los archivos .mod (SPICE models) que contienen los modelos de simulación de los dispositivos electrónicos que van a utilizarse. Estos archivos no están incluidos en la instalación por defecto de ngspice, pero son proveídos por los mismos fabricantes de componentes. Estos modelos deben ser enlazados a los componentes desde gschem.
Instalación en Debian/Ubuntu/Linux Mint:
$ sudo apt-get install ngspice
Para instalar gschem y gnetlist instalamos el paquede gEDA:
$ apt-get update && apt-get install geda pcb gerbv
Abrimos gschem:
$ gschem
, buscamos "añadir componente" en la barra de herramientas (su ícono es una compuerta and) y usamos los siguientes componentes:
SPICE simulation elements > vsin-1.sym
Diodes (generic) > diode-1.sym
Basic devices > resistor.sym
Power rails > gnd-1.sym
La interfaz de gschem es bastante intuitiva. Para girar 90° un componente sólo hay que seleccionarlo y presionar las teclas E y R (una después de la otra). Una vez terminado el circuito se deben configurar los componentes para poder generar un netlist que pueda ser simulado correctamente por ngspice. Dando doble click en el diodo se abrirá una ventana dónde debemos añadir una propiedad value cuyo valor será 1N4001 y damos click en "añadir":
Hacemos lo mismo con la fuente de AC. En este caso, value ya aparecerá en la tabla por lo que solo debemos modificar su valor directamente escribiendo "sin 0 5 60Hz". Para agregar un valor a la resistencia, le damos click derecho a su símbolo y buscamos "añadir propiedad", se abrirá una ventana dónde en "nombre" escribimos "value" y en "valor" escribimos su resistencia en Ohms (100 para este ejemplo), en la última opción seleccionamos "Mostrar solo valor". Después de esto ahora sólo hace falta enlazar el archivo de modelo de SPICE al símbolo del diodo. Para esto regresamos a "agregar componente" y buscamos SPICE simulation elements > spice-model-1.sym. Para este modelo en particular las propiedades deben ser las siguientes:
Observen que en file he escrito la ruta al archivo de modelo para el diodo 1N4007 (pueden descargar un modelo de ese diodo aquí, cambiando la extensión de .txt a .mod) . Guardamos el esquema con el nombre diodo.sch. El esquema terminado debe verse algo así:
Para generar el netlist escribimos:
$ gnetlist -g spice-sdb -o diodo.net diodo.sch
[NOTA: consultar sintaxis y opciones de gnetlist]
Ejecutamos con ngspice:
$ ngspice diodo.net
Ya dentro de la consola de ngspice escribimos:
tran 100us 100ms #dónde se indica 100us de step simulando de 0 a 100ms
plot v(2)
Se abrirá una ventana con la gráfica del voltaje en la resistencia:
NOTA: Deben tomar siempre en cuenta el nombre del modelo que está declarado dentro del archivo .mod. El modelo del 1N4007 que estoy usando es diferente al que pueden descargar en diodes.com. Si usan ese archivo, deben asigar valores para la propiedad value de DI_1N4007 en vez de 1N4007 (o simplemente cambiar el nombre en el script del modelo). Este es el contenido del archivo de diodes.com, señalo el lugar donde va el nombre del modelo:
*SRC=1N4007;DI_1N4007;Diodes;Si; 1.00kV 1.00A 3.00us Diodes, Inc. diode
.MODEL DI_1N4007 D ( IS=76.9p RS=42.0m BV=1.00k IBV=5.00u
+ CJO=26.5p M=0.333 N=1.45 TT=4.32u )
Es necesario crear un directorio en donde estén guardados los archivos .mod (SPICE models) que contienen los modelos de simulación de los dispositivos electrónicos que van a utilizarse. Estos archivos no están incluidos en la instalación por defecto de ngspice, pero son proveídos por los mismos fabricantes de componentes. Estos modelos deben ser enlazados a los componentes desde gschem.
Instalación en Debian/Ubuntu/Linux Mint:
$ sudo apt-get install ngspice
Para instalar gschem y gnetlist instalamos el paquede gEDA:
$ apt-get update && apt-get install geda pcb gerbv
Abrimos gschem:
$ gschem
, buscamos "añadir componente" en la barra de herramientas (su ícono es una compuerta and) y usamos los siguientes componentes:
SPICE simulation elements > vsin-1.sym
Diodes (generic) > diode-1.sym
Basic devices > resistor.sym
Power rails > gnd-1.sym
La interfaz de gschem es bastante intuitiva. Para girar 90° un componente sólo hay que seleccionarlo y presionar las teclas E y R (una después de la otra). Una vez terminado el circuito se deben configurar los componentes para poder generar un netlist que pueda ser simulado correctamente por ngspice. Dando doble click en el diodo se abrirá una ventana dónde debemos añadir una propiedad value cuyo valor será 1N4001 y damos click en "añadir":
Hacemos lo mismo con la fuente de AC. En este caso, value ya aparecerá en la tabla por lo que solo debemos modificar su valor directamente escribiendo "sin 0 5 60Hz". Para agregar un valor a la resistencia, le damos click derecho a su símbolo y buscamos "añadir propiedad", se abrirá una ventana dónde en "nombre" escribimos "value" y en "valor" escribimos su resistencia en Ohms (100 para este ejemplo), en la última opción seleccionamos "Mostrar solo valor". Después de esto ahora sólo hace falta enlazar el archivo de modelo de SPICE al símbolo del diodo. Para esto regresamos a "agregar componente" y buscamos SPICE simulation elements > spice-model-1.sym. Para este modelo en particular las propiedades deben ser las siguientes:
Observen que en file he escrito la ruta al archivo de modelo para el diodo 1N4007 (pueden descargar un modelo de ese diodo aquí, cambiando la extensión de .txt a .mod) . Guardamos el esquema con el nombre diodo.sch. El esquema terminado debe verse algo así:
Para generar el netlist escribimos:
$ gnetlist -g spice-sdb -o diodo.net diodo.sch
[NOTA: consultar sintaxis y opciones de gnetlist]
Ejecutamos con ngspice:
$ ngspice diodo.net
Ya dentro de la consola de ngspice escribimos:
tran 100us 100ms #dónde se indica 100us de step simulando de 0 a 100ms
plot v(2)
Se abrirá una ventana con la gráfica del voltaje en la resistencia:
NOTA: Deben tomar siempre en cuenta el nombre del modelo que está declarado dentro del archivo .mod. El modelo del 1N4007 que estoy usando es diferente al que pueden descargar en diodes.com. Si usan ese archivo, deben asigar valores para la propiedad value de DI_1N4007 en vez de 1N4007 (o simplemente cambiar el nombre en el script del modelo). Este es el contenido del archivo de diodes.com, señalo el lugar donde va el nombre del modelo:
*SRC=1N4007;DI_1N4007;Diodes;Si; 1.00kV 1.00A 3.00us Diodes, Inc. diode
.MODEL DI_1N4007 D ( IS=76.9p RS=42.0m BV=1.00k IBV=5.00u
+ CJO=26.5p M=0.333 N=1.45 TT=4.32u )
Etiquetas:
Electrónica,
Linux,
ngspice,
SPICE
Suscribirse a:
Entradas (Atom)

















