Hardware ESC 8xSERVO CONTROL on PIC (Oshonsoft BASIC)

Status
Not open for further replies.
What I'm saying is HOW are these values possible?

They should be increasing by 250 each time but are instead getting 6 smaller.

Mike.
 
Have you read my replies? As I stated, 1000 WILL NOT WORK. As explained above.


The only place servoPos is written is in the for loop and should contain values between 2000 and 3750. How can other values be in there?

Mike.
Hi M,
I read all of your replies, carefully.

The examples I posted show 1000 and I understand won't work, and today I was tesing, following you replies with 2000 to 4000, using the same method, and it was working.
C.
 
Firstly, my code is perfectly indented,


And I can cut/paste to Notepad++ and it stays perfectly indented.

Can Oshonsoft not do simple maths? i*250+2000 should be simple maths, why is it wrong?

Mike.
 
How does 7*250+2000 equal 2214? So, 7*250 = 214!!!! How. And 6*250 equals 220.

As I said previously, I'm fast loosing faith in Oshonsoft. No wonder you can't get things to work.

Mike.
 
They should be increasing by 250 each time but are instead getting 6 smaller.
From that table of values, it's doing the 'i*250' portion as a byte (with a byte result) and then adding that to 2000.

I don't know what the syntax would be to get it to do the math using words... never used it.
 
How does 7*250+2000 equal 2214? So, 7*250 = 214!!!! How. And 6*250 equals 220.

As I said previously, I'm fast loosing faith in Oshonsoft. No wonder you can't get things to work.

Mike.
Hi M and T,
Perhaps the calculation needs brackets or something? Leave it with me, I'll check.

Here's a test using the #486 method (with 2000-4000)
C
 

Attachments

  • 2000 to 4000.jpg
    196.1 KB · Views: 233
Those timing diagrams are all correct. But I am still amassed that a simple for next loop doesn't work correctly.

Mike.
 
From that table of values, it's doing the 'i*250' portion as a byte (with a byte result) and then adding that to 2000.
Well spotted. Can a cast be used or does i need to be a word to force 16 bit calculation?
Or both.

Maybe,
Dim i as word
servoPos(i)=i * (word)250+2000

Mike.
 
Here's a version with i defined as a word and all the 0bs changed to %.
Code:
'18F4431 32MHz XTL REMOTE_SLAVE 164 389 030223 1200
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 SIMULATION_WAITMS_VALUE = 1  'Comment in for SIM out for PIC

Dim servoCount as byte
Dim i as Word
Dim wordTemp As Word
Dim servoPos(8) as word
Dim frame as word

'need to ensure the 164 is reset at power on.

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            'snd 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
Next i
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
While 1
  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 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=31000         '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
  'change any servo positions here
Wend
End

I'll also attach it as a text file,

Mike.
Edit, it also contains code to clear the shift register.
 

Attachments

  • No_ISR.txt
    2.6 KB · Views: 260
Hi M,
Here's the result
C
 

Attachments

  • #510.jpg
    179.5 KB · Views: 239
Except for the idle time of 16mS which is caused by a typo by me,
frame=31000
should be
frame=39000

Sorry,

Mike.
 
What else does it need to do?
Receive a string via the UART?
Parse said string?
Set servoPos depending on the string?

Maybe we should try using interrupts again so the parsing can take as long as it needs to.

Mike.
 
What else does it need to do?
Receive a string via the UART?
Parse said string?
Set servoPos depending on the string?

Maybe we should try using interrupts again so the parsing can take as long as it needs to.

Mike.
Hi M,
I don't know yet, what it needs to do, the plan is to get the servos/motors sorted out first.

We can try interrupts again, and a main loop with parsing and much more, which I think will be large.

hasta maniana
C
 
If we use interrupts again, the main loop will be empty.
The ISR can also service the UART.
Do you have UART code that can be used as an example?

Mike.
I know it's past midnight there so goodnight. It's mid morning here.
 
Here's a version that (hopefully) should work on interrupts,
Code:
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 frame 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
  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
Next i
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
PIE1.CCP1IE=1
INTCON.PEIE=1
INTCON.GIE=1
While 1
  'adjust servo positions here
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
      Endif
    Endif
    CCPR1H = wordTemp.HB      'put value back into CCPR1
    CCPR1L = wordTemp.LB
    PIR1.CCP1IF = 0           'clear interrupt flag
  Endif
resume
resume

There's no priority set as the default is to vector to the high priority interrupt (0x0008).

Can we just try this as is and see if it works?

Here's a picture of the ISR in Notepad++,

I hope you agree that having the indenting aids in following what the code is doing.
The dotted lines match up the If, Else & EndIf that go together.
The first If isn't actually needed as CCP1 is the only thing that can trigger interrupts but that's about to change.
The second If decides if we're doing the 0.5mS positive pulse or the remainder of the servo time.
The third If decides if we've done all servos and if so outputs the remaining time (in frame) and resets everything.

Also attached is the text file.

Mike.
 

Attachments

  • ISR.txt
    2.7 KB · Views: 239
Last edited:
I don't think you need this line,
Define SIMULATION_WAITMS_VALUE = 1 'Comment in for SIM out for PIC
As no delays are used.

Mike.
 
Strange, it seems in some cases, versions of the Basic "compiler" may produce integer values when multiplying byte "i" by 250. However, in the PIC18 IDE (not compiler version), I get the proper values calculated:

Code:
Dim i As Byte
Dim servopos(8) As Word

For i = 0 To 7
    servopos(i) = i * 250 + 2000
Next i

End
Produces the right values:



Is it possible that somehow servopos is being modified elsewhere?
Also, integer overflow could produce values that change by 6, based on multiplying by 250, but a byte can only hold 255 maximum.
Put a "Break" after the Next i statement and verify the values are correct before allowing the rest of the code to run...
 
Last edited:
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…