11 diciembre 2012

Programar en BASIC desde Android


Existe alguna alternativa para programar DESDE un dispositivo Android.

Una de ellas es una versión de BASIC llamada "De Re BASIC!", creada por el autor de Atari Basic y de Apple DOS 3.1, de código abierto, y que se puede descargar desde:

http://laughton.com/basic/

En esa página tendremos acceso al fichero ".apk" que podremos instalar en nuestro móvil o tablet (si permitimos la instalación "desde fuentes no fiables"), y que permite editar nuestros programas en BASIC desde el propio dispositivos y lanzarlos también desde él mismo.

Tras instalarlo, en nuestro dispositivo aparecerá una nueva aplicación llamada "BASIC!", con un icono que muestra un telescopio, y al lanzarla veremos un editor que nos permite añadir texto y que inicialmente muestra:

REM Start of BASIC! Program

En esta versión del lenguaje, podemos encontrar las estructuras típicas del lenguaje BASIC, como IF-ELSE, FOR-TO-NEXT, WHILE, GOTO (con etiquetas, no con números de línea), GOSUB e incluso un PRINT para escribir en modo consola. Por ejemplo, para escribir la palabra "hola" podríamos añadir a nuestro esqueleto de programa: print "hola"

REM Start of BASIC! Program
print"hola"

Pero también tenemos acceso a construcciones más avanzadas: desde dibujar en modo gráfico hasta acceso a servicios típicos de un dispositivo Android, como el GPS, la cámara, envío de correo y de SMS, sockets TCP/IP, SQL...

Por ejemplo, el esqueleto de un programa básico que dibujara sería:

REM Start of BASIC! Program
gr.open 255,255,255,255
gr.color 255,0,0,0,0
gr.line n,0,0,100,120
gr.render
do
until 0 

que mostrará una línea desde la esquina superior izquierda de la pantalla hasta el punto de coordenadas 100,120 (en color negro, sobre fondo blanco) y esperará hasta que se pulse el botón de "Retroceso" del dispositivo.

Un ejemplo más detallado podría ser un juego para niños que estén empezando a leer, que escogiera una letra al azar y la mostrara en pantalla; al tocar la pantalla, generaría una nueva letra y así sucesivamente. El fuente completo podría ser algo como

! Letras al azar, de una en una

! Modo grafico con fondo blanco
GR.OPEN 255, 255, 255, 255
! Orientacion vertical
GR.ORIENTATION 1
! Leer ancho y alto del dispositivo
GR.SCREEN ancho,alto

posX = ancho/4

! Color negro para el texto
GR.COLOR 255, 0, 0, 0, 0

! Tamanyo: la mitad del ancho
GR.TEXT.SIZE ancho/2

! Alineacion izquierda
GR.TEXT.ALIGN 1

DO
  GR.CLS
  codigoLetra = 65+RND()*26
  GR.TEXT.DRAW P, posX, alto/2, CHR$(codigoLetra)
  GR.RENDER

  DO
    GR.TOUCH tocado,x,y
  UNTIL tocado

UNTIL 0

! El programa acaba al pulsar ATRAS
! Este ONERROR evita un mensaje de error
! de "graphics not open"
ONERROR:
END 

Aplicaciones como ésta se podrían llegar a "empaquetar" en un fichero ".apk", para distribuir el programa a otras personas que no tengan BASIC! instalado, pero ese es un proceso relativamente laborioso. Existe una aplicación que permite automatizarlo hasta cierto punto, pero que a cambio exige que usemos una versión concreta del Android SDK, que tengamos una cuenta en Google Market, etc. Para un aficionado resulta más sencillo instalar BASIC! junto con nuestro programa en el dispositivo de destino y evitar complicaciones.

Este entorno no permite crear interfaces de usuario usando las funciones nativas de Android, pero sí permite crear páginas web interactivas que se comuniquen con un programa en BASIC... pero esa es otra historia y deberá ser contada en otro momento...

30 septiembre 2012

Caja de Tente para RaspberryPi

Existe más de una propuesta de caja de Lego para el RasperryPi. Basta buscar "lego case raspberrypi" en cualquier de los principales buscadores para encontrarlas. Pero en España, el juguete de construcción histórico, mucho antes de que Lego acaprase el mercado, fue Tente, del fabricante español Exin, creador también del Cinexin, Exin Castillos, Madelman...

Hoy en día es fácil encontrar piezas de Lego y relativamente complicado encontrar su equivalente de Tente, que se dejó de comercializar en 2007, por lo que hay que recurrir al mercado de segunda mano. Aun así, yo conservo (parte de) la colección de mi infancia, así que me pregunté hasta qué punto sería factible hacer una caja de Tente para el RaspberryPi.

El hecho de que el resultado sea bueno con un juego de construcción como éste depende mucho del grosor de los "bloque unitarios" y de la variedad de piezas de que se disponga. Aunque las piezas de Tente y de Lego son  incompatibles, su tamaño es muy similar, cerca de los 8 mm. Esto supone que un RaspberryPi ocupe una superficie de unos 7x11 bloques unitarios de Tente. Por tanto, para construir una caja compacta haría falta usar una superficie 9 de ancho (si queremos que las paredes que den firmeza estén en los laterales de los conectores de audio y video) y entre 10 y 15 de largo (con 10 asomaría un poco el extremo de la placa con el conector de SD; con 14 la tarjeta SD quedaría totalmente cubierta y el conector Ethernet estaría al ras de la pared; con 15 serian los USB lo que queda al ras de la parte exterior). El grosor de las paredes sería como mínimo de 8 mm (un bloque) o incluso de unos 16 mm (dos bloques). En el lateral del conector de video y analógico y en el de USB serían aceptables los 8 mm; en los demás laterales... no tanto...

Como las "placas" más habituales en Tente son las de 6x8, 4x8 y 2x8, hacer una caja de condiciones supone tener una cierta variedad. Por ejemplo, hacer esos 9 de ancho y 15 largo supondría tener muchas placas de 2x3 que permitan completar hasta tamaño impar... y yo tengo pocas de esas...

Mi "experimento" tiene 10 bloques de ancho, de modo que el conector HDMI queda demasiado dentro para mi gusto (tras una pared de 16 mm). A cambio, tiene algún detalle simpático, como la apariencia de "casita", una ventanita para ver los LEDs, o un techo que se puede levantar parcialmente con unas bisagras.

No es una caja muy práctica, así que la destruiré, pero ha sido un intento entretenido y con su punto de nostalgia, adecuado para una mañana de domingo...  ;-)



(No soy el primero que hace algo así, como mínimo alguien con nick "Goskum" también ha creado una, que se puede encontrar en http://www.raspberrypi-spanish.es/foro/viewtopic.php?f=11&t=2&start=40 )

30 agosto 2012

Calendarios inactivos en Android

Hoy no toca hablar de programación, sino del día a día de un informático, en concreto de cómo planificar compromisos pendientes usando el calendario de un teléfono móvil Android.

Google Calendar es una fantástica aplicación de "agenda online", que permite anotar con facilidad citas puntuales o repetitivas, con o sin alarmas. Incluso se pueden tener varios calendarios, asignar distintos colores a cada uno de ellos, y compartir alguno con otras personas, algo que es ideal cuando se trabaja en grupo y los compromisos de una persona afectan a las demás. Lo único necesario para usar Google Calendar es tener una cuenta de Google (por ejemplo, la del correo Gmail).

Y los teléfonos Android se suelen integrar bastante bien con los servicios de Google. Pero a veces no tan bien como sería deseable. En mi caso, con mi Samsung Galaxy, se me mostraba el calendario "principal", pero no los demás subcalendarios (cosa que no ocurría con mi anterior HTC). No he encontrado solución en los ajustes del teléfono, así que he probado otras aplicaciones de calendario, con funcionalidades distintas, y una de ellas sí me ha resuelto el problema.

Para un espacio pequeño, Smooth Calendar es muy claro y fácil de leer, además de que se puede configurar o actualizar a petición haciendo un clic sobre su widget.

Para espacios más grandes (por ejemplo, 4x3 "bloques de pantalla"), Simple Calendar va muy bien, y es más personalizable que Smooth Calendar, aunque sólo se puede personalizar en el momento de colocar el widget en pantalla, porque no responde a los clics. Para cambiar algún detalle, hay que eliminar el widget y volverlo a instalar. Por defecto no muestra todos los calendarios, pero se pueden pedir en el momento de configurarlos. Éste es el que me hizo darme cuenta de que mis calendarios adicionales "existían" para el móvil pero aparecian marcados como "inactivos" (inactive), de modo que no se sincronizaban y no se mostraban sus detalles. Y no he encontrado en ningún apartado de la configuración del móvil la forma de marcarlos como "activos".

Navegando un poco por la red llegué a un foro en el que alguien ya había tenido ese problema. Como el foro original está en inglés, y encontrar cosas por la red puede ser tarea casi imposible, reproduzco aquí la solución de compromiso que encontró ese usuario, por si le sirve a alguien más: instalar otro gestor de calendarios gratuito distinto, Business Calendar Free, que sí permite marcar los calendarios como activos o inactivos. Después, si Business Calendar te parece demasiado "aparatoso", puedes no usarlo o incluso desinstalarlo. Pero al menos ya habrás ganado el acceso a esos calendarios ocultos, que deberían estar accesibles pero no lo estaban.

13 agosto 2012

Raspberry Pi y PyGame - Introducción

El fin de semana del 21 de julio (de 2012), un grupo de adolescentes decidió usar su Raspberry Pi y el lenguaje Python para hacer un marathon de programación colaborativa de 24 horas, que llamaron "Raspithon". Usaron la biblioteca de juegos Pygame (basada en SDL) para crear un juego de asteroides, que iban programando entre 4 personas, usando un repositorio Git como punto en el que centralizar todo lo que iban creando.

Puedes leer la propuesta que hicieron, el post que habla sobre los resultados e incluso descargar el programa resultante desde GitHub.

Si cuatro chavales de entre 12 y 16 años, que ni siquiera se conocen entre ellos, son capaces de crear un juego... ¿es que cualquiera puede hacer un juego con Pygame? Sí y no. Python es más fácil de aprender que otros lenguajes como C, pero aun así necesita algo de dedicación si se quiere tener soltura. SDL es una biblioteca de un nivel bastante bajo, de modo que no es especialmente sencilla; Pygame la "encapsula" y la hace un poco más accesible, pero aun así no es trivial. Además, no todo tipo de juegos se podrá hacer con una cantidad de esfuerzo razonable: Pygame puede ayudar para juegos en 2D (plataformas, matamarcianos simples, etc) pero no simplifica las tareas adicionales que conllevaría crear un juego en 3D, de modo que un juego de este tipo puede suponer una cantidad de trabajo desproporcionada.

¿Y basta con un Raspberry Pi? Sí. La instalación básica de Raspbian (de fecha 15-07-2012) incluye Pygame, aunque sólo para la versión 2.7 de Python, pero debería ser suficiente.

¿Y si no tengo un Raspberry Pi... no puedo? Claro que sí. Python es multiplataforma. Cualquier Linux podría bastar (tendremos que usar Synaptic o nuestro gestor de paquetes para instalar "python-pygame"). Incluso en Windows debería ser fácil de instalar... aunque yo lo he probado (¿aún?).

Un programa básico en Python, usando PyGame para que un "marciano" rebote en la pantalla podría ser así:

import pygame, sys
pygame.init()

ancho = 800
alto = 600
velocidadX = 3
velocidadY = 3

pantalla = pygame.display.set_mode( (ancho, alto) )

imagen = pygame.image.load("spaceinvader.png")
rectanguloImagen = imagen.get_rect()

while 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT: sys.exit()

    rectanguloImagen = rectanguloImagen.move( (velocidadX, velocidadY) )
    if rectanguloImagen.left < 0 or rectanguloImagen.right > ancho:
        velocidadX = -velocidadX
    if rectanguloImagen.top < 0 or rectanguloImagen.bottom > alto:
        velocidadY = -velocidadY

    pantalla.fill( (0,0,0) )
    pantalla.blit(imagen, rectanguloImagen)
    pygame.display.flip()


En mi caso, ha bastado con teclear esto en el editor Geany, guardarlo con el nombre "rebota1.py" y pulsar el botón "ejecutar".

El fuente debería ser fácil de seguir incluso si no conoces Python:
  • "Importamos" las bibliotecas que vamos a usar: pygame (por supuesto) y "sys", que usaremos para abandonar el programa cuando sea necesario: import pygame, sys
  • Inicializamos pygame: pygame.init()
  • Declaramos los que serán el ancho y el alto de la pantalla de juego, en puntos, porque los usaremos para preparar la pantalla pero también para que "rebote" nuestro "marciano": ancho = 800, alto = 600
  • Preparamos también la velocidad a la que se moverá el "marciano" (la cantidad de puntos que se desplazará en cada "fotograma" del supuesto "juego"): velocidadX = 3, velocidadY = 3
  • Preparamos la pantalla (el ancho y el alto se deben indicar entre paréntesis, porque no son dos números aislados, sino un "par"): pantalla = pygame.display.set_mode( (ancho, alto) )
  • Cargamos la imagen que representará nuestro marciano (esa imagen deberá existir y estar en la misma carpeta que se encuentra nuestro fuente): imagen = pygame.image.load("spaceinvader.png")
  • Cada imagen estará contenida en un "rectángulo", que será el que movamos: rectanguloImagen = imagen.get_rect()
  • Y empieza la parte que se va a repetir indefinidamente: while 1:
  • Revisamos todos los "sucesos" del sistema; si alguno de ellos es una petición de salir del programa (porque se pulse la X de la ventana), salimos al sistema:    for event in pygame.event.get():   if event.type == pygame.QUIT: sys.exit()
  • En cada fotograma, desplazamos el "marciano" a la que será su siguiente posición:      rectanguloImagen = rectanguloImagen.move( (velocidadX, velocidadY) )
  • Si se sale por un lado de la pantalla o por el opuesto, en horizontal, cambiamos su "velocidad", para que pase a moverse en dirección contraria:  if rectanguloImagen.left < 0 or rectanguloImagen.right > ancho:  velocidadX = -velocidadX
  • Y hacemos las mismas comprobaciones en vertical: if rectanguloImagen.top < 0 or rectanguloImagen.bottom > alto: velocidadY = -velocidadY
  • Rellenamos la pantalla de color negro (el color (0,0,0), sin nada de rojo, verde ni azul, es el negro):  pantalla.fill( (0,0,0) )
  • Volcamos la imagen a la pantalla: pantalla.blit(imagen, rectanguloImagen)
  • Y hacemos que lo que hemos preparado en pantalla sea visible:  pygame.display.flip()
  • Todo eso se repetirá hasta que abandonemos el programa.

El resultado será pobre, pero es un comienzo:



¿Quieres más?  Deja un comentario... ;-)

(Ese fuente se basa en uno tomado de uno de los muchos tutoriales de Pygame disponibles en la red; en concreto, en uno de Pete Shinners; si quieres ver más detalles, aquí tienes un texto paso a paso).

10 agosto 2012

Raspberry Pi y SDL

Mi primer intento de recompilar para Raspberry Pi una aplicación basada en SDL (el emulador de Amstrad CPC llamado Caprice) no fue un éxito.

Resulta que en la instalación básica de Raspbian (al menos en la recopilación de 15-07-2012) no incluye SDLdev (la parte de SDL que es necesaria para compilar programas usando SDL). Pero no es grave, tampoco es difícil añadirlo. Los pasos son:

  • Actualizar (update) los componentes que ya están instalados.
  • Ampliar (dist-upgrade) la distribución con los nuevos paquetes que hayan decididos sus recopiladores.
  • Reiniciar el equipo.
  • Instalar SDLdev y el resto de herramientas de desarrollo.
  • Recompilar el fuente.
Los primeros cuatro pasos equivalen a las siguientes órdenes

sudo apt-get update
sudo apt-get dist-upgrade
sudo shutdown -r now
sudo apt-get install gcc build-essential libsdl1.2-dev

Y el último paso supone entrar a la carpeta en la que está el fuente (en mi caso, "cpc") y recompilarlo (en este caso con "make"):

cd cpc
make -f makefile.unix

Aparecerá algún mensaje de aviso si el fuente incluye construcciones que actualmente se consideren obsoletas (como en el caso de Caprice), pero aun así debería compilar correctamente, y aparecer un ejecutable llamado "cap32". Si lo lanzamos desde consola tecleando

./cap32

nos aparecerá la versión del emulador basada en consola:



Si lo lanzamos desde el entorno gráfico, usando el gestor ficheros ("file manager") que tenemos en la carpeta de accesorios ("accesories") del menú, aparecerá la versión del emulador para entorno gráfico:


Esto no lo he descubierto yo desde cero, sino gracias a la ayuda de conversaciones mantenidas en los propios foros de Raspberry Pi y también a partir de los esfuerzos de otros usuarios, que habían portado ya juegos como Quake3.

09 agosto 2012

Raspberry Pi, Geany y CPC

Tercer contacto... Ahora toca ampliar un poco el software de mi Raspberry Pi.

Vamos a empezar por lo fácil: el software que ya existe en los repositorios, en mi caso el editor Geany, que me gusta usar como entorno de desarrollo. Son muy pocos pasos y relativamente sencillos:

  • Asegurarnos de que el "router" o la red que nos da acceso a Internet está totalmente operativa, por ejemplo probando a conectar antes otro ordenador y navegando desde él.
  • Conectar el cable de red entre el Pi y el router, el HDMI entre el Pi y el monitor, introducir la tarjeta SD con el sistema operativo (Raspbian 2012-07-15), conectar el teclado y el ratón (yo lo haré usando un Hub, para dejar un conector USB libre, en el que luego pueda conectar un pendrive con más datos) y finalmente conectar el cable de alimentación.
  • Cuando termine el arranque, si el "router" nos ha asignado una dirección IP correctamente, ésta se nos dirá justo antes del login, algo como "My IP address is 192.168.0.101". Aun así, podemos entrar al entorno gráfico con "startx" y lanzar el navegador "Midori", para comprobar de una forma "más visual" que tenemos acceso a Internet.
  • Entonces ya podemos abrir un terminal (o cerrar el entorno gráfico) y usar "apt-get" para instalar el software que nos interese y que aún no tengamos disponible. Por ejemplo, para "geany" seria
sudo apt-get install geany

Eso es todo. Si lo reconoce, nos mostrará un resumen y nos pedirá confirmación. Ahora deberíamos tener en el menú Desarrollo una nueva opción que nos permita lanzar Geany para poder teclear y compilar nuestros fuentes con comodidad.

Eso sí, no siempre será tan fácil, porque hay paquetes de software que no se encuentran en los repositorios, y habrá que "recompilarlos" a partir de su código fuente. Es el caso del emulador de Amstrad CPC llamado Caprice y de otros muchos paquetes de software minoritarios. En este caso, los pasos serán:
  • Descargar el código fuente de la aplicación, desde su página oficial (muchos de estos proyectos de código abierto están alojados en sitios como Sourceforge, Google Code o GitHub).
  • Si la descarga la hemos hecho desde otro ordenador, tampoco será un problema llevarlo al Pi: podemos volcarlo a un pendrive y conectar después ese pendrive a uno de los conectores USB del Pi (por eso había usado antes un Hub para conectar el teclado y el ratón, de modo que me quedara un USB libre).
  • Creamos una carpeta (eso es sencillo, se puede hacer desde el entorno gráfico) y copiamos en ella el fichero descargado (ídem).
  • Descomprimimos el fichero. En mi caso, basta con abrir un terminal, entrar a la carpeta "cpc" que he creado (usando la orden "cd cpc") y descomprimir el fichero zip ("unzip caprice32-4.2.0-src.zip").
  • En la mayoría de proyectos de programación en C basados en Linux, existe un "makefile", que nos permitirá recomprimir simplemente tecleando "make".
  • En el caso del emulador Caprice, como se puede compilar tanto para Windows como para Linux, hay dos makefiles distintos, así que lo intentaremos recompilar con "make -f makefile.unix").  ¿Y cómo se pueden saber esos detalles? Pues básicamente mirando si hay varios ficheros llamados "makefile", o bien buscando un "readme.txt" que nos lo cuente (habitualmente en inglés).
  • Al cabo de un instante, nuestro programa debería estar listo para funcionar.
Por supuesto, puede haber problemas. En mi caso, este programa necesita la biblioteca de juegos conocida como SDL. Esta biblioteca viene preinstalada en Raspbian, pero sólo con los módulos de usuario, de modo que se puede jugar a juegos, pero no crearlos. Tenemos que instalar libsdl-dev, que son los módulos de desarrollo ("dev" es la abreviatura de "development"). La orden es la misma que la usada para instalar Geany:

sudo apt-get install libsdl1.2-dev

¿Y cómo sé que la biblioteca se llama exactamente así? Pues con una búsqueda sencilla: tecleando "sudo aptitude search sdl" y mirando cuales de los resultados contienen "sdl" y "dev". Incluso podría bastar con el paquete "libsdl-dev", que a su vez buscaría el que corresponde a la versión más reciente.

Nuevamente, hay problemas: en mi caso, recibo un error de que no encuentra la sub-biblioteca "pulse audio", de modo que no consigue completar la instalación. Tampoco es un problema insalvable: hay usuarios que han creado una "actualización de Raspbian" que soluciona ese problema. Pero por hoy es bastante, así que eso queda aplazado para la siguiente entrega...

29 julio 2012

Raspberry Pi, Raspbian y teclado español

Es el momento de un segundo contacto "público" con mi Raspberry Pi (puedes leer el primer contacto, si no sabes lo que es). En esta ocasión, con la última distribución oficial, la "Raspbian" (una Debian optimizada para el Raspberry Pi) de fecha 15 de julio de 2012, para ver cómo configurar el teclado español y jugar un poco más.

La imagen del sistema operativo ocupa cerca de 450 Mb comprimida, y casi 2 Gb descomprimida, por lo que lo razonable es usar una tarjeta SD de 4 Gb o más. Una vez volcamos la imagen a la tarjeta usando (por ejemplo) Win32DiskImager, podemos insertar la tarjeta en el Raspberry, conectar el teclado y el ratón, el HDMI y el cable de alimentación...

Al final del arranque aparecerá la pantalla de "raspi-config", la herramienta de configuración:


En ella tenemos opciones como:

  • info - información sobre qué es esta herramienta
  • expand_rootfs - para que el sistema de ficheros de nuestra distribución de Linux utilice todo el espacio que permita nuestra tarjeta SD.
  • configure_keyboard - para elegir la configuración de teclado (en mi caso, uno "Generico de 105 teclas", que aparece como "Generic 105 key") y su distribución (se propone "English (UK)", pero deberíamos escoger "Other" y luego "Spanish"; se nos preguntará ciertas variantes, como el teclado de Apple Macintosh, o el catalán, pero generalmente bastará con dejar simplemente "Spanish"). Finalmente se nos preguntará también cómo queremos que se comporte la tecla AltGr (se puede dejar con su valor por defecto) y si queremos que la combinación Ctl+Alt+Borrar pueda cerrar el entorno gráfico, algo que a mí si me gusta conservar, por si el entorno gráfico llegase a bloquearse, algo que es muy poco frecuente.
  • change_locale - para indicar la configuración regional. Lo razonable en España es escoger "es_ES.UTF-8". Aun así, tenemos que asumir que lo habitual es que los mensajes de error de consola, e incluso los menús en modo gráfico, no estén traducidos al castellano y nos aparezcan en inglés.
  • change_timezone - para indicar la zona horaria, que en nuestro caso podría ser Europe / Madrid, aunque no es algo crítico, porque el Pi no tiene reloj interno, y la fecha y hora se perderá de una sesión de trabajo a la siguiente.
  • memory_split - para elegir el reparto entre memoria principal y memoria de video. Como mi uso no va a ser intensivo en gráficos, prefiero dejar más memoria principal (224+32).
  • ssh - para habilitar o bloquear el servidor de ssh, por si quisiéramos conectar al Pi desde la red (para mi no es importante, con el uso que le voy a dar).
  • boot_behaviour - para indicar el comportamiento de arranque: si queremos que comience con entorno gráfico o con una consola en modo texto. A mí me gusta que arranque en consola, y, si quiero usar el entorno gráfico, sólo tengo que teclear "startx".
  • update - para intentar actualizar la utilidad raspi-config. En mi caso, no tengo el Pi conectado a Internet, así que no me he molestado en probarlo.


Cuando hayamos terminado, vamos hasta la opción "Finish" (pulsando el tabulador) y el sistema se reiniciará. Al volver a arrancar,

Si tecleamos "startx" para arrancar el entorno gráfico (o si hemos elegido que arranque hasta llegar a él), veremos la nueva apariencia, con el escritorio LXDE, el logo de Raspberry Pi como fondo de pantalla y ciertas herramientas de programación ya en forma de acceso rápido en el escritorio:


En el apartado "programación" (programming) encontramos menos herramientas que en la versión anterior de Debian para el Pi. Al menos, yo he echado en falta el comodísimo "Geany" como editor:


Si queremos programar en Python 3, basta con entrar a IDLE 3 y comenzar a teclear:


Para usar otros lenguajes, como C, puede resultar más incómodo que antes: el editor incluido, Leafpad, no realza la sintaxis en colores, ni permite compilar desde él, por lo que tendremos que hacerlo desde consola:


Cuando terminemos, podemos usar la opción "Logout" para cerrar el entorno gráfico:


y veremos que no hay opción de "apagar", sino sólo ese "Logout" que nos devolverá a la consola:


Podríamos desenchufar ya el cable, pero en general será más fiable si nos aseguramos de que no hay datos que estén pendientes de guardar, pidiendo al sistema que cierre toda la sesión de trabajo (aunque no se apagará físicamente) con "sudo shutdown -h now"


Cuando volvamos a encender, nuestros datos y nuestros programas seguirán estando allí. Eso sí, no podemos guardar datos directamente en la tarjeta SD como forma rápida de compartir información entre el Pi y un PC convencional, porque la partición no es accesible desde Windows. No es grave. En otro ratito llevaremos programas del PC al Pi para recompilarlos para ARM desde su código fuente. Pero claro... eso será en otro ratito...

02 junio 2012

Raspberry Pi - Primer contacto real

Ayer llegó mi Raspberry Pi, el ordenador de bolsillo por un precio cercano a los 30 dólares.

Las ventas comenzaron el 29 de febrero, pero ese día los distribuidores estaban tan saturados que era casi imposible conectar con ellos. El primer lote de 10.000 unidades se agotó en poquísimo tiempo, y un gran número de interesados tuvimos que limitarnos a "mostrar nuestro interés", para que nos avisaran cuando llegara un segundo lote o incluso uno posterior.

El 16 de mayo recibí por fin un mensaje de RS Components que me decía que había llegado mi turno para hacer el pedido. El precio final era de 24,40 € (el equipo) + 5,48 € (impuestos) + 6,28 € (envío), un total de 39,16 €.

Dos semanas después (y casi 3 meses más tarde del lanzamiento oficial), por fin lo tengo en casa. Dentro de un sobre acolchado había una caja de cartón con el logotipo de Raspberry Pi:


La caja tiene un par de sellos de garantía en su parte inferior, para garantizar que el equipo llega tal y como ha salido del distribuidor:


Y al abrir, la caja aparece una "guía rápida" (en inglés), que no he llegado a leer, porque ya estaba informado sobre el dispositivo y su forma de uso, y bajo ella, espuma para que no se dañe el el envío:


Al retirar esa espuma aparece el Pi, dentro de una bolsa antiestática.


Voilá! Al abrir la bolsa antiestática tenemos la pequeña maravilla:


Para el sistema operativo, nos podemos dirigir a la página de descargas de Raspberry Pi. De allí, los creadores del dispositivo recomiendan utilizar Debian Linux 6. Basta descargar el correspondiente fichero ZIP, descomprimirlo, y volcarlo a una tarjeta SD de al menos 2 GB usando (por ejemplo) Win32DiskImager, para el que tenemos un enlace de descarga en esa misma página.

Cuando esté volcado, introducimos la tarjeta SD en el conector del Pi. Para ponerlo en marcha, basta conectar una televisión, un teclado USB y una fuente de alimentación con conector MicroUSB. Si vamos a usar algún entorno gráfico, interesará conectar también un ratón. Y si vamos a conectar a Internet, necesitaríamos un cable de red convencional, con conectores RJ45 (podríamos usar también un adaptador WiFi USB, pero su instalación puede no ser automática).

En mi caso, no tenía intención de conectar a Internet, pero sí quería probar el entorno gráfico y la consola, así que he optado por usar un cable HDMI para conectar a una televisión FullHD, un teclado y un ratón inalámbricos y el cargador de mi smartphone Android:


En la televisión irá apareciendo toda la secuencia de arranque, como suele ocurrir en los sistemas Linux:


En mi televisor, la imagen aparecía ligeramente mal encuadrada. Es posible que ocurra si estamos en algún modo automático, o 4:3 o algún zoom manual. En mi caso, le he dicho al televisor que el zoom que quería es el de "escaneado exacto", y entonces ya se veía perfectamente el logotipo, toda la secuencia de arranque y el mensaje de "login":


Para esta distribución de Linux, el usuario es "pi" y la contraseña es "raspberry". Al introducir estos dos datos, ya estaremos en una "consola" normal, en la que podríamos manejar el sistema mediante órdenes, que son ciertas palabras reservadas.


Si nos asustan las pantallas negras y preferimos usar ratón, basta con teclear "startx" para lanzar el entorno gráfico LXDE.


Aun así, si queremos usar el Pi para tareas técnicas, que es lo que sugieren sus creadores, como podría ser aprender a programar, podemos desplegar el menú (similar al de un Windows 95 o posterior) y entrar a la categoría que nos interese. Por ejemplo, para programar tenemos preinstalado el editor Geany, muy cómodo de usar, que realza la sintaxis en colores y permite compilar nuestros fuentes y lanzar los ejecutables resultantes desde el mismo entorno:


Aun así, el resultado ha sido ligeramente menos fácil: el sistema viene configurado para un teclado inglés, de modo que teclear algo como #include , que es habitualmente la primera línea de un programa en lenguaje C, puede resultar complejo, porque los símbolos de puntuación no estarán donde esperaríamos si manejamos un teclado español, y puede que tengamos que "investigar" donde se encuentra cada uno de esos símbolos.

La altenativa razonable es cambiar la configuración del teclado de nuestro Pi, para que se adapte a un teclado español. Pero eso será dentro de un par de días...  ;-)

25 abril 2012

Google Drive empieza... pero no para todos

Google Drive, el servicio de almacenamiento online de Google, que ofrece 5 Gb de espacio gratuito, ya está en marcha. Para distinguirse de otros servicios como Dropbox, ofrece edición colaborativa de documentos (¿qué diferencias habrá con Google Docs?) además de simple almacenamiento de ficheros.

Pero... todavía no llega a todos. A mí me dice "Tu Google Drive todavía no está lista.". Habrá que esperar para ver si lo que ofrece merece la pena, porque Dropbox (por ejemplo) empieza con menos espacio (2 Gb), pero va dando más espacio libre a medida que otras personas recomendadas por ti van accediendo al servicio, hasta un límite de 16 Gb, más del triple que Google Drive. Si tú tampoco tienes acceso todavía a Google Drive y quieres probar Dropbox para ir entrando en contacto con eso de "dejar cosas" en la nube, aquí tienes una invitación, para poder empezar con 500 Mb extra.

Eso sí, como las cosas en la nube están "al alcance de cualquiera que sea capaz de descubrir tu contraseña", yo tampoco te recomendaría dejar documentos muy privados en cualquiera de estos servicios "en la nube", porque es "casi imposible" que nadie consiga entrar a tu cuenta, pero... sólo casi, especialmente si no tienes mucho cuidado al elegir tus contraseñas e incluso tus antivirus.

29 febrero 2012

Raspberry Pi (casi) a la venta

Oficialmente hoy comienzan las ventas de Raspberry Pi, un primer lote de 10.000 unidades. La información de dónde comprarlo se hacía pública a las 6.00 GMT (7.00 hora española peninsular) en su página oficial.

Finalmente, la distribución es a través de dos grandes cadenas de electrónica con sedes en todo el mundo: RS Componentes y Farnell.  A las 8.15, la segunda de éstas permanecía caída. El interés de la comunidad ha provocado que muchos usuarios accedieran a la vez y desbordara la capacidad de los servidores de estas empresas. Desde la propia Raspberry Pi sí esperaban esta cantidad de accesos simultáneos, y han cambiado momentáneamente su habitual página de inicio en formato de Blog por una página estática.

En este momento, ambas cadenas de componentes permiten sólo decir que se está interesado, pero no comprar. En las conversaciones mantenidas en el twitter de Raspberry Pi se comenta que Farnell ya ha agotado sus existencias y que RS pondrá los equipos a la venta hacia el final de la semana.

Si aún no sabes qué es Raspberry Pi o si quieres intentar reservar uno, aquí tienes los accesos directos a las páginas en ambas tiendas on-line:

En RS componentes:

http://es.rs-online.com/web/generalDisplay.html?id=raspberrypi

y Farnell

http://es.farnell.com/raspberry-pi/raspbrry-pcba/sbc-raspberry-pi-model-b/dp/2081185

Suerte! (pero deja uno para mí también... ;-) )


15 febrero 2012

Java para C# - 06 - Ficheros

Ahora vamos a ver un ejemplo de uso de ficheros en C#, que haga tres operaciones en ficheros:

  • Volcar de un fichero de texto a otro nuevo fichero de texto todas las líneas que cumplan una cierta condición (por ejemplo, comenzar por "A").
  • Contar las veces que aparece un cierto byte (como la letra "A") dentro de un fichero de cualquier tipo.
  • Copiar un fichero de cualquier tipo, usando bloques de 512 Kb de tamaño.

Podría ser así:

using System;
using System.IO;

class Ficheros
{
   
    public static void Main()
    {
        // Volcar a un fichero las líneas de otro (de texto)
        // que empiecen por "A"
        // Errores: sólo se comprueba si no existe el de origen
       
        StreamReader ficheroEntrada;
        StreamWriter ficheroSalida;
        string linea;
       
        if (! File.Exists("ejemplo.txt"))
        {
            Console.WriteLine("No encontrado ejemplo.txt");
            return;
        }
       
        Console.WriteLine("Copiando fichero de texto...");
       
        ficheroEntrada = File.OpenText("ejemplo.txt");
        ficheroSalida = File.CreateText("ejemplo2.txt");

        linea = ficheroEntrada.ReadLine();
        while (linea != null) {        
            if ((linea.Length > 1) && (linea[0] == 'A'))
                ficheroSalida.WriteLine(linea);
            linea = ficheroEntrada.ReadLine();
        }

        ficheroEntrada.Close();
        ficheroSalida.Close();
           
        // ----------------
        // Cantidad de "A" en un fichero de cualquier tipo
        // Mirando errores solo con try-catch
       
        Console.WriteLine("Contando A...");
        int contador = 0;
       
        try
        {
            BinaryReader ficheroEntrada2 =
                new BinaryReader(File.Open("ejemplo.exe", FileMode.Open));
            long tamanyo = ficheroEntrada2.BaseStream.Length;
            for(long i=0; i<tamanyo; i++)
                if (ficheroEntrada2.ReadByte() == Convert.ToByte('A'))
                    contador++;
            ficheroEntrada2.Close();
        }
        catch (Exception errorDeFichero)
        {
            Console.WriteLine(
                "Ha habido problemas: {0}",
                errorDeFichero.Message );
        }

        Console.WriteLine("Cantidad de A: " + contador);
       
        // ----------------
        // Copiar todo un fichero, con bloques de 512 Kb
        // Sin ninguna comprobación de errores
       
        Console.WriteLine("Copiando fichero binario...");
        const int BUFFER_SIZE = 512*1024;
       
        byte[] data = new byte[BUFFER_SIZE];
       
        FileStream ficheroEntrada3 = File.OpenRead("ejemplo.exe");
        FileStream ficheroSalida3 = File.Create("ejemplo2.exe");

        int cantidadLeida;
       
        do
        {
            cantidadLeida = ficheroEntrada3.Read(data,0,BUFFER_SIZE);
            ficheroSalida3.Write(data,0,cantidadLeida);
        }
        while (cantidadLeida == BUFFER_SIZE);
       
        ficheroEntrada3.Close();
        ficheroSalida3.Close();
        Console.WriteLine("Terminado!");
    }
  
}

Al convertir a Java, nos encontramos con unas cuantas diferencias:
  • Para comprobar si un fichero existe, la expresión es un poco más larga, porque hay que crear un objeto de tipo File.
  • Todas las operaciones de ficheros deben ir forzosamente encerradas en un bloque try-catch.
  • Los constructores para acceder a ficheros suelen ser más complicados que en C#. Por ejemplo, para leer un fichero de texto, se usa un BufferedReader, que se apoya en un FileReader, que a su vez se basa en un File que creamos a partir de un nombre de fichero.
  • El uso de ficheros de texto es básicamente igual: intentamos leer una línea, y obtendremos "null" si ya no se ha podido leer ninguna (el fichero ha terminado).
  • Para leer datos de tipo byte hasta el final de fichero, en vez de mirar el tamaño, podemos leer el dato y guardarlo dentro de un "int". Si el valor obtenido es -1, indica que no se ha podido leer (fin de fichero).
  • Para leer bloques y guardar bloques, podemos usar una construcción muy similar a la de C#, indicando el array, la posición y la cantidad de datos.
El resultado podría ser:

import java.io.*;

class Ficheros
{
   
    public static void main( String[] args )
    {
        // Volcar a un fichero las líneas de otro (de texto)
        // que empiecen por "A"
        // Errores: sólo se comprueba si no existe el de origen
               
        if (! (new File("ejemplo.txt")).exists() )
        {
            System.out.println("No encontrado ejemplo.txt");
            return;
        }
       
        System.out.println("Copiando fichero de texto...");
       
        try
        {
            BufferedReader ficheroEntrada = new BufferedReader(
                    new FileReader(new File("ejemplo.txt")));
            BufferedWriter ficheroSalida = new BufferedWriter(
                    new FileWriter(new File("ejemplo2.txt")));

            String linea=null;
            while ((linea=ficheroEntrada.readLine()) != null) {
                if ((linea.length() > 1) && (linea.charAt(0) == 'A'))
                {
                    ficheroSalida.write(linea);
                    ficheroSalida.newLine();
                }
            }

            ficheroEntrada.close();
            ficheroSalida.close();
        }
        catch (IOException errorDeFichero)
        {
            System.out.println(
                "Ha habido problemas: " +
                errorDeFichero.getMessage() );
        }
           
        // ----------------
        // Cantidad de "A" en un fichero de cualquier tipo
        // Mirando errores solo con try-catch
       
        System.out.println("Contando A...");
        int contador = 0;
       
        try
        {
            FileInputStream ficheroEntrada2 =
                new FileInputStream(new File("ejemplo.exe"));
           
            int dato;

            while ((dato = ficheroEntrada2.read()) != -1) {
               if (dato == 65) // Codigo ASCII de A
                    contador++;
            }
            ficheroEntrada2.close();
        }
        catch (Exception errorDeFichero)
        {
            System.out.println(
                "Ha habido problemas: " +
                errorDeFichero.getMessage() );
        }

        System.out.println("Cantidad de A: " + contador);
       
        // ----------------
        // Copiar todo un fichero, con bloques de 512 Kb
        // Sin ninguna comprobación de errores
       
        System.out.println("Copiando fichero binario...");
        final int BUFFER_SIZE = 512*1024;
       
        try
        {
            InputStream ficheroEntrada3 = new FileInputStream(
                    new File("ejemplo.exe"));
            OutputStream ficheroSalida3 = new FileOutputStream(
                    new File("ejemplo2.exe"));
           
            byte[] buf = new byte[BUFFER_SIZE];
            int cantidadLeida;
            while ((cantidadLeida = ficheroEntrada3.read(buf, 0, 
                    BUFFER_SIZE)) > 0) 
          {
                ficheroSalida3.write(buf, 0, cantidadLeida);
            }
            ficheroEntrada3.close();
            ficheroSalida3.close();
        }
        catch (Exception errorDeFichero)
        {
            System.out.println(
                "Ha habido problemas: " +
                errorDeFichero.getMessage() );
        }
  
        System.out.println("Terminado!");
    }
}

Como siempre, si tienes dudas, ya sabes: usa los comentarios o el foro de Java de AprendeAProgramar.