Shop OBEX P1 Docs P2 Docs Learn Events
Multiple 8x8 LED Matrix Control with MAX7219 - Page 2 — Parallax Forums

Multiple 8x8 LED Matrix Control with MAX7219

2456

Comments

  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-01-28 13:33
    I uploaded a major update to post #3.

    I think the methods in the child object are cleaner now. There aren't so many "rotated" versions of methods.

    The main loop in the demo alternates between rotated displays and normal displays.

    I added methods to make it easier to plot points and lines. The points and lines can be plotted on the combined arrays or there are methods to effect only a single array.

    The object could greatly be improved with a double buffer. As it is now the plotted lines flash as they rotate. With a double buffer I could fill one section of memory while displaying another. I don't think the double buffer will be very hard to program but I'm getting kind of tired of this object for now. I'm sure I'll work on it more when my 16 array PCBs get delivered.

    Once I have a larger number of displays to play with, I'll add support for multiple rows of arrays. The current driver can only make use of a single row.

    I haven't made a video of the new code in action. but it can do a bit more than the previous version.

    The best thing about the new code is I now have a clear understanding to the relationship between LEDs and the bits in the Propeller's RAM. The two types of displays (rotated and normal) store bitmaps in RAM differently from each other.

    The method "IdentifyDisplays" will place a "1" in the first array, a "2" in the second and so on.

    Here's the code:
    PUB IdentifyDisplays | localCharacter
    
      result := arrayAddress
      localCharacter := "1"
      repeat arraysInUse
        if rotatedFlag
          RotateCharacter(activeFontId, localCharacter, result)
        else
          bytemove(result, fontAddress[activeFontId] + (8 * (localCharacter - FIRST_CHARACTER)), 8)
        result += 8
        localCharacter++
      LoadBitsToArray(arrayAddress)
             
    

    "arrayAddress" holds the memory location where the active bitmap is stored.

    On a normal array, the numeric characters can be placed in the active bitmap with a simple "bytemove".

    So if two arrays were used, the contents of the active bitmap would be:
                            byte %01100000
                            byte %11100000
                            byte %01100000
                            byte %01100000
                            byte %01100000
                            byte %01100000
                            byte %01100000
                            byte %01100000
                  
                            byte %01110000
                            byte %10011000
                            byte %00011000
                            byte %00011000
                            byte %00110000
                            byte %01100000
                            byte %11000000
                            byte %11111000
    

    If the arrays are rotated, then these characters would be stored like this:
                            byte %00000010
                            byte %11111111
                            byte %11111111
                            byte %00000000
                            byte %00000000
                            byte %00000000
                            byte %00000000
                            byte %00000000
                  
                            byte %11000010
                            byte %11100001
                            byte %10110001
                            byte %10011111
                            byte %10001110
                            byte %00000000
                            byte %00000000
                            byte %00000000
    

    I considered not changing the bitmaps for the two type of displays but this would require rotating the bits prior to sending them to the MAX7219 chip. This would have severely increased the overhead of sending the bitmaps to the displays.
  • Ron CzapalaRon Czapala Posts: 2,418
    edited 2014-02-01 21:27
    @Duane
    In an effort to understand how your code works, I stripped out a lot things to get down to basics.

    Your use of the dirb and outb registers for rotating a character map threw me and I decided to try a different approach.

    I'm not sure if it is any slower but I find it easier to follow.

    My program uses you ShiftOutSingle to display a character in each of my five arrays.

    Here is the rotate logic:
    VAR
      byte work                     'byte for rotate column
    
       RotateChar(4,@freeDesign080)
       RotateChar(3,@freeDesign105)
       RotateChar(2,@freeDesign112)
       RotateChar(1,@freeDesign112)
       RotateChar(0,@freeDesign110)
    
    
    
    PUB RotateChar(arynum, charptr) | idx,idy,idz,setb
       idz := 1
       repeat idy from 7 to 0
          work := 000000
          repeat idx from 0 to 7
             setb := (byte[charptr + idx] & (|<idy))  'get bit# idy from font
             if setb > 0 
               work |= (|<idx)                        'set bit# idx in work
          ShiftOutSingle(arynum, idz, work)
          idz+=1
    
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-02-02 11:33
    . . .
    Your use of the dirb and outb registers for rotating a character map threw me and I decided to try a different approach.
    . . .

    I can't say that I blame you. It's hard to see what I was doing as I look at the code today.

    My first attempt to rotate the bits ended up placing the bits back in their original location. I was at least expecting the bits to be scrambled if I got it wrong, not put back in their original location.

    The dirb and outb can be used like dira and outa, but the "b" registers don't affect any I/O pins. I'm sure I learned the trick used here on the forum.

    In case those at home want to follow along here's the original version (the one that works).

    "localFont" can be either zero or one to indicate which of the two fonts to use.
    "localCharacter" is the letter to be rotated, for example "a". "destination" is the memory location where the eight bytes of the rotated character bitmap is to be stored.
    PUB RotateCharacter(localFont, localCharacter, destination)
    
      result := fontAddress[localFont] + (8 * (localCharacter - FIRST_CHARACTER))
      if destination == -1
        destination := result
      RotateBitmap8x8(destination, result)
      
    PUB RotateBitmap8x8(destination, source) | temp[2], scratch[2], rowOld, rowNew, colOld, colNew, testResult, testBit, bitOfInterest
    '' This method rotates the bits in eight bytes
    '' located at "source" and places the rotated bytes
    '' in "destination".
    '' "source" and "destination" may be the same
    '' location.
    '' The rotation is 90 degrees clockwise
    
    
      'Pst.Str(string(13, " RotateCharacter"))
        
      longfill(@temp, 0, 2)
      bytemove(@scratch, source, LINES_IN_ARRAY) 
      repeat rowNew from 0 to 7
        bitOfInterest := 7 - rowNew
        repeat rowOld from 0 to 7
          dirb[7..0] := byte[@scratch][rowOld]
          outb[rowOld] := dirb[bitOfInterest]
        byte[@temp][rowNew] := outb
        'Pst.Str(string(13, " %"))
        'Pst.Bin(byte[@temp][rowNew], LINES_IN_ARRAY)
                  
      bytemove(destination, @temp, LINES_IN_ARRAY)
     
    

    I don't think I was trying for speed, I was just trying to get it to work. As I look at the above code I find it very hard to see what I was doing. IMO, rotating bits in a bitmap doesn't lend itself to easy to read code.

    If one were really interested in getting text to scroll quickly, it would be a good idea to store the font bitmaps in a rotated state.

    A rotated font would allow one column of bits to be easily read by just reading a single byte from the bitmap. As the font is currently stored, a column of bits has to be extracted from eight different bytes.

    One reason for storing the bitmaps as they currently are is because it was easier to type them in this way. I think it's easier to read the vertical "1" and "2" in post #32 then the rotated numbers. Neither of these reasons is a very good one. It wouldn't be hard to write a program to output the bitmaps in their rotated state which could then be pasted into the DAT section of a program. How the font looks in the DAT section isn't a very important consideration.

    I noticed the Simplytronics font isn't even displayed in binary.

    Here's Simplytronic's "1" and "2" "bitmaps".
    ASCII_0508_049 byte        $20,$60,$20,$20,$20,$20,$70,$00    ' -1-           
    ASCII_0508_050 byte        $70,$88,$08,$30,$40,$80,$F8,$00    ' -2-
    

    Having the bitmap stored as hex only requires on line be character. Obviously the the Simplytronics font wouldn't be any harder to read in a rotated state than its current state.

    I'm sure I'll be thinking more about these issues once my 16 array PCBs arrive. I think I submitted my order just after the cutoff date to have them made prior the "New Year" festivities so I probably have to wait a month before I receive them.

    I also plan to work on scrolling larger bitmaps across multiple rows once I have some larger arrays to play with.
  • Ron CzapalaRon Czapala Posts: 2,418
    edited 2014-02-02 11:51
    Duane Degn wrote: »
    ...
    If one were really interested in getting text to scroll quickly, it would be a good idea to store the font bitmaps in a rotated state.
    ...
    It wouldn't be hard to write a program to output the bitmaps in their rotated state which could then be pasted into the DAT section of a program.

    I thought about writing a VBScript to rotate the bits and replace the character bit maps but decided that there might be a reason to use them as is.
    Duane Degn wrote: »
    A rotated font would allow one column of bits to be easily read by just reading a single byte from the bitmap.
    As the font is currently stored, a column of bits has to be extracted from eight different bytes.

    That's what my code does - it extracts a bit (using the "decode value" operator |<) from the same column in each row and builds a new byte setting the appropriate bits.
    Effectively grabbing a column, and rotating it 90 degrees to the right...

    This thread was helpful: http://forums.parallax.com/showthread.php/118828-1-Bit-variables-in-Propeller
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-02-02 13:25
    I thought about writing a VBScript to rotate the bits and replace the character bit maps but decided that there might be a reason to use them as is.

    Ron,

    I just wrote a Spin program that rotates the fonts and outputs the bits to the terminal.

    Here's the last of the output.
    
    
    ASCII_0508_121          byte %10011100
                            byte %10100000
                            byte %10100000
                            byte %10010000
                            byte %01111100
                            byte %00000000
                            byte %00000000
                            byte %00000000
    
    
    ASCII_0508_122          byte %01000100
                            byte %01100100
                            byte %01010100
                            byte %01001100
                            byte %01000100
                            byte %00000000
                            byte %00000000
                            byte %00000000
    
    
    ASCII_0508_123          byte %00001000
                            byte %00110110
                            byte %01000001
                            byte %00000000
                            byte %00000000
                            byte %00000000
                            byte %00000000
                            byte %00000000
    
    
    ASCII_0508_124          byte %00000000
                            byte %00000000
                            byte %01110111
                            byte %00000000
                            byte %00000000
                            byte %00000000
                            byte %00000000
                            byte %00000000
    
    
    ASCII_0508_125          byte %00000000
                            byte %00000000
                            byte %01000001
                            byte %00110110
                            byte %00001000
                            byte %00000000
                            byte %00000000
                            byte %00000000
    
    
    
    
    
    
    
    
    ASCII_0508_126          byte %00001000
                            byte %00000100
                            byte %00001000
                            byte %00010000
                            byte %00001000
                            byte %00000000
                            byte %00000000
                            byte %00000000
    

    I'm using WYSIWYG so the percent signs wont come through correctly.

    I was going to post it after I clean it up. If you'd like I'll post it before cleaning it up.

    I just noticed the SimplyTronics font isn't left justified. My scrolling software assumes fonts are left justified. I'll need to decide if I care enough to edit the font.
  • Ron CzapalaRon Czapala Posts: 2,418
    edited 2014-02-02 13:55
    Duane Degn wrote: »
    Ron,

    I just wrote a Spin program that rotates the fonts and outputs the bits to the terminal.

    ...

    I'm using WYSIWYG so the percent signs wont come through correctly.

    I was going to post it after I clean it up. If you'd like I'll post it before cleaning it up.

    I just noticed the SimplyTronics font isn't left justified. My scrolling software assumes fonts are left justified. I'll need to decide if I care enough to edit the font.

    Pretty slick!

    I tweaked some of the freeDesign character maps like the lower case "i".

    It looked strange left justified - created a big gap between it and the following character, so I shoved it over a couple of pixels...
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-02-02 15:30
    I tweaked some of the freeDesign character maps like the lower case "i".

    It looked strange left justified - created a big gap between it and the following character, so I shoved it over a couple of pixels...

    Is this with the font scrolling?

    There should be the same number of spaces between each character when scrolled (if the font is left justified).

    Part of the setup process finds the width of each character and stores it in the "characterWidth" array, so then the "ScrollCharacter" method is called it wont use the empty columns of the bitmap.
    PRI ScrollCharacter(characterPtr) | fontPtr, localSize   '' Font does not need to be rotated.
    
    
      fontPtr := fontAddress[activeFontId] + (LINES_IN_ARRAY * (byte[characterPtr] - FIRST_CHARACTER))
      localSize := [B]characterWidth[/B][(activeFontId * CHARACTERS) + (byte[characterPtr] - FIRST_CHARACTER)]
    
    
      ScrollBitmap(fontPtr, localSize)
      
      ScrollBlank(LINES_BETWEEN_CHARACTERS)
    
    
    

    The space between character can be changed by changing the value of "LINES_BETWEEN_CHARACTERS".
    Spaces have a defined width of matching the width of the letter "n". In my education media class (we called it the "bulletin board" class) they called this "n spacing" where the space was supposed to have the same width as the letter n.

    After the width of a font has been found the space width (which would have initially been zero) is changed to match the width of a "n".

    From the "FindWidth" method.
      byte[result + (SPACE - FIRST_CHARACTER)] := byte[result + ("n" - FIRST_CHARACTER)] - LINES_BETWEEN_CHARACTERS
      
    

    If you were to just place a character in the buffer with bytemove, then you'd want to make sure and adjust the spacing.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2016-07-19 17:55
    I've attached the program to rotate the fonts. I didn't remove the unused methods and variables from the MAX7219 object.

    Here's the main part which rotates and displays the fonts (somewhat edited).
    ' . . . some cut . . .
      CHARACTERS_PER_PAUSE = 5 ' how many new character to display in terminal at once
       SPACE_BEFORE_BYTE = 24 ' used to format the output
                             
    VAR
     ' . . . some cut . . .
    
      byte scratchArray[8]  
    OBJ
      Pst : "Parallax Serial Terminal"
      Format : "StrFmt"  ' from LocalRoger
    PUB Main | localCharacter, fontName[2]
    ' . . . some cut . . .
    
      fontAddress[FREE_DESIGN] := @freeDesign032
      fontAddress[ASCII_0508] := @ASCII_0508_032
      fontName[FREE_DESIGN] := @fontName0
      fontName[ASCII_0508] := @fontName1
      
      Pst.Start(115_200)
    
    
      repeat
        result := Pst.RxCount
        New_Line
        Pst.Str(string("Press any key to start."))
        waitcnt(clkfreq / 2 + cnt)
      until result
       
      repeat result from 0 to MAX_FONT_INDEX  ' find width of both fonts
        repeat localCharacter from FIRST_CHARACTER to LAST_CHARACTER
          RotateCharacter(result, localCharacter, @scratchArray)
          New_Line
          DisplayFontAsBinary(result, fontName[result], localCharacter)  
          if localCharacter // CHARACTERS_PER_PAUSE == 0
            Pst.CharIn
            New_Line
            New_Line
            New_Line
    
    
      New_Line
      Pst.Str(string("Program Ended"))
      repeat
             
    DAT
    
    
    fontName0               byte "freeDesign", 0
    
    
    fontName1               byte "ASCII_0508_", 0
    
    
    fontNameScratch         byte 0[15]
    
    
    byteHeadingText         byte "byte %", 0
    
    
    spaceText               byte " "[SPACE_BEFORE_BYTE]
    
    
    PUB DisplayFontAsBinary(fontIndex, namePtr, localCharacter) | spacesToPrint, byteIndex
    
    
      New_Line
      'fontNameScratch := 0
      result := Format.Str(@fontNameScratch, namePtr)
      result := Format.fdec(result, localCharacter, 3, -3)
      spacesToPrint := SPACE_BEFORE_BYTE - strsize(@fontNameScratch)
      Pst.Str(@fontNameScratch)
      repeat spacesToPrint
        Pst.Char(32)
      Pst.Str(@byteHeadingText)
      Pst.Bin(scratchArray[0], 8)
      repeat byteIndex from 1 to 7
        New_Line
        Pst.Str(@spaceText)
        Pst.Str(@byteHeadingText)
        Pst.Bin(scratchArray[byteIndex], 8)
        
    PUB New_Line
    
    
      Pst.ClearEnd
      Pst.Newline
    

    The output from the terminal could be cut and pasted into a program to use the rotated font.
  • Ron CzapalaRon Czapala Posts: 2,418
    edited 2014-02-02 15:53
    No, it wasn't during scrolling - at least not with the freeDesign font but it does with the other font. Probably because it isn't left justified as you said earlier.
    It can be seen at .25 secs in my latest video above.

    I'm glad you explained now the FindWidth, etc functions work.
  • Ron CzapalaRon Czapala Posts: 2,418
    edited 2014-02-26 12:15
    I've been studying your program code when I found time and had some difficulty - you are obviously very adept with SPIN.

    I took a stab at creating a stripped down version as I went along.

    Instead of calculating and storing the width of each character map, I drop blank columns on the fly as I load them into the buffer.

    Of course, I had to modify the ASCII_0508 patterns to left justify them for this to work.

    I added a character shifting approach to display and shift characters rather than columns and a All Characters routine to scroll thru the entire font.

    Think I'm finally getting a better handle on driving these MAX7219 modules thanks to your efforts! :smile:
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-02-26 13:01
    I was just looking through your code. I like your idea of measuring the width of a character on the fly. I was kind of concerned about the time is would take. It's one of those speed vs memory trade offs. I chose speed over memory savings but I might switch to the way you're doing it. I don't like having to have a separate memory for each characters width.

    You're ordering the arrays opposite to how I am (at least in the latest drivers). I might have ordered them differently with my first attempt.

    Thanks for sharing your modifications. I'll likely incorporate some of your changes into my version.

    I'm seriously thinking of making a PASM version of the method "LoadBitsToArray". Once I'm up to 16 or more arrays, animations and scrolling text will take too long to shift out bits in Spin.

    I also want to use a double buffer so one buffer can be updated while the other one is displayed.

    I started adding a double buffer in the Spin version but I realized, it didn't do any good unless I add a second cog to shift out bits from one buffer while the other buffer is being written to. If I'm going to the trouble of adding a second cog, I'll probably have it run PASM.

    IMO, these LEDs are a fun way of learning about memory manipulation and shifting bits.
  • Ron CzapalaRon Czapala Posts: 2,418
    edited 2014-02-26 13:14
    Duane Degn wrote: »
    I was just looking through your code. I like your idea of measuring the width of a character on the fly. I was kind of concerned about the time is would take. It's one of those speed vs memory trade offs. I chose speed over memory savings but I might switch to the way you're doing it. I don't like having to have a separate memory for each characters width.

    You're ordering the arrays opposite to how I am (at least in the latest drivers). I might have ordered them differently with my first attempt.

    Thanks for sharing your modifications. I'll likely incorporate some of your changes into my version.

    I'm seriously thinking of making a PASM version of the method "LoadBitsToArray". Once I'm up to 16 or more arrays, animations and scrolling text will take too long to shift out bits in Spin.

    I also want to use a double buffer so one buffer can be updated while the other one is displayed.

    I started adding a double buffer in the Spin version but I realized, it didn't do any good unless I add a second cog to shift out bits from one buffer while the other buffer is being written to. If I'm going to the trouble of adding a second cog, I'll probably have it run PASM.

    IMO, these LEDs are a fun way of learning about memory manipulation and shifting bits.

    That last code I had from you was from Jan 28. Ordering the arrays from right to left was a PAIN - I may change mine around although I've gotten used to dealing with the way they are ordered now.

    I also had trouble trying to use your waitcnt delay routines in my version but my approach seems to work with without problems (due the 53 sec system counter rollover).

    I hope you continue to post your code as you make improvements.
    - Ron
  • Ron CzapalaRon Czapala Posts: 2,418
    edited 2014-03-05 17:16
    @Duane,

    I figured out what you meant by the "ordering" of the arrays. The ShiftoutSingle procedure in the code I grabbed from your posted zip handled the arrays as 4 to 0 (left to right) while all my other code was ordering them 0 to 4 (left to right).

    No wonder I was having trouble!! :smile: Now everything is ordered 0 to 4.

    I created some routines that let me set any individual LED on or off using a column number (1 to 40 with five arrays) and row number (1 to 8).
    I use the memory array to store the bit pattern for each of the 40 columns so I can maintain the status of each LED.
    I set or clear one bit in a byte representing a particular column and update only that specific column using the ShiftoutSingle routine.

    Here is a video setting individual LEDs at two different speeds and directions...

    (The camera keeps trying to adjust the exposure)

    EDIT: Here is the routine
    VAR
      byte work
    
    PUB SetPixel(colnum, rownum, status) | arraynum, arraycol, pixel
    'turn individual LED on or off
    'colnum ranges from 1 to number of arrays x 8
    'rownum ranges from 1 to 8
    'status: 1 turns on LED, 0 turns it off 
      work := byte[arrayAddress-1+colnum]
      arraynum := (colnum-1) / 8
      arraycol := ((colnum-1) // 8) + 1
      pixel := 7 - (rownum - 1)
      if status 
        work |= (|<pixel)                                   'set bit 'pixel' to 1
      else
        work &= !(|<pixel)                                  'set bit 'pixel' to 0 
      ShiftOutSingle(arraynum, arraycol, work)
      byte[arrayAddress-1+colnum] := work
    
    
    
  • NWCCTVNWCCTV Posts: 3,629
    edited 2014-05-30 16:28
    @Duane Degn, I just wanted to say thanks for the help with this. I ordered several of these from EBay but low and behold the 10 uf capacitor location on the board did not show a + or -. Try explaining that to the Chinese seller!!!! Fortunately yours is marked. I have one of them going. Just a quick question, is CS the Data Out? I want to daisy chain the ones I have but need to verify this before moving forward.

    EDIT: I could actually use a quick schematic of how to daisy chain.

    EDIT::: After looking at post #23 I was able to figure it out. Great work all!

    EDIT:::: @Ron Czapala, Is the code in post #44 an add on to other code or what? I would like to accomplish the same thing as in yor video.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-05-30 20:55
    NWCCTV wrote: »
    is CS the Data Out?

    No, CS stands for Chip Select. Though it's technically not really the normal chip select used with standard SPI chips. Instead it's called "Load" on the MAX7219 datasheet. Even though it's technically called "Load" all the PCBs I've seen which use the MAX7219 label it "CS".

    Data Out is labeled "DOUT" in the photo photo below.

    attachment.php?attachmentid=105766&d=1388095080

    (Photo from post #1 of this thread.)

    All the pins on one side of the board are electrically connected to the pins on the other side except the data pins. One side has a Data In "DIN" and the other side a Data Out "DOUT".

    Here's the traces of one of the small PCBs I made.

    attachment.php?attachmentid=105925&d=1388820034

    With four of the pins, you can follow the red traces from the 5-pin header on the left side across the board to the 5-pin header on the right. All the pins on the left are electrically connected to the corresponding pins on the right except the center pins which are the data pins (the pins are in the same order as on the green PCB pictured above).

    The microcontroller connects to the Data In pin on the first board and the Data Out of the first board connects with the Data In pin on the second board. The chain can be continued by connecting the Data Out pin of one board to the Data In pin of the next board in line.

    Lots of this boards have the headers positioned so one board can be chained to the next using jumpers. Here's a picture showing some boards from ICStation and small purple boards I made. Both types of PCBs can be linked with jumpers.

    While I like the ICStation boards, I think I also like these boards from Electrodragon.

    Dot-Matrix-Chain-Display-Kit-Max7219-V2-350x350.jpg

    The Electrodragon boards have mounting holes.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-05-30 21:12
    The code attached to post #3 includes a "SetBufferPixel" method. I think it's similar to Ron's "SetPixel" method.
    PUB SetBufferPixel(localX, localY, localState) | arrayIndex, localBit'' Changes bit value at location localX, localY in active array to localState.
    '' Returns the index value of the byte containing the pixel.
    '' Returns -1 if the coordinates are outside the buffer area.
    '' The changes made to the buffer do not change the LEDs until
    '' "LoadBitsToArray" is called or the register with the
    '' updated pixel is written.
    

    "localState" should be set to one to turn the pixel on or set to zero to turn it off.

    One problem with my driver is it's really slow. Tom Crawford has written a PASM driver which updates the arrays much faster than my Spin version.

    I still need to incorporate Tom's code in with mine.

    My latest code will use the ROM font to display text with an array 32 pixels high but by the time I make an array that's 32 pixels high and at least 32 pixels wide, the refresh rate using Spin becomes painfully slow. Incorporating Tom's driver will solve this problem. I've built a large display but I haven't spent the time needed to get the code working properly. Getting Tom's code to work with mine has been at the top of my Propeller todo list for a while now and as has been the case for the at least a month, I'm just a few days away from getting back to work on this project. I really do want to get back to this project so can make use of my larger display. I presently have 64 x 64 pixel display which I intend to expand to 96 x 64 very soon.
  • NWCCTVNWCCTV Posts: 3,629
    edited 2014-05-31 08:35
    I must be doing something wrong. I have 2 Arrays daisy chained but the text does not scroll from one to the other. Rather, the text is the same on both arrays. Anyone know what the issue is?
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-05-31 09:31
    There's a constant "ARRAYS_IN_USE" that needs to be set to the number of arrays you're using.

    If you post your code as an archive we can take a look at it.

    A picture of your wiring may be helpful.
  • NWCCTVNWCCTV Posts: 3,629
    edited 2014-05-31 10:15
    I don't think a picture will be of much help as it is a spider web so I will explain what I have. I am using a Prop BOE Board.LED Master Array: VCC to 5V, GND to Ground (on BOE Board), DIN to Pin 14, CLK to Pin 13, CS to Pin 14. LED Slave Array: VCC to 5V, GND to Ground (On BOE Board), DOUT to DIN on Master, CLK to CLK on Master, CS to CS on Master. I have changed "ARRAYS_IN_USE" to 2. The code I am trying is the 3 Demos you created, Max7219Demo131226c, Max7219Demo140128d and Max140116e. I also tried Ron's ScrollDemo and I get the same results. I will post a video as soon as I figure out how to shrink the size down without having to zip it.
    DAT programName         byte "Max7219Demo131226c", 0
    CON
    {{
      ******* Public Notes *******
    
      Author: Duane Degn
      Date: December 26, 2013
      MIT License
      An attempt to control an 8x8 LED array with a MAX7219 chip.
      The number of arrays may be changed by changing the
      "ARRAYS_IN_USE" constant.
      The constants marked with "User changeable" may be
      changed based on the LED project is configured.
      The code in this program is pretty much all original.
      I did look at Hover1's 7-segment MAX7219 code. Which
      helped get me started.
     
    }}
    {
      ******* Private Notes *******
       131225c Displays a message one character at a time.
       25c Appears to be working.
       25d Change font with each message.
       25e Try to rotate text.
       25e Didn't work.
       25g Rotation worked.
       25h Try to add scrolling.
       25j Working reasonably well.
       25k Seems to scroll single rotated array correctly.
       25l Try adding additional array.
       25l Doesn't work. The two displays are almost the
       same. Both have lots of glitches.
       25m Better but a lot of noise on the last display.
       25n Much worse.
       25o Abandon 25n.
       26a Start moving MAX7219 specific code to a
       child object.
       26a Appears to work correctly.
       26b Make the split.
       26b Appears to work correctly using the child
       object "Max7219MultiArray131226b".
       26c Start adding a few features.
       
    }
    CON ' Parent Constants                    
                         
      _clkmode = xtal1 + pll16x 
      _xinfreq = 5_000_000
      CS_PIN = 15                   '' User changeable
      DATA_PIN = 14                 '' User changeable
      CLOCK_PIN = 13                '' User changeable
      ARRAYS_IN_USE = 2             '' User changeable
      
      QUOTE = 34
    VAR
     
      byte arrayBuffer[Leds#LINES_IN_ARRAY * ARRAYS_IN_USE]
    OBJ
      Leds : "Max7219MultiArray131226c"
      
    PUB Demo
      Leds.Init(CLOCK_PIN, DATA_PIN, CS_PIN, ARRAYS_IN_USE, @arrayBuffer)
      waitcnt(clkfreq * 2 + cnt) ' time to open terminal window
      MainLoop
      
    PUB MainLoop 
       
      repeat
        Leds.SetFont(Leds#FREE_DESIGN)
        Leds.ScrollRotatedText(@message0)
     
        Leds.SetFont(Leds#ASCII_0508)
        Leds.ScrollRotatedText(@message0)
    DAT
    message0                byte "Merry Christmas  ", 0
    
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-05-31 13:09
    Without switching the wires, switch the order of the arrays. Put the array on the right on the left.

    After doing the above, slap your forehead.

    It's easier to see the arrays are working correctly by pausing the video than it would be in real life since it's hard to freeze images in our brain.

    I'm pretty sure the order isn't consistent in my first attempts at a driver so be prepared to rearrange the arrays when trying different versions of the driver.
  • NWCCTVNWCCTV Posts: 3,629
    edited 2014-05-31 13:26
    Got it. Thanks. I misunderstood what you were saying but then it became clear and I slapped my forehead!!!!
  • NWCCTVNWCCTV Posts: 3,629
    edited 2014-05-31 16:13
    So what do you use to power the arrays? I am using a 12V 2 Amp Wall Wart on my BOE Board and it controls 2 of the Arrays. I then hooked up my bench top power supply to power the third one. Working on soldering the fourth one and I am thinking of putting together a case to hold all 4 in and was thinking of using @erco's favorite rechargeable batteries. I just need to put together a Prop on a small PCB to control the arrays as I do not want to waste an entire Prop BOE Board for them!!
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-05-31 17:07
    NWCCTV wrote: »
    So what do you use to power the arrays?

    Electricity.

    I'm still trying to figure out the best way to power these type of arrays. When I'm working at the computer, I tend to use my bench supply. Sometimes I'll power one or two arrays from a QuickStart's Vin pin while the QuickStart is powered by an USB connection.

    There are lots of 5V chargers with USB connections on them. These might be a good power supply for a few arrays.

    For a portable display, I've used four AA NiMH cells with a holder like this one (it has a built in power switch). I also use Li-Ion cells and LiPo packs along with a DC-DC regulator.

    I agree with your not wanting to use the PropBOE just to control your arrays. Currently, the least expensive Propeller board I'm aware of is the Propeller Project Board. If you can find some QuickStart boards on sale from Radio Shack they would work well to control the arrays.
  • NWCCTVNWCCTV Posts: 3,629
    edited 2014-05-31 17:23
    The project board is quite large for controlling 4 arrays. Any reason the Prop Mini would not work? http://www.parallax.com/product/32150
    I can also put my own together with chip and a crystal and a few other components. I think if the Prop Mini will work that might be the easiest way to go. I am going to mount the 4 I currently have in something, possibly Polymorph if the Shack still has it on sale. I would like to get my hands on one of your 16 array boards. I could have some fun with one or two of those!!!
  • NWCCTVNWCCTV Posts: 3,629
    edited 2014-05-31 17:36
    How can I make my arrays work like Ron did in post #44?
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-05-31 19:22
    NWCCTV wrote: »
    Any reason the Prop Mini would not work? http://www.parallax.com/product/32150

    Not that I'm aware of.
  • GarethGareth Posts: 278
    edited 2014-06-11 06:58
    Duane Degn wrote: »
    If any of you use this object, I hope you let me know. It's always fun to learn when someone else is using code I wrote.

    I'll add some details on how to use the program in the following posts.

    I have wired up 4 of these displays and was really amazed at the brightness they give out...... even @3.3V supply to them (outside in sunlight ....wonderful)
    Your examples work well and I am currently try to clear the "Chaff from the Wheat" to see what is going on....
    IMG_1930[1].jpg



    Q:- I have a question with regards to using the 8x8 Led Array in a 2x2 array ie a square of 4 modules.
    I have only seen examples of them working in a linear scrolling fashion...
    .......so what i am asking is there an easy way to give for example an X,Y coordinate and get it to plot a point say 12,12 ..... ?

    IMG_1931[1].jpg

    I used a triple stacked "Turned Pin IC sockets" to raise the two right most arrays (2&4) .... which means they can easily be butted together.
    IMG_1932[1].jpg

    Regards G
    1024 x 768 - 84K
    1024 x 768 - 96K
    1024 x 768 - 80K
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-06-11 08:03
    Gareth wrote: »
    Q:- I have a question with regards to using the 8x8 Led Array in a 2x2 array ie a square of 4 modules.
    I have only seen examples of them working in a linear scrolling fashion...
    .......so what i am asking is there an easy way to give for example an X,Y coordinate and get it to plot a point say 12,12 ..... ?

    Hi Gareth,

    I do have code which allows any arbitrary size of array and there's code to place a pixel anywhere on the array.

    I've used this code to display 32x32 bitmaps and to scroll the Parallax font from ROM.

    I've been meaning to get back to working on this code and add Tom's PASM MAX7219 driver to allow faster display updates. I've been planning on working on this code "sometime in the next few days" for the last few months. I'll work on it today.

    I don't know if you've seen the thread about the smaller arrays? Post #102 of the thread shows a partially populated PCB with can hold 16 of the small arrays. I successfully used my code on a 64x32 pixel array but when I tried it on a 64x64 display, it didn't work correctly. I'm planning on adding two more of the PCBs to my display to make it 96x64 pixels and I'll need to use Tom's code to speed up the refresh.

    I'll be working on this today and I'll hopefully have code to allow easy X, Y placement of pixels on any size of array posted today or tomorrow.

    I've never tried to run the MAX7219 chips at 3.3V. I'm surprised they work. Interesting.

    I'll be working on the code in between my experiments to add color to Polymorph. I wonder who I should blame the coloured Polymorph distraction on?
  • GarethGareth Posts: 278
    edited 2014-06-11 09:08
    Duane Degn wrote: »
    I've used this code to display 32x32 bitmaps and to scroll the Parallax font from ROM.
    Aha... I am glad you are doing the ROM extraction for the Max chip...............my POV ROM extraction was quite a feat too....

    Indeed yes I have been watching your Mega Panel .... woohooo .... this is one reason for me to check these display types out..... that display is calling out for the "Life" program..

    I was on my way to try to trap the x,y coords and port and cross jump the result to each display...messy however a quick work around.... I have not tried Toms driver yet....so will do so "Next" before i go further...

    Re:- 3.3Volts ..... surprised me to....... strangely I just checked the Max Spec sheet and it quotes the supply voltage 5.5V down to about 4.0V ...... even stranger....

    Coloured PM ... oh I still remember the pigment ,,lots of it,,, and glowing hands after the UV pigment ....
    BTW if you add around 40% by volume graphite to the PM a calculated guess "says" it will conduct.... more about that in the not to distant future....... exciting times are developing.
    8x8Smiley100.png
    100 x 100 - 19K
  • wilson16wilson16 Posts: 1
    edited 2014-12-02 22:01
    Hai everyone , is possible two set module max7219 running with different pattern on LED dot matrix at the same signal line?
    For example, one of dot matrix scrolling "L" to left another one dot matrix just display 'G' only.
Sign In or Register to comment.