Magic Lantern Forum

Developing Magic Lantern => Scripting Corner => Scripting Q&A => Topic started by: wolf on February 14, 2013, 01:16:10 AM

Title: Motion "control" with picoc
Post by: wolf on February 14, 2013, 01:16:10 AM
Accidentally I connected a headphone to mic input and could hear a crackling noise while playing the test beep. It seems that the mic power turns off while playing the beep().
I made a simple AVR stepper control and triggered it with the mic port. Every beep triggers one step. Of course it could be done with the headphone port too.
I build a slider out of old roller skater bearings and two rods and pulled the camera with a sewing thread with the stepper motor. Some improvements could be done, but I'm quite happy with the result :-) The slider works also without motor ok.

Thanks to a1ex for implementing picoc to ML and recently adding the ability to stop a running script.

(http://i.imgur.com/mxFHiJz.jpg)     (http://i.imgur.com/036iGss.jpg)

The result:


the code
picoc:

/*
@title Slide it
@param   s Steps *100
@range   s 1 40
@default s 30
@param   p Pics
@range   p 0 500
@default p 400
@param   w Interval sec.
@range   w 0 100
@default w 2
@param   d Display
@range   d 0 1
@default d 0
*/

#define STEP_WAIT 0.3
#define PRESS_WAIT 0.2
#define DISPLAY_WAIT 0.5
int i,a;
float wait_rest;
while (i<400)
{
    i++;
    for (a=0; a<(s*100/p); a++)
    {
        beep();
        sleep(STEP_WAIT);
    }
    wait_rest=(w-PRESS_WAIT-(a*STEP_WAIT));
    if (wait_rest>0)
        if(d)
            sleep(wait_rest);
    if( (!d) && (wait_rest-DISPLAY_WAIT>0) )
    {
        sleep(wait_rest-DISPLAY_WAIT);
        lv_resume();
        sleep(DISPLAY_WAIT);
    }
    press(SHOOT_HALF);
    sleep(PRESS_WAIT);
    unpress(SHOOT_HALF);
    if(!d)
        lv_pause();
}



#ifndef F_CPU
#define F_CPU 8000000UL
#endif

#include <avr/io.h>
#include <util/delay.h>


void delay(uint16_t ms)
{
    while(ms--)
        _delay_ms(1);
}

int main(void)
{
    uint16_t n=0;
    uint16_t turn_off=0;
    uint8_t hs[4]= {9,5,6,10};
    DDRB |= (1<<PB0) | (1<<PB1) | (1<<PB2) | (1<<PB3) | (1<<PB4);
    while (1)
    {
        while(!(PINB &(1<<PB4)))
        {
            n++;
            delay(100);
            if (!turn_off)
                PORTB=0;
            turn_off=0;
        }
        if(turn_off<200)
        {
            turn_off++;
            PORTB=hs[n & 3];
            delay(1);
        }
        else
        {
            PORTB=0;
        }
    }
}


Title: Re: Motion "control" with picoc
Post by: coutts on February 14, 2013, 02:19:46 AM
this is great! very neat
Title: Re: Motion "control" with picoc
Post by: SDX on February 17, 2013, 04:18:45 PM
Nice find.. that's awesome actually. I've been waiting for some efficient way to control my slider using ML. I've tried achieving this by making a optocoupler using the status LED - the timing of the camera was too imprecise for serial signals.

A little suggestion to the slider: Having two rods that run so close to each other gives some instability. When you only want to use this for timelapse, you don't need it to run that fast either. I've build several versions so far using a threaded rod instead. That's not very fast, but very precise. Also, that is quite powerful and allows you to move almost any kind of camera even on vertical axis.
I have some pictures of it here (http://www.flickr.com/photos/simon_dibbern/sets/72157632784545755/). It has been modified several times and contains some unused parts, especially the electronics are a pure mess, as you might see. I'm really looking forward to add your find to it.

Actually it runs quite smooth.
Can you tell me, on which camera you have experienced the power-off of the mic, and, have you experienced that other events can cause such a effect as well?

EDIT: I can not hear any sounds when connecting a headset to mic jack on my 600D. Even when playing around with the beep-sound parameters (volume, duration, ..)
Title: Re: Motion "control" with picoc
Post by: Francis on February 17, 2013, 06:31:44 PM
Well done! Great to  see this sort of innovation.
Title: Re: Motion "control" with picoc
Post by: scrax on February 18, 2013, 01:46:54 AM
Quote from: SDX on February 17, 2013, 04:18:45 PM
EDIT: I can not hear any sounds when connecting a headset to mic jack on my 600D. Even when playing around with the beep-sound parameters (volume, duration, ..)

Maybe that's due to the different chip, maybe is possible to send the beep to headphone or maybe not since it say that 600D not suppor Play and monitoring together if you try to Play beep tone from Beep,test tones submenu.
I tried with and without audio monitor on and it gives same message.

Don't know why it's not possible since I was supposing we can now route the audio signal from speaker to monitor. Maybe is related on how the beep is generated.

But I'm sure that we can have clip on monitor since we worked on removing them by setting properly the audio chip for record.

With those settings:
Override Audio: ON
Analog G and boost: 0
Input source: External (nothing attached to mic in)
when changing some value in Wind Filter submenu you will hear the clipping problem I'm talking.with higher volume you will hear the ground noise stopped by the clip.
So if that clipping is enough to trigger something just adding DC filter toggle to picoC will make the script approach work also on 600D
Title: Re: Motion "control" with picoc
Post by: wolf on February 18, 2013, 10:23:13 AM
@SDX
I started 'cause of stability with a upside down hanging camera under the rods between two tripods, just as slider. It's kind of ok but not very comfortable somehow.
Made the tracks  already wider and it became less shaky.
I bought already an opto-isolator for galvanic isolation of port but it isn't bulid in yet. 

Did see your camera robot, really nice. Do you have a rendered clip online too? I guess it works fine.

Maybe I try it with a threaded rod too. To pull the camera uphill would be nice and I'm sure it's more precise. 
Anyhow I had always the energy consumption and bicycle transport in my mind. The stepper is driven by 4xAA cells. It's easy to disjoint the gear.
Without energy problems, I  control it over laptop with  piggyphoto. https://github.com/alexdu/piggyphoto. Preview picture... And a usb card http://www.obdev.at/products/vusb/prjdetail.php?pid=0

I use a 550D with:

Input source internal mic
Mic Power        ON  
Output Volume         0db          #to play the beep as silent as p.
Headphone Mon.     ON   

I think the headphone  port would work also, but I like the mic jack more than usb to plug and work with in the fields. ;-)




Title: Re: Motion "control" with picoc
Post by: a1ex on February 18, 2013, 10:30:56 AM
@wolf: can you try to see if toggling Mic Power on and off will actuate your stepper motor?

If so, I'll add some function in PicoC that controls that output without playing beeps.
Title: Re: Motion "control" with picoc
Post by: SDX on February 18, 2013, 10:37:05 AM
Can you estimate how fast it is going to be? Would be awesome to be able to send serial data.
Title: Re: Motion "control" with picoc
Post by: wolf on February 18, 2013, 10:41:36 AM
It triggers the electronics but it seems that the lenght of the signal doesen't fit to my AVR controller program.
So I guess it could work. Anybody out there with an oscilloscope to analyze the output?
Title: Re: Motion "control" with picoc
Post by: wolf on February 18, 2013, 11:19:57 AM
Plugged it to audacity and turned it on and off repeatedly, to me the the signal seems to be promising. :-)
http://i.imgur.com/IIOMktb.jpg
Title: Re: Motion "control" with picoc
Post by: a1ex on February 18, 2013, 12:32:01 PM
So... low-speed RS232 is quite doable, right?

I would try this (550D, 60D, 5D2):


while(1)
{
    audio_ic_write( AUDIO_IC_SIG1
                    | 0x10
                    | ( mic_pow ? 0x4 : 0x0 )
                    ); // power up, no gain
    mic_pow = !mic_pow;
    msleep(10);
}


For smaller delays you can't use msleep, but you can try busy waiting and look at the DIGIC clock (0xC0242014). It will keep the CPU busy, but for small signals it shouldn't be a problem.
Title: Re: Motion "control" with picoc
Post by: wolf on February 18, 2013, 01:05:51 PM
I don't know how hard it is to implement a serial data transmission protocol.
With AVR UART it maybe would  be possible to connect the camera to a controller.

Title: Re: Motion "control" with picoc
Post by: wolf on February 18, 2013, 01:22:31 PM
Off topic:
I tried to use bmp_printf with picoc.

void Libbmp_printf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
{
    bmp_printf(0x00020000,Param[0]->Val->Integer,Param[1]->Val->Integer,Param[2]->Val->Pointer);
}
...
    { Libbmp_printf,    "void bmp_printf(int,int,char *, ...);" },


It works somehow, but I can't print values like ("%d",x). Is this much more complicated or did I something simple wrong?
Title: Re: Motion "control" with picoc
Post by: wolf on February 18, 2013, 09:05:38 PM
@a1ex
how to set DIGIC clock (0xC0242014)?
and do you think this could be done that simple?

char n;
#define BAUD 1000/300 //?? 3.33ms timing ????

void mic_power(int x)
{
    if (x)
        mic_pow=1;
    if(!x)
        mic_pow=0;
    audio_ic_write( AUDIO_IC_SIG1
                    | 0x10
                    | ( mic_pow ? 0x4 : 0x0 )
                  );
}

void freeze(int n)
{
;;
}

void send_232(char n)
{
    printf("0"); //startbit
    freeze(BAUD);
    for (int i=0; i<8; i++)
    {
        if ((1 << i )&n)
        {
            mic_power(1);
            msleep(BAUD);
        }
        else
        {
            mic_power(0);
            msleep(BAUD);
        }
    }
    mic_power(1);//parity
    freeze(BAUD);
    mic_power(1);//stopbit
    freeze(BAUD);
}

send_232('A');

Title: Re: Motion "control" with picoc
Post by: a1ex on February 18, 2013, 09:23:07 PM
You can't do msleep(3), but you can do msleep(10), msleep(20) etc.

You can't set DIGIC clock, but you can read it. See for example busy_vsync.

For high-speed communication you may need some timer interrupts. They are documented here: http://magiclantern.wikia.com/wiki/Register_Map (g3gg0 can help if you want to use one).

I suggest to try first with 10ms delays (or maybe more). When that works well, move on to something faster.

Now, the easy way: encode the RS232 signal as an audio clip and... just play it as WAV (look in beep.c).