HW 8 channel SERVO/MOTOR output on 18F4431 (Oshonsoft)

Thread Starter

camerart

Joined Feb 25, 2013
3,853
'PIR1.CCP1IF = 0 should be uncommented
128 take away: index=index+1
It was my mistake.
Hi J,
We're getting warm!
The LED flashes were not precise. so I used STOP on OSC
EDIT: I changed LED flash to 20ms, see OSC2 I can now see them 'live'
C
 

Attachments

Last edited:

Thread Starter

camerart

Joined Feb 25, 2013
3,853
Hi j,
In #70 your said "set TRISD = 0" PORTD is also used for SPI, can you clarify why PORTD needs to = 0 please?
C
 

Thread Starter

camerart

Joined Feb 25, 2013
3,853
Hi,
The 'PWM' is now working, but needs some attention. (Later)
There is now an issue, where while the 4431 PIC is running the compass stops. If I program or verify the 4431, the compass works while this is happening.
Any ideas?
C
 

Thread Starter

camerart

Joined Feb 25, 2013
3,853
Hi,
As some of you know, this is a part of big project with many aspects to juggle, so apologies for re-opening this topic.

I have a mate who is a 'programmer' so now I'm chief researcher and tester, while he 'tidies' up the CODE.

Anyway, I have the program on test (posted here earlier) but something doesn't seem right? It seems very slow, and I can't find what's slowing it. I have 1x SERVO connected to '0' and it pulses each app 500ms, then releases.

I have 20sheets of D/S to try to figue it out, but I find it very difficult to follow.

When I look for PIC SERVO control, I ususally find PWM in there somewhere. I think this is using a different CCP, where PWM isn't used.

Is this program the best?
C
Code:
'18F4431 32MHz XTL REMOTE_SLAVE 030123 0930 TEST
Define CONFIG1L = 0x00
Define CONFIG1H = 0x06  '8mHz x4 =32
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 SIMULATION_WAITMS_VALUE = 1  'Comment in for SIM out for PIC
Define CLOCK_FREQUENCY = 32
Define SINGLE_DECIMAL_PLACES = 2

Dim m2s(4) As Byte
Dim s2m(4) As Byte  '0=s2m(0), 1=s2m(1), 2=Batt volts '10s', 3=Batt volts 'units'
Dim datam2s0 As Byte  'At the moment QEIDEG is being used CHANGE later.&
Dim datam2s1 As Byte  'At the moment QEIDEG is being used CHANGE later.&
Dim datam2s2 As Byte
Dim datam2s3 As Byte

ANSEL0 = 0  '%00000000
ANSEL1 = 1  '%00000000

Symbol slave4431_cs = PORTC.6

TRISA = %11011000  '7=OSC, 6=OSC, 4=QEIB 3=QEIA 2=TEMP SEROUT
TRISB = %00000000
TRISC = %01000100  '6=1-slave4431_cs, 2=MOSI
TRISD = %00000000  '6=led, 7=led

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

'START:
yled = 1
rled = 1
WaitMs 1000
yled = 0
rled = 0
WaitMs 1000
yled = 1
rled = 1
WaitMs 1000
yled = 0
rled = 0
WaitMs 1000

'*********** SETUP SERVO *************************************
Dim index As Byte
Dim motor_servo(8) As Word
Dim time_now As Word
Dim time_set As Word
Dim shift_reg As Byte
'********** END SETUP SERVO **********************************

WaitUs 100

Hseropen 9600  'After initialisation
Hserout "Ready!4431", CrLf

'Init spi
Call init_spi()  'initialise spi -here SSPEN=1 sets the pin directions for SPI
'Set them from your program as needed.

motor_servo(0) = 0300  'MIN 0300 max 2200  'Port bit 0, Near min position
motor_servo(1) = 1500  'Port bit 1, Mid position
motor_servo(2) = 2300  'Port bit 2, Near max position
motor_servo(3) = 1300  'Port bit 3, Under mid position
motor_servo(4) = 1700  'Port bit 4, Over mid position
motor_servo(5) = 1200  'Port bit 5, etc
motor_servo(6) = 1900  'Port bit 6
motor_servo(7) = 1400  'Port bit 7

'T1CON = %00011111  '0x31  '8:1, switch on REFERENCE REMOVE
T1CON.T1CKPS1 = 1  '11 = 1:8 Prescale value
T1CON.T1CKPS0 = 1  '"   "   "
T1CON.T1OSCEN = 1  '1 = Timer1 oscillator is enabled
T1CON.T1SYNC = 1  'Do not synchronize external clock input
T1CON.TMR1CS = 1  'External clock from pin RC0/T1OSO/T1CKI (on the rising edge)
T1CON.TMR1ON = 1  'Enables Timer1

'Without an output pin defined, just an interrupt from CCP
'CCP1CON = 0x02  'ccp_compare_toggle
'CCP1CON = %00001001  '0x09 Compare mode; initialize CCPx pin high; on compare match, force CCPx pin low (CCPxIF bit is set)
CCP1CON.CCP1M3 = 1  'Compare mode; initialize CCPx pin high; on compare match, force CCPx pin low (CCPxIF bit is set)
CCP1CON.CCP1M2 = 0
CCP1CON.CCP1M1 = 0
CCP1CON.CCP1M0 = 1

'And enable the interrupts for the hardware used
'the reference for CCP1, so no time interrupt required.
PIE1.CCP1IE = 1
'INTCON1.PEIE = 1  'INTCON bit 6'ADDED #81 &
'INTCON1.GIE = 1
INTCON.PEIE = 1  'INTCON bit 6'ADDED #81 &
INTCON.GIE = 1  'CHANGED &
'NOTE, line from old program CCP1IP = 1  'High Priority interrupt for CCP1

main:

'motor_servo(0) = 2200  'MIN 0300 max 2200  'Port bit 0, Near min position

'Toggle rled
'WaitMs 10
    s2m(0) = 10  'TEST DATA1
    s2m(1) = 11  'TEST DATA2
    s2m(2) = 12  'TEST DATA3
    s2m(3) = 13  'TEST DATA4
   
'SSPBUF = s2m(0)
'qeideg.LB = m2s(0)
    'While slave4431_cs = 1  'Waiting till CS goes ON =0
        'Wend
    'While Not SSPSTAT.BF
        'Wend
       
'SSPBUF = s2m(1)
'qeideg.HB = m2s(1)
    'While slave4431_cs = 1  'Waiting till CS goes ON =0
        'Wend
    'While Not SSPSTAT.BF
        'Wend
'******************************************************
'SSPBUF = s2m(2)
'datam2s2 = m2s(2)
    'While slave4431_cs = 1  'Waiting till CS goes ON =0
        'Wend
    'While Not SSPSTAT.BF
        'Wend
       
'SSPBUF = s2m(3)
'datam2s3 = m2s(3)
    'While slave4431_cs = 1  'Waiting till CS goes ON =0
        'Wend
    'While Not SSPSTAT.BF
        'Wend
''*****************************************************

Goto main
End                                              
'int_ccp1
On High Interrupt
Save System

PIR1.CCP1IF = 0  'clear IF ADDED

shift_reg = ShiftLeft(shift_reg, 1)  'Shift the bit left one place.
'shift_reg = shift_reg + shift reg would do the same.
LATB = shift_reg  'Write the shift register bits to the port CHANGED &

'Increment index for next servo time value
index = index + 1

If index < 8 Then  'All servos already done?

yled = 1
'WaitMs 100

    'No, do next servo

    'Set the duration for this output, as a new offset
    'from the last compare time.
    time_set = time_set + motor_servo(index)

    CCPR1L = time_set.LB  'Write the compare time to CCP1 register.
    CCPR1H = time_set.HB

yled = 0

Else
    'No output needed as the port is already updated.
    'output_c(0); 'Turn off all servo bits.

    'restarting the sequence.

    time_set = time_set + 1500  'add 1.5mS for the next interrupt
    'Update CCP
    CCPR1L = time_set.LB  'Write the compare time to CCP1 register.
    CCPR1H = time_set.HB

    If index > 15 Then  '15 * average 1.5mS = 22.5mS, a reasonable frame repeat time
   
        'Set up for a new sequence
        index = 0
        shift_reg = 1  'Set a bit that will be at port bit 0.
   
        time_now.LB = TMR1L  'Get the timer present count
        time_now.HB = TMR1H
        time_set = time_now + motor_servo(index)  'And set the first duration
        LATB = shift_reg  'Write the shift register bits to the port CHANGED &
        CCPR1L = time_set.LB  'Write the compare time to CCP 1 register.
        CCPR1H = time_set.HB
    Endif
Endif

'Toggle yled


Resume                                          

Proc init_spi()  'PIC 18F4431
'4431
TRISC.6 = 1  'CS=1
TRISD.3 = 1  'SCK from MASTER ******INPUT*****
TRISD.1 = 0  'MISO  ****** OUTPUT *******
TRISD.2 = 1  'MOSI  ****** INPUT *******

'MODE 0,0
SSPSTAT.SMP = 0  'Input data sampled at middle of data output time ** not about clock generation **
SSPSTAT.CKE = 0  '0 Output data changes on clock transition from active to idle ** AS ABOVE **
SSPSTAT.5 = 0  'I2C only
SSPSTAT.4 = 0  'I2C only
SSPSTAT.3 = 0  'I2C only
SSPSTAT.2 = 0  'I2C only
SSPSTAT.1 = 0  'I2C only

SSPCON = 0  'RESET THE CONTROL REGISTER ************ADDED
SSPCON.WCOL = 0  'Collision detect
SSPCON.SSPOV = 0  'Overflow
SSPCON.SSPEN = 1  'Configure SCK,SD0,SDI,/SS ** HAS TO BE 1. To reset or reconfigure SPI mode, clear the SSPEN bit,
                        'reinitialize the sspcon registers And Then set the SSPEN Bit from the datasheet !!!!!!!!!!!!!!!!
SSPCON.CKP = 1  '1 = Idle state for clock is a high level
SSPCON.SSPM3 = 0  '0100 = SPI Slave mode, Clock = SCK pin, SS pin control enabled,
SSPCON.SSPM2 = 1
SSPCON.SSPM1 = 0  'SLAVE MODE
SSPCON.SSPM0 = 0

End Proc
 

Thread Starter

camerart

Joined Feb 25, 2013
3,853
Hi,
Thinking about my PWM comment, I seem to recall that PWM is used to control DC motors, and probably not right for my brushless motors and SERVOS.
(It was probably mentioned before)
C
 

Thread Starter

camerart

Joined Feb 25, 2013
3,853
All of the BLDC servo's I have used, I used PWM (transconductance) drive amps for them.
Hi M,
I've just looked up (again) BLDC = Brushless DC motor, and I was getting mixed up with DC and AC motors!
Also PIC CCP the P=PWM!
I'm updating my mind to Motor/Servo control, and how it's done, along with the complicated D/S in the CCP section.
Thanks,
C.
 

Thread Starter

camerart

Joined Feb 25, 2013
3,853
Hi,
If you look at my image #30, the times follow each other tightly, I can't visualise this yet, but it's filtering through.
Also an earlier suggestion, is either produce each channel PWM using interrupts, or use the PWM pins themselves, so this is a choice.
A note is: there are 4x complimentary PWMs (I think) so even though there are more pins, this doesn't mean there are as many PWM pins, so it looks like the only option for more that 4x PWM pins is INTERRUPTS.
All this is a bit scrambled at the moment, but hopefully, I'll understand more as I proceed.
C
 

MaxHeadRoom

Joined Jul 18, 2013
30,873
Hi M,
I don't suppose there's much difference, apart from size?
C
One big difference is the closed loop feedback to the controller, this is required when operating a BLDC motor down to zero RPM in such as CNC arenas, otherwise severe 'cogging' occurs at low RPM if used open loop.
 

Thread Starter

camerart

Joined Feb 25, 2013
3,853
One big difference is the closed loop feedback to the controller, this is required when operating a BLDC motor down to zero RPM in such as CNC arenas, otherwise severe 'cogging' occurs at low RPM if used open loop.
Hi M,
I think the CCP on the PIC has this sort of feedback, but it's not needed for this.
C
 

Thread Starter

camerart

Joined Feb 25, 2013
3,853
Hi,
Here are the working programs SERVO plus the FULL REMOTE SLAVE program. Both work independantly.

When the relevant sections from this SERVO program are inserted into the FULL SLAVE program, TMR1L doesn't increment TMR1H. What could cause this?

I've looked through the attached program, and I think it may be something to do with PIE1, or similar, but it's a bit advanced for me.
C
 

Attachments

Last edited:

Thread Starter

camerart

Joined Feb 25, 2013
3,853
Is timer1 used elsewhere than generating servo pulses?
Hi J,
I don't think so, I'll re-check.

The PIE1 register contains TMR1 and TMR2 and CCP1. TMR2 is used elseware.

EDIT: Timer1 is only used for SERVOS.
C
 

Attachments

Last edited:

Thread Starter

camerart

Joined Feb 25, 2013
3,853
Timer1 is on low interrupt so timer2 interrupts it.
Maybe switching priorities helps?
Hi J,
Yes, I switched it as a test. Timing and interrupts are a difficult concept, and there is a SERVO timing that can slow them down, which I'll also look at to see where they fail.
Thanks.
C
 
Top