Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

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

OK, finally got around to having a go at this code,
Here is (Hopefully) a version of a soft UART to try,
Code:
'18F4431 32MHz XTL REMOTE_SLAVE 164 160223 2330

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


Dim wordTemp As Word
Dim i As Word
Dim cnt As Byte
dim fifo(32) as byte
dim fifoStart as byte
dim fifoEnd as byte
Dim ccpDone As Bit
Dim previous as Bit
Dim TXbyte as byte
Dim bitCount as byte
Dim str as string
dim serialCount as word

OSCCON = %01110000        '& h70
TRISA = %11000000            '7=OSC, 6=OSC,
TRISC = %11111010            '6=1-slave4431_cs, 2=74HC164 CLK, 0=74HC164 DATA
LATC.0 = 0                    'ensure data is low
LATC.2 = 0                    'and clock
For i = 0 To 7
    LATC.2 = 1                'send positive clock edge
    LATC.2 = 0                'send negative edge
Next i
TRISC = %11111010            'CCP2 (RC1) output
T1CON = %00100000            'prescaler = 4
T1CON.0 = 1                    'start timer
PIE2.CCP2IE = 1            'CCP2 interrupts enable
INTCON.PEIE = 1
INTCON.GIE = 1
While 1
    if serialCount>=9600 then        'every second do this
        serialCount=0
        str="Mike Was Ere!!" + CrLf
        for i=0 to len(str))
            putFifo(str(i))
        next i
    Endif
Wend
End   

proc putFifo(dat as byte)
    dim temp as byte
    temp=fifoStart
    if ((fifoEnd-temp) AND 0x1f)=0x1f then        'is fifo full
        while fifoStart=temp                            'yes so wait for interrupt
        wend                                                'to make room
    Endif
    fifo(fifoEnd)=dat                                    'add data to queue
    fifoEnd=(fifoEnd+1) AND 0x1f                    'and increment pointer
End Proc   

function getFifo() as byte                            'note, doesn't test if fifo is empty
    getFifo=fifo(fifoStart)                            'so always call getFifoLen first
    fifoStart=(fifoStart+1) AND 0x1f
End Function                                                                                    

function getFifoLen())
    getFifoLen=(fifoEnd-fifoStar) AND 0x1f
End Function

On High Interrupt            'go via location 0x0008
Save System
    if PIR2.CCP2IF Then
        serialCount=serialCount+1
        wordTemp.LB=CCPR2L                    'ensure next interrupt is
        wordTemp.HB=CCPR2H                    'in 208*2=832 instruction cycles
        wordTemp=wordTemp+208                '208 is 2,000,000/9600
        CCPR2L=wordTemp.LB                    'write it back
        CCPR2H=wordTemp.HB
        LATC.1=PORTC.1                            'ensure latch is same as current CCP output
        if ccpDone then
            bitCount=0
            if getFifoLen() then
                TXbyte=getFifo()
                CCP@CON=%1001
                ccpDone=false
                previous=0
            Endif
        else
            'we're sending a byte
            if bitCount<9 then
                if TXbyte.1=previous then
                    'just need the interrupt
                    CCP2CON=%1010
                else
                    'we need to flip the bit
                    if previous Then
                        'we need a zero next
                        previous=0
                        CCP2CON=%1001
                    else
                        'we need a one next
                        previous=1
                        CCP2CON=%1000
                    endif
                endif
                TXbyte=shiftRight(TXbyte,1)
            else
                'doing the stop bits
                if bitCount<10 then
                    if previous then
                        CCP2CON=%1010        'just need interrupt
                    else
                        previous=1
                        CCP2CON=%1000        'go high next interrupt
                    endif
                else
                    ccpDone=true
                Endif
            Endif
        Endif
        bitCount=bitCount+1
        PIR2.CCP2IF=0
    Endif
Resume
It is the UART only and is totally untested.

First, let's see if it will compile and if not, iron out any bugs.

Once it's working on its own then we can incorporate it into the rest of the code.

It should send a string out of RC1 every second saying "Mike Was Ere!!" - emphasise "should".

Also attached as text file.

Mike.
 

Attachments

  • soft UART only.txt
    3.2 KB · Views: 232
Note, there are lots of variables that are actual numbers due to not knowing how to use the equivalent of #define.
And a few spurious closing brackets due to the stupid editor I'm using in Linux. I noticed this one, for i=0 to len(str))
on line 55.

Mike.
 
Hi M,
A quick test in Osh:
Line that don't compile:
56, 57, 79, 80
I commented out () ') on a few lines, which then compiled.
79 needs 'as BYTE'

80 'getFifoLen' won't compile

I stopped there, as it got compilicated.
C
 
This was missing from getFifoLen,
function getFifoLen() as byte
getFifoLen=(fifoEnd-fifoStart) AND 0x1f
End Function

It had fifoStar instead of fifoStart.

How do you access characters in a string as, putFifo(str(i)) doesn't compile?
I assume that str(2) will give me the third character of str. - zero based.
Does it need splitting? I.E.
Dim temp as Byte
temp=str(i)
putFifo(temp)

Mike.
 
Hi M,
Other developments:

I've just ordered new GPS modules M9N, almost the same as M8N, but better.

Due to complicated reasons, these may be the first genuine GPSs.
This may mean that they can communicate via SPI, instead of UART.
I am makng some PCB test boards, so I can try again, as I tried for ages previously.

C.
 
This was missing from getFifoLen,
function getFifoLen() as byte
getFifoLen=(fifoEnd-fifoStart) AND 0x1f
End Function

It had fifoStar instead of fifoStart.

How do you access characters in a string as, putFifo(str(i)) doesn't compile?
I assume that str(2) will give me the third character of str. - zero based.
Does it need splitting? I.E.
Dim temp as Byte
temp=str(i)
putFifo(temp)

Mike.
Hi M,
Tomorrow, I will see my mate who when not busy is working on SPI, but we can have a better go at this CODE.

I'm not sure about your questions, these things are new to me, but let's see what happens tomorrow.
C
 
I can confirm that this works in C. It is sending to an Arduino very happily.

If the loop is causing a problem then maybe this will work,
Code:
'18F4431 32MHz XTL REMOTE_SLAVE 164 160223 2330

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


Dim wordTemp As Word
Dim i As Word
dim fifo(16) as byte
dim fifoStart as byte
dim fifoEnd as byte
Dim ccpDone As Bit
Dim previous as Bit
Dim TXbyte as byte
Dim bitCount as byte
dim serialCount as word

OSCCON = %01110000        '& h70
TRISA = %11000000            '7=OSC, 6=OSC,
TRISC = %11111000            '6=1-slave4431_cs, 2=74HC164 CLK, 0=74HC164 DATA 1=serial out
LATC.0 = 0                    'ensure data is low
LATC.2 = 0                    'and clock
LATC.1=1                        'serial idle
For i = 0 To 7
    LATC.2 = 1                'send positive clock edge
    LATC.2 = 0                'send negative edge
Next i
T1CON = %00100000            'prescaler = 4
T1CON.0 = 1                    'start timer
PIE2.CCP2IE = 1            'CCP2 interrupts enable
fifoStart=0
fifoEnd=0
INTCON.PEIE = 1
INTCON.GIE = 1
While 1
    if serialCount>=9600 then        'every second do this
        serialCount=0                    'clear the count
        putFifo("M")                    'send the string as seperate bytes
        putFifo("i")
        putFifo("k")
        putFifo("e")
        putFifo(" ")
        putFifo("W")
        putFifo("a")
        putFifo("s")
        putFifo(" ")
        putFifo("E")
        putFifo("r")
        putFifo("e")
        putFifo("!")
        putFifo("!")
        putFifo(0x0d)
        putFifo(0x0a)
    Endif
Wend
End    

proc putFifo(dat as byte)
    while ((fifoEnd-fifoStart) AND 0x0f)=0x0f
    wend    
    fifo(fifoEnd)=dat                                    'add data to queue
    fifoEnd=(fifoEnd+1) AND 0x0f                    'and increment pointer
End Proc    

function getFifo() as byte                            'note, doesn't test if fifo is empty
    getFifo=fifo(fifoStart)                            'so always call getFifoLen first
    fifoStart=(fifoStart+1) AND 0x0f
End Function                                                                                     

function getFifoLen() as byte
    getFifoLen=(fifoEnd-fifoStart) AND 0x0f
End Function

On High Interrupt            'go via location 0x0008
Save System
    if PIR2.CCP2IF Then
        serialCount=serialCount+1
        wordTemp.LB=CCPR2L                    'ensure next interrupt is
        wordTemp.HB=CCPR2H                    'in 208*2=832 instruction cycles
        wordTemp=wordTemp+208                '208 is 2,000,000/9600 = 104uS or the time for 1 bit at 9600 baud
        CCPR2H=wordTemp.HB                    'it's really important that the high byte gets written first
        CCPR2L=wordTemp.LB                    'write it back
        LATC.1=PORTC.1                            'ensure latch is same as current CCP output
        if ccpDone then
            bitCount=0
            if getFifoLen() then
                TXbyte=getFifo()
                CCP2CON=%1001                    'pin high and low on next interrupt = start bit
                ccpDone=false
                previous=0
            Endif
        else
            'we're sending a byte
            if bitCount<9 then
                if TXbyte.1=previous then
                    'just need the interrupt
                    CCP2CON=%1010
                else
                    'we need to flip the bit
                    if previous Then
                        'we need a zero next
                        previous=0
                        CCP2CON=%1001
                    else
                        'we need a one next
                        previous=1
                        CCP2CON=%1000
                    endif
                endif
                TXbyte=shiftRight(TXbyte,1)
            else
                'doing the stop bits
                if bitCount<10 then
                    if previous then
                        CCP2CON=%1010        'just need interrupt
                    else
                        previous=1
                        CCP2CON=%1000        'go high next interrupt
                    endif
                else
                    ccpDone=true
                Endif
            Endif
        Endif
        bitCount=bitCount+1
        PIR2.CCP2IF=0
    Endif
Resume

I've made a couple of other changes that may have caused problems on rare occasions.

Does this now compile?

Mike.
 

Attachments

  • soft UART only.txt
    3.4 KB · Views: 235
Forgot to mention that I halved the size of the fifo buffer from 32 to 16 to save memory. If the fifo gets full it will wait for enough bytes to be sent and then add the new byte to the buffer. The straight lined write to putFifo (putFifo("M") etc.) will fill the buffer but the first byte should already be being sent so will have made room. The fifo can hold a maximum of size-1 = 15.

Mike.
 
Hi M,
There is an issue with:
'putfifo("M") 'send the string as seperate bytes

If getfifolen() Then

So far.

EDIT: I'm other getting odd errors, and have asked AAC, they have OSH experts.
It's not out of the question, that the language you're using could be an issue?
C
 
Last edited:
Hi M,
I posted it on AAC for a second OSH opinion, and there apear to be compatibility issues, plus other compile errors.
Let's see what my mate thinks.
C
 
OK, try this. I've changed all the "M" etc to ascii values and placed fifo length into a variable.
Code:
'18F4431 32MHz XTL REMOTE_SLAVE 164 160223 2330

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


Dim wordTemp As Word
Dim i As Word
dim fifo(16) as byte
dim fifoStart as byte
dim fifoEnd as byte
Dim ccpDone As Bit
Dim previous as Bit
Dim TXbyte as byte
Dim bitCount as byte
dim serialCount as word
Dim length as Byte

OSCCON = %01110000        '& h70
TRISA = %11000000            '7=OSC, 6=OSC,
TRISC = %11111000            '6=1-slave4431_cs, 2=74HC164 CLK, 0=74HC164 DATA 1=serial out
LATC.1=1                        'serial idle
T1CON = %00100000            'prescaler = 4
T1CON.0 = 1                    'start timer
CCP2CON=%1010                'interrupt only
PIE2.CCP2IE = 1            'CCP2 interrupts enable
fifoStart=0
fifoEnd=0
INTCON.PEIE = 1
INTCON.GIE = 1
serialCount=0
putFifo(0xff)                'send a dummy byte to get in sync
While 1
    if serialCount>=9600 then        'do this every second 
        serialCount=0                    'clear the count
        putFifo(77)                    'send the string as seperate bytes
        putFifo(73)
        putFifo(107)
        putFifo(101)
        putFifo(32)
        putFifo(87)
        putFifo(97)
        putFifo(115)
        putFifo(32)
        putFifo(69)
        putFifo(114)
        putFifo(101)
        putFifo(33)
        putFifo(33)
        putFifo(13)
        putFifo(10)
    Endif
Wend
End    

proc putFifo(dat as byte)
    while ((fifoEnd-fifoStart) AND 0x0f)=0x0f
    wend    
    fifo(fifoEnd)=dat                                    'add data to queue
    fifoEnd=(fifoEnd+1) AND 0x0f                    'and increment pointer
End Proc    

function getFifo() as byte                            'note, doesn't test if fifo is empty
    getFifo=fifo(fifoStart)                            'so always call getFifoLen first
    fifoStart=(fifoStart+1) AND 0x0f
End Function                                                                                     

function getFifoLen() as byte
    getFifoLen=(fifoEnd-fifoStart) AND 0x0f
End Function

On High Interrupt            'go via location 0x0008
Save System
    if PIR2.CCP2IF Then
        serialCount=serialCount+1
        wordTemp.LB=CCPR2L                    'ensure next interrupt is
        wordTemp.HB=CCPR2H                    'in 208*2=832 instruction cycles
        wordTemp=wordTemp+208                '208 is 2,000,000/9600 = 104uS or the time for 1 bit at 9600 baud
        CCPR2H=wordTemp.HB                    'it's really important that the high byte gets written first
        CCPR2L=wordTemp.LB                    'write it back
        LATC.1=PORTC.1                            'ensure latch is same as current CCP output
        if ccpDone then
            bitCount=0
            length=getFifoLen())
            if length>0 then
                TXbyte=getFifo()
                CCP2CON=%1001                    'pin high and low on next interrupt = start bit
                ccpDone=false
                previous=0
            Endif
        else
            'we're sending a byte
            if bitCount<9 then
                if TXbyte.1=previous then
                    'just need the interrupt
                    CCP2CON=%1010
                else
                    'we need to flip the bit
                    if previous Then
                        'we need a zero next
                        previous=0
                        CCP2CON=%1001
                    else
                        'we need a one next
                        previous=1
                        CCP2CON=%1000
                    endif
                endif
                TXbyte=shiftRight(TXbyte,1)
            else
                'doing the stop bits
                if bitCount<10 then
                    if previous then
                        CCP2CON=%1010        'just need interrupt
                    else
                        previous=1
                        CCP2CON=%1000        'go high next interrupt
                    endif
                else
                    ccpDone=true            'stop bits will still be generated - this happens at bitCount=10
                 Endif                            'and output will stay high until next byte
            Endif
        Endif
        bitCount=bitCount+1
        PIR2.CCP2IF=0
    Endif
Resume

Mike.
 

Attachments

  • soft UART only.txt
    3.5 KB · Views: 215
OK, try this. I've changed all the "M" etc to ascii values and placed fifo length into a variable.
Code:
'18F4431 32MHz XTL REMOTE_SLAVE 164 160223 2330

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


Dim wordTemp As Word
Dim i As Word
dim fifo(16) as byte
dim fifoStart as byte
dim fifoEnd as byte
Dim ccpDone As Bit
Dim previous as Bit
Dim TXbyte as byte
Dim bitCount as byte
dim serialCount as word
Dim length as Byte

OSCCON = %01110000        '& h70
TRISA = %11000000            '7=OSC, 6=OSC,
TRISC = %11111000            '6=1-slave4431_cs, 2=74HC164 CLK, 0=74HC164 DATA 1=serial out
LATC.1=1                        'serial idle
T1CON = %00100000            'prescaler = 4
T1CON.0 = 1                    'start timer
CCP2CON=%1010                'interrupt only
PIE2.CCP2IE = 1            'CCP2 interrupts enable
fifoStart=0
fifoEnd=0
INTCON.PEIE = 1
INTCON.GIE = 1
serialCount=0
putFifo(0xff)                'send a dummy byte to get in sync
While 1
    if serialCount>=9600 then        'do this every second
        serialCount=0                    'clear the count
        putFifo(77)                    'send the string as seperate bytes
        putFifo(73)
        putFifo(107)
        putFifo(101)
        putFifo(32)
        putFifo(87)
        putFifo(97)
        putFifo(115)
        putFifo(32)
        putFifo(69)
        putFifo(114)
        putFifo(101)
        putFifo(33)
        putFifo(33)
        putFifo(13)
        putFifo(10)
    Endif
Wend
End   

proc putFifo(dat as byte)
    while ((fifoEnd-fifoStart) AND 0x0f)=0x0f
    wend   
    fifo(fifoEnd)=dat                                    'add data to queue
    fifoEnd=(fifoEnd+1) AND 0x0f                    'and increment pointer
End Proc   

function getFifo() as byte                            'note, doesn't test if fifo is empty
    getFifo=fifo(fifoStart)                            'so always call getFifoLen first
    fifoStart=(fifoStart+1) AND 0x0f
End Function                                                                                    

function getFifoLen() as byte
    getFifoLen=(fifoEnd-fifoStart) AND 0x0f
End Function

On High Interrupt            'go via location 0x0008
Save System
    if PIR2.CCP2IF Then
        serialCount=serialCount+1
        wordTemp.LB=CCPR2L                    'ensure next interrupt is
        wordTemp.HB=CCPR2H                    'in 208*2=832 instruction cycles
        wordTemp=wordTemp+208                '208 is 2,000,000/9600 = 104uS or the time for 1 bit at 9600 baud
        CCPR2H=wordTemp.HB                    'it's really important that the high byte gets written first
        CCPR2L=wordTemp.LB                    'write it back
        LATC.1=PORTC.1                            'ensure latch is same as current CCP output
        if ccpDone then
            bitCount=0
            length=getFifoLen())
            if length>0 then
                TXbyte=getFifo()
                CCP2CON=%1001                    'pin high and low on next interrupt = start bit
                ccpDone=false
                previous=0
            Endif
        else
            'we're sending a byte
            if bitCount<9 then
                if TXbyte.1=previous then
                    'just need the interrupt
                    CCP2CON=%1010
                else
                    'we need to flip the bit
                    if previous Then
                        'we need a zero next
                        previous=0
                        CCP2CON=%1001
                    else
                        'we need a one next
                        previous=1
                        CCP2CON=%1000
                    endif
                endif
                TXbyte=shiftRight(TXbyte,1)
            else
                'doing the stop bits
                if bitCount<10 then
                    if previous then
                        CCP2CON=%1010        'just need interrupt
                    else
                        previous=1
                        CCP2CON=%1000        'go high next interrupt
                    endif
                else
                    ccpDone=true            'stop bits will still be generated - this happens at bitCount=10
                 Endif                            'and output will stay high until next byte
            Endif
        Endif
        bitCount=bitCount+1
        PIR2.CCP2IF=0
    Endif
Resume

Mike.
Hi M,
Getting warm!
Once commented out, it compiles.

These lines have error:

length = getFifoLen() ') With ')' commented out, it's ok.

'putFifo(0xff) 'send a dummy byte to get in sync £/
While 1
If serialCount >= 9600 Then 'do this every second
serialCount = 0 'clear the count
'putFifo(77) 'send the string as seperate bytes £/
'putFifo(73)
'putFifo(107)
'putFifo(101)
'putFifo(32)
'putFifo(87)
'putFifo(97)
'putFifo(115)
'putFifo(32)
'putFifo(69)
'putFifo(114)
'putFifo(101)
'putFifo(33)
'putFifo(33)
'putFifo(13)
'putFifo(10)
Endif
Wend
 
How on earth are you supposed to use a procedure? putFifo is a procedure that expects a byte as a parameter. How is putFifo(xx) not that? What does it need to be?

Mike.
Edit, what is the error on those lines?
 
Does it compile if you put the value in a byte variable?
I.E.
Dim temp as Byte
temp=255
putFifo(temp)

instead of
putFifo(0xff)

Mike.
 
How on earth are you supposed to use a procedure? putFifo is a procedure that expects a byte as a parameter. How is putFifo(xx) not that? What does it need to be?

Mike.
Edit, what is the error on those lines?
Hi M,
I'm no programmer, but could the problem be:
proc putFifo(dat as byte)

I've never seen and extra word such as 'dat' before.
C
 
Hi M,
I'm no programmer, but could the problem be:
proc putFifo(dat as byte)

I've never seen and extra word such as 'dat' before.
C
From the manual,
proc.png

on page 10.

Hi M,
Would you prefer that if I can get the GPS module to communicate via SPI, instead of UART, we leave this CODE, till I find out?
C
This code is to output comments so you can debug, or so I thought. The hardware UART is reading the sentence from the GPS.

Mike.
 
From the manual,
View attachment 140785
on page 10.


This code is to output comments so you can debug, or so I thought. The hardware UART is reading the sentence from the GPS.

Mike.
Hi M,
You didn't answer my question, so I assume you want to procede, even though it may not be used.

I'll check the words used, in case they are reserved, or need 'cleaning' as I did earlier, by removing them into a txt file and re-entering them into Osh.
I'll carry on.
C
 

Latest threads

New Articles From Microcontroller Tips

Back
Top