ISR Multiplexing strategy with brightness/gamma adjustment

Go To Last Post
33 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My plan to support multiple brightness levels has been to run the ISR a multiple number of times faster.  For example, if I want 100 Hz refresh and have 8 rows, that would be 800 Hz with a single brightness.  If I want 8 levels of brightness, I would run it at 6400 Hz and then the ISR would look at the brightness level and decide which of those 8 extra cycles it should turn off the row, then every 8 cycles it would go on to the next row.  I'm not saying that is the best approach, but I've used it and it works.  Besides the inefficiency of the extra ISR cycles, you just can't get too many levels of brightness and forget about gamma adjusting them.

 

So this takes me to the second idea which I've tried with some success.  Instead of having evenly sliced slots, adjust the time so that it turns at the time to turn off the row and then delay the proper time to enable the next row.  So now you don't have 8 times the cycles for 8 levels or brightness, but only 2 cycles.  I tried this with a compare match and was pushing it ahead the X cycles I wanted, but as long as the timer is running fast enough such as a 16 bit timer running at clk/1, you might have 10000 cycles to work with.  We can easily then pick between returning at 8000 cycles or 8020 cycles.  This gives the granularity to do gamma correction, but there is one issue when I was testing it.  If you are trying to do a small amount (like the lowest settings which when gamma) you run into only a few cycles.  If you push ahead the compare match only a few cycles then you probably have already missed it.  That was as far as I got with the testing.  Clearly you can't let the on cycles vs off cycles get too small.  Then I thought about testing the amount and just waiting in the ISR for a small number of cycles like less than 50 or so, but that seems like a kludgy ugly solution.

 

So...what ideas do you guys have for multiplexing with some granular control over how many cycles it is on vs. how many cycles it is off.  Would an approach of using two compare matches solve the too small problem?  Is there a better way all together to do it?

 

I'm going to be implementing this on a mega4809 and it has additional interrupt features if those open up any new ideas too.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

>If you push ahead the compare match only a few cycles then you probably have already missed it. 

 

just set the counter to 0, clear the compare flag since it may have already set, enable the next led

 

https://github.com/cv007/ATTiny416XplainedNano/blob/master/Display3Led.cpp  (m_isr)

https://photos.app.goo.gl/AbbeWW...

 

I use the compare to disable and setup the next segments, the overflow to setup the brightness/compare match and enable the next digit. I also have the compare isr at level 1 for the low values, but probably not necessary (all my isr's go through one isr and use function pointer lookup, so it doesn't hurt as its a little slower).  The 16bit timer works pretty nice to get the levels wanted- especially low levels. The pwn feature could also be used, but then you are tied to specific pins and may be limited by number of outputs available or may prevent other peripheral use wanted, or just makes board layout more difficult.

 

With c++, I have the tca period set by the clock freq in use to get the refresh I want depending on number of digits, and a 64 level brightness table created at compile time based on the period.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

control over how many cycles it is on vs. how many cycles it is off.  

My plan to support multiple brightness levels has been

of ???

 

Your post fails to mention anywhere what it is...an lcd display? 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

LED

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

curtvm - thanks for the code samples - I will take a look at them!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why not use the timer compare match output pin to directly turn off the display, rather than turning the display off in software?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've got 7 rows and it might be a different row to turn off each time.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Surely you can use PWM.

You have a fixed multiplex period.

The OVF ISR() sets the next column and duty cycle.

 

You don't say what sort of display.    It seems unusual to vary the individual segment brightness in a 7-seg array.

You normally select the digit, set the segments for that digit.  Works fine for 2-8 digits.

You would need a PWM pin for each digit.

 

If you are driving a 8x8 array you enable one column at a time.    Just like 7-seg array.

If you want to vary the brightness of individual LEDs in the same column it gets difficult.

 

Why do you think that full colour TFT or grayscale OLED controllers were invented?

 

David.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Display is 5x7 LED, LTP-305.  Don't want a grayscale, just an overall brightness level.  Perhaps there are easier ways to do that.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Overall brightness is easy.

One PWM channel.

 

OVF ISR() switches the OCRnx pin to the column-enables via a  3-line to 8-line decoder.

 

The column enables must have external drivers anyway.   To cope with the high common current.

Row drivers can probably be directly from a PORT.   The segment current is manageable.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm going to drive the columns from I/O pins, 12.5mA max current each, 20 to 24 of them.

 

The rows will be driven with logic level mosfets.

 

Would you try to PWM all 7 rows?

 

I don't want more parts than 4 dual fets and 24 resistors...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you don't want to add any more parts (understandable), what about just waiting (polling loop) in the ISR for very low brightness values, while letting the compare interrupt run (and turn off the display in that ISR) for larger values.  If you're clever you can even come up with some useful work to do while you're polling.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So far kk6gm that is my best idea - decide how long it takes the ISR to run and then use that as a threshold to decide whether to allow the interrupt to come back and handle it or just wait them and handle it.  Then there is the complication of if we are waiting in an ISR, do other higher priority ISR's need to run and should it enabled sei while waiting...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm guessing you selected that display intentionally, at least in part due to its small physical size.

 

If not perhaps you could make your own LED matrix with WS2812B LEDs.

 

Have you had a change to play with one?

They are truly fun to tinker with.

They have their own HW controller inside the RGB LED, so you automagically get 256 intensity levels and 16,777,216 colors, per LED.

You send it a serial data stream, and it stays at that color until you update.

Yo don't have to multiplex / scan anything, they can all be strung together in a long daisy chain.

 

You could easily have a yellow or blue display, for example, and have it turn red for warning / critical values.

 

JC

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


I would love to make a large matrix (wall art or something with the WS1812B's someday).

 

My goal here is to make a smart style display using four LTP-305's similar to the HCMS series like the:

 

https://www.digikey.com/products...

 

I like how they can be chained together and I am wanting to make something similar.  I was hoping for a DIP module that was the side of the displays, but getting around the vertical through hole is a pain so it will have to be taller by 0.1" on the top and 0.1" on the bottom for horizontal header that can then be connected to a lower pcb with the AVR on it.  it is sort of a crazy idea.  I want to be able to use simple SPI to shift either pixel data for a graphics mode even just ascii values for a text mode that has a built in font, something the HCMS series lacks.  I also want to be able to chain them together to make an 8, 12, etc. char display.

 

Here is a rough mock up - the top and bottom horizontal row connect this pcb (the driver pcb) to the ltp-305 pcb (seen below).

 

The 8 pairs of header not on the top and bottom rows will be the "DIP" package of it and these pins will extend to the bottom and can plug into a standard DIP-28 0.6" width socket.  They will carry vcc/gnd/rs/ss/clock/datain/dataout.

 

 

Top LTP-305 board - it connects the rows together and exposes the 6 columns for each one and 2 rows per digit until all 7 rows are represented as well in the top/bottom header.  My thought is cutting the header shorter so the two pcb's can fit together close.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The sot23's in the above are not dual fet's though - they were the only closely sized package so I used them for now.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have a number of displays-

https://goo.gl/photos/rTCwusquFn...

https://photos.app.goo.gl/3hO0dZ...

 

various pic16f's and avr tiny416

 

They all use npn/pnp to drive the commons (npn for CA, pnp for CA- opposite normal, no base resistor needed), and have no resistors at all. The only one that uses hardware output is one of the pic16f's, where the ccp is used to do a one shot (single pwm) directed out via pps (can output to any pin, anytime)-

https://github.com/cv007/3DigitLed/blob/master/disp.c

The rest use code like I linked to previously. Even with a longer than normal isr method I use in the tiny I have no problem doing minimal brightness. Anything less than the isr time will be unusable anyway with 13/14bits to work with, so no need to stick around in the isr.

 

With 7 drivers and a tca period of 14285 (10Mhz/100/7), if 100 clock cycles is minimum brightness because of isr (most likely less), that is a 0.7%  100*100/10Mhz (0.1%, I think that's right this time, maybe) minimum brightness value and all brightness values start with the same 'error'. To help out, you can turn on the driver last thing in overflow, and turn off the driver first thing in the compare isr- then it becomes the time it takes to turn on driver, exit isr, enter isr (basiclly prologue/epilog length, which is going to probably be closer to 50 cycles at worst).

 

I use uart to communicate between all modules. They all see the same info at the same time, and each digit has an address so each also has its own brightness and is looking for its data by the address- which will auto increment or can use an address that is a 'broadcast' address so can send same brightness to all at once, for example. They all update their displays on the cr and/or lf, so they all visibly change at the same time.

Last Edited: Fri. Aug 16, 2019 - 05:56 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

You could possibly have an easier time using a surface mount dip socket   example :   https://www.digikey.com/product-detail/en/mill-max-manufacturing-corp/214-44-314-01-670800/ED90237-ND/1212134

 

Of course, the through hole setup gives you precise alignment, smd sockets might move around slightly during soldering.   Or, you could hand solder displays to pads on topside, though that might get a bit repetititve & hard to do if the displays are butted where you can't access  pins between displays.

 

I have a number of displays-

https://goo.gl/photos/rTCwusquFn...

https://photos.app.goo.gl/3hO0dZ...

 

 

Sweet!

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Fri. Aug 16, 2019 - 08:03 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

curtvm - Those are excellent!  I've seen people drive displays without resistors before, but I'm not sure what the pulse current is.  Do they rely upon an I/O pin only being able to deliver so much current before it can't do more?

 

avrcandies - I want something I can hand solder and having the displays up against each other is a real limiter.  Still, I'd love to have a single pcb...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

>but I'm not sure what the pulse current is.  Do they rely upon an I/O pin only being able to deliver so much current before it can't do more?

 

I have not measured although would be easy enough, but I do try to stress them by running at full brightness (several years now, no problems). The only problem I ever had, was with a pic16 that had something like a 350ma total current figure in the datasheet (and high drive current for pins)- I was using mosfets to drive, and could get into power problems at highest brightness. Then I switched to pnp/npn to reduce efficiency a little which worked ok in that case, and just stuck with transistors from then on as they seem to work fine in all cases and getting max brightness is never a problem. I guess I'm also relying on the somewhat self regulation taking place due to the typical dropping/rising voltage as current increases along with the multiplexing reducing the on time.

 

I'm probably breaking some rules, but I'm not ready to start adding more parts when not actually needed. The boards created are small enough, so 5-6 parts is more than enough for me as I don't really enjoy the process of placing smd parts on a board (or ordering parts). Less parts=better.

 

> I want something I can hand solder 

 

I only have a cheap hotplate, but you would be surprised what you can do with it. I used to limit myself to hand soldering soic/1.27 and 0.8, now can do 0.6, 0.5 qfn without much problem on the hotplate which gives more part options and reduced footprint.

 

I think I have some of those HCMS displays stashed away, and looking at the current prices of those I may have to dig them out and sell them :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I was somewhat thinking about hotplate, but then I'd still have to carefully position them and deal with solder paste which I don't currently do.

 

I had an idea to eliminate the top and bottom row headers (which I'd really like to do) and that is to use 50mil header on the left and right edges between displays 1 and 4.  I think that might be workable.

 

I love the HCMS displays - you can get them on eBay for a decent price with patience - mouser/dk prices are insane on them.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

>but then I'd still have to carefully position them and deal with solder paste which I don't currently do.

 

I have solder paste, but just can't keep it good. I did buy some more lately, and tried it again- its just not easy to work with unless you have stencils or a paste dispenser that can put it down on a pad without much effort. What I usually do is take a bare board, liberally put some no-clean flux on each pad, then just drag solder every pad. That can be done rather quickly as the flux does all the work. Then leave flux in place as a sort of glue, place all parts on top of the pre-soldered pads and hotplate the board. When done and cooled off, I cleanup the board and it usually turns out pretty good.

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

After more thinking, I think I'm going to try the socket that avrcandies posted above along with the skillet method curtvm has suggested.  I'm going to join the 4 sockets together with some header so they are at least aligned to each other and then presolder the circular pads they sit on and apply some flux and try to carefully align the 4 sockets and see if I can get that to work.  If so, then I should be able to do a single PCB which should be so much nicer.  Probably a 4 layer pcb, but it is small so oshpark can make them pretty cheaply!

 

Any more thoughts about the ISR?  With the 24 columns to change and 7 rows to change, are there any hardware peripherals I can use to help that or should I just use the ISR to change the pins??

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I use a frying pan for soldering my PCBs.

It works well for me.

 

I don't have templates for applying the solder, so I use a syringe and a needle to squirt a small amount out onto the pads.

Lessons learned:

If the solder paste is to dry, it won't apply well.

It has to be pretty soft to be able to extrude it.

The stuff that comes in big plastic "syringes" works well.

I use that to fill my syringe.

 

The smaller the diameter of the syringe the better.

I use a "tb" or insulin syringe.

That way a small displacement of the plunger gives a small amount of paste squirting out the needle.

If the syringe is too large, then even a short push of the plunger gives tons of pasted, far too much for a pad.

 

I use a pretty large bore (gauge) needle, that has been cut very short.

 

Good luck!

 

JC

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


Good tips DocJC - I just don't use enough solder paste (as in any) to justify trying to keep it fresh.  I know a guy who always has fresh and would give me some though (because he is super cool).  I'm going to try to just solder the pads ahead of time, bathe it in flux, sit the sockets (connected with header) on top and see if it stays aligned as I apply the heat in a frying pan.  We'll see how it does.  I still have a ton of things to do as in build up a breadboard to test it, then lay out a circuit board.

 

Here is the latest look at what it might be.  Disregard the air wires, this is me testing what type of via's can I get away with on the edge of the board without ticking off the DRC.  The red is top layer and I connect all the rows together except for one.  As I am color blind I don't even know what color that is I assigned to layer two, yellow maybe, that is handling the one row I couldn't tie together on the top layer.  I'm using a fatter trace because apparently the inner layers have half the copper.  Bottom layer shows a package for the smaller atmega4809 tqfp-48 which is welcome over the larger tqfp-44 I would have tried to make work.  Not sure if it will stay like it is or rotate 45 degrees into a diamond for easier routing.  I'd love to do it as a 2 layer, but I don't know that that is possible.

 

The green through holes are for the "DIP packaging" it will be so there will be pin header straight down which forms a DIP-28 0.6" spacing with missing pins every 2.  Luckily there is some room under the SMD sockets that were pictured about for me to add these layer and solder them from the side!

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


 

I think I'm going to try the socket that avrcandies posted above

Double check the width (if you didn't already), just to be sure the display pins will fit the socket.

 

I'm going to join the 4 sockets together with some header so they are at least aligned to each other

CLEVER!

 

 

please note that when the sockets are right next to each other, the middle pins can prob only be hand soldered  by going though the top opening of the socket (no side access).  Of course,  with your header positioning trick, you could just paste up the pads and reflow all the the sockets perfectly positioned to one another, no hand soldering at all.

 

 

 

There's also this lead style, no stock at Digikey  https://www.digikey.com/product-detail/en/preci-dip/110-87-314-41-105191/1212-1008-2-ND/3757258

 

I use a frying pan for soldering my PCBs.

 

My wife complains that her fries taste like lead.  I complain that my circuit board tastes like bacon.

 

 

 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Sat. Aug 17, 2019 - 06:24 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Gotta mark the "PCB pan" from the others!!!

 

I am tempted to try skipping the sockets too.  In this case put the displays down into some female header that aligns them properly and then putting masking tape across the top surfaces to keep them aligned.  Then set them on the pcb and bake.  In the end remove the masking tape.  Not sure if that will work, but it might be worth trying.  I like the socket option for replacement or changing the display color between red and green.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't think hand soldering would be an option at all, but I like your solder it from the top through the pin idea.  I'm going to just apply a bubble of solder to all the pads, flux it, position the stack of 4 sockets or displays on top and try to fry pan head the pcb underneath to reflow it...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Oh yes, it will almost certainly work, if you can keep them positioned exactly where you want them  (use high temp "orange" kapton tape?) ..I took a look at the first socket & it appears there is no top access for soldering...a solid block of plastic.

 

No sockets, also saves a good bit of $$$

 

You might squirt them with hi temp silicone rtv to form a "block", then just peel it away later. 

 

I'm going to just apply a bubble of solder to all the pads

NO!! you will get uneven leveling pre-soldering & maybe big aggravation.  Just apply smd solder paste to the pads...then the display legs can poke through it & they will be perfectly level before the reflow of the paste. It will form a beautiful fillet around each leg.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Sat. Aug 17, 2019 - 06:37 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You don't think gravity will do the job?  I'd rather avoid that paste if possible.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You don't think gravity will do the job?  I'd rather avoid that paste if possible.

Probably, if you put on slight weight & they all get melted at the same time.  If pad solder is too uneven, just getting things positioned could be a pain --things want to slide around if not level.

 

 

 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So, back to the firmware side, with 7 rows to toggle on and off and 24 columns to set during that toggle, any better idea than just bit banging the pins in an ISR ?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So after trying get used to and figure out the Type B timers, I've come up with the below so far.  The Type B is unlike any timer I've dealt with before - can't say I like it.

 

zzz is 16 gamma adjusted brightness levels - you can see I picked a relevant name...
 

//uint8_t data[7]={0x1f,0x1,0x2,0x4,0x8,0x10,0x1f};
uint8_t data[7]={0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f};

ISR (TCB0_INT_vect)
{
  static uint8_t row;

  //setup disable interrupt
  TCB1.CNT=0;
  TCB1.INTFLAGS=0x01;
  TCB1.INTCTRL=0x01;

  //disable all rows
  PORTF_OUTCLR=0xff;

  //advance row
  row++;
  if (row==7)
    row=0;

  //set next data
  PORTD_OUT=data[row];

  //clear this interrupt
  TCB0.INTFLAGS=0x01;

  //enable new row
  PORTF_OUTSET=_BV(row);
}

ISR (TCB1_INT_vect)
{
  //disable all rows
  PORTF_OUTCLR=0xff;

  //disable this interrupt
  TCB1.INTCTRL=0x00;

  //PORTC_OUTSET=_BV(5);
  //PORTC_OUTCLR=_BV(5);
}

uint16_t zzz[16]={39,100,209,381,633,984,1451,2054,2813,3749,4883,6235,7830,9688,11834,14290};

int main()
{
  uint8_t c1;

  //pd0-pd5 - columns
  //pf0-pf6 - rows
  //pc5 - debug

  //switch to 10 MHz
  _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB,0x01);

  //enable interrupts
  sei();

  //set columns and rows as output
  PORTD_DIRSET=0xff;
  PORTF_DIRSET=0xff;

  //set debug as output
  PORTC_DIRSET=_BV(5);

  //700 Hz TCB0
  TCB0.CTRLA=0x01;
  TCB0.INTCTRL=0x01;
  TCB0.CCMP=14290;

  //set mode for brightness reducer TCB1
  TCB1.CTRLA=0x01;
  //TCB1.CCMP=zzz[15];

  for(;;);

}

 

Last Edited: Tue. Aug 20, 2019 - 01:28 AM