PCA9685 to picaxe 18m2

#1
I can't access the i2c address..in my new servo driver 16 channels (PCA9685), please help I just soldered the A1 port should be the i2c address 0x42.
thank you
 
Last edited:

hippy

Technical Support
Staff member
#2
The PCA9685 datasheet shows the Device Address to be -
Code:
.-----.-----------------------------.-----.
|  1  | A5 | A4 | A3 | A2 | A1 | A0 | R/W |
`-----^-----------------------------^-----'
For a PICAXE which uses an 8-bit Device Address, A1 active, R/W set to 0 -
Code:
.-----.-----------------------------.-----.
|  1  |  0 |  0 |  0 |  0 |  1 |  0 |  0  | 
`-----^-----------------------------^-----'
So that's 0x84 for a PICAXE.
 
#3
Further to the advice by hippy the datasheet Ali indicate there are no pull up resistors on the ports so I suggest they could be floating.
Therefore in addition to pulling the address pin A2 high it is recommended to pull all the other pins down to zero volts/low logic voltage level.
 
#4
hi guys, thank you for your help, I changed the address to 0x84 but doesn't work,

why 84?

yes, I added two 4k7 ohms in V+ on sda and scl, and I'm using the picaxe 18m2

I made this simple program, I had some experience in some i2c devices like sd20 or some oled displays but this device I don't know what happened.

setfreq m8

start:

i2cslave 0x84, i2cfast_8, i2cbyte

pause 500


writei2c 0, (200)

writei2c 1, (200)

writei2c 2, (200)

writei2c 3, (200)


pause 500

goto start
 
Last edited:
#6
thank you but it is the same issue.

setfreq m8

start:

hi2csetup i2cmaster, 0x84, i2cfast_8, i2cbyte

pause 500


writei2c 0, (200)

writei2c 1, (200)

writei2c 2, (200)

writei2c 3, (200)


pause 500

goto start
 
Last edited:

Aries

New Member
#7
Hippy explained why 0x84 is the device address. If you have A1 set to 1, and the others (A0,A2-A5) set to zero, then the address is 10000100. The apparent address is shifted to the left to allow for bit 0 to be the read/write indicator. Make sure you have pulled A1 up and the others are pulled down. As Westaust says, any unconnected pins may be floating and so the address would be undefined.

I'm not sure what you are trying to write (I have not read the datasheet in detail), but the LED addresses start at x06 and then come in pairs (LO and HI),
so I would expect - if you are trying to light LEDs - to see something like
Code:
 hi2cout x06,(1,1)
 hi2cout x08,(2,2)
and so on.
 

hippy

Technical Support
Staff member
#8
It will also be necessary to set the MODE1 register before the chip becomes active. When powered up the default appears to be that the chip will be in a low-power 'sleep' state and that will need to be cleared.

LED brightness control is achieved by writing four bytes per LED; it seems necessary to enable address auto-increment to allow multiple bytes to be sent with a single HI2COUT command.

It may also be necessary to set MODE2 register so the LED drives are set as appropriate and the external /OE is configured as required.
 

Aries

New Member
#10
From the NXP documentation ...
"Overview

The PCA9685 is an I²C-bus controlled 16-channel LED controller optimized for Red/Green/Blue/Amber (RGBA) color backlighting applications. Each LED output has its own 12-bit resolution (4096 steps) fixed frequency individual PWM controller that operates at a programmable frequency from a typical of 24 Hz to 1526 Hz with a duty cycle that is adjustable from 0 % to 100 % to allow the LED to be set to a specific brightness value. All outputs are set to the same PWM frequency."

so you can see why we are confused
 

hippy

Technical Support
Staff member
#11
hi, I'm trying to control some servos.
I was about to post exactly what Aries has.

Though it's a LED controller I would guess that should work for controlling servos using a typical 50Hz / 20ms frame rate assuming a suitable rate can be selected. Servos usually require an accurate pulse length but are often more flexible with the frame frequency and rate.

The PCA9685 has a single 8-bit clock pre-scaler ( register $FE ) and, according to the datasheet, its value should be set as -

pre-scaler value = ( clock / ( 4096 * update frequency ) ) - 1

For a 25MHz clock and 50Hz frequency -

pre-scaler value = ( 25MHz / ( 4096 * 50Hz ) ) - 1 = 121

Note that the pre-scaler can only be written when in sleep mode, so it's probably the first register which needs to be set, or at least set before taking the chip out of sleep mode.

So, if a 'PWM value' of 0 to 4095 gives an on period of 0ms to 20ms it should then be a simple matter of converting a servo position of 50 to 250 into a suitable off times to write to the LED control values -

offTime = servoPosition * 4095 / 2000

Untested, but I would guess something like -

Code:
Symbol MODE1_REG     = $00
Symbol MODE2_REG     = $01
Symbol LED0_REG      = $06
Symbol PRESCALE_REG  = $FE

Symbol offTime       = w0 ; 0 to 4095
Symbol offTime.lsb   = b0
Symbol offTime.msb   = b1

Symbol register      = b2

Symbol servoNumber   = b3 ; 0 to 15
Symbol servoPosition = b4 ; 50 to 250

PowerOnReset:
  HI2cSetup I2CMASTER, $84, I2CSLOW, I2CBYTE
  Hi2COut MODE1_REG,    ( %00110000 )
  For servoNumber = 0 To 15
    servoPosition = 150
    Gosub SetServo
  Next
  Hi2COut PRESCALE_REG, ( 121 )
  Hi2COut MODE2_REG,    ( %00000100 )
  Hi2COut MODE1_REG,    ( %00100000 )

MainLoop:
  Do
    servoNumber = 0
    For ServoPosition = 100 To 199
      Gosub SetServo
      Pause 20
    Next
    For ServoPosition = 200 To 101 Step -1
      Gosub SetServo
      Pause 20
    Next
  Loop

SetServo:
  register = servoNumber * 4 + LED0_REG
  servoPosition = servoPosition Min 50 Max 250
  offTime = servoPosition * 2
  offTime = servoPosition ** 3112 + offTime
  HI2cOut register, ( 0,0, offTime.lsb,offTime.msb )
  Return
Edited: Fixed maths overflow of 250 * 4095
 
Last edited:
#12
woowwwww guys thank you, you are amazing.... wowwww I have a question, how can I use more servos at the same time?
 
Last edited:

hippy

Technical Support
Staff member
#13
how can I use more servos at the same time?
Each chip should handle 16 servos. In the suggested example code set 'servoNumber' between 0 and 15, set 'servoPosition' to the position required and then "Gosub SetServo" to set that servo.
 

hippy

Technical Support
Staff member
#15
thank you guys for your help I found the way how to activate all 16 servos... I really appreciate your help.
You are welcome, and I am sure everyone who helped is delighted with your success.

A good way to show appreciation, as well as helping others in future, is to post the code which you have got working. Having a 'reference design' of something known to work is always a good thing, better than guessing how it should be without knowing if that's right or not.

I have never used multiple servos but this looks like a good chip to use for that even though it was not intended for such a thing. It should be fairly easy to adjust the channel timing to have servo pulses sequentially rather than starting simultaneously if that is desirable. It may also have other uses beyond LED's or servos; multiple motor drives is one thing which springs to mind.

I'll be honest, I had never heard of the chip before you mentioned it, so thanks for doing so.
 
Last edited:

Hemi345

Senior Member
#16
I missed this thread, but doubt I could have offered any help with it driving servos.
I have an Adafruit module utilizing this chip running a stepper motor on my greenhouse/cold frame project. It works well but was a brain bender to decipher the datasheet and ended up using Adafruit's example Arduino code to translate it into PICAXE BASIC. I'll post my code snippet in the finished projects section just in case someone else needs a little help making it work with steppers.
 

mikeyBoo

Senior Member
#17
hi r1erick2
I use a PCA9685 (from Adafruit) to run the lighting effects on my fishing yak control system. If you have the patience to read through the Picaxe Basic code in the following link, there is everything you need to know to use the PCA9685 with any Picaxe that has I2C.

https://picaxeforum.co.uk/threads/picaxe-kayak-control-project.28063/

see also: https://www.nxp.com/docs/en/data-sheet/PCA9685.pdf

Note that the proc (aka subroutine) “LED.outputs_Set” shows how to set multiple PCA9685 channels with a single I2C write. All procs that control the PCA9685 begin with “LED.” You may also want to look at the proc init. Note that I only use the first 8 channels but the software would be easy to expand to all 16.

Note that when writing to multiple lights/servos there are 2 preceding zeros. This specifies an offset to keep multiple devices from bumping the power source at once (offsets not usually needed for servos, but for home lighting or electronic billboards may be an issue).

for example: (where AL AH are the low-byte hi-byte for the 0…4095 timing interval for the first channel, etc.)

hi2cout $6,(0,0,AL,AH,0,0,BL,BH,0,0,CL,CH,0,0,DL,DH,0,0,EL,EH,0,0,FL,FH,0,0,GL,GH,0,0,HL,HH)

You would need to modify the code to generate 1…2mS pulses rather than 0…100% lighting, but the basic reading/writing methods would be the same.

Pwm1_rw2_sch.pdf has some notes about how to generate the timing pulses for servos using the PCA9685.

I did not include the PCB artwork because I did not want to include an entire servo project under this post.

I also included my notes file to help you understand what the PCA9685registers do.

It occurs to me that it would be easy to adapt my code to run a 16 zone LED home lighting system.
Guess that would make a nice project. Anyone interested?

Would anyone be interested in a 16-channel Picaxe servo controller project?
 

Attachments

#18
Hi to everyone, thank you again, I will check this new info, I modify some lines in the program and works very well, I'm using this code to communicate to 6x6 robot, the robot has some ESC, servos, and lights and works awesome, my next issue is to communicate a PS2 (PlayStation 2) steering wheel controller and pedals to picaxe 18m2, I need many memory banks to make different routines and vibration function because has a lot of buttons. if somebody knows about it please help me because I'm really lost on it. I will show you some pictures of my project soon.
 
Last edited:

mikeyBoo

Senior Member
#19
hi r1erick2,
Something I forgot to mention in my previous post. You may wonder why my notes on servos in the attached .pdf Pwm1_rw2_sch.pdf use a 200 Hz update frequency on the servos instead of the typical 50 Hz. Well, on the PCA9685 the base frequency is used by all 16 channels. When controlling lights you need the 200 Hz to make sure there is no flicker at low PWM values (i.e. a very dimmed light). All servos I’ve used work just fine at 200 Hz (they are looking for the 1…2mS pulse, not a specific update period).

The net effect is that using a base frequency of 200 Hz, you could for example control 8 dimmable lights and 8 servos
using the same PCA9685. That way your robot can be stylish as well as functional (always wanted to say that).

Note that the PCA9685 is a set it and forget it device. You won’t need to update anything until you change a setpoint.
Looking forward to seeing your project. It sounds interesting. Best of luck!
 
Top