]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/safe_numerics/example/Motor.c
1 // Demo program for stepper motor control with linear ramps
2 // Hardware: PIC18F252, L6219
19 // 1st step=50ms; max speed=120rpm (based on 1MHz timer, 1.8deg steps)
23 // ramp state-machine states
30 // Types: int8,int16,int32=8,16,32bit integers, unsigned by default
31 int8 ramp_sts
=ramp_idle
;
32 signed int16 motor_pos
= 0; // absolute step number
33 signed int16 pos_inc
=0; // motor_pos increment
34 int16 phase
=0; // ccpPhase[phase_ix]
35 int8 phase_ix
=0; // index to ccpPhase[]
36 int8 phase_inc
; // phase_ix increment
37 int8 run_flg
; // true while motor is running
38 int16 ccpr
; // copy of CCPR1&2
39 int16 c
; // integer delay count
40 int16 step_no
; // progress of move
41 int16 step_down
; // start of down-ramp
42 int16 move
; // total steps to move
43 int16 midpt
; // midpoint of move
44 int32 c32
; // 24.8 fixed point delay count
45 signed int16 denom
; // 4.n+1 in ramp algo
47 // Config data to make CCP1&2 generate quadrature sequence on PHASE pins
48 // Action on CCP match: 8=set+irq; 9=clear+irq
49 int16
const ccpPhase
[] = {0x909, 0x908, 0x808, 0x809}; // 00,01,11,10
51 void current_on(){/* code as needed */} // motor drive current
52 void current_off(){/* code as needed */} // reduce to holding value
54 // compiler-specific ISR declaration
57 { // CCP1 match -> step pulse + IRQ
58 ccpr
+= c
; // next comparator value: add step delay count
61 case ramp_up
: // accel
65 denom
= ((step_no
- move
)<<2)+1;
67 { // even move: repeat last delay before decel
72 // no break: share code for ramp algo
73 case ramp_down
: // decel
74 if (step_no
== move
-1)
75 { // next irq is cleanup (no step)
80 c32
-= (c32
<<1)/denom
; // ramp algorithm
81 // beware confict with foreground code if long div not reentrant
82 c
= (c32
+128)>>8; // round 24.8format->int16
84 { // go to constant speed
86 step_down
= move
- step_no
;
91 case ramp_max
: // constant speed
92 if (step_no
== step_down
)
95 denom
= ((step_no
- move
)<<2)+5;
98 default: // last step: cleanup
100 current_off(); // reduce motor current to holding value
101 disable_interrupts(INT_CCP1
);
102 run_flg
= FALSE
; // move complete
104 } // switch (ramp_sts)
105 if (ramp_sts
!=ramp_idle
)
107 motor_pos
+= pos_inc
;
109 CCPR2H
= CCPR1H
= (ccpr
>> 8); // timer value at next CCP match
110 CCPR2L
= CCPR1L
= (ccpr
& 0xff);
111 if (ramp_sts
!=ramp_last
) // else repeat last action: no step
112 phase_ix
= (phase_ix
+ phase_inc
) & 3;
113 phase
= ccpPhase
[phase_ix
];
114 CCP1CON
= phase
& 0xff; // set CCP action on next match
115 CCP2CON
= phase
>> 8;
116 } // if (ramp_sts != ramp_idle)
117 } // isr_motor_step()
119 void motor_run(short pos_new
)
120 { // set up to drive motor to pos_new (absolute step#)
121 if (pos_new
< motor_pos
) // get direction & #steps
123 move
= motor_pos
-pos_new
;
127 else if (pos_new
!= motor_pos
)
129 move
= pos_new
-motor_pos
;
133 else return; // already there
136 c32
= c
<<8; // keep c in 24.8 fixed-point format for ramp calcs
137 step_no
= 0; // step counter
138 denom
= 1; // 4.n+1, n=0
139 ramp_sts
= ramp_up
; // start ramp state-machine
141 TMR1ON
= 0; // stop timer1;
142 ccpr
= make16(TMR1H
,TMR1L
); // 16bit value of Timer1
143 ccpr
+= 1000; // 1st step + irq 1ms after timer1 restart
144 CCPR2H
= CCPR1H
= (ccpr
>> 8);
145 CCPR2L
= CCPR1L
= (ccpr
& 0xff);
146 phase_ix
= (phase_ix
+ phase_inc
) & 3;
147 phase
= ccpPhase
[phase_ix
];
148 CCP1CON
= phase
& 0xff; // sets action on match
149 CCP2CON
= phase
>> 8;
150 current_on(); // current in motor windings
151 enable_interrupts(INT_CCP1
);
152 TMR1ON
=1; // restart timer1;
158 disable_interrupts(GLOBAL
);
159 disable_interrupts(INT_CCP1
);
160 disable_interrupts(INT_CCP2
);
165 enable_interrupts(GLOBAL
);
172 { // repeat 5 revs forward & back
179 // end of file motor.c