RE: Trying to Understand Complicated Source w/ Classes from the ServoCape and Python3/ServoCape and the PCA9685

40 views
Skip to first unread message

Mala Dies

unread,
May 5, 2020, 4:29:37 PM5/5/20
to BeagleBoard
Hello,

I have a, to me, piece of complicated text in Python3 format.

Anyway...

I have been unable to make the conversion of the wrapper to another Python3 file.

So, here is the source in case you are interested:

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

Now...

How would I actually use this source to promote a servo movement with the ServoCape?

I have tried particular source from different tutorials, the python.org site, and examples of classes online.

None really cover the BBB and expansion Capes like this source is listed. Anyway...

What steps if any would you take to make a servo move w/ this Cape and source?

  • Would I need a Adafruit_BBIO library for GPIO/PWM or a similar library?
Seth

jonnymo

unread,
May 5, 2020, 5:09:33 PM5/5/20
to Beagle Board
If you provide a link to the source of this that would help.

But, basically in your own Python code you would first import the class

Ex:
   from source_file import Pca9685

The you could create an instance of this like:

   my_servo_control =  Pca9685(bus_num, addr_val)

You could need to know the value of bus_num and addr_val to set these.

Then you could call the methods as such:
   my_servo_control.read_reg(reg_val)

 Again, you would need to know what the value of reg_val is to set the 'reg' parameter for the 'read_reg' method.

You still need to know where it is getting the 'write_i2c_block_data' and 'read_i2c_block_data' methods from though.  
Perhaps 'import smbus' is missing?


A course in Python wouldn't hurt.


Cheers,

Jon 
  

--
For more options, visit http://beagleboard.org/discuss
---
You received this message because you are subscribed to the Google Groups "BeagleBoard" group.
To unsubscribe from this group and stop receiving emails from it, send an email to beagleboard...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/beagleboard/5e42131b-733f-413d-91e9-eb204e204f84%40googlegroups.com.

Mala Dies

unread,
May 5, 2020, 6:01:26 PM5/5/20
to BeagleBoard
Hello,

Okay.

So, I am using smbus2 in python3 for the communication of the i2c interface on the ServoCape (PCA9685).

So:

from smbus2 import SMBus
from ServoLib import Pca9685
from time import sleep


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

So, everything under this first section of my python source should work as described:

x.__init__
x
.read_reg
x
.write_reg
x
.read_regs
x
.write_regs
x
.get_pwm
x
.set_pwm


Is this correct?

Seth


To unsubscribe from this group and stop receiving emails from it, send an email to beagl...@googlegroups.com.
To unsubscribe from this group and stop receiving emails from it, send an email to beagl...@googlegroups.com.

jonnymo

unread,
May 5, 2020, 6:22:17 PM5/5/20
to Beagle Board
When you call the methods in the Pca9685 you need to pass the appropriate parameters.

 Ex:
 read_reg( self, reg )

  You need to pass a reg value to this.
   reg_val = some_reg_val

   read_result = x.read_reg(reg_val) 

   print(read_result)


I can't see the rest of your code so I am not sure if it will work or not.

Search the web for Python3 tutorials.

Jon

To unsubscribe from this group and stop receiving emails from it, send an email to beagleboard...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/beagleboard/0a7798ae-13f3-453b-9963-78290a9c005f%40googlegroups.com.

Mala Dies

unread,
May 5, 2020, 6:47:30 PM5/5/20
to BeagleBoard
Hello,

Okay. So, I will go and research this idea more. I have been reading at python.org under classes so far. I just found the w3schools.com page for Python.

I will try this page online and return service if things are getting too odd for me.

Seth

P.S. Thank you.

Mala Dies

unread,
May 5, 2020, 8:07:53 PM5/5/20
to BeagleBoard
from smbus2 import SMBus
from ServoLib import Pca9685
from time import sleep

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

x.read_reg(2)
x.write_reg(2, 1)
x.read_regs(2, 5)
x.write_regs(2, len(int(0))

angle  = int(input("What would your favorite angle be now? ")
if angle <= 180 or angle >=0:
    angle = x.get_pwm(1)
    f     = angle + x.set_pwm(0, 2000, 0)
    print("Your angle is " + angle)

Jon,

Seth here. Yep. Here is some source. I am not sure if you have the Cape or not but I was wrangling w/ getting the basics to work first, e.g:

read_reg
write_reg
read_regs
write_regs
get_pwm
set_pwm 

and so on...

I got the first couple of functions from the class being called to not give any errors. Then, https://pastebin.com/bXWhdrzA, this link is the error I received.

I then made some changes as you can tell in the source for write_regs w/ len(int).

Seth

P.S. I know this is partial source and not worth showing off but I wanted to see if you can configure what exactly it is that I am doing incorrectly.

When you typed reg_val before in this post, were you referring to hexadecimal register values?





On Tuesday, May 5, 2020 at 5:22:17 PM UTC-5, jonnymo wrote:

On Tuesday, May 5, 2020 at 5:22:17 PM UTC-5, jonnymo wrote:

On Tuesday, May 5, 2020 at 5:22:17 PM UTC-5, jonnymo wrote:

jonnymo

unread,
May 5, 2020, 8:13:59 PM5/5/20
to Beagle Board
My reference to  reg_val  was just a reference and an example. I have no idea what you need for the value which is something you need to research.

I have no idea where you got the original code from, but you should start there.

Jon 

To unsubscribe from this group and stop receiving emails from it, send an email to beagleboard...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/beagleboard/415f46f3-ff25-4da9-b12d-904b7bceb3e3%40googlegroups.com.

jonnymo

unread,
May 5, 2020, 8:38:01 PM5/5/20
to Beagle Board
Oh, the error you are seeing is that 'int' does not have a len.  What you may try is to convert it to a string and then get the len:

Ex:
  int_len =  len(str(0)

or
Ex: For values greater than 0.
  int_len = int(math.log10(int_val)) + 1

But I am not sure why you are getting the length of 0.

I don't have a cape, so I can not help you there.

Cheers,

Jon 

Mala Dies

unread,
May 5, 2020, 9:28:07 PM5/5/20
to BeagleBoard
Hello,

I moved on from that error: Here is the new source that runs fine...

from smbus2 import SMBus
from ServoLib 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 = (1)
x.pwm_set = (45, 2000, 0)
sleep(5)

angle = int(input("What would your favorite angle be now? "))
if angle <= 180 or angle >=0:
    angle = x.pwm_get
    print("Your angle is ", angle)

    angleOne = int(input("What shall the angle be? "))
    if angle >= 45:
        angleOne = x.pwm_set
        print("The sustained angle is ", angleOne)
        sleep(5)

I receive no errors but nothing happens. So, it is running until the end and the source says what it says. 

I know I am missing something silly that is in front of my face.

...

I thought I could run the source and make the Servo at S1 move already. Nope!

Seth

P.S. Oh. No Cape? Dang! Okay, no issue. If you see where I may be moving too fast and not reading in on the correct info, do not hesitate to type me another note. Anyway, thank you.
Reply all
Reply to author
Forward
0 new messages