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

You should print with Serout only when isDone = 1.
The danger with this is that if isDone gets set then it doesn't get cleared and you're back to it continuously sending.
If code is added as shown above (#252) then it can send serial once per second.

I don't know how to clear overrun or framing errors as I've never experienced them. As the comment says, just wishful thinking. Line 283 says 'this is kinda wishful thinking

Mike.
 
To send a string with the ISR serial send, do,
Code:
str="Whatever you want"
for i=0 to len(str)-1
    call putFifo(str(i))
next i

The output should appear on RC1 which was (mistakenly) input but is now output.
I'm not sure if the -1 is needed. I.E on len(str)-1


Mike.
 
Last edited:
I think the confusion is because camerart keeps using the Oshonsoft software serial output routine instead of your ISR driven routine. He puts Serout statements to print out debug or test items to verify things are working.
Maybe take his latest "Serout" statement in his last code posting, and re-write it to output the same with your ISR serial routine, to the same port/bit. That said, the Oshonsoft Serout is just timing loops for its bit-banging, and should not have any affect on anything else that is interrupt driven. All it does is delay the main code while the bits are sent out.
He needs to determine which method, if any, affects his overall code performance, including the servos. If one affects the servos more than the other method, that gives an indication as to where to focus attention to.
 
Maybe take his latest "Serout" statement in his last code posting, and re-write it to output the same with your ISR serial routine, to the same port/bit.
The problem is because it uses CCP2 to generate the output pulses it has to be on PORTC.1. (no PPS on that chip)

I wrote the code in C (on a PIC18F2620) before converting and used an Arduino with soft serial to read the serial in and send it to the monitor.

C, do you have an arduino lying around that you could do the same with?

Mike.
 
Can we try this code?
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

'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 buff(80) As Byte
Dim strCount As Byte
Dim rec As Byte
Dim isDone As Bit
Dim cnt As Byte
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 ms as word
Dim readMsFlag as bit
Dim tick as byte
Dim tickLED as word
Dim str as string
Dim pos as word
Dim dir as byte
Dim serialCount as byte
Dim length as byte

Symbol rled = PORTD.7
Symbol yled = PORTD.6

OSCCON = %01110000        '& h70
gosub initIO
gosub initServos
gosub initSerial
gosub initTMR1
gosub initTMR2
ccpDone=1
'Start up leds
rled = 1
WaitMs 1000
rled = 0
WaitMs 1000
rled = 1
WaitMs 1000
rled = 0
WaitMs 1000
tick=0
ms=0
INTCON=0xc0                        'only PEIE and GIE set
WaitMs 2                            'let serial flush and get stable
str="$test stringW"
for i=0 to len(str)-1
    call putFifo(str(i))
next i
While 1
    If (ms.LB - tick) > 20 Then
        tick=ms.LB
        'this code gets executed 50 times per second (every 20mS)
       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                    'no interrupts
          servoPos(i)=pos
          INTCON.GIE = 1                    're enable interrupts
          servoDir(i)=dir                'servoDir not used by ISR
        Next i
    Endif
    'example code to flash an LED at 1Hz
    call getMS
    if (getMS-tickLED)>500 then            'note cannot be more than 65535 (65 seconds!!!!)
        'this code executed every 500mS which is 1Hz
        tickLED=getMS
        rLED= NOT rLED
    endif
Wend
End                     

function getMS() as word
    readMsFlag=0
    getMS=ms
    if readMsFlag then
        getMS=ms
    endif
end function                                      

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

initSerial:
    'setup USART for 9600 baud receive
    RCSTA = %10010000
    TXSTA.BRGH = 1
    BAUDCON.BRG16 = 1
    SPBRG = 207
    PIR1.RCIF = 0
    PIE1.RCIE = 1
    strCount = 0
    isDone = 0
    ccpDone = 1
    PIE2.CCP2IE=1
return

initServos:
    For i = 0 To 7
        servoPos(i) = i * 250 + 2000    '1ms(2000) to 1.875(1 7/8ths - 3750)ms in 1/8th mS steps
        servoDir(i) = i And 1    '<<<<<<<added
    Next i
    servoCount = 8                    'cause it to reset
    CCP1CON = %1000                'will go high on interrupt - will start a 0.5mS pulse
    frame = 1000                    'start everything in 4000 cycles
    PIE1.CCP1IE = 1
return

initTMR1:
    T1CON = %00100000            'prescaler = 4
    T1CON.0 = 1                    'start timer
return

initTMR2:
    'setup 1mS interrupt = 8,000,000/16 = 500,000/10 = 50,000 set PR2=49 = 50,000/50 = 1000 = 1mS
    T2CON = %01001010                            'pre=16, post=10
    T2CON.TMR2ON=1                                'turn it on
    PR2 = 49                                        'This is timer 2 period register. I.E. reset after 50 clocks (0 to 49 = 50 counts)
    PIE1.TMR2IE = 1                             'timer 2 interrupts enable
return

initIO:
    TRISA = %11000000            '7=OSC, 6=OSC,
    TRISB    = %00000000
    TRISC = %11111000            '6=1-slave4431_cs, 2=74HC164 CLK, 0=74HC164 DATA 1=Serial out
    TRISD = %00000000
    LATC.3=0
    LATC.3=1
return

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*4=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                        'are we idle
            bitCount=0                            'yes so reset things
            length=getFifoLen()                'is anything in the fifo?
            if length>0 then                    'yes so start a new transmision
                TXbyte=getFifo()                'get byte to transmit
                CCP2CON=%1001                    'pin high and low on next interrupt = start bit
                ccpDone=false                    'tell everything we're no londer idle
                previous=0                        'set previous equal to start bit
            Endif
        else
            'we're sending a byte
            if bitCount<9 then                'have we done a complete byte
                if TXbyte.0=previous then    'no so send next bit,
                    'just need the interrupt as next bit is same as previous bit
                    CCP2CON=%1010
                else
                    'we need to flip the bit
                    if previous Then            'did we previously send a one?
                        'we need a zero next
                        previous=0                'we're sending a zero next
                        CCP2CON=%1001            'will go to zero next match
                    else
                        'we need a one next
                        previous=1                'we're sending a one next
                        CCP2CON=%1000            'will go to zero next match
                    endif
                endif
                TXbyte=shiftRight(TXbyte,1)'shift next bit to zero position
            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                'this will get reset if idle
        PIR2.CCP2IF=0
    Endif
    If PIR1.TMR2IF Then                        'Is it a timer 2 interrupt
        getMsFlag=1                                'make any read invalid
        Cnt = Cnt + 1                            'Increment count
        ms=ms+1                                    'increment milliSecond
        If Cnt >= 5 AND NOT isDone Then    'Has 5mS passed without a byte being received
            isDone=0
            strCount=0
            cnt=0
        Endif
        PIR1.TMR2IF = 0
    Endif
    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
            Endif
        Endif
        CCPR1H = wordTemp.HB            'put value back into CCPR1
        CCPR1L = wordTemp.LB
        PIR1.CCP1IF = 0                'clear interrupt flag
    Endif
    If PIR1.RCIF Then
        cnt=0                                'stop any timeout happening
        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
            while PIR1.RCIF            'if any bytes in the buffer
                rec = RCREG                'throw them away
            wend
            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
            'the following is waiting for a "$" sign
            If strCount=0 Then        'are we already receiving
                'waiting for $            'no so wait
                If rec = "$" Then        'for $ to appear
                    buff(strCount)=rec'start receiving
                    strCount = 1        'must have been zero previously
                Endif
            Endif
            'the following gets executed if we've allready got a "$" sign
            'but not got a "W" yet.
            If isDone=0 And strCount<>0 Then
                if strCount<80 then    'only store it if there's room in the buffer
                    buff(strCount)=rec    'no so carry on storing
                    strCount = strCount + 1    'this may cause strCount to get to 80 = buffer full
                Endif
                If rec = "W" Then        'have we got the "endOfString" character
                    isDone = 1            'yes, so set done true
                Endif
            Endif
            If isDone=0 AND strCount>79 Then 
                'buffer has overflown
                strCount = 0
            Endif
        Endif
    Endif    'end RS232 if
Resume
Do the servos move?
Does the red (assuming rLED = red) LED flash at 1Hz?

Mike.
Hi M,
ADDED:
Dim getmsflag As Bit
Call getMS()
I've re-named it for my clarification:
18F4431 32MHz XTL PCB9 REMOTE_SLAVE GPS_SERVO M 200423 0800
The M is from you, before I 'play'

Same result:
Start flash Y, 1Hz flash N
Servos set in one position.

Why not use the #255 CODE, it's almost working?
I have to solder a wire onto RC1.
C
 
Last edited:
The problem is because it uses CCP2 to generate the output pulses it has to be on PORTC.1. (no PPS on that chip)

I wrote the code in C (on a PIC18F2620) before converting and used an Arduino with soft serial to read the serial in and send it to the monitor.

C, do you have an arduino lying around that you could do the same with?

Mike.
Hi M,
This would mix me up completely
C
 
Hi M,
#260
Servos moving
1flash/sec.
:)

EDIT: When I connected the board up after soldering the RC1 wire for outputting, the SERVOS moved and LED flashed. This is hit and miss, and I'm not sure why this is happening?

Nothing is coming from the RC1 PIN?
C
 
Last edited:
To send a string with the ISR serial send, do,
Code:
str="Whatever you want"
for i=0 to len(str)-1
    call putFifo(str(i))
next i

The output should appear on RC1 which was (mistakenly) input but is now output.
I'm not sure if the -1 is needed. I.E on len(str)-1


Mike.
Hi M and S,
Yes, I use the SEROUT for debugging. Once proved it is removed.
This does change the SERVO smoothness, but only temporarily

I assume the ISR CODE goes inside the WAIT 1 LOOP, is this correct?

There is some intermittent behaviour, so I'm checking for voltage spikes, when the SERVOS move, and may need larger CAPS.
C
 
ADDED:
Dim getmsflag As Bit
As explained in #248,
That should be readMsFlag which is already defined as a bit and needs changing in the ISR.

This is only used on the very rare occasion that a Timer2 interrupt comes as the ms is being read so shouldn't affect anything but it's better to change it.

The servos/LED randomly working suggests something isn't being initialized. Assuming the servos aren't loaded then they should take minimal power and not cause glitches/spikes.

The RC1 pin will only output for a few mS after turn on, I'll write some code so it sends every second.

I'll have another look see if I can spot anything.

Mike.
 
Here's a new version with the corrections and serial send every second,
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

'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 buff(80) As Byte
Dim strCount As Byte
Dim rec As Byte
Dim isDone As Bit
Dim cnt As Byte
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 ms as word
Dim readMsFlag as bit
Dim tick as byte
Dim tickLED as word
Dim tickSerial as word
Dim str as string
Dim pos as word
Dim dir as byte
Dim serialCount as byte
Dim length as byte

Symbol rled = PORTD.7
Symbol yled = PORTD.6

OSCCON = %01110000        '& h70
gosub initIO
gosub initServos
gosub initSerial
gosub initTMR1
gosub initTMR2
ccpDone=1
'Start up leds
rled = 1
WaitMs 1000
rled = 0
WaitMs 1000
rled = 1
WaitMs 1000
rled = 0
WaitMs 1000
tick=0
ms=0
tickLED=0
tickSerial=0
INTCON=0xc0                        'only PEIE and GIE set
WaitMs 2                            'let serial flush and get stable
While 1
    If (ms.LB - tick) > 20 Then
        tick=ms.LB
        'this code gets executed 50 times per second (every 20mS)
       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                    'no interrupts
          servoPos(i)=pos
          INTCON.GIE = 1                    're enable interrupts
          servoDir(i)=dir                'servoDir not used by ISR
        Next i
    Endif
    'example code to flash an LED at 1Hz
    call getMS()
    if (getMS-tickLED)>500 then            'note cannot be more than 65535 (65 seconds!!!!)
        'this code executed every 500mS which is a 1Hz flashing LED
        tickLED=getMS
        rLED= NOT rLED
    endif
    'this will output str once per second
    if (getMS-tickSerial)>1000 then
        'this code executed every 1000mS
        tickSerial=getMS
        str="$test stringW"    'this string cannot be more than 15 characters long or the servos may glitch
        for i=0 to len(str)-1
            call putFifo(str(i))
        next i
    endif
Wend
End                       

function getMS() as word
    readMsFlag=0
    getMS=ms
    if readMsFlag then
        getMS=ms
    endif
end function                                        

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

initSerial:
    'setup USART for 9600 baud receive
    RCSTA = %10010000
    TXSTA.BRGH = 1
    BAUDCON.BRG16 = 1
    SPBRG = 207
    PIR1.RCIF = 0
    PIE1.RCIE = 1
    strCount = 0
    isDone = 0
    ccpDone = 1
    PIE2.CCP2IE=1
return

initServos:
    For i = 0 To 7
        servoPos(i) = i * 250 + 2000    '1ms(2000) to 1.875(1 7/8ths - 3750)ms in 1/8th mS steps
        servoDir(i) = i And 1    '<<<<<<<added
    Next i
    servoCount = 8                    'cause it to reset
    CCP1CON = %1000                'will go high on interrupt - will start a 0.5mS pulse
    frame = 1000                    'start everything in 4000 cycles
    PIE1.CCP1IE = 1
return

initTMR1:
    T1CON = %00100000            'prescaler = 4
    T1CON.0 = 1                    'start timer
return

initTMR2:
    'setup 1mS interrupt = 8,000,000/16 = 500,000/10 = 50,000 set PR2=49 = 50,000/50 = 1000 = 1mS
    T2CON = %01001010                            'pre=16, post=10
    T2CON.TMR2ON=1                                'turn it on
    PR2 = 49                                        'This is timer 2 period register. I.E. reset after 50 clocks (0 to 49 = 50 counts)
    PIE1.TMR2IE = 1                             'timer 2 interrupts enable
return

initIO:
    TRISA = %11000000            '7=OSC, 6=OSC,
    TRISB    = %00000000
    TRISC = %11111000            '6=1-slave4431_cs, 2=74HC164 CLK, 0=74HC164 DATA 1=Serial out
    TRISD = %00000000
    LATC.3=0                        'reset shift register
    LATC.3=1                        'and allow it to run
return

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*4=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                        'are we idle
            bitCount=0                            'yes so reset things
            length=getFifoLen()                'is anything in the fifo?
            if length>0 then                    'yes so start a new transmision
                TXbyte=getFifo()                'get byte to transmit
                CCP2CON=%1001                    'pin high and low on next interrupt = start bit
                ccpDone=false                    'tell everything we're no londer idle
                previous=0                        'set previous equal to start bit
            Endif
        else
            'we're sending a byte
            if bitCount<9 then                'have we done a complete byte
                if TXbyte.0=previous then    'no so send next bit,
                    'just need the interrupt as next bit is same as previous bit
                    CCP2CON=%1010
                else
                    'we need to flip the bit
                    if previous Then            'did we previously send a one?
                        'we need a zero next
                        previous=0                'we're sending a zero next
                        CCP2CON=%1001            'will go to zero next match
                    else
                        'we need a one next
                        previous=1                'we're sending a one next
                        CCP2CON=%1000            'will go to zero next match
                    endif
                endif
                TXbyte=shiftRight(TXbyte,1)'shift next bit to zero position
            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                'this will get reset if idle
        PIR2.CCP2IF=0
    Endif
    If PIR1.TMR2IF Then                        'Is it a timer 2 interrupt
        readMsFlag=1                                'make any read invalid
        Cnt = Cnt + 1                            'Increment count
        ms=ms+1                                    'increment milliSecond
        If Cnt >= 5 AND NOT isDone Then    'Has 5mS passed without a byte being received
            isDone=0
            strCount=0
            cnt=0
        Endif
        PIR1.TMR2IF = 0
    Endif
    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
            Endif
        Endif
        CCPR1H = wordTemp.HB            'put value back into CCPR1
        CCPR1L = wordTemp.LB
        PIR1.CCP1IF = 0                'clear interrupt flag
    Endif
    If PIR1.RCIF Then
        cnt=0                                'stop any timeout happening
        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
            while PIR1.RCIF            'if any bytes in the buffer
                rec = RCREG                'throw them away
            wend
            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
            'the following is waiting for a "$" sign
            If strCount=0 Then        'are we already receiving
                'waiting for $            'no so wait
                If rec = "$" Then        'for $ to appear
                    buff(strCount)=rec'start receiving
                    strCount = 1        'must have been zero previously
                Endif
            Endif
            'the following gets executed if we've allready got a "$" sign
            'but not got a "W" yet.
            If isDone=0 And strCount<>0 Then
                if strCount<80 then    'only store it if there's room in the buffer
                    buff(strCount)=rec    'no so carry on storing
                    strCount = strCount + 1    'this may cause strCount to get to 80 = buffer full
                Endif
                If rec = "W" Then        'have we got the "endOfString" character
                    isDone = 1            'yes, so set done true
                Endif
            Endif
            If isDone=0 AND strCount>79 Then   
                'buffer has overflown
                strCount = 0
            Endif
        Endif
    Endif    'end RS232 if
Resume

Mike.
 

Attachments

  • code 210423 1100.txt
    9.6 KB · Views: 255
Can anyone confirm if the -1 is needed here,
Code:
        for i=0 to len(str)-1
            call putFifo(str(i))
        next i

Mike.
That would be the right syntax since you are treating the string as an array of bytes. Your string is 13 characters long, so a FOR loop should only extract 13 bytes, indexed 0 to 12.
 
Hi M, and S,
#270 compiles
Start up flashes Y
SERVO moves CW once. STIFF
1Hz flash comes on and stays on.
Freeze.

No RC1 output! Would you show where RC! is outputted in the CODE please?
C
 
Last edited:
Hi M,
There are 2x $ in the BUFF?
C
 

Attachments

  • 2x$.jpg
    2x$.jpg
    99 KB · Views: 230
It seems the first if strcount=0 stores the $ and simply falls through to the next if strcount <> 0 where rec is still $. Thus it adds it twice. The first if should jump to the end of the “uart if” routine
 
It seems the first if strcount=0 stores the $ and simply falls through to the next if strcount <> 0 where rec is still $. Thus it adds it twice. The first if should jump to the end of the “uart if” routine
Hi S,
I attempted to fix it, but failed.
Let's see what M comes up with.
Thanks
C.
 
I don't know why, but my latest PIC18 IDE does not compile that code. That said, a suggested way to solve it is to exit the first $ capture with "Goto Wayout::

Code:
    If PIR1.RCIF Then
        cnt = 0                                'stop any timeout happening
        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
            While PIR1.RCIF            'if any bytes in the buffer
                rec = RCREG                'throw them away
            Wend
            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
            'the following is waiting for a "$" sign
            If strCount = 0 Then        'are we already receiving
                'waiting for $   'no so wait
                If rec = "$" Then        'for $ to appear
                    buff(strCount) = rec  'start receiving
                    strCount = 1        'must have been zero previously
                    Goto Wayout
                Endif
            Endif
            'the following gets executed if we've allready got a "$" sign
            'but not got a "W" yet.
            If isDone = 0 And strCount <> 0 Then
                If strCount < 80 Then    'only store it if there's room in the buffer
                    buff(strCount) = rec    'no so carry on storing
                    strCount = strCount + 1    'this may cause strCount to get to 80 = buffer full
                Endif
                If rec = "W" Then        'have we got the "endOfString" character
                    isDone = 1            'yes, so set done true
                Endif
            Endif
            If isDone = 0 And strCount > 79 Then
                'buffer has overflown
                strCount = 0
            Endif
        Endif
Wayout:
    Endif    'end RS232 if
 
I don't know why, but my latest PIC18 IDE does not compile that code. That said, a suggested way to solve it is to exit the first $ capture with "Goto Wayout::

Code:
    If PIR1.RCIF Then
        cnt = 0                                'stop any timeout happening
        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
            While PIR1.RCIF            'if any bytes in the buffer
                rec = RCREG                'throw them away
            Wend
            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
            'the following is waiting for a "$" sign
            If strCount = 0 Then        'are we already receiving
                'waiting for $   'no so wait
                If rec = "$" Then        'for $ to appear
                    buff(strCount) = rec  'start receiving
                    strCount = 1        'must have been zero previously
                    Goto Wayout
                Endif
            Endif
            'the following gets executed if we've allready got a "$" sign
            'but not got a "W" yet.
            If isDone = 0 And strCount <> 0 Then
                If strCount < 80 Then    'only store it if there's room in the buffer
                    buff(strCount) = rec    'no so carry on storing
                    strCount = strCount + 1    'this may cause strCount to get to 80 = buffer full
                Endif
                If rec = "W" Then        'have we got the "endOfString" character
                    isDone = 1            'yes, so set done true
                Endif
            Endif
            If isDone = 0 And strCount > 79 Then
                'buffer has overflown
                strCount = 0
            Endif
        Endif
Wayout:
    Endif    'end RS232 if
Hi S,
I gave it a quick try, which cured the 2x$, and looked like it was moving SERVOS in 'sim' No LED flash.
I'll spend more time tomorrow.
Thanks
C
 

Latest threads

New Articles From Microcontroller Tips

Back
Top