Friday 15 May 2020

Tims PCA 9685 Controller


This is a little application I made to control Servo and LED via the PCA9685 LED controller chip.

PCA9685 16x Servo Driver



With this application, it is possible to control 64 PCA9685 devices, each with 16 servo or LED attached.
A total of 1024  items (Servo/LED).

The devices need to be connected to an Arduino, communicating via I2C.
The Arduino requires the firmware installing that is included in the Tims_PCA_9685_Controller.zip
With the Application you can run scripts of pre determined positions of all the Servo/LED connected.
If you have more than one PCA9685, you can quickly switch between them.

There are some setting where you can adjust the Min, Max and Centre of each Servo.


In Tims_PCA_9685_Controller.zip  there is a little program called XLoader.
Just choose the HEX file to Upload:
Tims_PCA9685_16_LED_Servo_Controller_UNO.hex is for the Arduino UNO.
Tims_PCA9685_16_LED_Servo_Controller_NANO.hex is for the Arduino NANO.
Tims_PCA9685_16_LED_Servo_Controller_NANO_Old.hex is for the Arduino NANO with Old Bootloader.
Select which Arduino you are uploading to.
Select the port it is connected to.
Click Upload.

Here is a demonstration of controlling Servo



Here is a demonstration of controlling LED.




I have done a version 2, version 2 allows for controlling both LED and Servo on the same PCA9685 breakout board.


Also has a Pre-Set window, where you can have 20 pre-sets stored and values and re-send them at a click of a button..


This window can be resized to suit your own preferences.


The current version is: 2.0.0.11 (firm updated at 2.0.0.8)
If you install this version 2 over a previous version 2 under 2.0.0.5
you will need to load default pre-sets, the file is included in the zip.

I had to change a few things in the original pre-sets code so that; when a pre-set is sent, it also moves the sliders to the settings sent.
This is so adjustments can be made from known setups.
The file it saves settings to is just a basic rtf text file.

I am currently working on a project, that uses servo and LED, and I am altering the tool as needed to help me with the project.
If I think other things will help, I will update it.

I will add more about it if I am asked.
If you like it let me know.






Using you own application, to communicate with the Arduino:

I use Visual Basic.
I send data like this:
If OKtoSendData And SerialPort1.IsOpen Then
OKtoSendData = False
SerialPort1.Write(New Byte() {86,
BitConverter.GetBytes(Value_00)(0), BitConverter.GetBytes(Value_00)(1),
BitConverter.GetBytes(Value_01)(0), BitConverter.GetBytes(Value_01)(1),
BitConverter.GetBytes(Value_02)(0), BitConverter.GetBytes(Value_02)(1),
BitConverter.GetBytes(Value_03)(0), BitConverter.GetBytes(Value_03)(1),
BitConverter.GetBytes(Value_04)(0), BitConverter.GetBytes(Value_04)(1),
BitConverter.GetBytes(Value_05)(0), BitConverter.GetBytes(Value_05)(1),
BitConverter.GetBytes(Value_06)(0), BitConverter.GetBytes(Value_06)(1),
BitConverter.GetBytes(Value_07)(0), BitConverter.GetBytes(Value_07)(1),
BitConverter.GetBytes(Value_08)(0), BitConverter.GetBytes(Value_08)(1),
BitConverter.GetBytes(Value_09)(0), BitConverter.GetBytes(Value_09)(1),
BitConverter.GetBytes(Value_10)(0), BitConverter.GetBytes(Value_10)(1),
BitConverter.GetBytes(Value_11)(0), BitConverter.GetBytes(Value_11)(1),
BitConverter.GetBytes(Value_12)(0), BitConverter.GetBytes(Value_12)(1),
BitConverter.GetBytes(Value_13)(0), BitConverter.GetBytes(Value_13)(1),
BitConverter.GetBytes(Value_14)(0), BitConverter.GetBytes(Value_14)(1),
BitConverter.GetBytes(Value_15)(0), BitConverter.GetBytes(Value_15)(1),
13, 10
}, 0, 35)
}
Threading.Thread.Sleep(100) 'wait a little for comunication to end.
End If
The above:
86 = ASCII for V.
BitConverter splits the values(16bit) in the array(16) into two bytes(8bit).
13 = ASCII for Carriage Return.
10 = ASCII for Line Feed.

As you are only turning on or off, your values will be 0 or 4095
To change to a different PCA I send the address-64 and the frequency I want it set at.
My basic code looks like this:
If OKtoSendData And SerialPort1.IsOpen Then
OKtoSendData = False
Dim frequencyBit0 As Byte = BitConverter.GetBytes(Convert.ToInt16(My.Settings.Frequency_NumericUpDown))(0)
Dim frequencyBit1 As Byte = BitConverter.GetBytes(Convert.ToInt16(My.Settings.Frequency_NumericUpDown))(1)
My.Settings.DeviceAddress = DeviceAddress
SerialPort1.Write(New Byte() {65,
DeviceAddress,
frequencyBit0, frequencyBit1,
13, 10}, 0, 5)
End If
65 = ASCII for A.
DeviceAddress is only 1 byte as I have reduced the value by 64.
frequency needs to be split into two bytes.
13 = ASCII for Carriage Return.
10 = ASCII for Line Feed.

It has to be bytes (8 bit values) you send.
V or A followed by numbers wont work, that would just be send as text values.

So for example:
To send command to change PCA at address 64 and set frequency to 1000 Hz, would need the following:

ASCII A = 65, to let Arduino know its an address change. (ASCII for V would let Arduino know 16(32) values are coming)
Address = 64 - 64 = 0
frequency = 1000, split this 16 bit value in to 2 8 bit values, LSB and MSB.
1000 16bit binary = 0000 0011 1110 1000.
LSB = 1110 1000 = 232
MSB = 0000 0011 = 3
A carriage return and line feed. 13 and 10.

So sent would be: 65 0 232 3 13 10

Your app must send it as bytes not text.

When Arduino receives a correct command it will confirm it in normal ASCII text, also Arduino will send an "ok".
When your app. receives an "ok" from Arduino, your app. knows that it can send another command.

An example of sending values would be:
As my script shows it: V 4095 4095 0 0 0 0 0 0 0 0 0 0 0 0 0 0
as it is sent in bytes: 86 255 15 255 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 13 10



22 comments:

  1. Would you be willing to share the source code for this? I am doing something similar where I want to control multiple PCAs from a Windows app.

    ReplyDelete
    Replies
    1. I will help you with your application if you would like?
      Which code do you have difficulty with? The Arduino/PCA? or windows?
      All they do is send/receive 16 values. (as it shows in one line of the script)
      Handshaking is done with an "ok".

      Delete
    2. Thanks for the offer. I think I am probably using a similar approach to yours. I am scripting the control of a large number of leds individually. I was only just getting started the other day and was interested in your techniques, I have since got my prototyp working where the program tells the Arduino what to do. The Arduino itself is pretty dumb as the program does the hard work. No hurdles to overcome currently just need to add a database and flesh the whole thing out!!

      Delete
    3. I'm glad to hear your making headway.
      My windows app. sends a 'V'(so Arduino knows 32 bytes are to follow) followed by the sixteen values split into LSB and MSB.

      On the Arduino side, when it receives a 'V' it reads the next 32 bytes into an array.
      I use that array to send the data to the PCA9685.

      If you look at a typical PCA9685 library, you should be able to work out how to send the data to the PCA9685 in four chunks using the wire library. (wire has only 32 byte buffer).

      Let me know if you need help.
      When you say a large number of LED's, would that be 1024?
      It would be soo cool to see if it is?

      By the way, if you are using the breakout boards as above, you may not need to fit resistors on you LED's.
      Each pin has a 220 ohm resistor in series fitted.

      Delete
  2. In my app I am currently sending serial text commands to the arduino in a similar way to you I have a 3 char cmd type (which I will reduce to one char I think) followed by the decimal address of the PCA then pin # then a value for a total of 10 bytes. The arduino decodes the command and sends it on to the relevant PCA. I am currently creating a PCA9685 object from a library on the Arduino but it is my intention to do away with that library and go straight through the wire library.

    I want to get it working first then optimize.

    This whole thing is for a friend who is building a model railroad and is intended to control all lighting not part of the train stuff. It will be a time based control. For example in the theoretical morning a light may come on in the bedroom of a house shortly followed by one in a the kitchen. Or a store could be opening up with lights coming on in the store and on the storefront.

    You are correct, no resistors needed. My test rig has two PCAs with six LEDs each. I used this rig to write code for his basement stairs so each light fades up in a sequence. I used the serial comms technique in an app to control a string of rgb leds for a teenage daughters bedroom lol.

    I doubt he will reach the max number of PCAs but I'm coding so he can. On that note the Adafruit site states that you can only string 62 together. https://learn.adafruit.com/16-channel-pwm-servo-driver?view=all#chaining-drivers The six jumpers used to set the address = 111111 binary or 63 decimal which would seem like 64 is the max (including zero) so some confusion there. Have you tried 64?

    If you have bypassed the PCA library on the Arduino I'd be interested in some snipets of how you send data to the wire library if you are willing.

    ReplyDelete
    Replies
    1. If you look at the picture of the PCA above, where the solder jumpers are, you will see a 1+ to the left and +RW to the right.
      This makes up the full 8 bits (1 byte). The first bit (+1) of the byte cannot be change and the last bit (+RW) sorted in library.
      The first bit that is never changed is part of the address, so when you have all jumpers open, you actually have 7 bits 1000000 = 64.
      If you run my application you will see I have made the choices like this.

      Edited
      I have updated blog to show my app. code.

      Delete
  3. need heip led are working put not my servo

    ReplyDelete
    Replies
    1. Do you have a dedicated power supply for you servos?
      On the V+ pin?

      Delete
  4. how do i do the arduino script with the vales using a pca9685?

    ReplyDelete
    Replies
    1. If you use an Arduino library like one from Adafruit: https://learn.adafruit.com/16-channel-pwm-servo-driver?view=all
      Then the command .setPWM(servo_number, 0, value ); should be what you use.
      The value in the command would be the value sent in the script.
      If you find the values are slightly out, alter the frequency in the library to get equal results.
      You will probably need to write a loop or something that uses an array of values created with my tool.

      Delete
  5. Tim, I want to thank you for this, it seems like what I need to calibrate the servos on my 4DOF arm. I just seem to have an issue uploading the HEX to the Nano. I just hangs on the Uploading... part. Any suggestions? I checked the port and it is the right one.

    ReplyDelete
    Replies
    1. I made two versions of HEX files for the Nano. One is for ones with the old bootloader (and China clones) and the other for the new bootloader that Arduino now have for the Nano.
      Are you using the correct one?
      Also do you have the drivers installed for the Nano you have.
      Check that it shows in windows device manager ok, when you plug it in.
      I'm guessing it will say: Arduino Nano (COM??) if genuine. (I don't have a genuine)
      Or: USB-SERIAL CH340 (COM??) for one bought from china.

      Delete
    2. I am rebuilding/upgrading a Gemmy Dr. Shivers Halloween prop, finding your post and program has made that MUCH easier!
      THANK YOU!!
      Now, I have a question (of course) :)
      I am using version 2. I see where I can save different preset files if I want to control different animatronics. How can I save/load the different trim files for each one? Where is this info saved?
      Thanks!!

      Delete
  6. Hello Tim

    I am a beginner in robotics

    It is a wonderful project "Tims PCA 9685 Controller"
    I managed everything works.
    But is it possible to make the servos run slower?

    Thank you

    ReplyDelete
  7. Hello,
    I'm using your controller to move a robot arm (6 axes), I would like to add some sensors such as a proximity sensor to close the clamp or a gyroscope to keep the clamp horizontally, or even just the Limit Swhitch.
    Could you kindly share the source so I can manage the inputs from Arduino?
    I use your example only to play and not professional
    Tabte congratulations for your work, it's fantastic, and thank you very much

    ReplyDelete
  8. Muy buena aplicación. sin embargo al guardar los scripts y tratar de cargarlos nuevamente me genera error. Gracias

    ReplyDelete
  9. Thank you very much for the application. I have a problem, I connect the whole circuit, pca 9685, a single servo, a connected source, an Arduino UNO, etc., I have windows 10, I have the program installed but when I move the servo controller from the program the servo does not move, and the Feedback only returns this:
    Port Closed For Some Reason
    Ver. 2.10
    Device Address Set to: 1000000
    Frequency Set to: 50
    okay
    okay
    okay
    okay
    okay
    okay
    okay
    okay
    ...
    Time Out
    Retrying
    Time Out
    Retrying

    maybe I'm missing something. Can you help me please?

    ReplyDelete
  10. Wow great project, nice sequencer, almost just what i need LOL. is it possible to put the script onto a arduino, so when for example push a button 1 on my esp32, the esp32 runs the script1 to the pca9685 and when i push button 2 , script 2 runs. so i can run my robot not connected to the computer. first i program the robot's esp32 using your stuff, then put a new code on the esp32 within it some of your scripts (case 1 one run script1, case 2 run 2)

    I have the esp32 and pca9685 connected to a bluetooth app with 4 buttons in it working, ( know its only putting on a led when pressed button in app, but i whant to runs a sequence with servo's and leds, evertime i pres 1 button.

    I can make the sequence with a nano, and then copy the script to a esp32 withs also using the adafruitpwmservo libary ?

    Thanks in advance,

    ReplyDelete
  11. hola buenas, se puede para la placa ESP32? me sería de gran ayuda, gracias.

    ReplyDelete
  12. Hi Tim. Many many thanks for this application. I am working on a werewolf head with multiple servo's and it is making it very easy to set up emotions.
    One issue I do have is that your scripts are not saved as plain ASCII, but rather with \rtfl etc embedded in it.
    Also - is it possible to see the ARDUINO source code as it would be great to set it up with a SD card and run pre-programmed scripts.
    Many many thanks
    Dave

    ReplyDelete
  13. Hi Tim.
    Really enjoying using your application, however when I save out a script, it is saved in a strange text format which makes it very difficult to edit with Notepad. i.e. Making a variety of snippets of movements and combining them in to a larger snippet.
    Can you assist with this issue?
    Many thanks
    Dave.

    ReplyDelete
  14. I need to apologize to all above.
    Never got any notification for a lot of posts, I have only just found them wanting moderation.
    Should any of you still need any info the best place to get in touch is at Instructables, There I go under the name of Palingenesis.
    https://www.instructables.com/member/Palingenesis/instructables/

    ReplyDelete