Welcome, Guest
Username: Password: Secret Key Remember me

TOPIC: Big GPS Clock

Re: Big GPS Clock 9 years 4 days ago #14894

I've returned to complete this project now that the 4" Segment Displays have arrived. They were pretty cheap, $16 for two segments with all of the appropriate drivers onboard.

The serial interface is easy enough to use, though I can not get them to work in a daisy chain - segment data is corrupted when it shifts through to the second display..

Re: Big GPS Clock 9 years 3 days ago #2385

  • hop
  • hop's Avatar
  • Offline
  • Platinum Boarder
  • Posts: 526
  • Thanks received: 46
I am really interested in these! I tried quite awhile ago to build a big 6 digit display using a MAX controller and failed miserably when I realized all the wiring I needed to do to connect the two displays. There were certainly easier ways to go about it, but it didn't work. Even after few hours effort and two full kits of static sized jumper wires.

As you know Graham, I'm moving forward (albeit slowly) with my Embedded Jeep project and one of the features is a custom maded console that shows external and internal temps, barometric pressure, GPS location, and direction. All these features are available on newer vehicles and also was an option for my Jeep when I bought it in '98, but at a substantial cost not worthy of the benefit. Since I found that I can get the mod case from a junk yard and that I have hard points on my Jeep for it, I'm exploring populating the console with my own creation. This device might be a candidate for that project.

Not sure your daisy chain issues and the cause of the problems. I'm sure you checked the data on a scope to see how the corruption might be affected. Since I am looking at this hardware, I'll get two and test it as well and let you know what I find out.

I noticed in the spec notes that it says it is not possible to connect them in series. On that note, I'm wondering if simple logic channeling the data and clock to a selected pair might do the trick. I'll explore that too.

Hop
Attachments:

Re: Big GPS Clock 9 years 3 days ago #2386

  • hop
  • hop's Avatar
  • Offline
  • Platinum Boarder
  • Posts: 526
  • Thanks received: 46
Another note... I wonder if the PWM is for both digits in the display OR for each segment. The reason I wonder about that is that it would be very cool to control the PWM for each segment to give that "24" effect for an unnecessary bling factor.

If not, I can use that MAX controller I mentioned in another thread (about using PWM to control my boat lighting) to control each digit of the display, and see if multiplexing two digits per controller will affect brightness significantly.

Hop

Re: Big GPS Clock 9 years 3 days ago #2392

  • jmessina
  • jmessina's Avatar
  • Offline
  • Senior Boarder
  • Posts: 44
  • Thanks received: 189
The DIM signal is connected to both displays, so you can't pwm just one.

I think the problem you're having with daisy-chaining the displays is probably due to the way they've connected the HC595 shift register controls. The HC595 has two sets of registers: the shift register (controlled by SCLK) and an output latch (controlled by RCLK). They've connected the two together which is perfectly valid, but it means that the output register is always 1 clock behind, or to put it another way, after you clock out the 16 bits of data into the two shift registers on the board, you need to add a 17th clock pulse to latch the data into the output latch. You can see this in the sample code in the datasheet...after the two 8-bit loops there's an additional clock.

If you're daisy-chaining modules, this 17th clock pulse is going to clock the wrong data into the next module. Re-write the driver to send out all of the 8-bit digit data for as many displays as you have, and then add a single extra clock at the end.

Also, the modules are going to be fairly slow...HC logic isn't the fastest of choices. Since they've added additional buffering to the CLK line, make sure that you have at least 100ns data setup and hold time between the serial data output pin and the clock pin transitions, and pay attention to the clock frequency called out in the spec sheet, esp as you daisy-chain modules.

Jerry

Re: Big GPS Clock 9 years 2 days ago #2396

Thanks for the info regarding the shift registers Jerry - I will update the program and see how things go. I've left the segments at work today (needed to make some measurements). The code as it stands now (I'll try your changes when I have the segments in hand):
{
*****************************************************************************
*  Name    : GPS Clock.bas   (project number 0049)                          *
*  Author  : Graham Mitchell                                                *
*  Notice  : Copyright (c) 2010 Graham Mitchell 2010                        *
*          : All Rights Reserved                                            *
*  Date    : 19/07/2010                                                     *
*          :                                                                *
*  Version : 1.0                                                            *
*  Notes   : A GPS clock... There's too many benefits to not make one. The  *
*          : time is ALWAYS accurate, and there's no need to ever make      *
*          : adjustments.                                                   *
*          :                                                                *
*          : The initial release interfaces with a LS20031 GPS Module,      * 
*          : although, any GPS module could be used.                        *
*          :                                                                *
*          : NMEA sentences are monitored until a valid RMC sentence is     *
*          : received. Time information is extracted and converted from a   *
*          : string to decimal numbers.                                     *
*          :                                                                *
*          : Time information is then advanced depending on the users time  *
*          : settings. Advancements work in 15 minute increments by         *
*          : holding the "AdjTime" button. User settings are saved to the   *
*          : EEPROM in case of power failure.                               *
*          :                                                                *
*****************************************************************************
}

// define device, clock and disable MCLRE
Device = 18F2520
Clock = 32
Config MCLRE = Off

// this module configures the internal oscillator to operate at 32Mhz from the get-go
Include "InternalOscillator.bas"
// the USART module is required to configure the baud rate
Include "USART.bas"
// NMEA module handles interrupt driven NMEA sentence retrieval
Include "NMEA.bas"
// EEPROM module for saving settings
Include "EEPROM.bas"
// the utils module is used for the function "Utils.Digit"
Include "UTILS.bas"


// program variables
Dim NMEAItem As TNMEA
Dim Field As String
Dim Skip As Byte

Structure TTime
    Hours As Byte
    Minutes As Byte
    Seconds As Byte
End Structure
Public Dim Time As TTime

Structure TAdjust
    Hours As Byte
    Minutes As Word
End Structure
Public Dim Adj As TAdjust

// pinouts for segments
Dim Data As PORTC.3, CLK As PORTC.5, DIMM As PORTC.2
Dim Data2 As PORTA.1, CLK2 As PORTA.2, DIMM2 As PORTA.0
Dim AdjTime As PORTB.0

// save the user adjustment settings to EEPROM
Sub SaveEEPROMSettings()    
    EE.Write(0,$AA,Adj.Minutes,Adj.Hours)            
End Sub

// load user adjustment settings from EEPROM. Should no information be found, then it loads zero for both minutes and hours.
Sub LoadEEPROMSettings()
    Dim tmpByte As Byte
    EE.Read(0,tmpByte)
    If tmpByte <> $AA Then
        EE.Write(0,$AA,$00,$00)
    EndIf
    
    EE.Read(1,Adj.Minutes,Adj.Hours)            
End Sub

// convert a single ascii character to decimal
Function CharToDec(ByVal pChar As Byte) As Byte
    Result = pChar - 48
End Function

// convert the passed string to decimal time
Sub StringToTime(ByRef pString As String) 
    Time.Seconds = (CharToDec(pString(4))*10) + CharToDec(pString(5))
    Time.Minutes = (CharToDec(pString(2))*10) + CharToDec(pString(3))
    Time.Hours = (CharToDec(pString(0))*10) + CharToDec(pString(1))   
End Sub

// function which returns true if a valid NMEA RMC sentence is in the buffer
Function GetGPSTime() As Byte
    Result = 0
    If NMEA.GetItem(NMEAItem) And NMEAItem.Valid Then
        NMEA.GetField(NMEAItem,0,Field)
        If Field = "$GPRMC" Then
            NMEA.GetField(NMEAItem, 1, Field)
            StringToTime(Field)
            Result = 1       
        EndIf
    EndIf
End Function

// check if the button "AdjTime" is pressed and increment adjustment registers as necessary
Sub CheckTimeAdjust()  
    If AdjTime = 0 Then
        Adj.Minutes = Adj.Minutes + 15
        If Adj.Minutes > 59 Then
            Adj.Minutes = Adj.Minutes - 60
            Adj.Hours = Adj.Hours + 1
            If Adj.Hours = 24 Then
                Adj.Hours = 0
            EndIf
        EndIf
        SaveEEPROMSettings()
    EndIf
    
End Sub

// advance the time based on the adjustment registers
Sub AdjustTime()
    Time.Minutes = Time.Minutes + Adj.Minutes
    Time.Hours = Time.Hours + Adj.Hours
    
    While Time.Minutes > 59
        Time.Minutes = Time.Minutes - 60
        Time.Hours = Time.Hours + 1
    Wend

    While Time.Hours > 23
        Time.Hours = Time.Hours - 24
    Wend
End Sub

// convert a decimal number to segment data
Function DecToSeg(ByVal pValue As Byte) As Byte
    Result = 0
    
    Select pValue
        Case 0
            Result = $FC
        Case 1
            Result = $60
        Case 2
            Result = $DA
        Case 3
            Result = $F2
        Case 4
            Result = $66
        Case 5
            Result = $B6
        Case 6
            Result = $BE
        Case 7
            Result = $E0
        Case 8
            Result = $FE
        Case 9
            Result = $F6
    End Select                
End Function

// send segment data to the displays
Sub SendBytes(ByVal pSeg0,pSeg1,pSeg2,pSeg3 As Byte)
    Dim i As Byte
    
    For i = 0 To 7
        Data = pSeg0 And $01
        CLK = 0
        CLK = 1
        pSeg0 = pSeg0 >> 1
    Next   
    For i = 0 To 7
        Data = pSeg1 And $01
        CLK = 0
        CLK = 1
        pSeg1 = pSeg1 >> 1
    Next   
    CLK = 0
    CLK = 1

    For i = 0 To 7
        Data2 = pSeg2 And $01
        CLK2 = 0
        CLK2 = 1
        pSeg2 = pSeg2 >> 1
    Next   
    For i = 0 To 7
        Data2 = pSeg3 And $01
        CLK2 = 0
        CLK2 = 1
        pSeg3 = pSeg3 >> 1
    Next   
    CLK2 = 0
    CLK2 = 1       
End Sub

// update the segment displays with current time
Sub DisplayTime()
    DIMM = 1
    DIMM2 = 1
    
    If Time.Seconds Mod 2 = 0 Then
        SendBytes(DecToSeg(Digit(Time.Minutes,1)),DecToSeg(Digit(Time.Minutes,2)),DecToSeg(Digit(Time.Hours,1)),DecToSeg(Digit(Time.Hours,2)))
    Else
        SendBytes((DecToSeg(Digit(Time.Minutes,1)) Or $01),DecToSeg(Digit(Time.Minutes,2)),DecToSeg(Digit(Time.Hours,1)),DecToSeg(Digit(Time.Hours,2)))
    EndIf
       
    DIMM = 0
    DIMM2 = 0
End Sub


// initialise the PIC and variables
Sub InitialisePIC()
    // configure I/Os
    SetAllDigital
    Low(Data)
    High(CLK)
    High(DIMM)
    
    Low(Data2)
    High(CLK2)
    High(DIMM2)
    
    // enable weak pullups
    INTCON2.7 = 0
    Input(AdjTime)        
    
    // configure USART module
    USART.SetBaudrate(br38400)
    
    // load saved settings (if they exist)
    LoadEEPROMSettings()

    // initialise variables
    Skip = 0
End Sub


// main program start...
InitialisePIC()

// main program loop
While True
    // GPS Outputs at 5Hz, sample every 3rd update (this creates a delay between time adjustments)
    If GetGPSTime() = 1 Then
        Inc(Skip)
        If Skip = 2 Then
            Skip = 0
            CheckTimeAdjust()
            AdjustTime()
            DisplayTime()
        EndIf
    EndIf  
Wend
I was having issues with corrupt data with the use of delays, and a quick work-around was to simply grab every 3rd NMEA sentence as it arrived. I can invoke the behaviour by changing the main program loop to the following:
// main program loop
While True
    If GetGPSTime() = 1 Then
        CheckTimeAdjust()
        AdjustTime()
        DisplayTime()
        DelaymS(500)
    EndIf  
Wend
The variables Adj.Minutes and Adj.Hours store the time advancement for local time correction. It would appear as if the program is corrupting the variables as the time changes erratically on the displays. I was able to isolate the RAM corruption to those two variables by changing the "AdjustTime" sub routine like so:
// advance the time based on the adjustment registers
Sub AdjustTime()
    // preload the corrupt RAM registers with zero
    Adj.Minutes = 0
    Adj.Hours = 0

    Time.Minutes = Time.Minutes + Adj.Minutes
    Time.Hours = Time.Hours + Adj.Hours
    
    While Time.Minutes > 59
        Time.Minutes = Time.Minutes - 60
        Time.Hours = Time.Hours + 1
    Wend

    While Time.Hours > 23
        Time.Hours = Time.Hours - 24
    Wend
End Sub
The above change preloads both variables before any time adjustments. The result is UTC time displayed without any odd behaviour.

From what I can gather, the user module "NMEA.bas" (which can be downloaded from the User Module Pack) has the appropriate context saving in place. Does anything stand out to you Jerry?

Re: Big GPS Clock 9 years 2 days ago #2397

  • jmessina
  • jmessina's Avatar
  • Offline
  • Senior Boarder
  • Posts: 44
  • Thanks received: 189
It sounds like there's some sort of buffer issue going on...if you wait the 5 seconds then you've gotten ~25 NMEA messages, which is quite a few characters. I took a quick glance it NMEA.bas and saw something I don't like to see, and that's trying to parse the message string inside the interrupt handler instead of just buffering the characters and processing them outside of the interrupt context. It does seem to have some optimizations where it's using pic registers to hold and pass data, and that's always a potential source of problems. Let me take a closer look at how it handles buffer overflows, uart errors and such...
Time to create page: 0.269 seconds