PDA

View Full Version : PCA9685 control



Scampy
- 25th March 2016, 21:43
Hi,

I've used the above chip in several projects before, but have noticed a small issue with a current project as the code is writing to the PCA chip each time in the loop and I think it's causing the flicker in the LEDs on the output pins of the PCA chip.

I have the following section of code repeated for each of the 16 channels



If Counter1 => CH1_on_Time and counter1 < CH1_off_time then ' check to see if the time in minutes since midnight matches the Channel on time
CH1_PWM = fadeset1 ' and of so set the PWM value (0 to 4095) to match the fadeset value (also 0 - 4095)
endif
If Counter1 => CH1_off_Time or Counter1 < CH1_on_time then ' check to see if the time in minutes since midnight matches the channel off time
CH1_PWM =0 ' and if it does, then set the PWM value to 0, this turning the channel off
endif


The comments are self explanatory. At the end of the main program loop I have a gosub to a subroutine that writes to the chip



pcaChannel = 0
i2cControl = $6 + 4*pcaChannel
I2CWRITE SDApin,SCLpin,i2cWriteAddress,i2cControl,[0,0,CH1_PWM.lowbyte,CH1_PWM.highbyte]



Now typically once the brightness (fadeset1, fadeset2, etc) has been set, and the condition is met to output the PWM value there would be no need to alter it whilst it's ON/OFF condition is met, and as the PCA chip maintains the value it only needs to be written to once at the start of the condition. However there is a need for the program to loop, and thus check for any of the on/off times are met and if so write the value of its corresponding fadeset variable, so how best to prevent the loop from writing to the PCA chip on each cycle.

Any ideas ?

Tabsoft
- 25th March 2016, 22:05
Have you thought of using a Flag variable?
During your checking routine, set a Flag if you need to write to the PCA.
Check the Flag to determine if you need to do the gosub to write to the PCA chip.

Scampy
- 25th March 2016, 22:05
Uhmmm - it only really seems noticeable when all the LEDs are on... I might need to do further investigation...

Scampy
- 25th March 2016, 22:17
Tabsoft, thanks for the suggestion,

It seem to dim for a split second only when all outputs are high, if only 15 are lit there is no distinguishing flicker.

Well it's not a power issue as I've just used a 5v supply rather than the 5v from the development board and it still dims very slightly when it the data is written to the PCA chip but only when all 16 channels are outputting a value

Belay that... its actually is noticeable with less than 15

Scampy
- 25th March 2016, 22:52
Have you thought of using a Flag variable?
During your checking routine, set a Flag if you need to write to the PCA.
Check the Flag to determine if you need to do the gosub to write to the PCA chip.

Can't get my head round it, at least because the condition at which the PCA get written to will be true.

I thought of


If Counter1 => CH1_on_Time and counter1 < CH1_off_time then ' check to see if the time in minutes since midnight matches the Channel on time
CH1_PWM = fadeset1
flag=1
endif


with a IF Flag=1 then gosub update... but that would still cause the update subroutine to be updated on each pass of the loop...

tumbleweed
- 26th March 2016, 00:00
Instead of just setting a flag, keep a copy of the last thing written to the PCA and only call the sub if it's different from CH1_PWM



If Counter1 => CH1_on_Time and counter1 < CH1_off_time then ' check to see if the time in minutes since midnight matches the Channel on time
CH1_PWM = fadeset1 ' and of so set the PWM value (0 to 4095) to match the fadeset value (also 0 - 4095)
endif
If Counter1 => CH1_off_Time or Counter1 < CH1_on_time then ' check to see if the time in minutes since midnight matches the channel off time
CH1_PWM =0 ' and if it does, then set the PWM value to 0, this turning the channel off
endif
...
' check to see if CH1_PWM is different from last programmed value
if (CH1_PWM <> PCA_PWM) then
gosub SetPCA
endif



SetPCA:
PCA_PWM = CH1_PWM
pcaChannel = 0
i2cControl = $6 + 4*pcaChannel
I2CWRITE SDApin,SCLpin,i2cWriteAddress,i2cControl,[0,0,PCA_PWM.lowbyte,PCA_PWM.highbyte]
return

Scampy
- 26th March 2016, 00:08
Instead of just setting a flag, keep a copy of the last thing written to the PCA and only call the sub if it's different from CH1_PWM



If Counter1 => CH1_on_Time and counter1 < CH1_off_time then ' check to see if the time in minutes since midnight matches the Channel on time
CH1_PWM = fadeset1 ' and of so set the PWM value (0 to 4095) to match the fadeset value (also 0 - 4095)
endif
If Counter1 => CH1_off_Time or Counter1 < CH1_on_time then ' check to see if the time in minutes since midnight matches the channel off time
CH1_PWM =0 ' and if it does, then set the PWM value to 0, this turning the channel off
endif
...
' check to see if CH1_PWM is different from last programmed value
if (CH1_PWM <> PCA_PWM) then
gosub SetPCA
endif



SetPCA:
PCA_PWM = CH1_PWM
pcaChannel = 0
i2cControl = $6 + 4*pcaChannel
I2CWRITE SDApin,SCLpin,i2cWriteAddress,i2cControl,[0,0,PCA_PWM.lowbyte,PCA_PWM.highbyte]
return


thanks, that seems logical as the only change will be if the ON or OFF condition is met. Thanks, I'll give that a try

Scampy
- 26th March 2016, 00:52
It must be something to do with the internals of the PCA chip as the modified code that includes Tumbleweed's suggestion has the same effect, even though the PIC code isn't running the subroutine (I have a led that is lit whilst the sub routine is being accessed and that pulses once when the lights come on, and once again when the lights go off)

Would there be anything to gain if the code in the SetPCA: section above is placed in the check section like this



If Counter1 => CH1_on_Time and counter1 < CH1_off_time then ' check to see if the time in minutes since midnight matches the Channel on time
CH1_PWM = fadeset1 ' and of so set the PWM value (0 to 4095) to match the fadeset value (also 0 - 4095)
endif
If Counter1 => CH1_off_Time or Counter1 < CH1_on_time then ' check to see if the time in minutes since midnight matches the channel off time
CH1_PWM =0 ' and if it does, then set the PWM value to 0, this turning the channel off
endif
...
' check to see if CH1_PWM is different from last programmed value
if (CH1_PWM <> PCA_PWM) then
PCA_PWM = CH1_PWM
pcaChannel = 0
i2cControl = $6 + 4*pcaChannel
I2CWRITE SDApin,SCLpin,i2cWriteAddress,i2cControl,[0,0,PCA_PWM.lowbyte,PCA_PWM.highbyte]
endif

tumbleweed
- 26th March 2016, 12:41
Would there be anything to gain if the code in the SetPCA: section above is placed in the check section like this
It'll save you the call/return (so slightly less time/code), but it won't really change the timing much in the grand scheme of things.

If the flicker is caused by writing too often to the PCA it won't change that at all.

Scampy
- 11th April 2016, 15:57
I took delivery of a logic analyser today and thought I would test it to see what the outputs are like at different brightnesses. I've got some really strange traces and wondered if anyone has any ideas as to why the PCA chip is behaving like this.

I set the brightness to 10%, and did a scan and this was the result

http://micro-heli.co.uk/LA1.png

I was expecting to see eight traces the same as channel 7 at the bottom, but the other channels seems to have a strange artefact, so I zoomed in to see if it was just something to do with the way the traces were being displayed on the screen, but this was the result

http://micro-heli.co.uk/LA2.png

The "normal" pulse was itself split up into a series of multiple pulses, so I zoomed in again and took a measurement

http://micro-heli.co.uk/LA3.png

I have no idea what's happening, and I still can't find any evidence of the chip refreshing momentarily once a second which would tie in with the regular 1sec flicker that is noticeable to the eye

Scampy
- 11th April 2016, 20:36
I think I've sorted it... possible ground loop, removed the GND wires between the LA and breadboard and now all seems fine