Jump to content

Search the Community

Showing results for tags '4094'.

More search options

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


  • News
    • Announcements
    • Suggestions
    • New users say Hi!
  • Spotlight!
    • Sponsor Spotlight
    • Sponsor Giveaways
  • Energia
    • Energia - MSP
    • Energia - TivaC/CC3XXX
    • Energia - C2000
    • Energia Libraries
  • MSP Technical Forums
    • General
    • Compilers and IDEs
    • Development Kits
    • Programmers and Debuggers
    • Code vault
    • Projects
    • Booster Packs
    • Energia
  • Tiva-C, Hercules, CCXXXX ARM Technical Forums
    • General
    • SensorTag
    • Tiva-C, Hercules, CC3XXX Launchpad Booster Packs
    • Code Vault
    • Projects
    • Compilers and IDEs
    • Development Kits and Custom Boards
  • Beagle ARM Cortex A8 Technical Forums
    • General
    • Code Snippets and Scripts
    • Cases, Capes and Plugin Boards
    • Projects
  • General Electronics Forum
    • General Electronics
    • Other Microcontrollers
  • Connect
    • Embedded Systems/Test Equipment Deals
    • Buy, Trade and Sell
    • The 43oh Store
    • Community Projects
    • Fireside Chat
  • C2000 Technical Forums
    • General
    • Development Kits
    • Code Vault
    • Projects
    • BoosterPacks


There are no results to display.

Find results in...

Find results that contain...

Date Created

  • Start


Last Updated

  • Start


Filter by number of...


  • Start



Website URL





Found 1 result

  1. Earlier this year I happened to be in Singapore in transit, and took the opportunity to visit Sim Lim Tower - a high-rise mall full of electronic components shops! Amazing place, and amongst other things (including super-cheap kits for the kids to build!) I picked up three 5x7 LED matrix panels for a dollar each (!!). They didn't have any part numbers that I could see, but after experimentation they turned out to be row-anode devices and once I figured out the pinout I decided to build a project out of them. As any of us who have children know, it's a daily battle to get kids to brush their teeth for long enough, and as any of us who have children also know, time spent on projects goes down better if there's a kid angle to it. So I decided to make a tooth brush timer, that will display a countdown from two minutes - interspersed with inspirational text and probably amusing patterns and other things to keep the kids entertained during their twice-daily two-minute ordeal. Poor things. Being given to doing things the hard way, I decided to design two boards - one for the LED panels, and one for the controller. I'll get to the controller board in a later post because it's quite complicated (since the board fab place makes 10 identical boards I decided to try to make it as multi-purpose as possible). The LED boards though are simpler, they just use a 4094 shift register to handle the columns (or rows, I decided to use my three matrices abutted end to end rather than side to side, giving me a display that's five LEDs high and twenty-one across. I found a nice 5x5 bitmap font on dafont.com, and decided that I had enough space for what I needed to display. Because if all the LEDs are on the 4094 will be over it's specified current limit, it drives the columns through seven PNP transistors. This meant quite a bit of routing, which is what led me to use a board fab house rather than attempt it all on veroboard. So, onto the code (I have attached the eagle files if anyone is interested). I wanted to use the USI module to drive the 4094's. Looking at the datasheet for a 4094, it clocks in it's data on a rising edge of the clock. So the USI module will need to be configured thusly (I'm running the CPU at 12Mhz). // Reset USI logic to allow configuration USICTL0 |= USISWRST; // Setup serial output for a 4094 shift register USICTL0 = USIPE6 // SDO enabled + USIPE5 // CLK enabled + USIMST // master mode + USIOE // output enable + USISWRST // leave in reset ; // clock phase = 1, interrupts enabled SICTL1 = USICKPH // phase = 1 + USIIE // interrupt enabled ; USICKCTL = USIDIV_4 // divide by 16, giving 500khz clock + USISSEL_2 // SMCLCK as clock source ; // release SPI for operation USICTL0 &= ~USISWRST; Now, the tricky part of this project is that I want to have greyscale (redscale!) on my LEDs. To do this I will have to not only row-scan the matrix, but also PWM each LED individually. And I want to do all this in the USI interrupt handler, and have a framebuffer in RAM that I can just write to at any time without having to worry about getting the LEDs to update. So first thing is the framebuffer, I'm just using one LED matrix at the moment so it's only a 5x7 array: unsigned char framebuffer[5][8]; // greyscale framebuffer So, for those unfamiliar with how to drive these types of LED matrices, here's a bullet-pointed flow-chart. Start at the first row. Clock bits into the 4094 shift register, corresponding to which LEDs in the current row are on. Because I'm using PNP transistors as high-side switches, a zero in the 4094 outputs will correspond to an LED being on. Once the bits are clocked in, set the 'strobe' input into the 4094 to high. This will latch the outputs of the 4094, causing them all to change at once to whatever you just clocked in. Now that the high-side transistors are all either on or off, according to which LED in the current row you want to be on, it's time to turn that row on using the low-side switch for that row. Of course there could be quite a bit of current flowing out through the row pin if all the LEDs in that row are on, so it's not safe to just hook it up to a GPIO pin. A FET is instead used as a low-side switch. Now the row is lit up. Move to the next row and goto 2. If we're at the last row, then instead goto 1 (which means start over). The above method, if run fast enough, will cause all the LEDs to appear illuminated in whatever pattern you desire. But it won't allow brightness control of individual LEDs. To get that we need another variable, that I'll call PWM. PWM will start at zero, and will be incremented at step 1 of the above bullet-pointed flowchart. When it reaches 16, it will be reset back to zero. So it's a rolling counter that will count up each time a frame is output to the matrix, and will roll over at 16. Using this, and the greyscale framebuffer above, we can modify the flowchart so that instead of just clocking in whichever LEDs are on into the 4094, we clock in whichever LEDs have a brightness value that is greater than the current PWM counter. Thus, when the framebuffer entry is zero for a particular LED, that LED is never illuminated because it's brightness value (zero) is never greater than the PWM value (zero to fifteen). And when the framebuffer entry is sixteen, it's always greater than the PWM counter, and thus that LED is illuminated every frame. In between values illumiate the LED for varying numbers of frames, which - if you run the whole process fast enough - will cause them to appear dimmer. The heart of this code is the following loop, which I would love some advice on how to optimise: output = 0; for(bit = 8; bit ; bit--) { output <<= 1; output |= (framebuffer[row][bit] > pwm) ? 0 : 1; // on if over pwm } This loop calculates what to output to the 4094 shift register for each row. It's quite alot of work for an interrupt handler, and it needs to be three times more work once I add the additional two LED panels. I'm sure the compiler in CCS does a good job of figuring out the loop and optimising it for me, but I should take a look at the assembly output and determine if I can do any better. Anyway, to kickstart the process, the main program calls NextRow(), and then sets up a timer and fiddles with the framebuffer at intervals. So, here's NextRow and the USI interrupt handler: unsigned char pwm = 0; unsigned char row = 0; void NextRow() { unsigned char bit; unsigned char output; // strobe low ready for next thingy P1OUT &= ~BIT3; // next row's data - work out if each pixel should be on output = 0; for(bit = 8; bit ; bit--) { output <<= 1; output |= (framebuffer[row][bit] > pwm) ? 0 : 1; // on if over pwm } USISRL = output; // 8 bits out, we'll come back to _usi once these bits have been clocked out. USICNT = 8; } #pragma vector = USI_VECTOR interrupt void _usi() { USICTL1 &= ~USIIFG; // reset interrupt flag // turn off rows P2OUT = 0; // latch data P1OUT |= BIT3; // Strobe high // turn on rows P2OUT = (1 << row); // next row row++; if (row == 5) { pwm++; pwm &= 0x0F; // loop pwm back to zero when it hits sixteen row= 0; // start at row zero again. } NextRow(); } I've left alot of stuff out here, setting up the clock module and the GPIO pins etc etc. Also there's code in the project that makes a pretty (ish) pattern, and the displays some numbers. The code and eagles files are attached, and assuming I can use the video feature of BBcode correctly, here's a video! http://www.youtube.com/watch?v=gvPZ8LyGYGY --Edit--- Well that youtube embed didn't work. Here's a link. How do you embed videos anyway? LED control.zip
  • Create New...