RE: ServoCape and Testing the Servo Headers

Hello,

I have a ServoCape from GHI and I have been trying to make it work recently.

There was this nice person that helped with some of the source, i.e. a wrapper in Python.

I tried to test the Servo Headers on the Cape a while back. It seems to have disabled my DMM.

Seth

P.S. I bought a new DMM today. I went back to test the ServoCape. The same pins, S16, on the Cape are rendering my DMM useless. Luckily, this time, I was able to make my DMM wake up after 30 seconds. Does anyone know how to use this Cape and if so, would you be so kind to tell me?

What are you trying to measure? What kind of a measurement were you doing? Voltage, Current, frequency, resistance, continuity etc?

what does “disabled” mean with respect to your DMM?

Servos need a PWM signal. If you check the schematic https://github.com/beagleboard/capes/blob/master/beaglebone/Servo/Servo_Cape_sch.pdf you will see you need VIN on the header as it’s what exposes power to the servo headers, but you shouldn’t need that to do simple tests to show what’s going on.

What model of DMM are you using? It is manual or auto range?

@Brett and @Dave_McLaughlin and @Mike,

Hello…I am using a auto range DMM, model DMMW3 from Woods, w/ the voltage test on the servo headers.

Brett, I mean disabled in that my DMM will not turn on when testing the servo headers on S16 w/ positive and negative.

Seth

Maybe lost in translation. When you say disabled, what exactly do you mean? The meter doesn’t read anything or it switches off when you touch the terminals.

What exactly are you trying to measure with the meter?

If you are trying to read the PWM with a meter, you are not going to see much depending on the meters sampling rate. Maybe once you have 50% PWM on you might see something. With a good meter you will see close to 50% of the PWM voltage but at 100% PWM you should see the full PWM voltage.

@Dave_McLaughlin,

Hello…disabled in the sense that the meter reads nothing and halts from being on w/ the meter display. I mean that the meter does not show anything on it while I am testing the Servo Headers on the Cape. It is almost like the meter is off.

I am measuring voltage only so far on the Servo Headers. Oh and sir, when you type 50% PWM, do you mean that i2c will not turn on the Servo from the Servo Headers by itself? Would I need another PWM library to use outside of the i2c library?

Seth

P.S. I am asking b/c I thought this i2c library, smbus2, would have gotten to make the servo move by itself. If this is indeed the issue, I understand. If it is not the issue and I do not need PWM library in Python, then I am stalled still.

Are measuring AC voltage?

Do you understand what the cape does and how servos work?

First up, you need to be able to talk to the chip (that does the PWM). It’s connected via the I2C bus, so that’s what your I2C library is allowing you to do.

Then, you need to tell that chip to do something. You’ll need to look at the control register structure to understand what that exactly needs. Look at the schematic and look for the chip ID and get the chip’s data structure. Then send it appropriate commands and see that this does, or does not, control an output. If you think you’ve done that in your code, then show us your code…

And on testing. There are headers on this cape, right? Use the voltage measurement setting on your DMM to make sure you can see 5v between GND and one of the power pins. That’s a simple test that you have your DMM set up correctly and it’s ready to measure the next thing you are about to test on the outputs.

Hello @Mike,

No sir. I am measuring DC.

Seth

Hello @Brett,

Hello again…yes and yes. The ServoCape handles servos and servos have motors in them w/ basically a pot that moves them in sync to what is described in the source.

So, would I need a PWM library to use for this Cape. Oh and here is the source:

from time import sleep

# relevant registers
MODE1       = 0x00
MODE2       = 0x01
LED         = 0x06
ALL_LED     = 0xFA
PRE_SCALE   = 0xFE

class Pca9685:
    def __init__( self, bus, addr ):
        self.addr = 0b10000000 | addr
        self.bus = bus
        self.write_reg( MODE1, 1 << 5 )  # initialize MODE1 register
        sleep( 500e-6 )  # wait 500us to allow oscillator to power up

    def read_reg( self, reg )
        return self.read_regs( reg, 1 )[0]

    def write_reg( self, reg, value ):
        return self.write_regs( reg, [ value ] )

    def read_regs( self, reg, count ):
        assert reg in range( 0, 256 )
        assert count in range( 1, 257-reg )
        return self.bus.read_i2c_block_data( self.addr, reg, count )

    def write_regs( self, reg, values ):
        assert reg in range( 0, 256 )
        return self.bus.write_i2c_block_data( self.addr, reg, values )

    def get_pwm( self, output ):
        assert output in range( 0, 16 )
        reg = LED + 4 * output

        [ on_l, on_h, off_l, off_h ] = self.read_regs( reg, 4 )
        on = on_l | on_h << 8
        off = off_l | off_h << 8

        phase = on
        duty = ( off - on ) & 0xfff
        if off & 0x1000:
            duty = 0
        elif on & 0x1000:
            duty = 4096

        return ( duty, phase )

    def set_pwm( self, output, duty, phase=0 ):
        assert duty in range( 0, 4097 )
        assert phase in range( 0, 4096 )

        if output == 'all':
            reg = ALL_LED
        else:
            assert output in range( 0, 16 )
            reg = LED + 4 * output

        on = phase
        off = ( duty + phase ) & 0xfff
        if duty == 0:
            off |= 0x1000
        elif duty == 4096:
            on |= 0x1000

        on_l = on & 0xff
        on_h = on >> 8
        off_l = off & 0xff
        off_h = off >> 8
        self.write_regs( reg, [ on_l, on_h, off_l, off_h ] )

And…

Then, since that source was given to me, I tried to set up the source to use w/ the wrapper just described as this:

from smbus2 import SMBus
from ServoFile import Pca9685
from time import sleep

i2c2 = SMBus("/dev/i2c-2")
x = Pca9685(i2c2, 0b111111)

x.read_reg   = 0
x.write_reg  = 0
x.read_regs  = (0, 5)
x.write_regs = (0, 0, 5)
x.pwm_get    = 0
x.pwm_set    = (0, 2000, 0)

angle = int(input("Please tell me your angle: "))
for a in range(0, 180):
    a = angle
    print("You angle is: ", a)
    sleep(2)

So far, this is what I have to work on. If I need to use a PWM library like you described b/c of the Servo needing a reading to account for, please let me know. I can probably use Adafruit_BBIO.PWM as PWM again.

Seth

You do not need to drive PWM - you just need to use the controls in the chip to make it send a different PWM control to the servo output.

Nowhere in your code are you converting from the angle you read from the user to a physical command to do anything, using your “x” object. That’s what you will need to figure out. I am assuming the PCA device command “x.pwm_set = (0, 2000, 0)” actually does something valid, and it sets it to nothing so you’ll see no voltage on the PWM pin. You need to figure out what command you need to issue next to alter the PWM signal. That’s reading the datasheet for that chip, not something I have done nor will I do that for you - you can do that homework :slight_smile:

Hello @Brett,

Okay. I will review the datasheet and not implement a PWM library. I will go to the datasheet for finding out exactly which command is needed for making angles work.

Seth

P.S. I might have gotten things confused as you can tell. Thank you. So, here I go. I will reply once I review the datasheet a bit more.

also remember that a servo expects a PWM in the order of 20ms frequency, and a pulse width of 1.5ms (1500us) to be centred, with a typical range of 1ms to 2ms for + and - 90 degree points. The 2000 in your PWM_SET command above likely sets the frequency to 2000us correctly.

also this is a great reminder of what embedded systems are about. What you’re trying to do is create some mapping in your code between a real world device, in this case the degrees position of a servo arm, and what control inputs you need the electronics to do.

Once you get the basics working by being able to have code that can cause the servo to move within the + and - 90 degree positions, you would then make that a function that takes a desired position and does the necessary calcs for you. That way, when you start to build a nerf gun turret (or whatever other use for the servos you’ve decided) you can just write code that calls on your function to move to a specific angle.

Hello,

Thank you for your ideas and knowledge. I am working on it still. I will see that this is and will be a defining moment in my life w/ programming, reading datasheets, and making electronics work.

Seth

P.S. I have failed before but I will stick w/ it and review more articles on how to communicate datasheets to real world examples to make things work. Partially b/c of my lack of background in understanding datasheets, software programming, and electrical engineering, I have been hit hard by the neat aspects of what is available versus what I can do that is available.

we’re here to help. we’re not going to give you “the answer”, we’ll prod you in the right directions to look. Crack open the datasheet and start asking different questions :slight_smile:

1 Like

Hello,

@Brett, I took another route so far outside of also reading the datasheet. I am looking here: https://github.com/adafruit/Adafruit_Python_PCA9685/blob/master/Adafruit_PCA9685/PCA9685.py.

Anyway, I think my start to the wrapper of PCA9685 needs updating. I think I need more registers added and some bits I can make available, made available.

Seth

P.S. I am on page 16 of 52 on the datasheet, e.g. section 7.3.3. So far, I am getting lost in it. I will need some more education in this dept. before I can ask the correct questions. Please bear w/ me. It may take some time for me.

you using this one from NXP? https://www.nxp.com/docs/en/data-sheet/PCA9685.pdf

Hello…that is the exact one I am using.

Seth