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



9 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. Thank you for sharing wonderful information with us to get some idea about it.
    Mulesoft Online Training india
    Mulesoft Online Training in Hyderabad

    ReplyDelete