Starten MAX7219

Bavelt

Golden Member

Ik heb een schakelingetje gemaakt, waarbij ik gebruik maak van een printje met acht 7-Segment displays.
Daarbij is een MAX7219 aan boord, die 8 Digits kan aansturen.

Het werkt ook wel, maar ik worstel een beetje met opstartproblemen.
In de meeste gevallen gaat het goed, maar toch gebeurt het redelijk vaak dat bij Power On alle displays op '88888888' komen te staan.
Resetten van de PIC16F1847 helpt niet; het enige dat echt helpt is spanning er af, even wachten en dan opnieuw spanning er op.
Dan is het soms: 'nee, nóg niet, opnieuw. En na enkele pogingen, ja nu doet hij het.

Zo ook in onderstaand klein Mikro Basic programmaatje. Een simpele teller.
Nu vraag ik me af wat er fout gaat en/of hier überhaupt wel iets aan te doen is. Wellicht vanwege de Chinese kwaliteit? Mee leren leven en paar keer de spanning uit-aan doen? Is wel een beetje vreemd en komt niet echt betrouwbaar over.

Of kan ik toch nog iets doen?

De source van het progamma: (het projectje is ook als bijlage meegestuurd)

'====================================================================================================
Program Test7219    'Test 7-Segment - 8 Digits leds with MAX7219
'====================================================================================================
' Project name: Test7219
' MCU:          PIC16F1847
' Oscillator:   Internal 8 MHz
' Display:      7-Segment 8 pieces with Max 7219 (SPI1)
' SDO:          LATB.2                   Pin 8
' SCK:          PORTB.4                  Pin 10
' D/C:          LATB.3                   Pin 9

 Dim Datapin    As sbit at LATB.2       'Pin 8  SDO  - SPI1
     SCKPin     As sbit at PORTB.4      'Pin 10 SCK  - SPI1
     D_C        As sbit at LATB.3       'Pin 9  Data Command
     
     Disp       As Byte
     Dsp        As Byte [8]

     Cnt        As Byte
     CntSec     As Longword
     i1         As LongWord

'====================================================================================================
Sub Procedure Max_Write(Dim pRow, pDig0 as Byte)
'====================================================================================================
 D_C = 0
 SPI1_Write(pRow)
 SPI1_Write(pDig0)
 D_C = 1
 Delay_ms(2)
End sub

'====================================================================================================
Sub Procedure Max7219_Init()
'====================================================================================================
 Max_Write(0x09, 0xFF)                   'Decode Mode Code B-Digital digits 7-0
 Max_Write(0x0B, 0x07)                   'Scan Limit 0-7
 Max_Write(0x0C, 0x01)                   'Normal Operation
 Max_Write(0x0A, 0x0C)                   'Intensity
End sub

'====================================================================================================
Sub Procedure Write_Display()
'====================================================================================================
 For Disp = 1 to 8
   Max_Write(Disp, Dsp[Disp - 1])
   Next Disp
End sub

'====================================================================================================
Sub Procedure Blank_Digits()            'Blank Digits Without Decimal point (0x7F)
'====================================================================================================
 For Disp  = 0 to 7
   Dsp[Disp] = 0x7F
 Next Disp
 Write_Display()
 Delay_Ms(20)
End Sub

main:

OSCCON     = %01110000                  '8Mhz Internal
ANSELB     = %00000000                  'All Port B Digital
ANSELA     = %00000000                  'All Port A Digital
TRISB      = %00000001                  'Port B.0 Input
TRISA      = %00001111                  'Port A0, A1, A2, A3 Input

SPI1_Init()                             'Init SPI
Max7219_Init()                          'Init MAX7219
Delay_ms(5)
Blank_Digits()                          'Blank Displays
Delay_Ms(5)

i1         = 0

While True

Inc(i1)
Dsp[7] = i1 /10000000 mod 10
Dsp[6] = i1 /1000000  mod 10
Dsp[5] = i1 /100000   mod 10
Dsp[4] = i1 /10000    mod 10
Dsp[3] = i1 /1000     mod 10
Dsp[2] = i1 /100      mod 10
Dsp[1] = i1 /10       mod 10
Dsp[0] = i1           mod 10

Write_Display()
Delay_Ms(1)

Wend

End.
Fouten zijn het bewijs dat je het probeert..

Ik denk dat je procedure Max_Write niet helemaal goed is, en dat het schrijven van de cijfers ook regelmatig fout gaat, maar dat doe je zo snel achter elkaar dat je het niet kunt zien.

Ik zou beginnen met een kleine delay (hoeft maar microsecondes te zijn) tussen het schrijven van de D_C uitgang en het versturen van de data. Je hebt die pin "data command" genoemd, maar is dat niet gewoon de chip select?

Eigenlijk zou ik verwachten dat het resetten van de PIC de chip wel opnieuw zou initialiseren, dus ik snap niet goed waarom dat niet zou helpen. Misschien dat hij met een verkeerde schrijfactie in een modus terechtkomt waar je hem niet meer uit krijgt?

[Bericht gewijzigd door SparkyGSX op maandag 9 januari 2023 17:43:49 (24%)

Een manager is iemand die denkt dat negen vrouwen in één maand een kind kunnen maken
Paulinha_B

Honourable Member

Het is geen antwoord op de vraag - excuus! - maar is dit nu niet gruwelijk onelegant EN weinig efficient?


Dsp[2] = i1 /100      mod 10
Dsp[1] = i1 /10       mod 10
Dsp[0] = i1           mod 10

Toch fraaier:


[...]
Dsp[2] = i1       mod 1000
Dsp[1] = i1       mod 100
Dsp[0] = i1       mod 10

of mis ik iets?

Overigens heb ik al in geen eeuwigheden geen Basic meer bedreven, en PICs zijn sowieso terra incognita voor me, maar een beetje vertraging hier en daar, zoals door Sparky gesuggereerd, kan nooit kwaad, en heb ik al heel wat vage problemen weten oplossen.

[Bericht gewijzigd door Paulinha_B op maandag 9 januari 2023 17:58:57 (27%)

Arco

Special Member

Met opstarten moet de D_C pin hoog zijn: die is nu laag... (ik hang voor de zekerheid altijd een pull-up aan SPI select pinnen)

Op 9 januari 2023 17:47:23 schreef Paulinha_B:
Het is geen antwoord op de vraag - excuus! - maar is dit nu niet gruwelijk onelegant EN weinig efficient?


Dsp[2] = i1 /100      mod 10
Dsp[1] = i1 /10       mod 10
Dsp[0] = i1           mod 10

Toch fraaier:


[...]
Dsp[2] = i1       mod 1000
Dsp[1] = i1       mod 100
Dsp[0] = i1       mod 10

of mis ik iets?

De uitkomsten zijn dan totaal verschillend: mod 1000 is wat anders als mod 10...

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Paulinha_B

Honourable Member

mod 1000 is wat anders als mod 10...

Dankje, daar was ik ook nog wel ;) Maar het ging niet om mod 10, wel om "i1 /100 mod 10"
Nogmaals, het kan best zijn dat ik iets mis, hoor, maar wat er staat wringt me lelijk tegen. Dat moet properder kunnen. Maar nogmaals, daar gaat het eigenlijk niet om.

Uw opmerking over de pin die aanvankelijk laag is, waar ze hoog moet zijn, heeft alle kans om relevanter te zijn.

Bavelt

Golden Member

Op 9 januari 2023 17:58:36 schreef Arco:
Met opstarten moet de D_C pin hoog zijn: die is nu laag... (ik hang voor de zekerheid altijd een pull-up aan SPI select pinnen)

Waarom is D-C laag? Omdat de poort (B.3) als output is gedefinieerd en dat default 0 is?

Maar een Pull-up aan een poort hangen die als output is ingesteld? Kan dat wel? Het is toch geen open collector?

Fouten zijn het bewijs dat je het probeert..
Bavelt

Golden Member

Op 9 januari 2023 18:04:23 schreef Paulinha_B:
[...] Dankje, daar was ik ook nog wel ;) Maar het ging niet om mod 10, wel om "i1 /100 mod 10"
Nogmaals, het kan best zijn dat ik iets mis, hoor, maar wat er staat wringt me lelijk tegen. Dat moet properder kunnen. Maar nogmaals, daar gaat het eigenlijk niet om.

Tja, je wilt natuurlijk wel iedere digit tonen.

Het kan ook wel anders. Dan krijg je dit:


While True

Inc(Dsp[0])
If Dsp[0] > 9 Then
   Dsp[0] = 0
   Inc(Dsp[1])
   If Dsp[1] > 9 Then
      Dsp[1] = 0
      Inc(Dsp[2])
      If Dsp[2] > 9 Then
         Dsp[2] = 0
         Inc(Dsp[3])
         If Dsp[3] > 9 Then
            Dsp[3] = 0
            Inc(Dsp[4])
            If Dsp[4] > 9 Then
               Dsp[4] = 0
               Inc(Dsp[5])
               If Dsp[5] > 9 Then
                  Dsp[5] = 0
                  Inc(Dsp[6])
                  If Dsp[6] > 9 Then
                     Dsp[6] = 0
                     Inc(Dsp[7])
                     If Dsp[7] > 9 Then
                        Dsp[7] = 0
                      End If
                   End If
                End If
             End If
          End If
       End If
    End If
 End If
 
 Write_Display()
 
Wend

Maar ik vraag me af of dit wel efficiënter is... :?

Fouten zijn het bewijs dat je het probeert..
Bavelt

Golden Member

Ondertussen heb ik de aanpassingen gedaan, zonder resultaat.

Als ik het 'programma' strip tot nagenoeg niks,
dan krijg ik:

main:

OSCCON     = %01110000                  '8Mhz Internal
ANSELB     = %00000000                  'All Port B Digital
ANSELA     = %00000000                  'All Port A Digital
TRISB      = %00000001                  'Port B.0 Input
TRISA      = %00001111                  'Port A0, A1, A2, A3 Input

D_C        = 1 

SPI1_Init()                             'Init SPI
Max7219_Init()                          'Init MAX7219

Dan nog gaat het vaak (ca 3 van de 10 keer) mis. De displays komen in een modus terecht waar het niet meer uitkomt, tenzij de spanning eraf gaat.
Het programma heeft daar dan dus geen invloed op. Resetten heeft dan ook geen effect.

Het moet iets zijn wat gebeurt als de voedingsspanning wordt ingeschakeld. Ik heb al diverse spanningen (tussen 4-5V) gebruikt, maar daar zit het hem ook niet in.

De MAX7219 heeft een eigen oscillator aan boord die wordt gebruikt voor de multiplexing. Zou daar iets raars kunnen zitten?
Het ding schiet in ieder geval in de stress.

Fouten zijn het bewijs dat je het probeert..
Bavelt

Golden Member

Dit zou hem wel eens kunnen zijn:

Als alle ledjes branden, is de MAX7219 in Testmode.

Door dit commando kan ik hem geforceerd uit de test mode halen:


 Max_Write(0x0F, 0x00)                   'Normal mode
Fouten zijn het bewijs dat je het probeert..
Lucky Luke

Golden Member

Ik heb de datasheet slechts diagonaal gelezen, maar:

Staat per ongeluk de display test aan? Dat register initialiseer je niet. (Datasheet zegt welliswaar dat alle control registers bij opstarten gereset zijn, maar toch… en resetten ze dan naar nullen of enen? (On initial power-up, all control registers are reset). Ik zou nullen aannemen, maar blijkbaar gaat er toch iets mi.

Datasheet zegt verder dat eens displaytest aan staat, hij aan blijft tot je ‘m uit zet. Dat klinkt nu ik het zo opschrijf erg opendeurkringverwijzing-ig, maar oorspronkelijke tekst is “ Note: The MAX7219/MAX7221 remain in display-test mode (all LEDs on) until the display-test register is reconfigured for normal operation.”)

Edit: ah, niet diagonaal genoeg gelezen, je had dat zelf ook al ontdekt. Ben benieuwd of dat het inderdaad is.

Eluke.nl | handgetypt | De mens onderscheid zich van (andere) dieren door o.a. complexe gereedschappen en bouwwerken te maken. Mens zijn is nerd zijn. Blijf Maken. (Of wordt, bijvoorbeeld, cultuurhistoricus)
Bavelt

Golden Member

Had ik net zelf inderdaad ook gevonden (zie post) :)

Ik was aan het speuren in de datasheet. Het was té toevallig dat ALLE ledjes aan zijn.
Ik denk inderdaad dat het resetten bij power-up niet helemaal lekker gaat / ging.

Ik kan de foute start nu niet meer reproduceren! Een goed teken!
Het grappige is dat ik wel vaker MAX7219's heb gebruikt. Maar dit is net weer een andere printje. Ik zal die andere programma's ook maar eens nalopen en dit er netjes in brengen.

Fouten zijn het bewijs dat je het probeert..
Bavelt

Golden Member

Dit was het inderdaad wel. Ik heb de wijziging ook aangebracht in een ander programmaatje dat gebruik maakte van dezelfde display-unit. Daar ging het ook af en toe mis, nu niet meer. :)

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

Ik denk dat je te vroeg SPI commando's verstuurt, voordat die MAX7219 wakker is...
Pull-up aan de chipselect moet eigenlijk altijd omdat alle i/o pins zwevende inputs zijn bij opstarten, dat kan verrassende resultaten geven...

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bavelt

Golden Member

Ah, weer wat geleerd... :)
Ondertussen werkt alles nu prima! Dat geeft de burger moed.

Fouten zijn het bewijs dat je het probeert..

Ik had hetzelfde.
Ook hetzelfde advies gevolgd
En dat werkte ook bij mij :)

Op het moment dat alles voor het eerst spanning krijgt, reset de microcontroller zichzelf voordat hij aan het programma begint, en in die tijd zijn meestal alle I/O pinnen "zwevend". Met een pullup weerstand aan de chip select negeert de max7219 wat er gebeurt in die tijd.

Bavelt

Golden Member

Wat ik me eigenlijk nog steeds afvraag: Is het raadzaam op de clock (SCK) en Datapin bij het gebruiki van SPI ook van een pull up weerstand te voorzien of is dat onnodig?

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

Niet nodig.
Zolang de /SS (slave/chip select) hoog is reageert de chip toch nergens op...

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bavelt

Golden Member

Het niet goed initialiseren van het Register om de display in test mode te zetten heeft een beetje een vervolg:

Ik merk dat de display-unit af en toe toch weer in de 'testmode' springt tijdens uitvoering van het programma.
Gevolg: alle ledjes branden weer.

Ik kan dit in principe simpel oplossen door het opnemen van

Max_Write(0x0F, 0x00)                   'Normal mode (disable test mode)

Als ik dit plaats voor iedere 'write' van de display gaat het wel goed. Maar toch voelt het niet helemaal lekker om dit steeds te doen. (zou alleen bij INIT moeten hoeven).

Het spul blijkt gewoon gevoelig voor de omgeving (ik schakel er een relais en pomp mee).
Toch maar gewoon (weliswaar als symptoombestrijding) laten staan?

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

Misschien storing? (worden motor en relais uit dezelfde voeding gevoed als de micro?)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bavelt

Golden Member

Op 14 januari 2023 14:37:05 schreef Arco:
Misschien storing? (worden motor en relais uit dezelfde voeding gevoed als de micro?)

Motor niet; die wordt door het relais vanuit de 230V geschakeld. Met een RC van 100 Ohm en 0,047 uF Condensator) over de contacten.
Het relais hangt wel aan de voeding van de PIC (+5V).

Ik heb een diode over het relais gezet.

Zonder het relais / motor krijg ik nooit een storing (dan gebruik ik een ledje).

Het commando Max_Write(0x0F, 0x00) biedt wel soelaas, maar is volgens mij meer symptoombestrijding dan de oorzaak aanpakken.

Daarbij vroeg ik me af of het toch niet mogelijk is om de motor met een Power FET (of 2) aan te sturen, zoals ik onlangs in een dimmer deed.
Dan heb je in ieder geval geen relais pieken, en vonken over contacten...

Fouten zijn het bewijs dat je het probeert..