Shop OBEX P1 Docs P2 Docs Learn Events
Servo driver dilemma with angles and continuous rotation servos — Parallax Forums

Servo driver dilemma with angles and continuous rotation servos

I've been happy with the servo driver in the Prop Tool Library, "jm_servo" up to now.

I like using angles 0..180 instead of microseconds.
But, seems need more resolution for my BoeBot, upgraded to Tank Bot and with P2 board.

With setting of 92 it slowly rotates one way and setting of 93, slowly rotates the other way.

Think I need to modify jm_servo to either be in tenths of degrees, or to add a calibration setting with finer resolution...

756 x 1008 - 230K

Comments

  • JonnyMacJonnyMac Posts: 8,990
    edited 2023-09-26 20:03

    Think I need to modify jm_servo to either be in tenths of degrees, or to add a calibration setting with finer resolution...

    If it's a CR servo you should output a pulse for 0 degrees and then use a screwdriver to set it to the stop point. TBH, hobby servos with plastic gears don't have great resolution, anyway, so going with finer resolution is kind of wasted on them. That said...

    jm_servo uses Smart Pin PWM mode so we are constrained by the system frequency and servo PWM timing.

      x.word[0] := clkfreq / 1_000_000                              ' set unit timing (1us)
      x.word[1] := 20_000                                           ' set period (20ms)
    

    You could change the unit timing to 0.1us, but then the period count would have to be 20_000_0 and will not fit into the 16-bits allowed by x.word[1].

    If you can spare a cog you can use a Smart Pin to generate a pulse every 20ms. Here is a simple, 2-servo driver with 0.1us resolution that you can paste into your robot app.

    var
    
      long  cog
      long  stack[32]
    
      long  pos0
      long  pos1
    
    
    pub dual_servo_start(svo0, svo1) : result
    
      set_servo(0, 1500_0)
      set_servo(1, 1500_0)
    
      cog := cogspin(NEWCOG, servo_cog(svo0, svo1), @stack) + 1
    
      return cog
    
    
    pub set_servo(ch, newpos)
    
      if (ch == 0)
        pos0 := 600_0 #> newpos <# 2400_0
      elseif (ch == 1)
        pos1 := 600_0 #> newpos <# 2400_0
    
    
    pri servo_cog(svo0, svo1) | looptix, t
    
      pinstart(svo0, P_PULSE | P_OE, clkfreq/10_000_000, 0)         ' set pulse output in 0.1us units
      pinstart(svo1, P_PULSE | P_OE, clkfreq/10_000_000, 0)         ' set pulse output in 0.1us units
    
      looptix := clkfreq / 1000 * 20                                ' sync timing
    
      t := getct()
      repeat
        wypin(svo0, pos0)
        waitus(2500)
        wypin(svo1, pos1)
        waitct(t += looptix)
    

    This uses the process I used in my 8-channel servo driver for the P1 (am porting to the P2). Here's the output from the above code with servo 0 set to 2000.0us and servo 1 set to 1000.0 us.

  • RaymanRayman Posts: 14,146

    Wow, I completely forgot about that zero adjustment pot.
    Ok, never mind, all good here...

Sign In or Register to comment.