Add GPS/PARSE to 8xSERVO-MOTOR CODE in Oshonsoft

Are you sure the original was using an 8MHz clock and not 32MHz?
The various constants and comments in the original imply it's counting at a 500ns rate (2MHz), and you get that with a 32MHz clock and a TMR1 prescaler of 1:4

The CONFIG setting shown:
Code:
Define CONFIG1H = 0x06  '8MHz XTL x4 HSPLL =32MHz
will get you HS oscillator, PLL enabled as the primary oscillator

Any OSCCON setting in the code may not matter if the lower two SCS1:SCS0 bits are '00', which specifies "use the primary oscillator setting", which comes from the CONFIG1H setting. You would have to have the CONFIG1H set for one of the INTOSC settings or SCS1:SCS0 = 1x to select the internal osc block for the IRCF[2:0] Internal Oscillator Frequency Select bits to matter
 
Hi T,
The original, used OSCCON set to internal 8mHz, which I added into my program, which is set to an external 8mHz XTL with 4XPLL 32mHz.

The timings in the original are for 8mHz, and if I'm correct the timings will be affected by the change. I've tried changing the timings, but so far haven't got any sense out of it..
C
 
What I'm saying is that if OSCCON ends in '00' then it doesn't change the osc setting set by the CONFIG1H word, so just because there's an 'OSCCON= xxxx' statement in the code doesn't mean anything.

The comments like this:
Code:
ServoPos(i) = i * 250 + 2000  '1ms(2000) to 1.875(1 7/8ths - 3750)ms in 1/8th mS steps
lead me to believe that's it's already set for 32MHz... 2000 counts of 500ns = 1ms, and you get 500ns counts with 32MHz and a 1:4 prescaler.

Is there a copy of the "original code" here somewhere?
 
Hi T,
I think this is the original?
It runs fine and moves the SERVOs.
Note there is the CONFIG and clock settings, then OSCCON. I thought that the OSCCON changed the timing from the CONFIG, so I commented it out before trying my 32mHz numbers.

The stalling problem, may be a conflict with CCP1. When this happened before many years ago, may also be the same, as I was working on a tracker which also used CCP.
C.

Code:
'18F4431 32MHz XTL PCB9 REMOTE_SLAVE GPS_SERVO 070224 1600

Define CONFIG1L = 0x00
Define CONFIG1H = 0x06  '8mHz XTL x4 =32mHz
Define CONFIG2L = 0x0c
Define CONFIG2H = 0x20
Define CONFIG3L = 0x04
Define CONFIG3H = 0x80
Define CONFIG4L = 0x80  'Set for HVP
Define CONFIG4H = 0x00
Define CONFIG5L = 0x0f
Define CONFIG5H = 0xc0
Define CONFIG6L = 0x0f
Define CONFIG6H = 0xe0
Define CONFIG7L = 0x0f
Define CONFIG7H = 0x40

Define CLOCK_FREQUENCY = 32
Define SINGLE_DECIMAL_PLACES = 2
Define STRING_MAX_LENGTH = 20

Define SIMULATION_WAITMS_VALUE = 1  'Comment in for SIM out for PIC

Dim wordTemp As Word
Dim ServoCount As Byte
Dim i As Word
Dim ServoPos(8) As Word
Dim servoDir(8) As Byte
Dim frame As Word
Dim gpsbuf(80) As Byte
Dim strCount As Byte
Dim rec As Byte
Dim isDone As Bit

Dim pos As Word
Dim dir As Byte

Symbol rled = PORTD.7

OSCCON = %01110000  '& h70
TRISA = %11000000  '7=OSC, 6=OSC,
TRISB = %00000000  '0=SEROUT
TRISC = %11110010  '6=1-slave4431_cs, 3=74HC164 MR, 2=74HC164 CLK, 0=74HC164 DATA'<<<<<<<<<<<<
TRISD = %00000000
LATC.0 = 0  'ensure data is low
LATC.2 = 0  'and clock
LATC.3 = 1  'Master reset HIGH for run.'<<<<<<<<<<<<<<

For i = 0 To 7
LATC.2 = 1  'send positive clock edge
ServoPos(i) = i * 250 + 2000  '1ms(2000) to 1.875(1 7/8ths - 3750)ms in 1/8th mS steps
LATC.2 = 0  'send negative edge
servoDir(i) = i And 1  '<<<<<<<added
Next i

'Start up led
rled = 1
WaitMs 1000
rled = 0
WaitMs 1000
rled = 1
WaitMs 1000
rled = 0
WaitMs 1000

'TRISC = %11111010  'CCP0 (RC2) & RC0 output'<<<<<<<<<<<<<<<<<<<<
ServoCount = 8  'cause it to reset
T1CON = %00100000  'prescaler = 4
T1CON.0 = 1  'start timer
CCP1CON = %1000  'will go high on interrupt - will start a 0.5mS pulse
frame = 1000  'start everything in 4000 cycles
strCount = 0
isDone = 0
'setup USART for 9600 baud receive
RCSTA = %10010000
TXSTA.BRGH = 1
BAUDCON.BRG16 = 1
SPBRG = 207
PIR1.RCIF = 0
PIE1.RCIE = 1
PIE1.CCP1IE = 1
INTCON.PEIE = 1
INTCON.GIE = 1

While 1  '\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\

    While ServoCount = 0  'wait for 20mS to pass (=1/50th of a second)
    Wend
    While ServoCount <> 0
    Wend
    For i = 0 To 7
        dir = servoDir(i)  'doesn't matter if ISR happens as servoPos isn't changed by ISR
        pos = ServoPos(i)
        If dir = 1 Then
            pos = pos + 40  'add 1/50th to the servo position
        Else
            pos = pos - 40  'subtract it
        Endif
        If pos < 2000 Then  'have we gone past the end?
            pos = 2000  'yes so make it the end stop
            dir = 1  'and turn it around
        Endif
        If pos > 4000 Then  'same for other end
            pos = 4000
            dir = 0
        Endif
        INTCON.GIE = 0
        ServoPos(i) = pos
        INTCON.GIE = 1
        servoDir(i) = dir  'servoDir not used by ISR
    Next i

        'Serout PORTB.0, 9600, "$ R W ", gpsbuf(0), gpsbuf(3), gpsbuf(44), CrLf

Wend

End

On High Interrupt  'go via location 0x0008
Save System

If PIR1.CCP1IF Then  'has CCP1 triggered?
    wordTemp.HB = CCPR1H  'get value of CCPR1 into wordTemp
    wordTemp.LB = CCPR1L
    If CCP1CON = 0x08 Then  'have we started the 1000 cycle pulse
        CCP1CON = 0x09  'yes so end the pulse after 0.5mS
        wordTemp = wordTemp + 1000  'adding 1000 will make pulse 0.5mS long
    Else
        LATC.0 = 0  'clear the data pin
        CCP1CON = 0x08  'No so output the timed gap
        If ServoCount < 8 Then
            'still doing the servos so add remainder of time
            wordTemp = wordTemp + ServoPos(ServoCount)
            wordTemp = wordTemp - 1000  'knock of the 1000 (0.5mS) already elapsed
            frame = frame - ServoPos(ServoCount)
            ServoCount = ServoCount + 1
        Else
            'done all the servos so just the frame gap to do
            wordTemp = wordTemp + frame
            frame = 39000  '40,000(20mS) minus time of positive pulse(0.5mS)
            ServoCount = 0  'start all over again
            LATC.0 = 1  'will become first pulse (is data pin of shift register)
        Endif
    Endif
        CCPR1H = wordTemp.HB  'put value back into CCPR1
        CCPR1L = wordTemp.LB
        PIR1.CCP1IF = 0  'clear interrupt flag
Endif

If PIR1.RCIF Then
    rec = RCREG  'get the received character
    If RCSTA.OERR Or RCSTA.FERR Then  'neither of these should ever occur.
            RCSTA.CREN = 0  'this is kinda wishful thinking
        If PIR1.RCIF Then
            rec = RCREG
        Endif
        RCSTA.CREN = 1  'as any data received is corrupt
        strCount = 0  'however, reset everything
        isDone = 0  'and hope for the best
    Else  'no errors so use the data
        If strCount = 0 And isDone = 0 Then  'are we already receiving
                'waiting for $           'no so wait
            If rec = "$" Then  'for $ to appear'<<<<<<<<<<<<<<<<<<<<<<<<
                gpsbuf(strCount) = rec  'start receiving
                strCount = strCount + 1
            Endif
        Else
            If isDone = 0 And strCount < 79 Then  'have we collected a full string?
                gpsbuf(strCount) = rec  'no so carry on storing
                strCount = strCount + 1
                If rec = "W" Then  'have we got the "endOfString" character'<<<<<<<<<<<<
                    isDone = 1  'yes, so set done true
                    'put break here
                Endif
            Else
                If isDone = 0 Then  '?????????<<<<<<<<<<<<<<<<<<<<<<<
                    'still waiting to start or buffer overflow
                    strCount = 0
                Endif
            Endif
        Endif  '<<<<<<<<<<<<<<<
    Endif
Endif  'end RS232 if
Resume
 
Last edited:
The OSCCON register allows you to select between different clock sources, depending on the lower two bits SCS1:SCS0...
00 = primary osc (the one set by CONFIG1H)
01 = secondary osc (TIMER1)
1x = internal osc

The code in #304 sets OSCCON = %01110000 (0x70), so the lower two bits tell it to use the primary CONFIG1H osc setting, which in this case is Define CONFIG1H = 0x06 '8mHz XTL x4 =32MHz. The comment is correct for that...
0110= HS oscillator, PLL enabled (clock frequency = 4 x FOSC1)

As long as you have an 8MHz xtal you should already be running at 32MHz with those settings.
All of the existing TMR/CCP settings in that code seem to match with that.

The only thing that doesn't is the UART setting, which is shown as:
Code:
'setup USART for 9600 baud receive
RCSTA = %10010000
TXSTA.BRGH = 1
BAUDCON.BRG16 = 1
SPBRG = 207

At 32MHz those register settings will get you a baud rate of 38400, not 9600 as the comment claims.
If you want 9600 baud then change the line to TXSTA.BRGH = 0

If you comment out the 'OSCCON = %01110000' in the above code nothing should change.
You shouldn't need to change anything.



 
Hi T,
Thanks for your detailed reply. You've answered many questions here.

If commenting out OSCCON makes no difference, I'll remove it.

Is there any difference between this CODE:
-------------------------------------------------
'setup USART for 9600 baud receive
RCSTA = %10010000
TXSTA.BRGH = 1
BAUDCON.BRG16 = 1
SPBRG = 207
-----------------------------------------------
and the Oshonsoft [ Hseropen 9600 ]?

Regarding 9600? This answers a question, where the GPS TX resets to 38400, which could be the GPS itself (default) or from the UART?

While replying to this message, I've been reading the D/S and being reminded that on this PIC, there is no TX.
The PIC has been suffering from stalling, and I have a post regarding this, but If I understand correctly, TXSTA should be set to '0'. I'll test this and report back.
C.
 
I don't use Oshonsoft, so take this fwiw...


Probably. For one thing, as I mentioned, at 32MHz those code settings will get you 38400 baud, so it's probably more like "Hseropen 38400". Hseropen will likely enable the TX output as well.

but If I understand correctly, TXSTA should be set to '0'.
If you set TXSTA = 0 then that will reset the TXSTA.BRGH bit (which will change the baud rate to 9600), and also clear TXEN which will disable UART output.

If you don't need the UART TX, then set TXSTA = 0 right after setting RCSTA so that any other changes to TXSTA aren't effected. An Hseropen statement would likely override all those settings provided it was after the register setup and not before it.
 
Last edited:
Hi T,
I tried the TXSTA.BRGH CODE section with TXSTA = 0 below TXSTA.BRGH = 1. This stalled.

I tired Hseropen 38400 with TXSTA = 0 below. This didn't stall.

This is in a skeleton program.
Next, to try it in a full program, where it reads the GPS, which is set to 38400, and see what happens.
Thanks.
C
 
There are at least four different combinations of BRGH, BRG16, and SPBRG/SPBRGH that get you 38400 baud at 32MHz:

BAUDCON.BRG16 = 0
TXSTA.BRGH = 0
SPBRG = 12

BAUDCON.BRG16 = 0
TXSTA.BRGH = 1
SPBRG = 51

BAUDCON.BRG16 = 1
TXSTA.BRGH = 0
SPBRGH = 0
SPBRG = 51

BAUDCON.BRG16 = 1
TXSTA.BRGH = 1
SPBRGH = 0
SPBRG = 207

I tried Hseropen 38400 with TXSTA = 0 below. This didn't stall
Setting TXSTA afterwards will reset any BRGH bit setting, so it might change the baud rate depending on the BRG16 setting as shown above.
If all you want to do is disable the TX then don't clear the whole register, just clear the TXEN bit:
Code:
Hseropen 38400
TXSTA.TXEN = 0        ' disable TX

or
Code:
'setup USART for 38400 baud receive only (disable TXEN)
RCSTA = %10010000
TXSTA = 0            ' TXEN=0, SYNC=0, BRGH=0
TXSTA.BRGH = 1
BAUDCON.BRG16 = 1
SPBRG = 207
 
Hi T,
As I added ENABLE HIGH, it stopped it stalled.
I think the problem could be around:
---------------------------------------------
When IPEN = 0:
1 = Enables all unmasked interrupts
0 = Disables all interrupts
When IPEN = 1:
1 = Enables all high-priority interrupts
0 = Disables all high-priority interrupts
-------------------------------------------
EDIT: Our messages #311 and 312 crossed at the same time!
C.
 
From what I see in the documentation they mention ENABLE HIGH and ENABLE LOW interrupt priorities,
so I would assume that means behind the scenes they use RCON IPEN=1 to enable interrupt priority.

In your code, right before the 'WHILE 1' loop you have:
Code:
INTCON.PEIE = 1
INTCON.GIE = 1

When you have IPEN=1 those two bits change function and are better thought of as:
Code:
INTCON.GIEL = 1
INTCON.GIEH = 1

So, you're enabling the low-priority intr but not specifying a vector. Not a good idea.
Also, just so you're aware, disabling the high-priority interrupt (INTCON.GIEH = 0) disables all interrupts.
In order to get a peripheral to use the low-priority vector you have to clear the proper IP bit in the IRPx register since they are all high-priority be default.

It may be better to stop messing with the INTCON bits and use ENABLE HIGH/DISABLE HIGH/ENABLE LOW/DISABLE LOW scheme.
 
Hi T,
It's a bit complicated to follow!
I think I've followed what you suggest, but any time I add ENABLE HIGH it eventually stalls.

Note: Farther down the program, in part of the SERVO CODE there is INTCON.GIEH = 0/INTCON.GIEH = 1

It looks like I've got to divide the program down to only the posted SERVO CODE, and slowly build it back up to the full program, and see where it breaks.

I look in more detail tomporrow.
C.
 
Hi T,
I think I've found the culprit, which may be obvious really!
With ENABLE HIGH, and the GPS disconnected from the UART, it has now run for a while without stalling.

I may have found the culprit!
This PIC reads the GPS and transfers it to the MASTER PIC via SPI, which has WHILE/WAITs in it's CODE, I've commented out the SPI, and it's running= moving the SERVOs and showing the GPS DATA.
C
 
Last edited:
Note: Farther down the program, in part of the SERVO CODE there is INTCON.GIEH = 0/INTCON.GIEH = 1
If you're talking about this portion:
Code:
        INTCON.GIE = 0
        ServoPos(i) = pos
        INTCON.GIE = 1
That's there to disable interrupts around updating the ServoPos data array which is shared between the main program and the ISR. You could use DISABLE HIGH/ENABLE HIGH there, but it's ok the way it is.

This PIC reads the GPS and transfers it to the MASTER PIC via SPI, which has WHILE/WAITs in it's CODE,
If there's other code than what you've shown it's really hard to make any suggestions...
 
Hi T,
There are 4x programs all talking to each other, and I've been told many times not to post FULL programs as they're too long, and I rarely get replies, that's why I keep them short snippets.

The reason I mentioned the INTCON.GIE being farther down the CODE, is following your sentence:
Also, just so you're aware, disabling the high-priority interrupt (INTCON.GIEH = 0) disables all interrupts.

I'm investigating my findings in #315, as I think I'm on the right track. I'll let you know what happens.
C
 
...and I've been told many times not to post FULL programs as they're too long,
I can appreciate that, but when you're talking about a program stalling/failing to work properly then you need to see ALL the code. Seemingly the problem occurs when you add in the portion you've not included here.

I'm investigating my findings in #315, as I think I'm on the right track.
Probably so. It's easy to imagine the SPI transfer code changing all the timing.
 
As usual, this thread has been "continued" over on another forum, with all the offending reasons for the code blocking issues being pointed out there that we were never privy to unless you try to piece together all the various bits and pieces about this project spread out across multiple forums/threads.

They get 1/2 the story, we get 1/2 the story. Once they "fix" their half on the other forum , it'll probably reappear here with a bunch of new code that screws up the half shown here.

It's no wonder this project has been going on for years now...
 
I wrote most of that (this) code but gave up when delays and software serial, which also blocks, was added. I wrote it in C on a 18F2620 and then converted to basic. Unfortunately, a disk crash cause it all to be lost. I think it ran at 32MHz using the internal oscillator. Actually just looked and found an early version that used PPS to steer the CCP1 output to the PORTB pins and it uses 32 MHz. Couldn't figure out pointers in basic so changed it.

Mike.
 
Cookies are required to use this site. You must accept them to continue using the site. Learn more…