I had a quick look at that today and it seems very inefficient,In #44 and the GPS CODE under '-------- PARSE UTILITIES -------------------------
Hi M,I had a quick look at that today and it seems very inefficient,
Is this a mistake or bug?
View attachment 140597
I was thinking this should be a for next loop but then noticed there's two difference at the beginning but only one at the end due to s2m(14) being used twice. If it's not a mistake then just remove the line, s2m(14) = buf(12) as it's not required. BTW, what is that code doing?
Mike.
Hi M,What is this nonsense?
View attachment 140607
We have nice fast interrupt driven code and then just throw a one second (yes one whole second) delay in and introduce something called "Define SEROUT_DELAYUS = 1000" = another random delay. And after a comment saying "This code can be any length but ideally less than 20mS".
I hate any kind of delay and any compiler that relies on them or that has them built in should be thrown in the bin.
Mike.
'18F4431 32MHz XTL REMOTE SLAVE GPS SERVO 240223 0830
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 SEROUT_DELAYUS = 1000 '<<<<<<<<<<<<<<<<
'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 outBuff(32) As Byte
Dim bitCount As Byte
Dim byteCount As Byte
Dim output As Word
Symbol rled = LATD.7 '<<<<<<<<<<<<<<<<
Symbol yled = PORTD.6 '<<<<<<<<<<<<<<
OSCCON = %01110000 '& h70
TRISA = %11000000 '7=OSC, 6=OSC,
TRISB = %0000000 '4=SEROUT'<<<<<<<<<<<<<<<
TRISC = %11111010 '6=1-slave4431_cs, 2=74HC164 CLK, 0=74HC164 DATA
TRISD = %00000000 '7=RLED 6=YLED'<<<<<<<<<<<<
'STARTUP LEDS <<<<<<<<<<<<<<<<<
rled = 1
yled = 1
WaitMs 1000
rled = 0
yled = 0
WaitMs 1000
LATC.0 = 0 'ensure data is low
LATC.2 = 0 'and clock
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
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
'setup 1mS interrupt = 8,000,000/16 = 500,000/10 = 50,000 set PR2=49 = 50,000/50 = 1000 = 1mS
T2CON = %01001110 '& h4e
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
'setup timer 5 to generate (CCP2) interrupts to enable 9600 baud transmission
T5CON=1 'timer 5 counts at 8MHz
CCP2CON=%1011 'special event trigger
PIR2.CCP2IF=0 'ensure IF is clear
CCPR2H=3 'CCPR2 (word) = 0x341 = decimal 833 = 8,000,000/9600
CCPR2L=0x41
'make a string that contains "$= ", #buff(0), " ", #buff(1), " ", #buff(2), " ", #buff(3), " ", #buff(4), " ", #buff(5), " ", #buff(6), CrLf
'put it in outBuff() and call (gosub) send.
INTCON.PEIE = 1
INTCON.GIE = 1
While 1
'adjust servo positions here
While servoCount = 0 'wait for 20mS to pass (=1/50th of a second)
Wend
While servoCount <> 0
Wend
For i = 0 To 7
INTCON.GIE = 0
If servoDir(i) = 1 Then
servoPos(i) = servoPos(i) + 40 'add 1/50th to the servo position
Else
servoPos(i) = servoPos(i) - 40 'subtract it
Endif
If servoPos < 2000 Then 'have we gone past the end?
servoPos(i) = 2000 'yes so make it the end stop
servoDir(i) = 1 'and turn it around
Endif
If servoPos(i) > 4000 Then 'same for other end
servoPos(i) = 4000
servoDir(i) = 0
Endif
INTCON.GIE = 1
Next i
If isDone Then
'deal with the received sentence here
'This code can be any length but ideally less than 20mS
isDone = 0
Endif
If PIE2.CCP2IE=0 then
'the buffer has been sent over RS232 in the interrupt
Toggle yled '<<<<<<<<<<<<<<<<<
Endif
Wend
End
'load outBuff with the data to send terminated with a zero.
send:
output=outBuff(0)
output=output OR %1100000000 'two stop bits
output=output*2 'one start bit
bitCount=10 '1 start, 8 data and 2 stop (1 intrinsic in code)
byteCount=1
PIR2.CCP2IF=0;
PIE2.CCP2IE=1 'enable the interrupts
return
On High Interrupt 'go via location 0x0008
Save System
If PIR2.CCP2IF And PIE2.CCP2IE then
if bitCount<>0 then
if output.0 then
LATB.4=1
Else
LATB.4=0
Endif
bitCount=bitCount-1
output=shiftRight(output,1)
Endif
if bitCount=0 AND outBuff(byteCount)<>0 then
'more bytes to send
output=outBuff(byteCount)
output=output OR %1100000000 'two stop bits
output=output*2 'one start bit
bitCount=10 '1 start, 8 data and 2 stop (1 intrinsic in code)
byteCount=byteCount+1
endif
if bitCount=0 AND outBuff(byteCount)=0 then
'sent all bytes
PIE2.CCP2IE=0 'so, no more interrupts
endif
PIR2.CCP2IF=0
Endif
If PIR1.TMR2IF Then 'Is it a timer 2 interrupt
cnt = cnt + 1 'Increment count
If cnt >= 5 Then 'Has 5mS passed without a byte being received
isDone = 0 'yes, so reset everything
strCount = 0
cnt = 0
Endif
PIR1.TMR2IF = 0 '0 = No TMR2 to PR2 match occurred
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
'put break here
Endif
Endif
If isDone = 0 And strCount > 79 Then
'buffer has overflown
strCount = 0
Endif
Endif
Endif 'end RS232 if
Resume
Hi M,I'm guessing that the line,
Serout PORTB.4, 9600, "$= ", etc.
Is a software serial function that outputs at 9600 baud on B4.
A function can be added to the ISR to make this happen.
Mike.
Hi M,I think this will output data at 9600 baud on B4.
Code:'18F4431 32MHz XTL REMOTE SLAVE GPS SERVO 240223 0830 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 SEROUT_DELAYUS = 1000 '<<<<<<<<<<<<<<<< '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 outBuff(32) As Byte Dim bitCount As Byte Dim byteCount As Byte Dim output As Word Symbol rled = LATD.7 '<<<<<<<<<<<<<<<< Symbol yled = PORTD.6 '<<<<<<<<<<<<<< OSCCON = %01110000 '& h70 TRISA = %11000000 '7=OSC, 6=OSC, TRISB = %0000000 '4=SEROUT'<<<<<<<<<<<<<<< TRISC = %11111010 '6=1-slave4431_cs, 2=74HC164 CLK, 0=74HC164 DATA TRISD = %00000000 '7=RLED 6=YLED'<<<<<<<<<<<< 'STARTUP LEDS <<<<<<<<<<<<<<<<< rled = 1 yled = 1 WaitMs 1000 rled = 0 yled = 0 WaitMs 1000 LATC.0 = 0 'ensure data is low LATC.2 = 0 'and clock 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 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 'setup 1mS interrupt = 8,000,000/16 = 500,000/10 = 50,000 set PR2=49 = 50,000/50 = 1000 = 1mS T2CON = %01001110 '& h4e 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 'setup timer 5 to generate (CCP2) interrupts to enable 9600 baud transmission T5CON=1 'timer 5 counts at 8MHz CCP2CON=%1011 'special event trigger PIR2.CCP2IF=0 'ensure IF is clear CCPR2H=3 'CCPR2 (word) = 0x341 = decimal 833 = 8,000,000/9600 CCPR2L=0x41 'make a string that contains "$= ", #buff(0), " ", #buff(1), " ", #buff(2), " ", #buff(3), " ", #buff(4), " ", #buff(5), " ", #buff(6), CrLf 'put it in outBuff() and call (gosub) send. INTCON.PEIE = 1 INTCON.GIE = 1 While 1 'adjust servo positions here While servoCount = 0 'wait for 20mS to pass (=1/50th of a second) Wend While servoCount <> 0 Wend For i = 0 To 7 INTCON.GIE = 0 If servoDir(i) = 1 Then servoPos(i) = servoPos(i) + 40 'add 1/50th to the servo position Else servoPos(i) = servoPos(i) - 40 'subtract it Endif If servoPos < 2000 Then 'have we gone past the end? servoPos(i) = 2000 'yes so make it the end stop servoDir(i) = 1 'and turn it around Endif If servoPos(i) > 4000 Then 'same for other end servoPos(i) = 4000 servoDir(i) = 0 Endif INTCON.GIE = 1 Next i If isDone Then 'deal with the received sentence here 'This code can be any length but ideally less than 20mS isDone = 0 Endif If PIE2.CCP2IE=0 then 'the buffer has been sent over RS232 in the interrupt Toggle yled '<<<<<<<<<<<<<<<<< Endif Wend End 'load outBuff with the data to send terminated with a zero. send: output=outBuff(0) output=output OR %1100000000 'two stop bits output=output*2 'one start bit bitCount=10 '1 start, 8 data and 2 stop (1 intrinsic in code) byteCount=1 PIR2.CCP2IF=0; PIE2.CCP2IE=1 'enable the interrupts return On High Interrupt 'go via location 0x0008 Save System If PIR2.CCP2IF And PIE2.CCP2IE then if bitCount<>0 then if output.0 then LATB.4=1 Else LATB.4=0 Endif bitCount=bitCount-1 output=shiftRight(output,1) Endif if bitCount=0 AND outBuff(byteCount)<>0 then 'more bytes to send output=outBuff(byteCount) output=output OR %1100000000 'two stop bits output=output*2 'one start bit bitCount=10 '1 start, 8 data and 2 stop (1 intrinsic in code) byteCount=byteCount+1 endif if bitCount=0 AND outBuff(byteCount)=0 then 'sent all bytes PIE2.CCP2IE=0 'so, no more interrupts endif PIR2.CCP2IF=0 Endif If PIR1.TMR2IF Then 'Is it a timer 2 interrupt cnt = cnt + 1 'Increment count If cnt >= 5 Then 'Has 5mS passed without a byte being received isDone = 0 'yes, so reset everything strCount = 0 cnt = 0 Endif PIR1.TMR2IF = 0 '0 = No TMR2 to PR2 match occurred 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 'put break here Endif Endif If isDone = 0 And strCount > 79 Then 'buffer has overflown strCount = 0 Endif Endif Endif 'end RS232 if Resume
Note, the two 1 second delays at the start of the code will mean that the shift register will have random outputs for 2 seconds. Ideally, move the 'STARTUP LEDS code to after the line isDone=0.
Mike.
Hi M,As I keep saying, the while wend loop is exactly the same as a main loop.
If you like, change the while 1 to main: and the wend to goto main and nothing will change.
Doing things in the main loop is fine and can take as long as you like but timing critical things like software serial probably disable interrupts and stop everything working so probably can't be used.
Have you put a string into outBuff and called send? I don't know how to make a string in Osh.
Can you show your code?
Mike.
Hi M,To get any output on B4 you need to load outBuff with a string to send and gosub send to start everything.
You can have 10 second waits but the servos will pause for 10 seconds, not because the output has stopped but because the code that sets their position has stopped. Everything (except moving the servos) is happening on interrupts at the moment. If you need to see an LED flashing then use a variable to count to 25 before toggling it and it'll flash at 1Hz due to the loop taking 20mS to execute.
When I said, Can you show your code? I meant the code that builds a string and calls send.
Mike.
Hi M,It can be either live or sim but to transmit anything on B4 requires a string being built and a call to send. If this isn't done then we won't know it the transmit is working or not. Can we do this?
Mike.
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?