Saltar al contenido.

Usando github (de nuevo)

Hace mucho probé (o intenté probar) el sistema de control de versiones git. No entendía demasiado bien el significado de todo aquello, ni las ventajas que tenía, además de que todas esas ordenes que se le daban por terminal al servidor más me parecían magia que otra cosa.

Pero ha pasado bastante tiempo de eso, y viendo como funcionan algunos grandes programas sobre git (Linux, KDE…) y otros están migrando a él por sus ventajas (FreeCAD), poco a poco fui entendiendo sus “bondades”.

La más evidente es la facilidad de colaborar y hacer un “fork” de un software. Por ejemplo, si yo tengo subida una aplicación, y hay cosas que te gustarían mejorar, simplemente puedes coger el código y modificarlo, para poder subirlo a un repositorio propio (fork). Si a mí me gustan tus modificaciones, podré fusionar “merge” ambos proyectos para añadir tus mejoras. - Sigue leyendo…>

Midiendo temperatura con LM35 y Pingüino (o Arduino)

Interactuar con el mundo real es una de los puntos fuertes de los microcontroladores. Una de las maneras de hacerlo es tomando una medida analógica que represente una magnitud real. En este caso, mediremos temperatura usando un pequeño integrado, el famoso LM35 (datasheet). Es el mismo que utilicé en mi proyecto Templogger.

La conexión con nuestra placa es muy sencilla, pero hay un pequeño detalle importante. Veamos cómo se ve en una protoboard:

Ese detalle importante del que hablo es la resistencia. Conecta el pin Vout del LM35 (el que da la tensión de salida) con GND (masa). Su función es estabilizar la señal, y sus valores pueden estar entre 10 y 100 kΩ. Sigue leyendo…

Modelo 3D de nuestra CNC con FreeCAD (Archivos incluidos)

Esta es una pequeña entrada, para colgar un pequeño archivo que hice hace unas semanas. La CNC que estoy haciendo está basada en la MantisCNC, usando una fresadora dremmel o similar como ruteadora. Este proyecto está muy bien explicado en el blog Txapuzas Electrónicas, en el que el autor añade planos y gran cantidad de detalles de construcción (muy recomendado).

Basándome casi totalmente en esos planos, con la pequeña diferencia del grosor de la madera (en mi caso 16 mm), he realizado un modelo en 3d, para que quien quiera pueda modificarla con mayor facilidad. Está creado totalmente en FreeCAD paramétricamente, así que la modificación es tremendamente sencilla. El proceso de modelado no es el mejor, pero iré mejorando en los siguientes proyectos que suba ;).

FreeCAD es un gran programa con un tremendo potencial, que puede ser de gran ayuda, por ejemplo, a aficionados que quieran diseñar sus piezas para impresión 3d con una herramienta avanzada y de código abierto. Además cuenta con una comunidad muy activa dispuesta a ayudar rápidamente a cualquier duda o problema que surja.

El diseño está dividido en 3 archivos, de la misma manera que los planos originales en .dxf (que podéis encontrar en el enlace que os he puesto antes).

Pincha aquí para descargar los archivos: TxapuCNC 3D por elelectronlibre

¡Espero que os sirva!

¡Saludos!

Pausa Navideña…

Llevo casi 2 semanas sin subir ninguna entrada. Los estudios tienen la culpa, no la navidad. Entre estas fiestas y enero intentaré avanzar con el curso de qt4 y python, además de actualizar el proyecto de CNC. No podré escribir con tanta asiduidad como este mes pasado, pero intentaré actualizarlo cuando pueda.

La buena noticia es que cuando vuelva de estos días, ¡añadiré Arduino a mis herramientas!

Feliz navidad!

EelCNC 0.1 – Interfaz Pinguino CNC 3 ejes – Esquema y PCB en KiCAD

Aviso: Esta no es una versión definitiva.

Tras mucho tiempo queriendo seguir avanzando en mi pequeño proyecto de CNC, he podido sacar tiempo y he diseñado la interfaz entre Pingüino y los drivers que moverán los motores. He puesto como versión la 0.1 porque es un mero prototipo, puede que en el futuro la mejore añadiéndole algún relé o mejorando la entrada y salida para sensores o actuadores.

Así es como quedan las pistas (no utilices esta imagen, al ser .png puede dar problemas de escala; descarga el archivo al final de la entrada):

Y así los componentes (no aparecen los puentes):

Una imagen explicativa de la distribución de los componentes en la PCB (no aparecen los puentes):

La conexión con los drivers es compatible con los de Esteca55, debido a que son unos de los más usados.

Y por último, os dejo unas fotos de la placa sin Pingüino conectado:

Y conectado:

Todos los archivos de KiCAD (esquemas, PCB…) están aquí: Descargar

Cuando pueda colgaré vídeos con el invento en funcionamiento.

Mi segundo día en la radio, hablamos de Software libre.

Por segunda vez volví a aparecer en la sección Revolución Binaria en “La Persiana”, esta vez hablando de Software Libre. Sólo comento las diferencias a grandes rasgos entre el software libre y el privativo, doy algún ejemplo (como Blender), mencionamos el tema de los formatos privativos…

Sin más dilación, aquí os dejo el enlace:

http://dl.dropbox.com/u/19401567/rev_binaria07-12-2011.mp3

¡Saludos!

¡El electrón libre en la radio!

El jueves pasado aparecí en la radio por internet Ágora Sol Radio, en el programa la persiana. Me invitó mi amigo Dante para hablar en su sección “Revolución binaria” sobre Tesla, sus inventos, etc. Yo, aunque nervioso, acepté de buena gana. Y acabé encantado, así que puede que mañana martes vuelva a salir. Si es así, intentaré colgar los extractos del programa con la sección aquí.

De momento, os dejo con el extracto del otro día. Perdonadme los nervios y los fallos que haya podido cometer, como dijo Homer: ¡Era mi primer día!

http://dl.dropbox.com/u/19401567/Rev-BinariaDanteyDani.mp3

Y aquí tenéis la página de la radio donde viene el programa completo.

http://madrid.tomalaplaza.net/2011/12/02/la-persiana-01122011/

Nuestra primera aplicación en python y qt4 [5]. Editar las operaciones.

Nuestro programa ya empieza a ser usable. Ya podemos añadir y borrar movimentos, pero si nos equivocamos en alguno, tenemos que borrarlo y volver a escribirlo, algo bastante poco práctico. Por ello vamos a crear una nueva función: EditarOperacion(). Aquí se ve lo que hace (esquemáticamente):

Como podemos ver, esta función, de por sí, no “edita” nada. Simplemente entra en un “modo edición” y copia los valores de nuestra operación a las cajas de texto, combobox, etc.
¿Qué es el modo edición? Supongo que hay más maneras de llevar a cabo esta función, pero esta es la que suelo usar. Creamos una variable que pertenezca a toda la clase (self.editando) cuyo valor determine cómo actúa la función de ingresar operación. Así, si la variable es cierta (valor “True” de una variable booleana), al ingresar una operación, en vez de crear una nueva fila se sustituirán los datos que tenemos en nuestra fila por los que hayamos añadido. Si su valor es “False”, la función IngresarOperacion() actuará como de costumbre. Además habilitaremos un botón (boton_Cancelar) que nos permita salir en cualquier momento del modo edición, y deshabilitaremos otro (boton_Borrar), para no crear conflictos.
Primero pongo el código de la función EditarOperacion():


def EditarOperacion(self):
 self.editando=True
 self.ui.boton_Cancelar.setEnabled(True)
 self.ui.boton_Borrar.setEnabled(False)
 self.filaeditada=self.ui.tableWidget.currentRow()
 self.elementoseditados=[]
 for i in range(5):
itemText = self.ui.tableWidget.item(self.ui.tableWidget.currentRow(), i).text()
  self.elementoseditados.append(str(itemText))
 #insertamos los datos de la tabla en sus lugares correspondientes
 if self.elementoseditados[0]=='Ingreso': self.ui.combo_Tipo.setCurrentIndex(0)
 elif self.elementoseditados[0]=='Gasto': self.ui.combo_Tipo.setCurrentIndex(1)
 if self.elementoseditados[1]=='Banco': self.ui.combo_Lugar.setCurrentIndex(0)
 elif self.elementoseditados[1]=='Hucha': self.ui.combo_Lugar.setCurrentIndex(1)
 self.ui.text_Comentarios.setText(self.elementoseditados[2])
 self.ui.text_Cantidad.setText(self.elementoseditados[4])
 self.ui.dateEdit.setDate(QtCore.QDate.fromString(self.elementoseditados[3],"dd/MM/yyyy"))

Ahora veamos esquemáticamente cómo quedaría la “nueva” función IngresarOperacion():

Ahora, veamos el código de la nueva función IngresarOperacion():

def IngresarOperacion(self):

#Asignamos cada valor que queremos ingresar a una variable
 self.tipo = str(self.ui.combo_Tipo.currentText())
 self.lugar = str(self.ui.combo_Lugar.currentText())
 self.fecha = self.ui.dateEdit.date()
 self.comentario = str(self.ui.text_Comentarios.toPlainText())
 self.cantidad = self.ui.text_Cantidad.toPlainText()
 if self.cantidad == "": self.cantidad = 0
 else: self.cantidad = float(self.cantidad)
 dia = self.fecha.day()
 mes = self.fecha.month()
 anno = self.fecha.year()
 self.fecha = str(dia) + '/' + str(mes) + '/' + str(anno)
 if self.editando == False:
 #Pasamos los nuevos datos a la base de datos
 self.datos=(self.tipo, self.lugar, self.comentario, self.fecha,self.cantidad)
 print self.fecha
 self.cursor.execute('INSERT INTO Operaciones (Tipo,Lugar,Comentarios,Fecha,Cantidad) VALUES(?,?,?,?,?)',self.datos)
 self.conexion.commit()
 self.actualizarBase()
 elif self.editando == True:
 #Actualizamos la base de datos
 self.datoseditados=(self.tipo, self.lugar, self.comentario, self.fecha,self.cantidad,\
 self.elementoseditados[0],self.elementoseditados[1],self.elementoseditados[2],\
 self.elementoseditados[3],self.elementoseditados[4])
 self.cursor.execute('UPDATE Operaciones SET Tipo=?,Lugar=?,Comentarios=?,Fecha=?,Cantidad=? WHERE Tipo=? AND Lugar=? AND Comentarios=? AND Fecha=? AND Cantidad=?',self.datoseditados)
 self.conexion.commit()
 self.editando=0
 self.ui.boton_Cancelar.setEnabled(False)
 self.ui.boton_Borrar.setEnabled(True)
 self.actualizarBase( )

La forma en que hemos usado la función UPDATE de sqlite es idéntica a que usamos en la parte anterior del tutorial con la función DELETE, por lo que no necesita mayor explicación.

Así queda hasta ahora nuestro programa completo:

# -*- coding: utf-8 -*-

import sys
from PyQt4 import QtCore, QtGui, Qt
from hucha_ui import Ui_Hucha
import sqlite3

class MyForm(QtGui.QMainWindow):
 def __init__(self, parent=None):
 locale=unicode(QtCore.QLocale.system().name())
 QtGui.QWidget.__init__(self, parent)
 self.ui = Ui_Hucha()
 self.ui.setupUi(self)
 self.IniciarBase()
 self.ActualizarBase()
 self.editando=False
 QtCore.QObject.connect(self.ui.boton_Ok,QtCore.SIGNAL("clicked()"
 ), self.IngresarOperacion)
 QtCore.QObject.connect(self.ui.boton_Borrar,QtCore.SIGNAL("clicked()"
 ), self.BorrarOperacion)
 QtCore.QObject.connect(self.ui.boton_Editar,QtCore.SIGNAL("clicked()"
 ), self.EditarOperacion)
 QtCore.QObject.connect(self.ui.boton_Cancelar,QtCore.SIGNAL("clicked()"
 ), self.CancelarEdicion)

 def EditarOperacion(self):
 self.editando=True
 self.ui.boton_Cancelar.setEnabled(True)
 self.ui.boton_Borrar.setEnabled(False)
 self.filaeditada=self.ui.tableWidget.currentRow()
 self.elementoseditados=[]
 for i in range(5):
 itemText = self.ui.tableWidget.item(self.ui.tableWidget.currentRow(), i).text()
 print 'itemText: ' + itemText
 self.elementoseditados.append(str(itemText))
 #insertamos los datos de la tabla en sus lugares correspondientes
 if self.elementoseditados[0]=='Ingreso': self.ui.combo_Tipo.setCurrentIndex(0)
 elif self.elementoseditados[0]=='Gasto': self.ui.combo_Tipo.setCurrentIndex(1)
 if self.elementoseditados[1]=='Banco': self.ui.combo_Lugar.setCurrentIndex(0)
 elif self.elementoseditados[1]=='Hucha': self.ui.combo_Lugar.setCurrentIndex(1)
 self.ui.text_Comentarios.setText(self.elementoseditados[2])
 self.ui.text_Cantidad.setText(self.elementoseditados[4])
 self.ui.dateEdit.setDate(QtCore.QDate.fromString(self.elementoseditados[3],"dd/MM/yyyy"))

def CancelarEdicion(self):
 self.editando=0
 self.ui.boton_Cancelar.setEnabled(False)
 self.ui.boton_Borrar.setEnabled(True)

 def IniciarBase(self):
 import os.path
 camino = os.path.abspath('basehucha_tutorial.db')
 print camino
 print os.path.isfile(camino)
 #Si la base de datos existe, la cargamos; si no, la creamos
 if not os.path.isfile(camino):
 self.conexion = sqlite3.connect('basehucha_tutorial.db')
 print 'Base creada'
 self.cursor = self.conexion.cursor()
 self.cursor.execute("CREATE TABLE Operaciones (Id INTEGER PRIMARY KEY, Tipo TEXT, Lugar TEXT, Comentarios TEXT, Fecha TEXT, Cantidad INT)")
 print 'Tabla creada'
 self.conexion.commit()
 else:
 self.conexion = sqlite3.connect('basehucha_tutorial.db')
 print 'Base conectada'
 self.cursor = self.conexion.cursor()

 def ActualizarBase(self):
 #Cargamos la base de datos y la colocamos en la tabla

self.cursor.execute("SELECT * FROM Operaciones")
 filas = self.cursor.fetchall()
 self.numerodefilas=len(filas)
 self.ui.tableWidget.setRowCount(self.numerodefilas)
 #print filas[0]

for j in range(self.numerodefilas):

fila = filas[j]
 for i in range(1,len(fila)):
 elemento = fila[i]
 print 'elemento= '+ str(elemento)
 #print i
 elemento = str(elemento)
 if elemento == 'None' : elemento = ' '
 item=None
 item = QtGui.QTableWidgetItem()
 item.setText(QtGui.QApplication.translate("Hucha", str(elemento), None, QtGui.QApplication.UnicodeUTF8))
 self.ui.tableWidget.setItem(j,i-1,item)

def BorrarOperacion(self):

 lineaSeleccionada=self.ui.tableWidget.currentRow()
 elementos=[]
 for i in range(5):
 itemText = self.ui.tableWidget.item(lineaSeleccionada, i).text()
 print 'itemText: ' + itemText
 elementos.append(str(itemText))
 self.cursor.execute('DELETE FROM Operaciones WHERE Tipo=? AND Lugar=? AND Comentarios=? AND Fecha=? AND Cantidad=?',(elementos[0],elementos[1],elementos[2],elementos[3],elementos[4]))
 self.conexion.commit()
 self.ActualizarBase()

 def IngresarOperacion(self):

#Asignamos cada valor que queremos ingresar a una variable
 self.tipo = str(self.ui.combo_Tipo.currentText())
 self.lugar = str(self.ui.combo_Lugar.currentText())
 self.fecha = self.ui.dateEdit.date()
 self.comentario = str(self.ui.text_Comentarios.toPlainText())
 self.cantidad = self.ui.text_Cantidad.toPlainText()
 if self.cantidad == "": self.cantidad = 0
 else: self.cantidad = float(self.cantidad)
 dia = self.fecha.day()
 mes = self.fecha.month()
 anno = self.fecha.year()
 self.fecha = str(dia) + '/' + str(mes) + '/' + str(anno)
 print self.editando
 #self.fecha=str(anno) +'-'+str(mes)+'-'+str(dia)
 if self.editando == False:
 #Pasamos los nuevos datos a la base de datos
 self.datos=(self.tipo, self.lugar, self.comentario, self.fecha,self.cantidad)
 print self.fecha
 self.cursor.execute('INSERT INTO Operaciones (Tipo,Lugar,Comentarios,Fecha,Cantidad) VALUES(?,?,?,?,?)',self.datos)
 self.conexion.commit()
 self.ActualizarBase()
 elif self.editando == True:
 #Actualizamos la base de datos
 self.datoseditados=(self.tipo, self.lugar, self.comentario, self.fecha,self.cantidad,\
 self.elementoseditados[0],self.elementoseditados[1],self.elementoseditados[2],\
 self.elementoseditados[3],self.elementoseditados[4])
 print self.fecha
 self.cursor.execute('UPDATE Operaciones SET Tipo=?,Lugar=?,Comentarios=?,Fecha=?,Cantidad=? WHERE Tipo=? AND Lugar=? AND Comentarios=? AND Fecha=? AND Cantidad=?',self.datoseditados)
 self.conexion.commit()
 self.editando=0
 self.ui.boton_Cancelar.setEnabled(False)
 self.ui.boton_Borrar.setEnabled(True)
 self.ActualizarBase( )
if __name__ == "__main__":
 app = QtGui.QApplication(sys.argv)
 myapp = MyForm()
 myapp.show()
 sys.exit(app.exec_())

Ante cualquier problema, simplemente comentad e intentaré solucionarlo.
¡Saludos!

Zooniverse, o cómo hacer ciencia mientras te tomas un aperitivo

Zooniverse es, como ellos mismos dicen, el sitio de ciencia ciudadana más grande, popular y exitoso del mundo.

¿Y qué es la ciencia ciudadana?

Es aquella en la que la gente normal, sin unos conocimientos específicos, pueden ayudar al progreso de la ciencia y, por tanto, del conocimiento. Esto suena muy bonito, pero es aún mejor: Tranquilamente sentado en tu sofá puedes estar detectando llamaradas solares en dirección a la Tierra en tiempo real, clasificar galaxias o incluso detectar planetas extrasolares.

¿Cómo demonios es eso posible?

La mayoría (si no la totalidad) de los proyectos científicos tienen un problema común: la ingente cantidad de datos a procesar. Normalmente se utilizan ordenadores, pero en muchos casos los humanos somos mucho mejores en la resolución de ciertos problemas. ¿Cuáles? Reconocimiento de patrones, principalmente. La evolución nos ha ayudado a ser unos expertos en reconocimiento facial, por ejemplo. También somos capaces de reconocer un lugar a simple vista, o una situación de peligro a partir de pocos datos… Y eso es algo que los ordenadores (de momento) simplemente no son capaces de hacer muy bien.

Sigue leyendo…

Nuestra primera aplicación en python y qt4 [4]. Añadir y borrar entradas.

Vale, ya sí que sí, ya tenemos una interfaz, y una base de datos a la que sabemos conectarnos. Hoy de una vez por todas vamos a poder rellenar esa base. Para ello, vamos a implementar dos funciones: IngresarOperacion() y BorrarOperacion(). Su nombre explica su función, pero voy a explicar un poco más detalladamente lo que hace cada una:

IngresarOperacion()

El esquema que va a utilizar esta función es muy sencillo:

Los datos ingresados los guardaremos en sus correspondientes variables (fecha,tipo…). La forma de hacerlo (o al menos una de ellas) es la siguiente: Sigue Leyendo…