Uso de MSP430 para fotografía secuencial

Lector de la-tecnologia [onefivefour] tenía una vieja cámara clave VistaQuest VQ1005 dando vueltas y quería hacer algo útil con ella. Anteriormente registró un temporizador 555 e hizo algunas fotografías de lapso de tiempo, pero quería tener más control del proceso. Específicamente, quería la capacidad de ajustar la demora entre disparos en un modo más granulado, así como una forma de evitar que VistaQuest se duerma después de estar inactivo durante 60 segundos.

Su arma elegida para realizar esta tarea fue la MSP430, porque el microcontrolador se puede encontrar bastante barato y porque es relativamente fácil de usar. Agregó algunos pines de cabeza a la placa LaunchPad para conectarlos al disparador de la cámara, así como al interruptor de encendido / apagado. Cuando el cable conectado al gatillo se tira hacia abajo, la cámara toma una fotografía. El cable conectado al interruptor / interruptor siempre se mantiene bajo, lo que garantiza que la cámara esté encendida y lista para funcionar cuando sea el momento de disparar.

Es un proyecto relativamente simple, pero ciertamente útil. Aunque hay muchas formas de construir un intervalómetro, el MSP430 es una gran plataforma para usar, especialmente para principiantes.

Quédese para ver un video rápido [onefivefour] juntos, mostrando las capacidades de su plataforma de lapso de tiempo.


  • Adán dice:

    Neto. Sin embargo, estoy un poco confundido, ¿esto presiona mecánicamente el botón?

    • un quinto dice:

      No presiona un botón mecánicamente; se hace electrónicamente. El cable "T" se mueve de 3V a 0VDC usando el LaunchPad MSP430.

  • Daniel dice:

    Buen trabajo ... y por cierto: Hermosos gatitos 😉

  • Sebastiano dice:

    Hola,

    También pirateé una cámara (a través de Arduino) y la puse en una plataforma de giro e inclinación:
    http://www.zipfelmaus.com/arduino-pantilt-system/

    Puede tomar imágenes de tiempo transcurrido e imágenes de ultra megapíxeles (panoramas).
    Sebastiano

  • pantalones dice:

    Proyecto ingenioso. Desafortunadamente, el código es "Todos los derechos reservados" y no tiene licencia, por lo que no se puede reutilizar aunque diga "Modifíquelo si lo desea". Concédale una licencia abierta como GPLv3 o Creative Commons. ¡Gracias!

    • un quinto dice:

      Tienes razón. Editaré el código para eliminar "todos los derechos reservados".
      Gracias por el comentario.

      [onefivefour]

  • Semanas dice:

    ^^^^^^^^^^^
    Eso suena a Stallman .. 🙂

    Semanas

  • F dice:

    Cosas que el autor podría hacer mejor:
    1) Explique mejor las ubicaciones del laúd (no tengo la cámara, así que no sé qué tan obvio es)
    2) Obtenga la terminología correcta (el MSP430 es solo el MCU, mientras que en el artículo, el Launchpad se llama constantemente "el MSP430".
    3) Proporcione un código de trabajo. La inclusión falta parcialmente y el último de un bucle no tiene una cabeza correcta.

    Este es un proyecto de MCU muy básico, pero desafortunadamente, este es solo el primer programa básico que le gustaría escribir para el MSP430. Veo dos puntos para mejorarlo:
    Primero, algunas cosas conceptuales. Actualmente, si hago esto bien, la cámara se encenderá al comienzo del bucle cada vez que se tome una imagen, pero no se apagará después de tomar una imagen. Debido a que hay mucho tiempo entre imágenes y la cámara utilizará una gran cantidad de energía en comparación con todo lo demás, el primer paso es encender la cámara, tomar una foto y luego apagarla, y solo entonces esperar a la siguiente imagen.
    Entonces, todo el asunto del MSP430 tiene que ver con el bajo consumo. Generalmente, para cualquier código MSP430, no desea que su procesador se ejecute realmente. Eso significa hacer algunas preguntas: (a) SI necesita funcionar, ¿a qué frecuencia necesita funcionar? ¿Realmente necesita operar a una frecuencia alta o puede ahorrar tiempo y operarlo a una frecuencia más baja? Baja frecuencia = menor potencia y debido a que el sistema de reloj del MSP430 es flexible, puede saltar fácilmente entre los relojes de la CPU en casi cualquier lugar de su código. (b) ¿Realmente necesita funcionar? La mayoría de las instrucciones del código aquí se resumen para esperar. El procesador no hace más que desperdiciar ciclos de reloj. Dado que la cantidad de ciclos que tiene que esperar es lo suficientemente grande, la mejor manera de hacerlo es cronometrar el temporizador desde una fuente de reloj lenta, apagar la CPU y disparar una interrupción del temporizador para cambiar el estado de una máquina de estado y luego despertar hasta. la CPU para cambiar los pines. Hay información sobre la optimización de bajo consumo en el sitio web de la plataforma de lanzamiento.
    Por supuesto, la desventaja es tener que cambiar la forma en que parpadean los LED, pero son solo indicadores de que algo está sucediendo, así que supongo que está perfectamente bien hacerlos parpadear una vez cada dos segundos aproximadamente. luego sea compatible con técnicas de optimización de bajo consumo (por ejemplo, podría usar el WDT para hacer parpadear los LED).

    • un quinto dice:

      [onefivefour] aquí… ..

      Todos los trucos y proyectos pueden usar mejoras. Solo soy un estúpido que quiere ser un programador con un pasatiempo geek, así que siéntete libre de modificar y ajustar el proyecto según tus necesidades.

      Gracias por revisar mi truco.

      • F dice:

        (Con suerte, el sistema de comentarios aquí puede aceptar este comentario bastante largo).
        Creo que la optimización de baja potencia es importante. Usted es un aficionado, parece ser lo suficientemente inteligente como para descubrir cómo programar el MSP430, por lo que realmente no hay excusa para no intentar optimizar su programa.
        Al principio, no pude ejecutarlo, así que adiviné sobre las instrucciones que faltaban y el tiempo estaba completamente perdido. Es una pena, porque realmente me hubiera gustado usar su programa y convertirlo en algo que necesite mucha menos energía. Sin embargo, lo usé como guía para redefinirlo, por lo que no se perdió mucho.

        Algunos consejos: Al programar, definitivamente necesita la Guía del usuario familiar (SLAU144). Sin él, estás completamente indefenso. Contiene todas las configuraciones de registro que necesita saber, pero tenga en cuenta que el MSP430 es una gran familia de dispositivos, por lo que hay muchas, muchas funciones que se describen en la guía de la familia, pero que no son en absoluto válidas para el MSP430G2231. . ¡Y esa es solo la guía para la serie MSP430x2xx!

        Entonces, en primer lugar, una breve lista de algunos conceptos importantes de operación de baja potencia. Un procesador necesita un reloj para funcionar. Un reloj más alto significa un funcionamiento más rápido, pero también requiere más energía. Por lo general, uno no puede realmente decidir sobre el reloj tanto como quisiera, muy probablemente porque el sistema de reloj es un poco inflexible o uno necesita algún componente para ser lo más responsable y rápido posible (por ejemplo, para la comunicación). El MSP430 tiene un sistema de reloj bastante flexible que permite sintonizar el oscilador interno sobre la marcha. Una cosa importante a considerar es la velocidad del reloj. ¿De verdad necesitas ser tan rápido? Si no lo hace, baje el reloj, ahorrará toneladas de energía.
        Entonces, mirando su aplicación, que realmente no hace nada crítico con el tiempo y solo coloca algunos pines, puede ser bastante radical y configurar el reloj en su configuración más baja. Hice algunas mediciones de etapa en mi lanzador con un programa en bucle inactivo con la configuración en la que se inició el MSP430G2231 (por lo que ahora las técnicas de baja potencia como configurar pines no utilizados en salidas, etc., por lo que el consumo de energía ahora será exagerado, pero para el debido a la comparación, eso realmente no importa). Cuando se ejecuta a 1 MHz "calibrado", utiliza aproximadamente 420 µA. Funcionando a 16 MHz (o más bien 15,96 MHz), usó alrededor de 4,93 mA. Funcionando a 102 kHz, la configuración de DCO más lenta que se puede lograr, dio un consumo de energía de aproximadamente 120 µA. Entonces, lo primero es configurar el reloj en la configuración más baja:
        DCOCTL = 0;
        BCSCTL1 & = ~ (RSEL3 + RSEL2 + RSEL1 + RSEL0);

        Cuando haces cosas en ráfagas y la CPU está encendida solo por un tiempo muy corto, como lo haremos nosotros, en realidad podría ser mejor configurar el reloj en el "punto óptimo" MIPS / W. Puede experimentar con diferentes configuraciones de reloj para averiguarlo.

        La siguiente técnica general en la programación de MCU en general, pero esencial para problemas de bajo consumo, son las máquinas de última generación. Básicamente, desea escribir programas que tengan "estados" en los que se encuentran y una forma de cambiar entre estados. Es difícil de explicar, pero su programa ya está escrito pensando en los estados.
        Estos son: (1) Encienda la cámara (2) Suelte el interruptor de la cámara (3) Encienda la imagen (4) Suelte el gatillo
        Las transiciones entre estados pueden ser cosas complicadas, como que los usuarios presionen botones o nuevos datos provenientes de una interfaz de comunicación, pero en su caso, las transiciones ocurren si ha pasado suficiente tiempo. Ahora, la clave para estructurar su programa para que sea una máquina de estado es que si el programa real en el estado ha terminado, solo tiene que esperar el evento que desencadenará la transición al siguiente estado. Y esperar sin tener que hacer nada es genial, porque entonces puede poner la MCU en modo de bajo consumo y activarla tan pronto como se produzca la transición. Su código espera MUCHO, por lo que la optimización de bajo consumo será especialmente útil allí.

        Ahora, ¿cómo afrontas el problema? Primero, organice su programa en estados. Eso es bastante sencillo. Necesitamos los cuatro métodos descritos anteriormente y una nueva variable para mantener el estado actual:

        boot_photo vacío (); // será el estado 0
        vacío release_on_switch (); // será el estado 1
        disparador_imagen vacío (); // habrá estado 2
        void release_trigger (); // habrá estado 3
        estado de char volátil = 0;

        Los métodos ahora se ven así. Puede averiguar los métodos restantes, pero en release_trigger (), el siguiente estado, por supuesto, será 0:
        trigger_image vacío () {
        P1OUT & = ~ BIT5; // Señal de activación de la unidad baja para tomar una foto
        estado = 3; // estado previo
        // Un poco de retraso para procesar la imagen, guardar en la tarjeta SD, etc.
        }

        Todavía necesitamos agregar el retraso. Por supuesto, podríamos usar los bucles del código original, pero eso desafiaría el objetivo de bajo consumo, por lo que necesitamos algo más. El MSP430 tiene un periférico temporizador / contador que aumentará su registro de valor cada vez. También puede configurar una interrupción para que se active cuando se alcance un valor específico. Debido a que sabemos qué tan rápido el temporizador aumenta su registro, podemos usar este mecanismo para esperar una cantidad de tiempo específica. Si el temporizador es lento, puede ser bastante grande. Ahora la idea es dejar que el procesador duerma casi todo el tiempo y luego ser despertado por la interrupción del temporizador, luego hacer las cosas en el estado en el que se encuentra, luego establecer el siguiente valor del temporizador para iniciar una interrupción y luego volver a dormirse. Suena complicado, pero no lo es.

        Primero tendremos que hacer las cosas aburridas, es decir, poner los relojes y separadores y qué no exactamente. Esto puede ser una verdadera molestia. Según su código, parece que con unos 5 minutos de tiempo entre imágenes será suficiente. Obtendremos el temporizador del VLO del MSP430, que funciona a unos 12 kHz. El mío funciona a alrededor de 10,4 kHz, pero si necesita estar en lo cierto sobre el reloj, albergar el cristal de reloj de 32 KiHz es probablemente una mejor idea. El temporizador aceptará la entrada de reloj de todo, por lo que también podríamos usar MCLK o SMCLK, pero mirando los modos de bajo consumo, solo ACLK no se apagará en LPM3.

        Lo que sigue ahora lleva mucho tiempo para buscar cosas en la guía del usuario familiar, medir las salidas del reloj para estar seguro, etc., así que solo describiré lo que es importante. Idealmente, queremos que todo nuestro retardo se ajuste dentro de los 16 bits proporcionados por el temporizador. Por lo tanto, no tenemos que escribir software para "extender" el valor del temporizador a más de 16 bits. El tiempo más largo que tendremos que esperar es de unos 5 minutos, así que veamos si podemos encontrar una manera de hacerlo fácilmente. El temporizador puede contar hasta 65535, por lo que tiene 65536 valores. ACLK es de aproximadamente 12 kHz y se puede dividir aún más por 1, 2, 4 u 8 por el sistema de reloj. Si usáramos ACLK directamente, obtendríamos una interrupción redundante del temporizador cada 5.4 segundos. Entonces, lo dividimos por 8 y obtenemos nuestro nuevo ACLK de 1500 Hz. Esto tardará unos 44 segundos en activar una interrupción redundante del temporizador. En lo que respecta al sistema de reloj, esto es tan lento como llegará a ser. Pero el periférico temporizador en sí tiene otro divisor de reloj personalizable: el reloj de entrada se puede dividir por 1, 2, 4 u 8 nuevamente. Si usamos 8 como separador allí, obtenemos aproximadamente 349.5 segundos hasta que el temporizador se desborde, que es aproximadamente 5 minutos y 50 segundos y, por lo tanto, absolutamente ideal para nuestro propósito.

        Entonces, el código:
        // aklk:
        BCSCTL3 = LFXT1S_2; // seleccione VLOCLK como ACLK
        BCSCTL1 | = IVA_3; // split ACLK / 8 -> ACLK ahora está alrededor de 1500 Hz

        // ajuste del temporizador
        TACCTL0 = CCIE; // habilitar captura / comparar interrupción
        TACCR0 = 5 * KOMBRAJ_PER_S; // espera 5 segundos para comenzar, solo porque
        TACTL = TASSEL_1 + ID_3 + MC_1; // seleccione ACLK como fuente de reloj; dividir la entrada entre 8; contar (iniciar temporizador)
        // entonces, el temporizador necesita 65536 / ((12000 Hz / 8) / 8) = 350 s para un desbordamiento

        Ahora solo tenemos que configurar el temporizador. Esto es un poco confuso y solo puedo recomendar mirar muchos códigos de muestra y leer los talleres y tutoriales que TI publicó en algún lugar de su sitio web (por ejemplo, http://processors.wiki.ti.com/index.php/Getting_Started_with_the_MSP430_LaunchPad_Workshop).
        El TimerA puede disparar tres interrupciones: Capture / Compare0, Capture / Compare1 y Overflow. Usamos la interrupción Capture / Compare0 aquí, por lo que debe habilitarse configurando TACCTL0 = CCIE;
        Para facilitar el desarrollo del código, recomiendo poner algunas definiciones en la parte superior del código. Definí el número de cálculos por segundo que hará el temporizador y el intervalo entre imágenes (no es realmente el intervalo entre imágenes, sino más bien el tiempo que esperará la MCU entre haber terminado de tomar la imagen en el estado 3 y comenzar en el estado 0 nuevamente) :
        #define COUNTS_PER_S 187.5
        // COUNTS_PER_S = número de conteos que el temporizador aumenta en 1 segundo
        #define SECONDS_BETWEEN_PICTURES 30

        Ahora, configuramos el registro de comparación de captura de TimerA 0 (para Capture / Compare0) en 5 * COUNTS_PER_S, por lo que el temporizador creará la primera interrupción 5 segundos después de que se inició, lo que hacemos solo por diversión. TACTL está configurado para usar ACLK como fuente de reloj, dividir la entrada de reloj entre 8 y contar hasta que se alcance el valor en CCR0, luego reiniciar el contador a 0. De esa manera no obtendremos interrupciones innecesarias.

        Entonces, ¿qué más necesitamos? Decidamos la interrupción del temporizador. Podrías hacer todo tipo de locuras allí, incluido el manejo de los estados de la máquina de estados, pero supongamos que no quieres hacer eso. Solo queremos que la interrupción del temporizador despierte al procesador del estado de bajo consumo de LPM3, por lo que la interrupción del temporizador es simplemente:
        #pragma vector = TIMERA0_VECTOR
        __stop void Timer_A () {
        _bic_SR_registro_sur_eliro (LPM3_bits); // simplemente se despierta de LPM
        }

        Casi hemos terminado con el código, lo único que queda es algún tipo de estructura para unirlo todo, enviar la MCU a una operación débil y realmente llamar a los métodos según el estado actual. Hacemos esto en el clásico bucle while:
        dum (1) {
        _bis_SR_registro (LPM3_bits + GIE); // ingresa LPM3 + interrupciones;

        cambiar (estado) {
        caso 0:
        button_photo ();
        rotura;
        caso 1:
        release_on_switch ();
        rotura;
        caso 2:
        trigger_image ();
        rotura;
        caso 3:
        release_trigger ();
        rotura;
        por defecto:
        rotura;
        }
        }

        _bis_SR_registro (LPM3_bits + GIE); habilitará interrupciones (GIE) y establecerá LPM3. Después de esta línea, el procesador básicamente se detiene y solo será despertado por la interrupción del temporizador. Después de eso, decidimos qué hacer a continuación en función del estado, que hasta ahora debería ser algo autoexplicativo.

        Por supuesto, esa no es la única forma de escribir código, ni probablemente sea la mejor forma. Usa tu estilo y tu experiencia para hacer las cosas de manera diferente.

        Entonces, ¿qué falta ahora?
        - LEDs parpadeantes como en el código original. Esto se puede lograr con el WDT, pero no tengo el valor de entrar en eso ahora mismo. Probablemente más tarde, si habrá algún interés.
        - Optimización de potencia incluso menor. Conectaría todos los pines no utilizados a VCC o GND externamente, luego habilitaría la resistencia interna de subir / bajar y sacarlos. De esa forma, no captarán señales ni cambiarán. No hice eso porque es complicado hacerlo en el Launchpad, ya que requiere un montón de cables. Sin embargo, no habría mucho problema en un pantab o en un circuito.

        Pues aquí lo tienes. En realidad, optimizar su código no es difícil, es bastante fácil. Seguro, las primeras veces que lo hagas te llevará años, pero si estructuras tus programas correctamente, tomará cada vez menos tiempo y podrás hacer más cosas mucho más rápido. Por ejemplo, su código no contenía una fórmula real para calcular el tiempo entre imágenes, por lo que fue una suposición aproximada. Usando temporizadores con una fuente de reloj definida (el VLO podría calibrarse con MCLK o incluso con el cristal de 32 KiHz), pero ahora puede ajustar fácilmente el tiempo entre imágenes con una resolución de aproximadamente 5 ms (dependiendo de la frecuencia real del VLO, por así decirlo). preciso, debes medirlo).

        -F.

    • un quinto dice:

      En cuanto a la declaración "incluir" en el blog. Debido a que está rodeado por "", no se mostró. Puede enviar un correo electrónico a Google y decirles que trabajen en él ... Tampoco soy un desarrollador web HTML profesional. 😉

      Quité el. Cualquiera que tenga la ambición de probar el proyecto descubrirá lo obvio con bastante rapidez.

      • Borroso dice:

        Bela hako! Configuré algo similar para intentar capturar el gran evento del eclipse (pero desafortunadamente no hay resultados para mostrar debido a $ # @! @ Weather).

        Usé el pin de salida para activar un relé sensorial de bajo voltaje. Sé que esto probablemente sea excesivo, podría usar un transistor, etc ... pero me gustó la idea de que el disparador de la cámara esté en su propio circuito aislado. No soy un tipo de electrónica, así que apunté a lo que se sentía seguro en lugar de lo que tendría sentido para la ingeniería.

        De otras experiencias de programación con Launchpad, creo que la mejor manera de lidiar con esto para el bajo consumo de energía es usar interrupciones activadas por el VLO. Utilice el reloj interno y salte el oscilador externo. También configure una interrupción para el P1.3 para cambiar los modos. Supongo que aquí podría crear creatividad, pero tal vez usando una resistencia cambiante y leerla (ajuste el temporizador para ayudar a resolverlo) para tener una forma manual y táctil de establecer la duración.

        Dicho esto, usé un disparo para un bucle en mi código y conté los ciclos del reloj. Devorador de masa total. Estilo terrible. Pero dos pilas AAA duraron toda la noche, así que realmente no me importa un bledo.

  • David dice:

    Estoy tratando de aprender a usar LaunchPad y sé muy poco sobre la codificación C. El código aquí está muy bien comentado y es un gran lugar para comenzar nuevos entintadores.
    ¡Gracias por compartir!

    • Jungla de hierro dice:

      ¡Gracias por el comentario, Dave!

Manuel Gómez
Manuel Gómez

Deja una respuesta

Tu dirección de correo electrónico no será publicada.