Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

BoostC Charlieplexed PWM 32

Status
Not open for further replies.
Transistors are 2N3904 NPN. Most people see that they're sourcing drivers and assume they're PNP (because the drawing is so fuzzy).
I used 2N2222A's with 1.2K base resistors.

and 20 ohm current limiting resistors on the rows
I've got 330's on the rows. Too much, but they were there and I wanted to start out safe.

Guess I'll go over the whole thing and trace every wire again. Sigh... :p
 
Wrote some test code and I have something happening. LED's are flashing, but not quite properly under my control yet. It's not dead. I just haven't figured out what the problem is yet. :D
 
Nice design Sir ...I like it very much....

May I hack your hardware design? but not the code :)

Also can you show the underneath of your board Sir if you don't mind?
Hi Gayan,

I'm not sure what you mean by "hack my design".

Attached is picture of bottom of board. It contains one surface mount PNP row driver transistor on GP0 (an experiment to increase peak current from 20 ma to around 50 ma).

Mike
 

Attachments

  • pwm-20 pcb bottom.PNG
    pwm-20 pcb bottom.PNG
    536 KB · Views: 500
  • PWM-20 v2 schem.PNG
    PWM-20 v2 schem.PNG
    59.7 KB · Views: 311
Hi Mike,
Nice demo, what do you have planned for the practical usage of the plex.?

I expect it will be a slighter larger PIC, to enable an external input of some kind.

Regards
 
Looks very nice. Did you say my program doesn't work?
No it doesn't. I slowed the clock down to a crawl and still get the same LEDs lit, but flickering now, as the update rate is too slow. Some of them are brighter than others and some aren't on at all. Is it supposed to animate (move)? I haven't really deciphered that ISR yet. Anyway, nothing moves.

Maybe what I'll do is draw up a schematic of what I've done and let you have a look. Maybe I did something different than you. Your schematic seemed just a tiny bit unclear to me. What program is that?
 
Last edited:
Hi Eric,

No practical plans. This board was originally the prototype for a Serial Addressable Bar/Dot Display Controller which I used in a power management system to display Battery Capacity and Battery Load conditions.

Now the board is just a test bed, though it's been programmed a couple times to display staggered night rider patterns for a visiting niece or nephew (grin).

Regards, Mike
 
No it doesn't. I slowed the clock down to a crawl and still get the same LEDs lit, but flickering now, as the update rate is too slow. Some of them are brighter than others and some aren't on at all. Is it supposed to animate (move)? I haven't really deciphered that ISR yet. Anyway, nothing moves.

Maybe what I'll do is draw up a schematic of what I've done and let you have a look. Maybe I did something different than you. Your schematic seemed just a tiny bit unclear to me. What program is that?

The program is working then. My program doesn't animate the LEDs. It simply shows how to use the LED PWM interface (the led[] array) to light the LEDs to some PWM level. Some are off (0) some are 0.625% duty cycle (1) and a couple are higher duty cycles. You simply stuff the led[] array with duty cycle values between 0 (off) and 31 (full brightness). You would animate the display my manipulating those led[] array PWM values within some simple loops.

I probably should have left my original smooth fade duty cycle values in there (also not animated), which were;

Code:
    led[0] = led[19] = 31;      // 100% brightness
    led[1] = led[18] = 23;      //  90% brightness
    led[2] = led[17] = 18;      //  80% brightness
    led[3] = led[16] = 14;      //  70% brightness
    led[4] = led[15] = 11;      //  60% brightness
    led[5] = led[14] = 9;       //  50% brightness
    led[6] = led[13] = 7;       //  40% brightness
    led[7] = led[12] = 5;       //  30% brightness
    led[8] = led[11] = 3;       //  20% brightness
    led[9] = led[10] = 2;       //  10% brightness
What's confusing about the schematic? Is it the dark blue diagonal "floating" row line?

Let me see if I can work up an explanation for that ISR which is doin' all the work.

Mike
 
Last edited:
Can someone help me come up with a Cylon night-rider routine for that demo program? Something like a night rider but with trailing LEDs that fade? I would try to throw something together quickly but Helen's sister's wedding is tomorrow and we have to do rehersal and dinner and stuff so I'm a little short of time today.

Regards, Mike
 
The program is working then. My program doesn't animate the LEDs.
Ah. Yes it is. The brightness setting code I had looked like this:
Code:
  led[0] = led[19] = 1;         //
  led[1] = led[18] = 1;         //
  led[2] = led[17] = 4;         //
  led[3] = led[16] = 0;         //
  led[4] = led[15] = 0;         //
  led[5] = led[14] = 1;         //
  led[6] = led[13] = 1;         //
  led[7] = led[12] = 0;         //
  led[8] = led[11] = 1;         //
  led[9] = led[10] = 1;         //
which looks totally random. I assumed something was wrong.

I replaced the numbers just now with your:
Code:
    led[0] = led[19] = 31;      // 100% brightness
    led[1] = led[18] = 23;      //  90% brightness
    led[2] = led[17] = 18;      //  80% brightness
    led[3] = led[16] = 14;      //  70% brightness
    led[4] = led[15] = 11;      //  60% brightness
    led[5] = led[14] = 9;       //  50% brightness
    led[6] = led[13] = 7;       //  40% brightness
    led[7] = led[12] = 5;       //  30% brightness
    led[8] = led[11] = 3;       //  20% brightness
    led[9] = led[10] = 2;       //  10% brightness
and now I understand. It looks great.

What's confusing about the schematic? Is it the dark blue diagonal "floating" row line?
The schematic isn't so bad I guess. I was just generally confused, but I'm starting to get my head around it now. Mostly I'm relieved that it was working all along and I didn't do some weird random screwup. :p

I still need to grind through that ISR till I understand exactly what's going on in there. I have most of the day off, so I think I'll grind today. :D
 
Last edited:
Can someone help me come up with a Cylon night-rider routine for that demo program? Something like a night rider but with trailing LEDs that fade? I would try to throw something together quickly but Helen's sister's wedding is tomorrow and we have to do rehersal and dinner and stuff so I'm a little short of time today.
I'll see if I can do something while I'm "grinding" anyway.
 
Hi Eric,

No practical plans. This board was originally the prototype for a Serial Addressable Bar/Dot Display Controller which I used in a power management system to display Battery Capacity and Battery Load conditions.

Now the board is just a test bed, though it's been programmed a couple times to display staggered night rider patterns for a visiting niece or nephew (grin).

Regards, Mike

Hi Mike,
The things we have to do for our kids.

I appreciate the test bed method of proving a concept, its so much easier than trying to develop an idea in the middle of an actual application.

It looks a useful feature which could be used for a number of practical projects.:)
 
Hey Mike! If you're still reading, I'm having a strange problem. I put stuff in the while() loop to alter the led[] array's contents on the fly, but nothing happens. I can't seem to use debug on this dinky little chip, and there's no spare pins to put a debugging blinky LED on, so I'm not sure what's happening. Any ideas?
 
Send me your code so I can double check you? Looks like you've got mclr enabled (your photo'). I'll just turn it back off for my board...

k8lh(at)arrl.net
 
Last edited:
Send me your code so I can double check you?

k8lh(at)arrl.net
Couldn't be much simpler. If I'm screwing this up I'll sure be embarrassed. :p Boostc.h has been included for the delays.
Code:
#include <system.h>
#include <boostc.h>

#pragma DATA _CONFIG, _MCLRE_ON&_WDT_OFF&_INTOSCIO
#pragma CLOCK_FREQ 8000000

unsigned char led[20];          // led matrix, pwm values 0..31
unsigned char shadow = 0;       // isr, trisio shadow register
unsigned char colpos = 1;       // isr, gpio column ring counter bit
unsigned char dcy = 15;         // isr, duty cycle counter, 0..31
unsigned char dc0 = 0;          // isr, row 0 (gp0) pwm value, 0..31
unsigned char dc1 = 0;          // isr, row 1 (gp1) pwm value, 0..31
unsigned char dc2 = 0;          // isr, row 2 (gp2) pwm value, 0..31
unsigned char dc3 = 0;			// isr, row 3 (gp4) pwm value, 0..31
unsigned char addr = (unsigned char) &led;

#define end_of_period dcy.5		// isr, end of 32 pwm steps
#define end_of_cycle colpos.6	// isr, end of 5 column update cycle

void main()
{
	unsigned char x,temp;
	osccon = 0b01110001;		// set 8 MHz INTOSC
	cmcon0 = 7;					// comparator off, digital I/O
	ansel = 0;					// a2d module off, digital I/O
	trisio = 0b00111111;		// set all pins to inputs
	gpio = 0;					// set all output latches to '0'

//  setup 100 usec Timer 2 interrupts (8 MHz clock)
	pir1 = 0;					// clear peripheral interrupt flags
	pie1 = 0;					// clear peripheral interrupt enables
	pie1.TMR2IE = 1;			// set Timer 2 interrupt enable bit
	tmr2 = 0;					// clear Timer 2 register
	t2con = 0b00000100;			// '0-------' unimplemented bit
								// '-0000---' TOUTPS<3:0>, postscale 1
								// '-----1--' TMR2ON, turn Timer 2 on
								// '------00' T2CKPS<1:0>, prescale 1
	pr2 = 200-1;				// 200 x 500-nsec 'ticks' = 100 usecs
	intcon = 0b11000000;		// '1-------' GIE, enable global ints
								// '-1------' PEIE, enable peripheral ints
								// '--0-----' T0IE, TMR0 ints disabled
								// '---0----' INTE, off
								// '----0---' GPIE, IOC disabled
								// '-----000' T0IF/INTF/GPIF flags
//  simple led interface to pwm driver, duty cycle values of 0..31
	led[0] = led[19] = 0;
	led[1] = led[18] = 0;
	led[2] = led[17] = 0;
	led[3] = led[16] = 0;
	led[4] = led[15] = 0;
	led[5] = led[14] = 0;
	led[6] = led[13] = 0;
	led[7] = led[12] = 0;
	led[8] = led[11] = 0;
	led[9] = led[10] = 0;

	while(1){
		led[0] = 2;
		led[1] = 3;
		led[2] = 5;
		led[3] = 7;
		led[4] = 9;
		led[5] = 11;
		led[6] = 14;
		led[7] = 18;
		led[8] = 23;
		led[9] = 31;
		delay_ms(200);
		led[0] = 1;
		led[1] = 1;
		led[2] = 1;
		led[3] = 1;
		led[4] = 1;
		led[5] = 1;
		led[6] = 1;
		led[7] = 1;
		led[8] = 1;
		led[9] = 1;
		delay_ms(200);
	}
}

/********************************************************************/
/*  interrupt service routine                                       */
/********************************************************************/
/*                                                                  */
/*  100 usec Timer2 interrupts, 32 interrupts/column (3.2 msecs)    */
/*  for 32 pwm brightness levels. 160 interrupts (16 msecs) for a   */
/*  complete 5 column update cycle (62.5 Hz refresh rate).          */
/*                                                                  */
/*  led array duty cycle parameter values of 0..31 produce actual   */
/*  duty cycles of 0% to 20% per LED in 0.625% (100 usec) steps.    */
/*                                                                  */
/*  57 to 84 cycles or approximately 42% "overhead" (8 MHz clock)   */
/*                                                                  */
/********************************************************************/
void interrupt()
{ 
	if(dc0 == dcy)				// if row 0 duty cycle match
		shadow.0 = 0;			//   clear shadow bit (gp0)
	if(dc1 == dcy)				// if row 1 duty cycle match
		shadow.1 = 0;			//   clear shadow bit (gp1)
	if(dc2 == dcy)				// if row 2 duty cycle match
		shadow.2 = 0;			//   clear shadow bit (gp2)
	if(dc3 == dcy)				// if row 3 duty cycle match
		shadow.4 = 0;			//   clear shadow bit (gp4)
	dcy++;						// increment duty cycle counter
	asm{
		movf		_colpos,W
		andwf		_shadow,W	// is the float bit required?
		btfss		_status,Z	// no, skip, else
		iorlw		0b00100000	// set the 'float' bit
		iorwf		_shadow,W	// pick up led bits
		iorwf		_colpos,W	// pick up column bit
		xorlw		0b00111111	// invert all
		movwf		_trisio		// update the column LEDs
	}

	if(end_of_period){			// if all 32 pwm steps complete
		dcy = 0;				// reset duty cycle counter
		asm{
			bcf		_status,C	// shift column bit mask
			rlf		_colpos,F
			btfsc	_colpos,3	// if gp3 bit position
			rlf     _colpos,F	// shift to gp4 bit position
		}
		if(end_of_cycle){		// if all 5 columns have been updated
			colpos = 1;			// reset colpos bit to column 0
			asm{				// reset led[] array address pointer
				movlw	_led
				movwf	_addr	// addr = (unsigned char) &led
			}
		}
		shadow = 0b00010111;	// setup shadow (all row bits "on")
		gpio = colpos;			// setup output latch, only 1 bit high
		fsr = addr;				// setup new column pwm work variables
		dc0 = indf;				// row 0 (gp0) pwm value, 0..31
		fsr++;
		dc1 = indf;				// row 1 (gp1) pwm value, 0..31
		fsr++;
		dc2 = indf;				// row 2 (gp2) pwm value, 0..31
		fsr++;
		dc3 = indf;				// row 3 (gp4) pwm value, 0..31
		addr = fsr + 1;			// save array address
	}
}
It should be flickering madly, but it doesn't. Just displays a nice ascending-brightness row of 10 LEDs.
 
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top