21 ene 2013

¿Cursando Fundamentos de programación en la UNED? Tengo un regalo para tí. Parte 3 y última

Pues después de mucho batallar y gracias a la inestimable ayuda de compañeros que me han resuelto dudas en el foro y de otra persona que sabrá perfectamente quién es cuando lo lea, he conseguido terminar esta última práctica. Como buen español, dejándolo para el final. Espero que, aunque sea bastante tarde os sirva. Estoy bastante cansado, así que, sin más, cuelgo el enlace
Práctica 4

19 ene 2013

Borrador práctica 4 de fundamentos de programación

Hola a tod@s. Como muchos de los que habéis seguido este blog sabréis, he ido incluyendo aquí los resultados de las prácticas de fundamentos de programación. Antes de incluirlas, siempre me había cerciorado bien de que estuviesen correctas (aunque no optimizadas). Sin embargo, debido al gran retraso que llevo con esta 4º y última, y tras dedicarle bastante tiempo sin obtener ningún resultado satisfactorio, he decidido colocar un borrador de mi estado actual. Lo comento aquí y luego añado el código.
La idea es tener un programa principal que se ejecuta continuamente hasta que se pulsa la opción salir. Para la gestión de las reservas utilizo tipos de datos definidos. Un tipo de datos denominado "TipoReserva" que contiene la "sala" (tipo int), la "fecha" (otro tipo definido formado por 3 tipos int) y el nombre de la "persona" que la realiza. Como podemos realizar hasta 100 reservas, pues creo he creado un tipo de datos llamado "TipoVectorReservas" que simplemente consta de 100 "TipoReserva". Cuando quiero introducir una reserva, hago que la información (previamente comprobada) se almacene en ese vector. Si quiero eliminar una reserva, leo los datos de la reserva a eliminar y la elimino de ese "vectorReservas". Por último, si quiero listar las reservas de un determinado mes, leo los datos necesarios y los paso como argumento a una función llamada ImprimirCalendario. Hubo momentos en los que he conseguido compilar el código y comprobé que obtenía resultados, no los esperados, pero resultados. Sin embargo debí hacer alguna modificación y desde entonces soy incapaz. 
Siento no haber podido colgarla ya funcionando correctamente. De cualquier forma espero que os pueda servir.
Borrador de la práctica
Actualización: He estado modificando y tratando de limpiar el código y creo que el nuevo borrador que tengo parece mejor, aunque sigo obteniendo errores de compilación que no consigo resolver. Podéis encontrarlo aquí
Borrador 1 de la práctica

8 ene 2013

El coche con control remoto usando Arduino ya está aquí

Ya he hablado de diferentes elementos y cómo utilizarlos con nuestro Arduino. Experimentos con un sensor de distancias, con un receptor de infrarrojos para la comunicación, arranque, parada e inversión de giro en motores... Todo ello destinado a utilizarlos en el coche que hoy os muestro. Ha sido una larga espera hasta tener a disposición todos los elementos necesarios (ya que la gran mayoría proceden de China), sin embargo, el montaje y programación han resultado sencillos. Ahora que tengo un mejor conocimiento de Arduino, puedo decir que me ha impresionado su sencillez, gracias en buena parte al gran trabajo de la gran comunidad que tiene detrás y que proporciona librerías, documenta proyectos... Y hubiese sido más sencillo y rápido la construcción de éste coche de haberme percatado antes de los problemas que provocaban un funcionamiento incorrecto, ésto es, el ruido generado por los motores y la utilización de una sola fuente de alimentación para el circuito.
El aspecto final del coche se muestra a continuación

Aspecto final del coche con control remoto

En la siguiente imagen podéis apreciar también el mando que utilizo para controlarlo
Conjunto de mando a distancia y coche

Por último mostraros una vista más detallada del frontal del vehículo, en el que se puede apreciar el servo sobre el cuál reside el sensor de distancia
Parte frontal del coche en la que se encuentra el servo y el sensor de distancias

Y una última que muestra las conexiones de la placa de prototipos
Placa de prototipos con las conexiones realizadas
El funcionamiento es el siguiente:
Con el mando a distancia podemos enviar diferentes señales en función del botón pulsado. Estas señales son leídas utilizando el receptor de infrarrojos e interpretadas por Arduino, para realizar la acción oportuna. Las diferentes acciones son (por ahora), avance recto, avance recto lento, giro a derechas y giro a izquierdas. Esto se consigue controlando individualmente la velocidad de cada uno de los motores (mediante PWM). Al mismo tiempo, cuando el vehículo se encuentra en movimiento, el sensor de distancia chequea si hay algún objeto cercano, en cuyo caso, para evitar la colisión, se procede a tomar la decisión de modificar el sentido de avance del coche. Como el sensor de distancias "ve" a los objetos que tiene justamente enfrente (tiene un ángulo de visión pequeño), se ha optado por colocarlo encima de un servo que permita girarlo, haciendo un barrido en función del sentido del movimiento del coche. Todas estas acciones se pueden ver en el vídeo a continuación
El código utilizado para lograr todo esto es:

/*Proyecto ArduinoCar utiliza un mando a distancia convencional para 
controlar remotamente un coche a escala con Arduino. Para el movimiento
del coche se utilizan motores independientes en la rueda izquierda (control
de la rueda conectado al pin 5) y la rueda derecha (control conectado al 6)
*/
//Libreria para comunicacion por infrarrojos
#include <NECIRrcv.h>
//Libreria para el sensor de distancias
#include <Ultrasonic.h>
//Libreria para el servo
#include <Servo.h>
//Pin al que se conecta el receptor infrarrojos
#define IRPIN 7
//Codigos del mando a distancia
#define OFF 3877142272
#define ON 4278222592
#define UNO 3893853952
#define DOS 3910565632
#define TRES 3927277312
//Inicializacion del sensor de ultrasonidos (trigger, echo)
Ultrasonic ultrasonic (8,9);
//Inicializacion del receptor infrarrojos
NECIRrcv ir(IRPIN);
//Inicializacion del servo
Servo servo;
//Variables globales a utilizar
unsigned long ircode;
unsigned long codigo;
//Setup inicial
void setup() {
  ir.begin() ;
  pinMode(5,OUTPUT);
  pinMode(6,OUTPUT);
  //Control del servo conectado al pin 13
  servo.attach(13);
  servo.write(90);
}
//Bucle que se ejecutara continuamente
void loop() {
  //Si hay datos recibidos desde el control remoto, los capturamos
  while (ir.available()) {
    ircode = ir.read();
    //Dependiendo del boton pulsado realizamos una determinada accion
    switch (ircode){
    case OFF:
    //Paramos el coche
    codigo=OFF;
    digitalWrite(5,LOW);
    digitalWrite(6,LOW);
    //El servo apunta al frente
    servo.write(90);
    break;
    case ON:
    codigo=ON;
    //El coche avanza recto
    digitalWrite(5,HIGH);
    digitalWrite(6,HIGH);
    servo.write(90);
    break;
    case UNO:
    //El coche tuerce a la izquierda
    codigo=UNO;
    analogWrite(5,160);
    digitalWrite(6,HIGH);
    //El servo apunta a la izquierda
    servo.write(150);
    break;
    case DOS:
    //El coche avanza recto a menor velocidad
    codigo=DOS;
    analogWrite(5,200);
    analogWrite(6,200);
    servo.write(90);
    break;
    case TRES:
    //El coche tuerce hacia la derecha
    codigo=TRES;
    analogWrite(6,160);
    digitalWrite(5,HIGH);
    //El servo apunta a la derecha
    servo.write(30);
    break;
    }
  }
  //Si detecta algun obstaculo a menos de 20 centimetros
  if (((ultrasonic.Ranging(CM))<=20) && (codigo!=OFF)){
    if (codigo==UNO){
      //Si el coche estaba torciendo hacia la izquierda, comienza a girar a la derecha
      digitalWrite(5,HIGH);
      digitalWrite(6,LOW);
      delay(200);
      //Devuelve el estado que tuviese
      analogWrite(5,160);
      digitalWrite(6,HIGH);
    }else if (codigo==TRES){
      //Si el coche estaba torciendo hacia la derecha, comienza a girar a la izquierda
      digitalWrite(5,LOW);
      digitalWrite(6,HIGH);
      delay(200);
      analogWrite(6,160);
      digitalWrite(5,HIGH);
    }else if (ircode==ON || ircode==DOS){
      //Si el coche avanzaba recto, realiza un giro mayor
      digitalWrite(5,LOW);
      digitalWrite(6,HIGH);
      delay(400);
      if (ircode==ON){
        digitalWrite(5,HIGH);
        digitalWrite(6,HIGH);
      }else {
        analogWrite(5,200);
        analogWrite(6,200);
      }
    }
  }
}

Por último comentar que tengo previsto introducir varias mejoras, alguna de ellas creo que bastante interesantes. La primera de ellas pasa por incluir la posibilidad de inversión de giro (aún no disponible debido a falta de componentes), la segunda consiste en añadir otro tipo de comunicación remota, bien por bluetooth o bien por radiofrecuencia, ya que la comunicación infrarroja tiene bastantes limitaciones y un último proyecto en el que Arduino utiliza sistema GPS para realizar un trazado de forma autónoma. Os mantendré informados...

7 ene 2013

Ubuntu para smartphones próximamente

Con algo de retraso os hago llegar (si es que no lo sabíais) ésta noticia que tan interesante me ha resultado. Ubuntu está trabajando en llevar su sistema operativo a los teléfonos inteligentes (smartphones). 
Aspecto visual de Ubuntu phone OS
Ya habíamos visto a Ubuntu for Android, que utilizaba un dock para correr la versión de escritorio de Ubuntu en nuestro Android. Ahora van un paso más allá y crean un sistema operativo dedicado a smartphone, en el que los gestos son la clave para acceder a todo lo que deseemos. 
En el siguiente vídeo podéis ver una demo de Ubuntu phone OS

Y en éste podéis ver la presentación de Mark Shuttleworth (inglés)
La noticia de Ubuntu for phones me parece sorprendente, ya que supondría poder tener una misma plataforma para televisión, ordenador, servidor, tablet y smartphone, algo hasta ahora nunca visto.
Mi opinión personal sobre Ubuntu es que está evolucionando a un ritmo muy bueno, aunque las últimas versiones resultaban pesadas para mi pequeño netbook, por lo que decidí pasar a Lubuntu. Sin embargo, leyendo en la wiki de ubuntu respecto a Nexus 7, parece que tienen previsto revisar el núcleo para hacer Ubuntu más rápido, ligero y con un menor consumo de recursos. BRAVO. Creo que esto podría ser un punto clave para hacer un buen sistema operativo para smartphones, aunque también necesitarán desarrolladores y fabricantes que cooperen. La tarea se antoja difícil, pero yo ya me estoy imaginando lo que puede suponer tener un smartphone con Ubuntu, sería tener un ordenador en la palma de mi mano.

5 ene 2013

Interfaces de comunicación SPI, I2C, UART...

Para alguien que comienza a utilizar Arduino puede resultar algo complejo entender las diferencias entre los diferentes tipos de interfaces de comunicación (y protocolos asociados). Existe mucha información relativa a cada protocolo, pero entender la relación que existe entre ellos quizá no sea trivial. Es por esto que me parece adecuado resaltar unos comentarios que he leído en un foro. El enlace podéis encontrarlo aquí. Esta vez me voy a tomar la molestia de traducirlo (algo resumido), ya que se encuentra en inglés.
capcom pregunta: Como aficionado novel a la electrónica, he oído los términos USART, UART, RS232, USB, SPI, I2C, TTL, etc. Entiendo que están basados en comunicación entre dispositivos, ordenadores, periféricos, etc. Tengo conocimientos básicos sobre cómo trabajan, pero tengo dificultad entendiendo cómo están relacionados. Por ejemplo, ¿es UART un subconjunto de USART? ¿Cuál es la diferencia entre RS232 y Serial?
Pregunta a la cuál, un tal stevenh, que en mi opinión parece bastante entendido en la materia, responde:
Serial es la palabra clave de todo lo que es "multiplexación de la división temporal". Indica que el dato es enviado en función del tiempo, un bit detrás de otro. Todos los protocolos que has nombrado son protocolos serie. 
UART (recepción-transmisión asíncrona universal) es uno de los protocolos serie más utilizados. La mayoría de los controladores disponen de hardware UART. Usa una línea de datos simple para transmitir y otra para recibir datos. Comúnmente, 8 bits de datos son transmitidos de la siguiente forma: un bit de inicio, a nivel bajo, 8 bits de datos y un bit de parada a nivel alto. El bit de inicio a nivel bajo y el de parada a nivel alto indican que siempre hay una transmisión de alto a bajo para iniciar la transmisión. Eso es lo que describe a UART. Puedes utilizarlo a 3.3V ó 5V, dependiendo de lo que tu microcontrolador use. Note que los microcontroladores que quieren comunicarse via UART tienen que fijar la velocidad de transmisión, la tasa de bits, ya que sólo disponen del bit de flanco de bajada para sincronizar. Esto es llamado comunicación asíncrona.
Para largas distancias de comunicación, utilizar 5V en UART no es fiable, por lo que es convertido a un voltaje más alto de +12V para un 0 lógico y -12V para un 1. El formato de datos se conserva. Es entonces cuando tienes RS-232.
La dependencia de la coordinación es uno de los puntos negros de UART, y la solución es USART (recepción-transmisión síncrona/asíncrona universal). Puede actuar igual que UART, pero también como un protocolo síncrono. Sincronización de datos, pero también del reloj. En cada pulso de reloj se indica al receptor que capte el bit. Los protocolos sincronizados, por contra, necesitan un mayor ancho de banda, como en el caso de Manchester encoding, o de una conexión extra para el reloj, como es el caso de SPI o I2C.
SPI es otro protocolo serie muy simple. Un maestro envia la señal de reloj, y tras cada pulso de reloj envía un bit al esclavo y recibe un bit de éste. Los nombres de las señales son por tanto SCK para el reloj, MOSI para el Maestro Out Esclavo In, y MISO para Maestro In Esclavo Out. Para controlar más de un esclavo es preciso utilizar SS (selección de esclavo).
I2C es un protocolo síncrono, y es el primero que vemos con algo "inteligente". I2C usa solo 2 cables, uno para el reloj (SCL) y otro para el dato (SDA). Esto significa que el maestro y el esclavo envían datos por el mismo cable, el cuál es controlado por el maestro, que crea la señal de reloj. I2C no utiliza selección de esclavo, sino direccionamiento. El primer byte enviado por el maestro se forma de 7 bits para la dirección (así que permite comunicarse con hasta 127 dispositivos) y un bit de lectura/escritura, indicando si el proximo byte vendrá desde el maestro o el esclavo. Tras cada byte recibido se envía una confirmación con el noveno pulso de reloj. Si el maestro quiere recibir datos solo genera pulsos de reloj. El esclavo tiene que cuidar que el próximo bit esté listo cuando la señal de reloj es dada.
Dos o más señales a través del mismo cable pueden causar conflicto, y ocurrirían problemas si un dispositivo envía un 1 lógico al mismo tiempo que otro envía un 0. Por tanto el bus es "cableado" con dos resistencia para poner el bus a nivel alto, y los dispositivos envían niveles bajos. Si quieren enviar un nivel alto simplemente lo comunican al bus.
TTL no es un protocolo. Es una vieja terminología para lógica digital, pero el nombre es a menudo utilizado para referirse a 5V de alimentación.
Reseñar que el protocolo TWI es I2C. El nombre TWI  es utilizado a veces (en la web de Arduino, por ejemplo), pero significan lo mismo.
Ejemplos de dispositivos que utilizan este protocolo son unos módulos que, conectándolos a un display lcd, permiten controlarlos por comunicación serie, ahorrando considerablemente el número de salida de Arduino necesarias. 

2 ene 2013

Reducción del ruido eléctrico generado por los motores

Una de las principales razones por la que adquirí Arduino fue la de poder realizar proyectos electrónicos físicamente (y sin mucho gasto). Y ciertamente creo que estoy aprendiendo mucho, ya que un proyecto real te permite contrastar los conocimientos teóricos y comprobar que, muchas veces, existen imprevistos que no han sido tenidos en cuenta. Éste ha sido mi caso cuando he comenzado a montar y programar el coche con control remoto. 
Resulta que probando cada uno de los componentes por separado (motor, recepción infrarroja, servomotor y sensor de distancias) todo funcionaba a las mil maravillas, así que era de esperar que a la hora de juntarlo todo también fuese a funcionar. Nada más lejos de la realidad. En cuanto ponía los motores en funcionamiento, era incapaz de llevar a cabo control remoto e incluso la propia tarjeta arduino parecía tener un comportamiento extraño. Mi primera explicación pasaba por un fallo en la programación, pero todo parecía correcto, posteriormente pensé que quizá no tuviese suficiente alimentación, lo cuál también descarté y así anduve buscando posibles errores hasta que me percaté de la posibilidad de que fuesen los propios motores los que introdujesen en el propio circuito un ruido eléctrico. Encontrado el error llegó la hora de buscar soluciones. Para ello hay varias, desde muy sencillas hasta algo más complejas. El artículo que más me ha interesado con posibles soluciones lo podéis encontrar aquí (también me parece interesante éste otro). En el podemos ver cómo colocar condensadores en los terminales del motor, existiendo diferentes configuraciones, cada una de las cuales proporciona un nivel de filtrado diferente. También hay que tener muy presente el tratar de utilizar cables de mucha sección y poca longitud, así como utilizar alimentaciones diferentes para señales y potencia (utilizar alimentación diferente para Arduino y motores).