jenswilly.dk


Archive for March, 2013

3D printed camera holder

9. March 2013 19:43 by Jens Willy Johannsen
Categories: 3D printing

Here's another 3D printed component: a tiltable camera holder. It consists of two parts: the base and the front plate. The front plate has four standoffs with 2 mm holes for mounting the camera PCB with M2 machine screws. It also has a small bracket with a 1 mm hole for the rod that connects to the servo.

The front plate is attached to the base by M2 machine screws. The holes in the base are larger than the screws so they can rotate freely and a washer between the screw head prevents the screw head from digging into the plastic.

Here is a model of the front plate (modelled in ViaCAD 2D/3D) and the front plate and base assembled and checked for clearance when rotating in Autodesk Inventor Fusion (click for full-size):

cam_holder_model
cam_assembly

And there is the finished and assembled piece:

3D printed camera holder (click for full-size image)

3D printed camera holder (click for full-size image)

CAD files

Comments 2 comments »

Repetitive Interrupt Timer on LPC1347

9. March 2013 19:30 by Jens Willy Johannsen
Categories: ARM

For my ROV project I need to control an RC servo to tilt the camera up and down. I've gotten that working nicely using a 16-bit timer to generate an appropriate PWM waveform.

But when I change the the position by a lot – for example, going from one endpoint to the middle position – the servo moves too fast. (Which, incidentally, draws a huge current which makes my 5 V rail drop enough to reset the MAX7456 – but that is fixable.) So I need to slow the movement down by gradually changing the position instead of jumping straight from one position to another.

The full servo movement corresponds to a change in timer match value by 1000 (the PWM timer is set up so the match values correspond to PWM pulse on-time in microseconds so minimum is 1000 and maximum is 2000). I would like the full range of movement to take one second so I thought that changing the position in increments of 10 at a frequency of 100 sounds about right.

Unfortunately, I'm fresh out of timers: CT32B0 and -1 are used for motor control PWM, CT16B0 is used for periodic analog-to-digital conversions (for the pressure sensor used as depth gauge) and CT16B1 is used for servo PWM. Yeah, sure, I guess I could use a timer for more than one purpose but since the LPC1347 actually has one more timer, I might as well use that: the Repetitive Interrupt Timer.

The Repetitive Interrupt Timer (RIT for short) generates interrupts every X clock cycles and if I configure the timer to fire an interrupt every 720,000 clock cycles I get a 100 Hz interrupt (on a 72 HMz PCLK) in which I can move the servo if necessary. Nice.

This is the code I came up with:

Repetitive Interrupt Timer on LPC1347

// MIN and MAX macros
#ifndef MIN
#define MAX(a,b) (((a)>(b))?(a):(b))
#define MIN(a,b) (((a)<(b))?(a):(b))
#endif

// Servo position variables
volatile uint16_t servo_position;
volatile uint16_t servo_target;

// Stop RI timer – otherwise we can't reset the counter
LPC_RITIMER->CTRL = 0;

// Init RI timer (we don't need to enable timer – it is always running as per the updated User Manual UM10524)
LPC_RITIMER->COMPVAL = 720000;
LPC_RITIMER->COMPVAL_H = 0;

// Reset counter (otherwise it might already be above the compare value and then it would take a loong time to overflow to zero)
LPC_RITIMER->COUNTER = 0;
LPC_RITIMER->COUNTER_H = 0;

// Set RITENCLR (clear on match), RITENBR (halt timer on debug) and RITEN (start timer)
LPC_RITIMER->CTRL = (1<< 1) | (1<< 2) | (1<< 3);

// Enable RIT interrupt
NVIC_EnableIRQ( RIT_IRQn ); 

// Interrupt routine 
// (Yes, it's a little weird that the interrupt routine is called OSTIMER but the NVIC interrupt is called RIT_IRQn)
void OSTIMER_IRQHandler()
{
    // Clear interrupt
    LPC_RITIMER->CTRL |= (1<< 0);   // Write RITINT to clear

    // If we're at target, do nothing
    if( servo_position == servo_target )
        return;

    if( servo_target > servo_position )
        servo_position += MIN( servo_target - servo_position, 10 );
    else // Not equal and not greater than, so it's less than – we don't need to check
        servo_position -= MIN( servo_position - servo_target, 10 );
}
Comments 4 comments »