saving RCREG to word


Closed Thread
Results 1 to 8 of 8

Hybrid View

  1. #1


    Did you find this post helpful? Yes | No

    Default Driving 8 servos

    Not sure I understand what you are doing but I found for an RC aircraft/UAV that 256 servo positions gives plenty of resolution and very smooth flight. By pulling the servo data down to a byte variable I have heaps of time to send 8 channels of servo data every frame time for very smooth servo operation.

    I have one PIC16F88 decoding the incoming radio PPM stream and building a fast packet of 8 single byte servo positions (plus start and checksum characters) at 115600 bps using Debug.

    The radio decoder measures the width of the 8 incoming channel pulses. It has the 4 - 12 mSec gap at the end of the frame in which to send a fast packet. At 115600 bps this takes about 2100 uSecs to send. This is fast enough to complete before the 16F88 has to find the next incoming data frame.

    This fast packet is massaged by a PIC16F887 where height hold, GPS and stability corrections are applied and a new past packet is built and sent to several 'servopods' that drive 1, 2 or 4 servos. The servopod reads the incoming packet and uses the new data if the checksum is good. Otherwise it uses last known good data for that channel.

    It all runs under PBP and needs no assembler accept for setting the WDT.

    Code:
    Data @0,$0D, $0A, "P4 Servo ver 1.05  BDT 21/03/2006",$0D, $0A
    data @40, 0, 0 'error counter
    '****************************************************************
    '*  Name    : P4_Servo_V105.BAS                                 *
    '*  Author  : Brian Taylor                                      *
    '*  Notice  : Copyright (c) 2006 Brian Taylor                   *
    '*          : All Rights Reserved                               *
    '*  Date    : 21/03/2006                                        *
    '*  Version : 1.05                                              *
    '*  Notes   :                                                   *
    '*          :                                                   *
    '****************************************************************
    '  This is P4 - 16F88 - the servo driver
    '  test code to debug the hardware
    '
    'Background.
    '  A 'standard' JR, Futaba, HS, etc RC system uses on a nominal 50 Hz
    '  refresh rate to the servos.  This gives a nominal 20 mSec frame time.
    '  Servos centre at 1.5 mSec and range from 1 to 2 mSec at the end stops. 
    '  Bitter experience shows digital servos burn out outside 1-2 mS values. 
    '  8 channels all at maximum, highly unlikely, takes 8 x 2 mSec leaving 
    '  4 mSec for sync, etc. 8 channels all at minimum width, also highly 
    '  unlikely, takes 8 mS leaving 12 mSec for sync, processing, etc.
    '  An 'average' frame has 8 channels at 1.5 mSec leaving 8 mSec for playtime.
    '  This code gets a 'fast packet' from the leveller PIC in about 2.1 mSec
    '  and drives all 8 servos regardless of whether they exist in hardware.
    '
    DEFINE LOADER_USED 1
    DEFINE OSC 20
    define no_clrwdt 1
    define loader_used 1     
    ' Set Debugin pin port
    DEFINE DEBUGIN_REG PORTB 
    DEFINE DEBUG_BAUD 115200   '76800 
    ' Set Debugin pin bit
    DEFINE DEBUGIN_BIT 7 
    ' Set Debugin mode: 0 = true, 1 = inverted
    DEFINE DEBUGIN_MODE 1
    
    '@ Device pic16F88, HS_OSC, BOD_OFF, PWRT_ON, WDT_ON, PROTECT_OFF
    
    '************************** Hardware assignment *************************
    'Port A     all digital
    Svo8        var   porta.0     'p 17 digital drive to servo 8 digital      out
    Svo7        var   porta.1     'p 18                  servo 7 digital      out
    Svo6        var   porta.2     'p 1  digital drive to servo 6 digital      out
    Svo5        var   porta.3     'p 2  digital drive to servo 5 digital      out
    Svo4        var   porta.4     'p 3  digital drive to servo 4 digital      out
    
    TRISA = %11100000
    ANSEL = %00000000
    CMCON = %00000111
    
    'Port B
    Svo3        var   portb.0     'pin 6  servo 3 drive                       out
    Svo2        var   portb.1     'pin 7  servo 2                             out
    RxD         var   portb.2     'pin 8  BootLoader input                    in
    Svo1        var   portb.3     'pin 9  Servo 1 drive                       out
    P4LED       var   portb.4     'pin 10 Diagnostic LED                      out
    TxD         var   portb.5     'pin 11 BootLoader output - diagnostic out  out
    P3_P4       var   portb.6     'p 12 Data in from P3                       in
    P2_P4       var   portb.7     'p 13 Servo packet data from P2             in
    TRISB = %11000100
    
    '****************************** Software assignment **************************
    A           var   byte
    B           var   byte
    C           var   byte
    W           var   word
    InCtr       var   byte
    Ch          var   byte[8]  ' the current channel data
    LastCh      var   byte[8]  ' last clean channel data
    FailCh      var   byte[8]  ' failsafe values invoked after N bad packets
    Delta       var   byte     ' maximum allowable servo step
    CheckSum    var   byte
    ErrorCtr    var   word  ' counts checksum errors in servo data from P2
    
    StepLimit   con   8    ' max allowed servo change per frame
                           ' damps out violent spikes
                           
    '--------------------------------- Initialise ------------------------
    Initialise:
    
    ShowRevision:
       serout txd, 2, [$0D, $0A] 
       for a = 0 to 79
          read a,b
          serout txd, 2, [b]
          clearwdt
       next a
       serout txd, 2, [$0D, $0A] 
    
    '   WDTCON = %00001001 ' invoke s/w WDT, 58 mSec timeout, 110 mSec recovery
       WDTCON = %00001010      ' longer WDT activate period 
       OPTION_REG = %10001010  ' No wpu, prescaler assigned to WDT & /4
                               ' OPTION_REG xxxx00 gives 15 mS, 10 gives 64 mS 
       INTCON = %00000000      ' disable all interrupts
       ANSEL =  %00000000      ' all digital
       CMCON  = %00000111      ' Comparators OFF to allow inputs on pins
       ADCON0 = %00000000
       ADCON1 = %00000000
    
    SetInitialServoPosition:
       Ch[0] = 0
       Ch[1] = 125
       Ch[2] = 125
       Ch[3] = 125
       Ch[4] = 125
       Ch[5] = 125
       Ch[6] = 125
       Ch[7] = 125
      
    high p4led        ' fires if WDT is invoked during preflight ground check.
    
    Start:
    
    GetServoData:
       debugin 90, failsafe, [a, ch[0], ch[1], ch[2], ch[3], ch[4], ch[5], _
          ch[6], ch[7], checksum]
       'A = throw away sync byte - often corrupted
       c = 0 ' checksum comparison
       for b = 0 to 7    ' build local checksum
          c = c + ch[b]
       next b
       if checksum = c then 
          goto goodpacket
       endif
       
    
    Failsafe:   ' Use last clean packet if internal processor to processor
                ' error occurs
       high p4led
       for a = 0 to 7
          ch[a] = lastch[a]
       next a
       
    GoodPacket:
    
    DriveServos:
       ' PULSOUT gives 2 uS steps at 20 MHz.  
       ' The servos need 1000 to 2000 uS at 50 Hz
       ' MUST MUST MUST define initial states as Pulsout is a toggle.
       svo1 = 0
       svo2 = 0
       svo3 = 0
       svo4 = 0
       svo5 = 0
       svo6 = 0
       svo7 = 0
       svo8 = 0
       
       clearwdt
       
       w = 500 + 2*ch[0]         ' W is in 2 uS steps = 1000 to 2000 uS
          pulsout svo1, w
       w = 500 + 2*ch[1]   
          pulsout svo2, w
       w = 500 + 2*ch[2]   
          pulsout svo3, w
       w = 500 + 2*ch[3]   
          pulsout svo4, w
       w = 500 + 2*ch[4]   
          pulsout svo5, w
       w = 500 + 2*ch[5]   
          pulsout svo6, w
       w = 500 + 2*ch[6]   
          pulsout svo7, w
       w = 500 + 2*ch[7]   
          pulsout svo8, w
    
    SaveLastValues:
       for a = 0 to 7
          lastch[a] = ch[a]
       next a
    
       low p4led
       clearwdt
    goto start  'getservodata
    HTH
    BrianT
    Last edited by BrianT; - 15th September 2008 at 11:14. Reason: clarity & layout

  2. #2


    Did you find this post helpful? Yes | No

    Default

    Darrel, thanks for the explanation. it makes sense.

    Brian, I approached the RX code a bit differently. For example I use a manchester decoder that tests 01 or 10 transition if there is a 11 or 00 bit it throws out the packet. So I don't have a checksum. I also have framing error and over run detection enabled for the UART. I am streaming out data at 4800bps.

    A modification since I am using a 900Mhz FSK radio, it does not need to have a balanced data stream so I can forgo the manchester. Instead I will send a word, high byte is true data and low byte is inverted data. The decoder then looks for identical payload once inverted between high and low byte, if not throw it out. All I am really controlling is 4 servos and 2 hardware PWM outputs which takes very little overhead since it is hardware unlike servos each 1 ~ 2ms.

    I noticed you used pulseout instead of portb.0=1 pauseus (4*pos+500) portb.0=0. Does the pulseout save in code execution time?

  3. #3


    Did you find this post helpful? Yes | No

    Default No optimisation done since it worked.

    Hi Magman,
    I did not optimise the code since I had plenty of time in the way I did it. It may turn out that your pauseus approach may save space and time. If I needed code space or clock cycles I would have checked that method out.

    I reckon a single checksum across all channels uses less time and code than the 100% redundancy approach you are taking with the true/inverted signalling but I agree yours is a safe and simple approach. If I get a bad packet or a bad channel within a packet (out of range or delta too big) I use the last good value for that channel. Given that real data does not jump much from frame to frame this method seems to fly quite well.

    My uplinks are 36 and 2400 MHz using the transmitter in PPM.

    What are you building. Is it an aircraft?

    Cheers
    BrianT
    Last edited by BrianT; - 15th September 2008 at 11:05. Reason: grammar

  4. #4


    Did you find this post helpful? Yes | No

    Default

    Looking over your code closely, I realized something. Do you pause in the TX output for 16 ~ 20ms before starting up your next frame?

    I am not doing that, it may be why I am seeing the results I am seeing. using a continuous back to back output from the TX @ 4800bps I am able to get 4 servo + 2 hardware PWM control. BTW I figured out why my servo is a bit coarse. in your code you multiply with a 2 constant. I am not moving in 2us increments. I am doing the following: 2* (4*byte + 500), So for every crank on the potentiometer I am moving in chunks of 8us, so I am not loosing packets, its my scaling factor....ggeeeezzz.


    yes, it is an aircraft. Actually VTOL.
    Last edited by Macgman2000; - 15th September 2008 at 13:56.

Similar Threads

  1. Read/Write Problem
    By Tobias in forum mel PIC BASIC Pro
    Replies: 1
    Last Post: - 10th February 2010, 01:51
  2. Minimizing code space
    By Tobias in forum mel PIC BASIC Pro
    Replies: 2
    Last Post: - 30th May 2009, 07:25
  3. SEROUT WORD variable problem
    By Tobias in forum mel PIC BASIC Pro
    Replies: 3
    Last Post: - 19th April 2009, 11:20
  4. DS2760 Thermocouple Kit from Parallax in PicBasicPro
    By seanharmon in forum mel PIC BASIC Pro
    Replies: 3
    Last Post: - 8th July 2008, 23:19
  5. calculation problem
    By nicolelawsc in forum mel PIC BASIC Pro
    Replies: 2
    Last Post: - 31st March 2006, 15:23

Members who have read this thread : 0

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts