Shop OBEX P1 Docs P2 Docs Learn Events
LED Matrix - Tri Color - Large (SparksFun product) ideas... — Parallax Forums

LED Matrix - Tri Color - Large (SparksFun product) ideas...

T&E EngineerT&E Engineer Posts: 1,396
edited 2007-09-26 21:47 in General Discussion
I did a search and did not see anything listed for SparkFun or particulaly their LED Matrix - Tri Color:

http://www.sparkfun.com/commerce/product_info.php?products_id=683

http://www.sparkfun.com/commerce/product_info.php?products_id=760

Has anyone bought one of these and done anything with it using a Basic Stamp 2 or SX-28/48/52 ? Just don't want to re-invent the wheel.

I bought one yesterday so it may be here by the weekend or begining of next week. It seemed expensive considering that I can get 10 bi-colored LED matrix modules on Ebay for under $20 including shipping. But if this is really an 8x8 "RGB" LED matrix then it·may be worth it.

It has 3 LEDs for each of the 64 elements being RED, GREEN and BLUE. Are these considered to be RGB LEDs (as I have not worked with them before or PWM but may want to give it a try)?

If so then is it possible to get 256 shades of RED, GREEN and BLUE to get 16.7M colors using PWM?

The impression I got is that it can get a few color combinations but certainly not anything like 16.7M colors.

Comments...

Thanks!

Post Edited (T&E Engineer) : 9/24/2007 9:37:46 AM GMT

Comments

  • RDL2004RDL2004 Posts: 2,554
    edited 2007-09-20 18:01
    A "RGB" LED is just 3 individual LEDs in the same molded package, one red, one green and one blue. They have 4 leads, one for each of the three LEDs and one common.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    - Rick
  • T&E EngineerT&E Engineer Posts: 1,396
    edited 2007-09-20 18:18
    If it is that simple then it appears that they are RGB. However, the 3 Anodes are common (rows) based on the schematic. What is a little confusing was a listing showing the description appearing like it had 6 colors being :Red, Green, Blue, Ultra Red, Ultra Green, Ultra Blue. I will have to just play with it and see what happens.

    Hopefully I can use a modified version of Bean's PWM program (attached) for the SX.




    Post Edited (T&E Engineer) : 9/20/2007 6:29:12 PM GMT
  • RDL2004RDL2004 Posts: 2,554
    edited 2007-09-21 00:47
    That's a pretty bad data sheet, but it looks to me like it covers four versions. Normal RGB (H?GB) and ultra-bright (UR, UG, UB), in both common cathode and common anode.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    - Rick
  • T&E EngineerT&E Engineer Posts: 1,396
    edited 2007-09-24 01:12
    I got my LARGE 8x8 RGB LED Matrix AND I also got the SPI controller card for it. I initially started to write some code for the Basic Stamp 2. However, it needs to see 64 bytes (color codes between 0 and 7) and SHIFTOUT is what I used sucessfully. However, since the BS2 is limited on Array sizes, I was not able to create a 64 byte array without running out of memory.

    I quickly went over the developing it for the SX-28. The new SX/B Beta Test code allows for large arrays on an SX-28 (larger than 16). I created a 65 byte array and was very sucessfull in displaying some information. I used a little of JonnyMac's code for his BADGE.sxb (modified significantly to PAINT_SPRITE the image). Thanks JonnyMac!

    I am still having issues trying to scroll data!!

    However, for 1 day's worth of work it was not too difficult to use this LED Matrix (especially with the SPI contoller card).

    http://www.sparkfun.com/commerce/product_info.php?products_id=760

    I took some pics (quality due to the flash is not good). They really look very well defined and good brightness level too for the 7 colors you get with control using the SPI controller.

    I was very impressed with this display and will probably buy more once I can figure out how to scroll. Help please...




    Post Edited (T&E Engineer) : 9/25/2007 2:01:26 AM GMT
  • PLJackPLJack Posts: 398
    edited 2007-09-24 10:46
    Those sure are pretty.
    Can you help me understand why you need a 64 byte array on the SX side?
    The PDF states that the backpack maintains a 64 byte array.
    It only requires that you send it 64 bytes in sequential order.
    You could store the patterns on an EEPROM and just send them over.
    Or you could store the fonts locally (SX) in vector format and extrapolate the 64 bytes on their way to the backpack.

    I think I see an EEPROM in your future. smile.gif

    Please keep us informed.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    - - - PLJack - - -



    Perfection in design is not achieved when there is nothing left to add.
    It is achieved when there is nothing left to take away.
  • T&E EngineerT&E Engineer Posts: 1,396
    edited 2007-09-24 11:50
    PLJack,

    I think the displays are the best I have seen meaning that (I didn't have to design the hardware - not much to figure out and SPI controller card is small). They are a bit pricey but all the design work is done for you and you need to write some simple software to "make the lights come on in 7 colors".

    The datasheet:
    http://www.sparkfun.com/datasheets/Components/matrix_backpack.pdf

    states that 64 bytes must be sequentially transfered to the "backpack" controller card. It also states a certain layout must be performed for this to work.

    The example in the data sheet says:

    To have a RGB matrix display “black, red,
    green, blue” on the first four positions of the
    first row, and black everywhere else:

    1. Assert CS.
    2. Delay 0.5 ms
    3. Transfer 0x00 via SPI
    4. Transfer 0x01 via SPI
    5. Transfer 0x02 via SPI
    6. Transfer 0x03 via SPI
    7. Transfer 0x00 sixty times via SPI
    8. Delay 0.5 ms
    9. De-assert CS.

    As you can see the first 4 bytes are 0, 1, 2, 3 (representing the first LED position to be off, the 2nd to be red, 3rd to be green and 4th to be blue). However, the controller card needs to see 64 bytes filled to be complete so 60 more "off" led or sending "0" must be done to make up the 4 + 60 bytes in the controller buffer.

    In my originally attached PBASIC (BS2) version it is done in 1 long statement as I would rather use an array but was not initially sucessfull with just READing data from DATA statements. I will look at this again in case I missed something.


    Out_LED:
    · LOW ChipSel····························· ' latch outputs LOW
    · PAUSE 1
    · SHIFTOUT DataIn, Clock, MSBFIRST, [noparse][[/noparse]$0,$1,$2,$3,$4,$5,$6,$7,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0]
    · PAUSE 1
    · HIGH ChipSel····························· ' latch outputs HIGH
    · RETURN

    In the above example I am turning on the 2nd-8th LED positions with $1,$2,$3,$4,$5,$6 and $7 (of course the $ Hex could have been left off since they are all under $9).
    $0 = None
    $1 = Red
    $2 = Green
    $3 = Blue
    $4 = Yellow = Red, Green
    $5 = Cyan = Green, Blue -> looks like light blue
    $6 = Magenta = Blue, Red -> looks like hot pink
    $7 = White = Red, Green, Blue -> looks like light pink

    In my originally attached SX/B (SX-28) version I use the larger array method. However, this software is only out for SX/B Beta Tester's at the moment as the 1.51.03 version only allows arrays up to 16 bytes. However, there are other ways to trick the SX/B into thinking there is a larger array (in the current 1.51.03 version) as JonnyMac has shown me in the past.


    I think I will look into EEPROM but just don't know an effective way to do this using PBASIC (BS2). I have been focusing on SX/B too much.

    Glad you liked it!

    More to come...

    PS: Attached is another couple of PICs as all done with the SX/B version. I have the LARGE 8x8 RGB LED display/controller next to a standard sized or smaller 8x8 Bi-Colored display matrix. What a difference!

    Post Edited (T&E Engineer) : 9/24/2007 12:02:47 PM GMT
    648 x 486 - 64K
    648 x 486 - 64K
  • PLJackPLJack Posts: 398
    edited 2007-09-25 00:12
    Hey, a letter "P".

    I haven't had the chance to use SPI.
    Am I wrong in assuming that the term "sequentially" means you can lazily send over the 64 bytes in the correct order, then raise the latch.
    In other words, multiple SHIFTOUT's.
    Or do you have to send the bytes in one transmission?
    If the former is true, then you can get pretty creative in producing your 64 bytes without an array.

    Looks like a good time though.

    As I was typing the above text I started thinking. (always trouble).
    Can you break up the 8x8 LED matrix into 4x4 squares with 4 LED's each?
    So that would be a 4 bit square. Each square would have 16 possible combinations.
    You could represent each square with one half of a Byte using the numbers 0 through 15.
    That way you could represent all 64 LED's with 16 Bytes.

    Now, I haven't thought that all the way through, color for example, but it sounds like it could work.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    - - - PLJack - - -



    Perfection in design is not achieved when there is nothing left to add.
    It is achieved when there is nothing left to take away.

    Post Edited (PLJack) : 9/25/2007 12:24:19 AM GMT
  • T&E EngineerT&E Engineer Posts: 1,396
    edited 2007-09-25 00:47
    I beleive that was the problem I had with the BS2 at least. It could not get it to work using multiple SHIFTOUT (or calling a subroutine to do that). That is why I needed to have them all in 1 shot (all 64 color code bytes) within the SHIFTOUT statement. I think this is because you need to do a LOW ChipSel and PAUSE 1 first before the SHIFTOUT statement AND then to finish using the PAUSE 1 and HIGH ChipSel statements.

    However, perhaps one could do the LOW ChipSel and PAUSE 1 and then the first SHIFTOUT statement. Then multiple SHIFTOUT statements "might" be able to be used (via subroutine calls {63}) followed by the PAUSE 1 and HIGH ChipSel to finish the job.

    I will have to set it up and try it out tomorrow.
  • PJAllenPJAllen Banned Posts: 5,065
    edited 2007-09-25 00:55
    Ah, yes... the Great Letter "P".

    You could be onto something.
  • T&E EngineerT&E Engineer Posts: 1,396
    edited 2007-09-25 02:04
    I have updated the PBASIC Basic Stamp 2 program to run identically to the SX/B SX-28 program. I just needed to play around with it more and I can read DATA statements into the PBASIC BS2 program now. There probably is a more eligant way to do this but it works to display characters, etc..

    PS: The letter "P" is the first letter in my sons name "Philip" - and thus the "h". I just wanted a couple of letters to experiment with. The other pattern shows all 7 colors - although the camera did not portray them colorwise correctly. Take my word, the colors and brightness is GREAT!

    (See the original post for the BS2 and SXB program updates.
  • ZootZoot Posts: 2,227
    edited 2007-09-25 17:50
    T&E -- I wrote this up before I saw that you had revised your BS2 program. This isn't that much different BUT it separates the pattern of the characters and/or bitmaps into bitmaps -- 8 bytes per character instead of 64. Second, it maps character data addresses to the ascii map so you can read strings of "messages" and lookup the character bitmaps pretty easily.

    For fun, I often use the "unusable" ascii characters (like ESCAPE and whatnot) for "custom bitmaps" -- you can still put the ascii byte in your message strings and it's quick way to dump bitmaps to a matrix LED display.

    This code only sets color on a per character or message basis, but it's easy enough to tweak to change colors for any pixels, rows, cols -- just hit the right spot in the cols/rows for...next loops (e.g. after dumping a row you could do color = color + 1, etc.)

    ' create all  all ascii chars from 0-127 as bitmaps -- it's worth it!
    ' use the "pre-0" characters for fun stuff
    ' note addresses -- this lets you call them by actual character
    ' same mapping will a master offset works nicely in an external EEprom as well
    
    CBLOCK CON 8  'size in bytes of a character bitmap
    
    DATA @ ","*CBLOCK,      %00000000,
                            %00000000,
                            %00000000,
                            %00000000,
                            %00000000,
                            %01100000,
                            %01100000,
                            %10000000
    
    DATA @ "H"*CBLOCK,      %11000011,
                            %11000011,
                            %11000011,
                            %11111111,
                            %11111111,
                            %11000011,
                            %11000011,
                            %11000011
    
    DATA @ "i"*CBLOCK,      %00000000,
                            %00000000,
                            %00011000,
                            %00000000,
                            %00011000,
                            %00011000,
                            %00011000,
                            %00011000
    
    DATA @ "&"*CBLOCK,      %00110000,
                            %01001000,
                            %00110000,
                            %01010000,
                            %10010011,
                            %10001100,
                            %10000110,
                            %01111001
    
    DATA @ " "*CBLOCK,      %00000000,
                            %00000000,
                            %00000000,
                            %00000000,
                            %00000000,
                            %00000000,
                            %00000000,
                            %00000000
    
    'etc.
    
    Message1 DATA  "Hi, Phillip! ", EOM
    Message2 DATA  "Parallax is so cool! ", EOM
    Message3 DATA  "T&E Engineer loves LED displays with cool things scrolling on them. ", EOM
    
    EOM      CON $AA     'or any other string terminator you care for. I use this EOM because it's the same as the Emic EOM
                         'which means I can use the same message strings for BOTH LED matrix displays and Emic text-to-speech (barring phoenetics)
                         'in practice, I ususally have a grid of pointers with addresses to the start of 128 or 256 strings so that strings of multiple lengths
                         'in unknown offsets can be located by referencing, say, an index # from 0-255, but that's a data storage side topic
    red      CON  $01    'added to 1 for sparkfun matrix backpack color/pixel byte
    green                CON  $02    '
    blue     CON  $03
    redgreen CON  $04
    'etc
    
    message  VAR   Nib   'message #
    EEaddr   VAR   Word  'eeaddr of curr char in message string
    ioByte   VAR   Byte  'work byte
    ioByte2  VAR   Byte  'work byte
    idx      VAR   idx   'work byte
    
    char     VAR   ioByte    'current char from message -- alias
    pixels   VAR   ioByte2   'current pixel data -- alias
    rows     VAR   idx.HIGHNIB  'counter for reading through rows
    cols     VAR   idx.LOWNIB   'counter for reading through cols
    speed    VAR   byte   'delay between chars in 10ms units
    color    VAR   Nib          'color for this CHARACTER -- you could do more on a pixel (or row or column) basis
    
    'PINS etc
    
    Start:
       char = " "  'clear display with a blank "space" character
       GOSUB doChar
    
       DEBUG CLS, "Message 1, 2 or 3?"
       DEBUGIN DEC1 message
       message = message-1//3
    
       DEBUG CR, "Color 1-6?"
       DEBUGIN DEC1 color
       color = color MIN 1 MAX 6
    
       DEBUG CR, "Speed in 10ms units?"
       DEBUGIN DEC speed 
       speed = speed MIN 1 'minimum 10ms
    
       doMessage:
           LOOKUP message, [noparse][[/noparse] Message1, Message2, Message3 ], EEaddr  'point to start of string text
    
           getChar:
              PAUSE speed*10       'delay between chars
              READ EEaddr, char 'get char of string; this could also be, e.g., I2C to external EE stroage
              IF char = EOM then doMessage  'would repeat/loop
              'IF char = EOM THEN done      'would stop
              GOSUB doChar
              EEaddr = EEaddr+1    'char done, do next character after...
              GOTO getChar
    
    done:
       GOTO Start
    
    
    doChar:
           LOW ChipSel 'get ready for SPI
           PAUSE 1
           FOR rows = 0 TO 7  'loop through rows       
              READ (char*8)+rows, pixels  'read row of pixels
              FOR cols = 7 TO 0 'loop cols and make a pixel byte...I THINK this is right -- you have to dump pixels from left to right, top to bottom?
                  SHIFTOUT DataIn, Clock, MSBFIRST, [noparse][[/noparse] pixels.BIT0(cols) * color ]  'if bit for this col/row is 1, then color gets you 1-7 if "on"
              NEXT
           NEXT
           PAUSE 1
           HIGH ChipSel 'latch it
           RETURN
             
    END             
    
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST

    Post Edited (Zoot) : 9/25/2007 5:57:36 PM GMT
  • T&E EngineerT&E Engineer Posts: 1,396
    edited 2007-09-25 18:00
    Outstanding Zoot!

    I can't wait to try this out tonight. ·You did all of this from your head without testing?

    Wow. Amazing. I will certainly keep everyone posted.
  • ZootZoot Posts: 2,227
    edited 2007-09-25 18:14
    You give me too much credit. Practically everything I know I learned from the forums smile.gif

    In any case, one personal idiosyncracy I'll point out -- I setup my bitmaps so they "read" correctly, even though there is a lot to be said for flipping them and rotating them (so you get the cols mirrored and you grab by columns, not rows. But I like to be able to "see" what I'm doing and "draw" whenever I'm in the mode.
    The real trick if you get into lots of messages or words is the data -- in one of my 'bots I have a 12x5 monochrome LED matrix display (much smaller obviously, but still 60 pixels). The basic drill on data storage is something like:

    32K external EEPROM
    0-255 ASCII character bitmaps in blocks of 10 bytes + 1 width byte 'the width of "proportional" character
    0-255 picture bitmaps 'drawings and "animation" frames in 10 byte blocks

    Then 8K of text strings of varying lengths. A utility program scans the data, and creates word sized "pointers" with the address of the start of each message from 0 to 255. The utility scans each byte and when it starts or finds an EOM, it knows where the first byte of the next message is. These 512 bytes (256 word addresses) are stored at the beginning of the 8k of the text strings. Then the whole shebang is dumped to the external EEPROM via I2C.

    With the "fluid" pointers, my main program can ask for message #129. Then the word address at 129*2+POINTERS is read. That word is the start of the actual character string.

    I can post my utility and data files if you want when I get to that machine later today. I use a multi-slot BS2p, so I can load all 8k of data in 4 slots, and the utility program runs in slot 0, but you an just easily break the data up into <2k chunks if you are doing something similar on an SX or BS2.

    I've watched your SX display work with some interest, because I'm going to be porting some of these tools and engines over to SX from Stamps, and you've paved the way quite nicely.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST
  • T&amp;E EngineerT&amp;E Engineer Posts: 1,396
    edited 2007-09-25 18:23
    Thanks Zoot and well done!

    I also have a BS2px (besides a BS2) if you think that would be more usefull. I tend to develop with the BS2, BS2px to get the basics down and then port over to the SX. However, sometimes I see limitations in the BS2 and go directly to the SX. However, you have shown me some great concepts that I would not have gone into purely because of my limited programming ability. I'm more of a hardware engineer but my programming is getting better day by day.

    I will let you know tonight how I make out.
  • T&amp;E EngineerT&amp;E Engineer Posts: 1,396
    edited 2007-09-25 21:45
    Zoot,

    You did a great job with this. I only had to modify the program very slightly as it only had a 2-3 letters (Hi ).

    I have it set up currently to flash the 'H' and then the 'i' and then the ' '. Very impressive in any color too (1-7)!

    Do you have the other 125+ characters or do I need to create them?

    The characters are 90 deg off (so I rotated the display) - looks good!

    Have you ever tried to scroll the letters (left·/ right, up / down, etc.)?

    The 'H' does have a bit slow clearing rate (e.g. changing from 'H' to 'i' you can see the display clear from top to bottom very breifly)

    (I tried it with a BS2px - that took care of the bit slow clearing rate - much fast changing from letter to letter).

    I have attached the modified "working" BS2 code awaiting replies to my questions.

    Thanks again!
  • T&amp;E EngineerT&amp;E Engineer Posts: 1,396
    edited 2007-09-26 14:47
    I played arround with ZOOTs program more last night and added a little RANDOM color routine to either:

    1. randomize the individual character colors (1-7)

    or

    2. randomize the individual LED pixel colors (1-7).

    Very simple to do as he stated.

    Zoot,

    If you have the rest of the data, I would love to·use·it!

    I would also like to port this over to SX/B if you have no objections.
  • ZootZoot Posts: 2,227
    edited 2007-09-26 18:41
    T&E -- glad you had fun! Do whatever you want with any code I post (it's not that good, really). In any case, here is a somewhat lengthy description of the text and module management I do for an Emic TTS and 12x5 data display.

    The attached Face.zip and Text.zip archives are the data and burning utilitities for my ascii characters, bitmap pictures and text strings (the latter are used for both TTS and LED scrolling text). Remember this display is 12x5, which means the character bitmaps are small -- 3x5 for the most part. Also my engine allows for proportional width characters. In any case, hopefully the concepts there are clear enough. The program slot-AudVid.bsp are the two VMs that run the display and Emic for my 'bot. Also attached is a zip with the current state of the whole 'bot program if anyone is interested. It works great, but I have a lot to do now that I've written a nice mixer for independent turn radius vs. absolute speed (but that's another topic for sure!).

    Not very brief rundown of what takes place in slot-AudVid.bsp:

    - this is one slot of an 8 slot 'bot program; this slot contains the virtual machines for Emic TTS and a 12x5 monochrome LED display (the latter driven by a MAX7221 -- similar to the 7219)

    - the main 'bot program counts "ticks" and different sensor, behavior and output tasks are run when their assigned time(s) come around. For example, the LED displays, motor *stops*, etc. are updated every tick (for fast animation and refreshes). The two Ping))) sonar units are run (not at the same time) once every 5 ticks. IR A/D conversion is run every other tick. This schema lets routines that can take a long time (e.g. waiting up to 20ms for sonar PULSIN, or 56ms for an RC PULSIN) are run in sequence, but things that are much faster to do are "slipped in" between all the longer tasks. I'm getting about 10hz through the whole shebang which isn't too bad for a relatively slow stamp. Additionally there is a global "counter" and a global heartbeat (1hz) from a DS1307 RTC... this lets a lot of VMs use a common counter for either program "loops" or for 1/2 second units. The only problem here is I used bytes for the two counters, so some of the cooler animations will "skip" when the rollover from 255 to 0 happens, depending on the divisor for post-scaling. Keep that in mind when looking at all the constants and vars -- I use the same set for all slots; all definitions are not necessarily applicable to every slot.

    - with that in mind, the VMs here allow the main program to PUT control (mode) and data (choice) bytes into set locations in SPRAM. The VMs for the Emic and the LED matrix display interpret the mode and choice and dump various cool stuff to the Emic and/or display automatically, in the "background". Both the LED matrix and the Emic are organized around a brutally common set of subroutines because lengthy, recursive text strings can be dumped to either.

    - both VMs only dump data once without repeating -- e.g., if text string #20 is sent to the Emic, it won't get sent again. Ditto bitmaps -- this keeps the painfully slow serial time to the Emic and the somewhat slow dumping of ~20 bytes or so to the MAX7221 from happening anymore than they have to. One thing I aim to do in the future is change the structure of the Emic VM so that the whole string isn't dumped, only partials -- this would let the Emic VM slip bytes in to the buffer without holding up the main program too long.

    - below is breakdown of the mode/data choices for each -- keep in mind that the main program is responsible for setting what gets used here -- and in a subsumption architecture this is really nice because whatever module last writes to the SPRAM locations asserts control of the display and/or speech. There's also comments in the code; but in some cases the comments in code could be slightly out of date.

    - the data for the bitmaps (display) and recursive text strings (display and emic) are written to external EEPROM. I have a separate set of utilities for formatting and dumping data to external EEPROM. Those are zipped below. The utilities work fine, but I wrote them *first* for this project (maybe 18 months ago) -- the code could be a lot more concise.

    - this material is for multi-slot stamps -- BUT that doesn't preclude using some of the basic concepts in single slot stamps -- if you're not using an Emic, the program is a lot smaller. Also you can dump external EE data 1k at a time or so if you need to (although lack of native I2C in the BS2 interpreter makes this a little more cumbersome). You could also just as easily use less data and store it directly in the Stamp EEPROM.

    Display (12x5 LED matrix) mode and data format:
    mode byte:
    special values: $00 = shut display down, $FF "forced" refresh every frame from bitmap in SPRAM
    bit assignments:
    I T S S N M M M
    0 0 0 1 0 0 1 0 = $12
    I = invert pixel values upon output?
    T = do a "transition" if switching to new bitmap
    S,S = speed of display against master counter (0-3)
    N = suppress automatic "talking waveform" if Emic is busy
    M,M,M = mode, 0-7:
    $0 = do nothing
    $1 = send recursive text string from EE using speed for speed of scrolling
    $2 = send bitmap (picture) from EE
    $3 = display decimal value of a byte or word from an SPRAM location
    $4 = do an animated "pattern" -- these are like screensavers -- using speed value

    Following the mode byte in SPRAM is the "choice" byte. How this byte is used depends on the mode:
    mode = $1 -- choice 0-255 will dump recursive text string with that index number from EE
    mode = $2 -- choice 0-255 will dump bitmap with that index number from EE
    mode = $3 -- choice 0-127 will be the SPRAM location to read. BIT7 assigns whether or not the value is to be read as a Byte or a Word.
    mode = $4 -- choice 0-3 -- screen saver animated patterns

    So for example, I can show·a·bitmaps from the main program by writing something like:

    PUT Mouth, $12, 100

    This will give me a speed of 1 (on a scale of 0-3), mode 2 (bitmap), and then show me bitmap #100. If I wrote something like:

    PUT Mouth, $12, RoboCounter//4+100

    I would see bitmaps #100-103 in sequence as the main program goes through it's paces (RoboCounter is the above mentioned master counter -- updated every tick through the main program).

    There is one more (optional) byte argument for the display: the brightness. The MAX7221 allows for a brightness of $0 - $F with $0 being dimmest (but not off). The display VM automatically fades the brightness (on every tick) to the set value, so it has a pleasing effect. I can also "pulse" the brightness by writing something like:

    PUT Mouth, $12, 100, RoboCounter.BIT4*$F

    This shows bitmap 100, with the brightness being set to $0 or $F every 16 ticks. Since the VM automatically fades in steps to the target brightness, this would fade from $0 to $F and back again every 32 ticks. It looks *way* cool. And... since there's a shutdown mode, this would blink the bitmap chosen (mode of $00 sends shutdown command to the MAX7221 driver) :

    PUT Mouth, RoboCounter.BIT0*$12, 100

    Last note on the display -- the entire current display bitmap is kept in SPRAM -- it's 60 pixels, so that's 10 bytes. This lets me mainupulate the bitmap directly and not be limited to dumping data solely from EE. There is one module in the 'bot where you play a "video game" on the front display using the sonars as an interface; this module writes it's own dynamic info to the display. Usually, the display (the "mouth" of the 'bot) is set to show smiley mouths, grimaces, "oh nos" and the like.

    ----
    Now, for the Emic, a lot of the modes and data choices are the same, because either VM handles text strings and the like:

    Emic mode and data format:
    mode byte:
    special values: $00 - do nothing
    bit assignments:
    V V V V N M M M
    0 1 0 1 0 0 0 1 = $51
    highnib = Emic volume 0-6
    lownib = mode, 0-7:
    $0 = do nothing
    $1 = send recursive text string from EE
    $2 = send special language chunk from EE
    $3 = speak decimal value of a byte or word from an SPRAM location
    following the mode byte in SPRAM is the "choice" byte. How this byte is used depends on the mode:
    mode = $1 -- choice 0-255 will dump recursive text string with that index number from EE
    mode = $2 -- speak special language chunk (these are randomly generated syntactically correct phrases)
    mode = $3 -- choice 0-127 will be the SPRAM location to read. BIT7 assigns whether or not the value is to be read as a Byte or Word.

    example: PUT SpeechAddr, $61, 20

    The above would speak phrase #20 (out of 0-255) from EE at a volume of 6

    A few points regarding my implmentation of the Emic:

    - unless suppressed by the display mode, if the Emic is busy, the LED display will show 4 frames of bitmaps at highspeed that are like an oscilloscope waveform. It's very "Robby the Robot"

    - there is a bit flag accessible to the main program that lets the main program "reset" the Emic...this good for when the 'bot needs to "interrupt" itself while speaking. It shows up as something like: emicQuit = emicBusy (if the emic is busy, reset it, so the next phrase will immediately be spoken)

    - recursive text insertion -- the data for text strings allows for inserting control codes followed by byte choices into the text string itself (see the data files). Essentially it's a way of writing a text string (to be displayed or spoken) and have other indexed phrases or "on the fly" information be inserted. E.g...

    DATA "There is an obstacle on my ", $F4, spkRoboDirOpp, " side. ", EOM

    ...the above, when interpreted by the VM, would insert the index number of the phrase "left" or "right" when it hits the control code. We set up a bunch of these special codes -- "left", "right", "back" can be inserted (these are chosen based on current values of sensor readings); the current time in hours and minutes; any other phrase from the index 0-255 (this lets us save a lot of memory and also reuse phrases by combining them, "special" language phrases that create syntactically correct english but are randomly chosen based on the current complexity of sensor readings, moto speed etc; last but not least, any byte/word value from SPRAM can be inserted. This can lead to fun phrasings like...

    DATA "Holy cow, ", $F2, subject, " it is now ", $F4, spkTime, "! ", EOM

    ...which, when parsed and read by the VM, will speak something like "Holy Cow, Great One, it is now twelve hours and ten minutes".

    ..or...

    DATA "Oh no, there is an obstacle ", $F3, $80 | snsrLaddr, " cm from my ", $F4, spkRoboDirOpp, " side! ", EOM

    ....which, depending on which sonar reading is smaller, would speak the word value from that sonar's spram address:

    "Oh no, there is an obstacle 281 centimeters from my left side!"

    Keep in mind that the above recursive text ALSO WORKS WHEN DUMPED TO SCROLLING TEXT on the LED display. Writing the same mode and data choice to the display addresses and the speech addresses will get the text scrolling on the screen at the same time it's being read (the sync can be off, but it's still pretty cool). Note also that I only wrote a one layer stack -- you can not insert a a recursive phrase into a recursive phrase (well you can, but then you'd never get back to the original message). I could easily set up the stack for more layers, but SPRAM was getting tight.

    Data organization:

    Bitmaps and ASCII characters are setup in the external EEprom in known block sizes, using the ASCII map, so no index pointers are needed. Note that for ASCII characters, the data includes a CHARACTER WIDTH byte -- this gives me proportional fonts that are correctly aligned by the VM. I.E., a lower case i takes up many fewer pixels than a capital W.

    Text strings 0-255 can be any length -- the utility program scans the 8k of data, builds up a list of 512 bytes of pointer addresses (256 words) at the start of the text blocks. The pointers are fetched by the text string VM so that the correct EEaddr is set for the start of the actual text. The utility allows for previewing of spoken data before burning, and playback of strings from burned EE to check.

    Whew. Hit me up with questions, comments, needs for clarifications. I didn't post this to completed projects, because the 'bot isn't really quite finished yet, and these two VMs are just one small part of the project.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST
  • T&amp;E EngineerT&amp;E Engineer Posts: 1,396
    edited 2007-09-26 19:30
    Wow. That took me a while to read through and skim through the BS2p files. I do not have an EMIC and with all the files you sent it is confusing to know where to start for my LED matrix. Can you clarify with specifics?

    You said that·your display·is 12x5 but my display is 8x8 so does that means I will have to create all 127 or so 8x8 characters of them manually?

    I also have quite a few MAX7219 available too.

    You also mention scrolling which I am interested in more than·quickly displaying·an 8x8 character to the display and then to the next 8x8 character.·Is this in your code somewheres?

    Sorry for the questions but I really like what I see but just can't go through it all easily to pick out what I need.

    I have 24LC16, 32 and I think a 128 available if needed and a BS2px and BS2.

    I can see you have been very busy on this project!

    PS: I also have built an 8x40 display using (5) bi-colored 8x8 LED matrix modules to give red, green and yellow outputs. I am using (10) A6821 SPI type serial chips. It is basically a serial (SPI) version of ULN2803s (which are parallel) or more like a high current output 74HC595. This way I can use only 3 lines (clock, data in, strobe) to control 40 * 2 columns. They also have /OE lines so I can turn any set of 8 (of the 5 modules) to either red, green or yellow colors. I have only written a scan routine across the 40 columns so far but hope to use something like your code to SPI data into the device.

    Comments?
  • ZootZoot Posts: 2,227
    edited 2007-09-26 19:42
    Somebody said...
    You said that your display is 12x5 but my display is 8x8 so does that means I will have to create all 127 or so 8x8 characters of them manually?

    Yep, sorry -- I haven't done an 8x8 character set. But you can certainly build off the already established ASCII set in my data files.
    Somebody said...
    You also mention scrolling which I am interested in more than quickly displaying an 8x8 character to the display and then to the next 8x8 character. Is this in your code somewheres?

    Yes. In slot-AudVid.bsp, go down to the Mouth_Machine sub. Scrolling is handled on column basis, not a character basis -- the short explanation is:

    1 - start new message; reset EEaddr to start of text string, reset character column count to 0
    2 - send one character column to display, using char and col at EEaddr and column
    3 - end of character?
    Y -> EEaddr = Eaddr+1 (next char);
    End of message? -- if yes, then done, if no then step 2
    N -> column = column + 1 (next column) and go to step 2
    4 - done
    Somebody said...
    I have 24LC16, 32 and I think a 128 available if needed and a BS2px and BS2.

    Any external EE that is big enough for your ASCII maps and text strings will work. This thread: http://forums.parallax.com/showthread.php?p=466264 has Jon Williams' I2C routines for BS2s that do not include native I2C in their interpreters.
    Somebody said...
    PS: I also have built an 8x40 display using (5) bi-colored 8x8 LED matrix modules to give red, green and yellow outputs. I am using (10) A6821 SPI type serial chips. It is basically a serial (SPI) version of ULN2803s (which are parallel) or more like a high current output 74HC595. This way I can use only 3 lines (clock, data in, strobe) to control 40 * 2 columns. They also have /OE lines so I can turn any set of 8 (of the 5 modules) to either red, green or yellow colors. I have only written a scan routine across the 40 columns so far but hope to use something like your code to SPI data into the device.
    That's your cool SX project, right? I saw that. Pretty.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST
  • ZootZoot Posts: 2,227
    edited 2007-09-26 19:50
    Oh, one other point about scrolling -- the "sliding window" technique is great if there isn't too much data to send (with sliding window you are essentially rewriting the entire content of the display while "cropping" the portion of text you want to see).

    In my case, since I hold the entire display in ram as a bitmap (10bytes), I can just push the contents of the rows right or left by X pixels, then add Y pixels onto either end. This is also how "tranisitions" are handled -- the state machine for the display can turn off or manipulate the existing RAM bitmap until all pixels are cleared, then the state machine allows the next image to be sent. The effect can be quite striking.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST
  • T&amp;E EngineerT&amp;E Engineer Posts: 1,396
    edited 2007-09-26 19:58
    Thanks Zoot.

    Since the controller needs to see 64 color characters, I will probably need to stick with 8x8 characters. I'm sure somewhere's on the internet there are 8x8 characters but I will certainly start with yours (and add more zeros? right?)

    I will look at the Mouth_Machine sub tonight and try to figure it out based on your steps. Great news about that.

    I have only worked with I2C once (sx-28) for a project where I wanted to save a value (in case power is lost) to then bring that value back again. I have not used it on the BS2 or BS2px. We'll see how that goes.

    When you saw my SX project of the 8x40 display, it was on many many solderless breadboards. I made my own PCB (sort of and did point to point soldering) so that the displays lie next to each other. However, this time I am not using 4017 decade counters because I had no control of colors (at least not directly) so I went another way using the A6821 which another engineer highly recommended for LED projects. It is almost identical (code writing to a 74HC595) but also gives you chip select control (/OE) and 500 mA per output leg of current that the 74HC595 does not give you.

    When you state "sliding window" are you just meaning that it is scrolling to the left or to the right column by column or something else. I would like to know more about this.

    More later. Thanks so much!
  • ZootZoot Posts: 2,227
    edited 2007-09-26 20:29
    Somebody said...
    I will probably need to stick with 8x8 characters. I'm sure somewhere's on the internet there are 8x8 characters but I will certainly start with yours (and add more zeros? right?)

    Yes. That's why I did a few for you -- mine are pretty small. 5x7 is common; I squeezed by on 3x5 for many, but legibility suffers. In any case, you will find, esp. for caps, that it doesn't take long to do each one.
    Somebody said...
    When you state "sliding window" are you just meaning that it is scrolling to the left or to the right column by column or something else. I would like to know more about this.

    Sliding window goes something like below. Say you have a 5 character display:
    
    DATA @ 0, "Some long message", EOM
    
    charLength = 4  'how many chars in "window" STARTING WITH 0 (so 4 = 5 chars)
    
    EEaddr = 0 'start of string
    StartMessage:
          charStart = 0 'what character to start with
      doMessage:
        FOR i = 0 TO charLength 'read from start chars to end of display
         READ EEaddr + charStart +  i, ioByte
         IF ioByte = EOM THEN startMessage  'EOM, yer done -- from here you can loop, repeat, stop, etc.
         'write the byte to display char position i -- your subs here
        NEXT
         'so when this loop is done the first time, chars 0-4 (the first 5) of the message are printed to display
        'when it's done the SECOND time, charStart = 1, so it grabs chars 1-5 and writes to display.
        'the effect is to scroll. It's called sliding window because you are always rewriting all the chars of the display, you're just
       'sliding a 5 character "window" over the full text string to choose *which* 5 chars to send
        PAUSE 100 'wait 1/10th second
        charStart = charStart + 1 ' "slide" window over one character
        GOTO doMessage
    
    
    



    Jon Williams did a great write up of these techniques (using an LCD alphanumeric display, but concept is identical) in a Nuts and Volts column. He has a state machine that lets you set window size and direction, so it's pretty cool. Unfortunately, I couldn't figure out exactly which NV column that appeared it -- I don't have it locally to look up.

    Oh wait, I just came across this -- it's another NV column about scrolling, flashing, chars, etc. with a BS2 to a 5x7 matrix display. That's in NV#70.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST

    Post Edited (Zoot) : 9/26/2007 8:34:04 PM GMT
  • T&amp;E EngineerT&amp;E Engineer Posts: 1,396
    edited 2007-09-26 21:36
    Zoot,

    I really!! appreciate your patients with me!

    The NV70, I have seen many times and it what I use for some of my designs - although based on MAX7219. I just never remember it being called a "sliding window" approach.

    http://www.parallax.com/dl/docs/cols/nv/vol2/col/nv70.pdf

    If you haven't seen it, you may want to see how to cascade MAX7219's on a BS2.

    http://forums.parallax.com/showthread.php?p=636061

    I used the NV70 as a baseline.
    ·
  • ZootZoot Posts: 2,227
    edited 2007-09-26 21:47
    No prob. The sliding window article is different than the NV #70 -- it deals with sending alphanumeric characters to a two-line serial LCD. Just can't remember which NV it is.

    Cascading on any kind of shift register/driver/display is nice when you have big matrices. I debated using two drivers for my 12x5 display, which would let me have better layout for the wiring in rows and columns, but I didn't want to spend the extra $$ nor use up the extra space for another 28-pin DIP if it wasn't absolutely necessary. One funky think about this particular 12x5 display is that the bytes for each 8 pixel group are staggered:


    [noparse][[/noparse]0000 - byte1, nib0 ][noparse][[/noparse]00000000 - byte0]
    [noparse][[/noparse]00000000 - byte2 ][noparse][[/noparse]0000 - byte1, nib1]
    [noparse][[/noparse]0000 - byte4, nib0 ][noparse][[/noparse]00000000 - byte3]
    [noparse][[/noparse]00000000 - byte5 ][noparse][[/noparse]0000 - byte4, nib1]
    [noparse][[/noparse]0000 - byte7, nib0 ][noparse][[/noparse]00000000 - byte6]

    Where the bytes are equiv. to the "digits" of the display.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST
Sign In or Register to comment.