Log in

View Full Version : First use of i2c from parallel output processing



queenidog
- 31st December 2017, 17:00
I did a project where I used a PIC 16F887 and used all the ports, A,B,C, D for outputs to triac boards. Lots of wires.

Now I want to do another similar project using I2C protocol, conversing with 16 channel port expanders connected to 16 channel triac boards. I need 7 of each type to do the job.

I've never used I2C but it is the obvious choice for my project since all components except MCU will be outside, a few meters from the MCU.

So...how do I do it? I've read a bit about I2C and looked at examples on MELabs website. They all deal with EEPROM communication. I just have to write out patterns 8 or 16 bits at a time to my 7 I2C devices.

My current programming references ports A,B,C,D. How do I get that information out to my 2-wire devices. Eg, If I currrently write out $FF to energize 16 lights, how do I program this output to go down the 2 wire I2C line. (I use counters and data tables to load my peripheral ports too...not sure where or how to write these values out, eg if I'm sending a stream of data to light 16 lights individually in a row.)

Thanks in advance

mpgmike
- 31st December 2017, 19:42
You didn't mention what your PIC16F877 will be talking to. Your expander board will need something to convert serial data from your PIC to hardware control. Once you have that decided, you must create your own communication protocol. I would recommend each I2C transmission constitute 2 BYTEs of data; 1st BYTE designates PORT (A, B, C, or D) with 2nd BYTE containing the PORT value. On the sending end, 1st BYTE may be $01 for PORTA, $02 for PORTB, etc. Second byte would be the data; $0F turns ON the lower 4 LEDs. A command "I2CWRITE DP, CP, cont, add, [$01, $0F]" would tell your expander board to light up the lower 4 outputs of the equivalent of PORTA. On the receive end, a SELECT CASE Byt1 can filter through the 1st byte; CASE IS = $01 : OutPortA = Byt2 : CASE IS = $02 : OutportB = Byt2 and so forth.

This isn't copy/paste code, but hopefully guides you in the right direction.

Scampy
- 1st January 2018, 11:51
I use a PCA9685 chip in several projects to control lighting. This gives me 16 channels (or 16 individual lights) which can have their brightness set in 4095 steps.

Variables used for the PCA chip



i2cControl var BYTE 'Used for PCA chip control
i2cReadAddress var BYTE
i2cWriteAddress var BYTE
pcaAddress var BYTE
oldMode var BYTE
newMode var BYTE
pcaChannel var BYTE



This code sets the chip up



'************************************************* ******************************
'Initialize the PCA9685

i2cReadAddress = pcaAddress << 1
i2cWriteAddress = i2cReadAddress | 1
i2cControl = $0 ;Reset
I2CWRITE SDApin,SCLpin,i2cWriteAddress,i2cControl,[$0] ;PCA9685_MODE1 $0
i2cControl = $0 'PCA9685_MODE1 $0
I2CREAD SDApin,SCLpin,i2cReadAddress,i2cControl,[oldMode] ;Get old mode
newMode = (oldMode & $7F) | $10 ;MODE1 Sleep
i2cControl = $0
I2CWRITE SDApin,SCLpin,i2cWriteAddress,i2cControl,[newMode] ;PCA9685_MODE1 $0
i2cControl = $FE ;PCA9685_PRESCALE $FE
I2CWRITE SDApin,SCLpin,i2cWriteAddress,i2cControl,[6] ;Prescaler is now 6 was 11
i2cControl = $0 ;PCA9685_MODE1 $0
I2CWRITE SDApin,SCLpin,i2cWriteAddress,i2cControl,[oldMode] ;Set old mode
i2cControl = $0 ;PCA9685_MODE1 $0
I2CWRITE SDApin,SCLpin,i2cWriteAddress,i2cControl,[oldMode | $A1 ] ;Set MODE1 AutoIncrementOn | $A1


I then have routines that check for on/off times and preset brightness (CHx_PWM) and then the values are written to the PCA chip



if (CH1_PWM <> PCA1_PWM) then ' check to see if the value has changed, and if it has
PCA1_PWM = CH1_PWM ' match the values in each variable and then write to the PCA chip
pcaChannel = 0
i2cControl = $6 + 4*pcaChannel
I2CWRITE SDApin,SCLpin,i2cWriteAddress,i2cControl,[0,0,CH1_PWM.lowbyte,CH1_PWM.highbyte]
endif


The above is repeated for each channel, but I'm sure you could have some FOR / NEXT loop to write the 16 values to the chip.


It might be clunky code, but it's been controlling the lighting in my wife's 12th scale dolls house for over a year now with no issues. I don't want to post up the full code as I may look at marketing my boards at some point in the future. The good thing about the PCA's outputs is that it can directly drive Meanwell LDD range of LED drivers, making it ideal for use in aquarium lighting, or with the use of a couple of resistors, FETs each channel can be used to switch high current 12v supplies on or off.

Using a PCA chip is a lot simpler than trying to wire up all the ports on a PIC for direct outputs. You could use more than each with a different address if you have multiple external boxes

Hope that helps

queenidog
- 1st January 2018, 17:11
Thanks for the reply. I've done more research, looked at Arduino examples (I have lots of Arduino, but PIC seems better because of the great IDE and PBP!)
The PIC will be talking directly to the port expanders (which use MCP23017s) that communicate with I2C. I realize now I don't need a 40 pin MCU, any fast MCU with I2C comm and memory to hold my program will do. I've seen some 8 pin PICs that MIGHT do the job!!

At issue at this point is the matrix switching I have to do which I'm doing it now for another Christmas Display. My new display will be a 5-point star shape with 6 segments, counting the pentagon in the middle. Each segment will have a port expander and 16 channel triac board. The incandescent lights I'm lighting will be RGB, so in order to light any individual light bulb I must enable the segment(s) and light color(s) (one board) and hold those triacs on until I can enable the individual light "triads".8555 See attached PDF file where I show the "boards" on the segment they are to control. Each of the lights shown (yellow or red) is actually a "triad" of RGB lights.

So basically I enable the segment and light COLOR, then enable up to 16 channels with another triac board which then turn on the lights. Can I do this with I2C? Or I should say with the MCP23017? I have to hold a value (data and address) while I set the other one up, then enable them both at the "same" time. I don't have any of my hardware setup or purchased yet so I can't test it.

Scampy
- 1st January 2018, 21:57
Are you wanting to turn on/off each of the 16 lamps in each of the segments individually, or just turn on/off all 16 lamps at the same time. If they are RGB, do you want to be able to change each of the RGB components of each lamp?

If I was going to do this I would either look at DMX and addressable LEDs / drivers, or, if you still wanted to do this with a PIC, then I would use 3 x PCA9685's per segment, one each for the individual R, G and B segment for each lamp. This way you can not only produce whatever colour you want, but also any brightness you want, and if you're clever even have it chasing and making patterns.

queenidog
- 7th January 2018, 14:35
My wife also does 1/12 scale "dollhouses" and has about 20 different scenes. And I light some of her work as well. Wife has won a number of competitions and has been published 1/2 dozen times.

queenidog
- 7th January 2018, 14:48
Attached is my proposal. One PIC driving 7 MCP23017 port expanders, driving 6-16 channel triac boards in a matrix (the seventh board is the matrix controller that controls what segment gets turned on and what color light). In other words I have to present the matrix code and the individual light code at the same time, like a logical AND circuit.

The "matrix controller" could be another i2c device, or it could just be 9 channels of DIO from the PIC, 6 channels for each segment of the star and 3 for the color, depending how easy it is to program the i2c version. I'm thinking of "repeated start" in the i2c code where a stop is not sent at the end of the string, but a start is instead. That way I can push the code to the MCP23017 simultaneously.

If I do the 9 channel DIO, then I can just put the i2c individual-light code into the same loop that defines what lights are going to light up. Make sense?

I envision it like this: 1) determine what segment to light, 2) determine what color, 3)enable those triacs and hold, 4)determine 16 bit light pattern to display, 5) transmit to I2C network. As soon as that happens of course, the lights should light. Then the code will jump to next routine.

The triac matrix is not a problem. I have that running now with straight DIO outputs from a PIC.

queenidog
- 7th April 2018, 00:19
I made a model, using mono-color LED, and I2C port expanders. Worked extremely well.
I then made a model using RGB LEDs, again with port expanders and wired in a matrix so I could turn on just the red, just the green, blue, or any other combination. Of 16 LEDS I could light up just one, in any color. Great. I'm on a roll.
I made a small "test bench" using SSRs and 110V incandescent bulbs, using the SSRs in a matrix (column and row). There was some leakage through bulbs that were not supposed to be on (not triggered by an SSR) but for the most part it was manageable. So I scaled it up to the proper size: 48 incandescent bulbs in RGB colors (16 of each) and fed by 16 SSRs. For the color I had 3 SSRs feeding a "color bus". Didn't work. So much leakage through the bulbs (they aren't like LEDs, diodes and one way current) that when I tried to light ONE bulb, I get all three colors active. This even though I might only activate the Red color bus for example. I'm hooped. Not sure what to do now.

mpgmike
- 7th April 2018, 03:41
Maybe add diodes so the bulbs work like LEDs?

queenidog
- 13th May 2018, 23:30
It's been a while since I was here 'cause I was really into getting the Arduino/AC matrix going. AC matrix with triacs or SSRs does not work. The matrix part works but there is too much leakage between the rows and columns of incandescent bulbs. I abandoned that project and now going to high intensity 3-10 W RGB LEDs. I currently have a model where I can light individual RGB LEDs in any fashion or color, through port expanders (MCP23017) and 3 DIO from an Arduino UNO. Well, I'm about to abandon the Arduino!! It's a great development tool if you can get through that absolutely horrid C++. I've been using it for 5 months now and it is a real PITA! Syntax will kill you, and the error reporting may as well not exist because the error message NEVER relates to the problem. I never had problems with PBP, using a LabX-1 from MELabs for development, then making my own MCU board. I'm going back that way. I'd like to thank all those that replied to my initial question which was kind of ..uh..stupid, now that I know I'm doing!! You guys have given me some good insight on how to get variables properly defined to make coding easier down the line. I have "stuff" running (16 LEDs each on 5 boards with a 16 channel port expander ) but to go further means more C++ thrashing. I spend more time fixing syntax than I do programming. I'm tired of it. Giving up. Going back to PIC and PBP.

queenidog
- 13th May 2018, 23:39
I basically want to light "everything" in as many patterns as possible: light chasers, all 16 at time, blinking, fading (maybe if I use PWM), rotating, etc, etc. I want individual control over 110 RGB high intensity (3-10 w) LEDs. Yeah, I'll need tons of power (each LED uses about 400mA @12 Volts (Vf about 9 volts since it is multi LED). Anyway, that's a issue down the road that I have to do some actual calculations for. I need my I2C to work in PBP now, having abandoned the Aruduino. Wish I could use addressable LEDs, but they don't have the luminosity to be viewed from 500 yards. My new matrix is three DIOs for RGB (to 110 lights) and 7-16 channel port expanders, as shown in diagram further down this thread. Forget about triacs. They don't work in a matrix with incandescent filaments.