Motion "control" with picoc

Started by wolf, February 14, 2013, 01:16:10 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

wolf

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.

     

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;
        }
    }
}



coutts


SDX

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. 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, ..)

Francis

Well done! Great to  see this sort of innovation.

scrax

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
I'm using ML2.3 for photography with:
EOS 600DML | EOS 400Dplus | EOS 5D MLbeta5- EF 100mm f/2.8 USM Macro  - EF-S 17-85mm f4-5.6 IS USM - EF 70-200mm f/4 L USM - 580EXII - OsX, PS, LR, RawTherapee, LightZone -no video experience-

wolf

@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. ;-)





a1ex

@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.

SDX

Can you estimate how fast it is going to be? Would be awesome to be able to send serial data.

wolf

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?

wolf

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

a1ex

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.

wolf

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.


wolf

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?

wolf

@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');


a1ex

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).