Code:
'****************************************************************
'* Name : Nacelle_Motors_16F1825_32Mhz_Int_SN754410.pbp *
'* Author : Ross A. Waddell *
'* Notice : Copyright (c) 2012 *
'* : All Rights Reserved *
'* Date : 10/20/2012 *
'* Version : 2.0 *
'* Notes : Motor control for TOS E engines using SN754110 *
'* : motor driver, plus steady-on amber lights *
'****************************************************************
' ***************************************************************
' TODOs
' ***************************************************************
' 1. Need to calibrate motor RPMs so they spin at the same rate
' -> Separate "MotorRPM" EEPROM variables?
' 2. Add power isolation as blinking running lights seem to increase electrical noise
DEFINE OSC 32 ' Set oscillator 32 Mhz
' ***************************************************************
' Device Fuses
' ***************************************************************
#CONFIG
__config _CONFIG1, _FOSC_INTOSC & _WDTE_ON & _PWRTE_ON & _MCLRE_OFF & _CP_OFF & _CPD_OFF
__config _CONFIG2, _PLLEN_ON & _STVREN_ON & _BORV_LO & _LVP_OFF
#ENDCONFIG
' ***************************************************************
' Initialization
' ***************************************************************
OSCCON = %11110000 ' 32 MHz internal osc (8 Mhz with 4x SPLLEN enabled)
pause 100 ' As advised by Darrel Taylor for EEPROM issue
DEFINE CCP2_REG PORTC ' Only need to define CCP2 pin as there are 2
DEFINE CCP2_BIT 3 ' possible choices: RA5 or RC3
PORTA = 0 ' Set initial value of PORTA to 0
PORTC = 0 ' Set initial value of PORTC to 0
;ADCON0 = 7
;ADCON1 = 7
ANSELA.0 = 0 ' Digital only on rotary encoder B pin
ANSELA.1 = 0 ' Digital only on rotary encoder A pin
ANSELA.2 = 0 ' Digital only on rotary encoder's button
ANSELC.0 = 0 ' Digital only on Stbd motor direction signal (Motor 1)
ANSELC.1 = 0 ' Digital only on Port motor direction signal (Motor 2)
ANSELC.2 = 0 ' Digital only on LED_0 pin (steady-on amber lights)
ANSELC.3 = 0 ' Digital only on CCP2 pin (Port engine)
ANSELC.5 = 0 ' Digital only on CCP1 pin (Stbd engine)
TRISA = %00000111 ' Make PORTA pins 0-2 input for rotary encoder
TRISC = %00000000 ' Make all PORTC pins output
' The INTEDG bit of the OPTION_REG register determines on which edge the
' interrupt will occur. When the INTEDG bit is set, the rising edge will
' cause the interrupt. When the INTEDG bit is clear, the falling edge will
' cause the interrupt.
OPTION_REG.6 = 1 ' 1=Rising edge (default) or button "PRESS";
' 0=Falling edge or button "RELEASE"
Old_Bits VAR BYTE
New_Bits VAR BYTE
RotEncDir VAR BIT ' 1=CW, 0=CCW
' Rot Enc pin A connected to PortA.1;
' Rot Enc pin B connected to PortA.0
Old_RPM VAR BYTE
I VAR BYTE
LED_0 VAR PORTC.2 ' Alias PORTC.2 as "LED_0"
MOTOR_1_DIR VAR PORTC.0 ' Alias PORTC.0 as "MOTOR_1_DIR"
MOTOR_1_PWM VAR PORTC.5 ' Alias PORTC.5 as "MOTOR_1_PWM"
MOTOR_2_DIR VAR PORTC.1 ' Alias PORTC.1 as "MOTOR_2_DIR"
MOTOR_2_PWM VAR PORTC.3 ' Alias PORTC.3 as "MOTOR_2_PWM"
ButtonPress VAR PORTA.2 ' Alias PORTA.2 as "ButtonPress"
TimeCnt VAR Word
LOW LED_0
LOW MOTOR_1_DIR
LOW MOTOR_1_PWM
LOW MOTOR_2_DIR
LOW MOTOR_2_PWM
' ***************************************************************
' Pin Connections
' ***************************************************************
' RA0 -> B pin of rotary encoder
' RA1 -> A pin of rotary encoder
' RA2 -> Button switch pin of rotary encoder
' RC0 -> Stbd motor direction signal (motor 1)
' RC1 -> Port motor direction signal (motor 2)
' RC2 -> Steady-on LED
' RC3/CCP2 -> Port motor PWM output (motor 2)
' RC5/CCP1 -> Stbd motor PWM output (motor 1)
' ***************************************************************
' Includes
' ***************************************************************
INCLUDE "DT_INTS-14.bas" ' Base Interrupt System
INCLUDE "ReEnterPBP.bas" ' Include if using PBP interrupts
' --> copy both files to PBP main folder
' (i.e. c:\pbp3)
INCLUDE "EE_Vars.PBP" ' copy file to PBP main folder (i.e. c:\pbp3)
' ***************************************************************
' EEPROM Variables
' ***************************************************************
MotorRPM VAR BYTE : @ EE_var _MotorRPM, BYTE, 150
PortEngDir VAR BYTE : @ EE_var _PortEngDir, BYTE, 0
' ***************************************************************
' ASM Interrupt Definitions
' ***************************************************************
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler IOC_INT, _RotEncAdjust, PBP, yes
; INT_Handler INT_INT, _RotEncBtnPress, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM
' ***************************************************************
' Set default values
' ***************************************************************
Old_RPM = MotorRPM
Old_Bits = PORTA & (%00000011)
HIGH LED_0 ' Turn on steady-on LEDs
LOW MOTOR_1_DIR ' Set stbd motor (motor 1) to fwd (CW)
' (always spins in the same direction)
IF PortEngDir = 0 THEN
LOW MOTOR_2_DIR ' Set port motor (motor 2) to fwd (CCW)
ELSE
HIGH MOTOR_2_DIR ' Set port motor (motor 2) to rev (CW)
ENDIF
' Spin up motors to saved value of _MotorRPM
' (Below a cycle of 66, the motors don't move at all)
IF MotorRPM > 66 THEN
FOR I = 65 to MotorRPM
pause 30
HPWM 1, I, 20000 ' Stbd engine (CCP1)
IF PortEngDir = 0 THEN
HPWM 2, I, 20000 ' Port engine (CCP2), fwd (CCW)
ELSE
HPWM 2, (255-I), 20000 ' Port engine (CCP2), rev (CW)
ENDIF
NEXT I
EndIf
HPWM 1, MotorRPM, 20000 ' Stbd engine (CCP1)
IF PortEngDir = 0 THEN
HPWM 2, MotorRPM, 20000 ' Port engine (CCP2)
ELSE
HPWM 2, (255-MotorRPM), 20000 ' Port engine (CCP2)
ENDIF
' Enable interrupts on RPM control now that motors are fully spun up
;INTCON = %10011000 ' Global int enabled, INTE enabled, IOCI enabled,
' INTF flag bit 0 clr, IOCI flag bit 0 clr
INTCON = %10001000 ' Global int enabled, IOCI enabled,
' INTF flag bit 0 clr, IOCI flag bit 0 clr
IOCAP.0 = 1 ' Enable positive (rising edge) change
IOCAP.1 = 1 ' Enable positive (rising edge) change
IOCAN.0 = 1 ' Enable negative (falling edge) change
IOCAN.1 = 1 ' Enable negative (falling edge) change
IOCAF.0 = 0 ' Clear interupt-on-change flag
IOCAF.1 = 0 ' Clear interupt-on-change flag
;INTCON.1 = 0 ' Clear RA2/INT External Interrupt Flag
@ INT_ENABLE IOC_INT ; Interrupt-on-Change interrupt
;@ INT_ENABLE INT_INT ; INT/Ext Interrupt
Main:
' Check if motor RPM has changed
IF MotorRPM <> Old_RPM Then
Old_RPM = MotorRPM
GOSUB ChngMotorHPWM
EndIF
TimeCnt = 0
While ButtonPress = 0
TimeCnt = TimeCnt + 1
Pause 10
If TimeCnt > 500 Then BtnAction
Wend
BtnAction:
If TimeCnt > 0 and TimeCnt < 200 Then
PortEngDir = PortEngDir + 1
If PortEngDir > 1 Then PortEngDir = 0
@ EE_write_var _PortEngDir ; save the new number to EEPROM
GOSUB ReversePortEng
ElseIf TimeCnt >= 200 Then
@ EE_write_default _MotorRPM
EndIf
GOTO Main
ReversePortEng:
LOW MOTOR_2_DIR ' Electrically stop motor 2
LOW MOTOR_2_PWM
pause 100
IF PortEngDir = 0 THEN
LOW MOTOR_2_DIR ' Set port motor (motor 2) to fwd (CCW)
ELSE
HIGH MOTOR_2_DIR ' Set port motor (motor 2) to rev (CW)
ENDIF
IF PortEngDir = 0 THEN
HPWM 2, MotorRPM, 20000 ' Port engine (motor 2), fwd (CCW)
ELSE
HPWM 2, (255-MotorRPM), 20000 ' Port engine (motor 2), rev (CW)
ENDIF
RETURN
ChngMotorHPWM:
HPWM 1, MotorRPM, 20000 ' Stbd engine (motor 1)
; Tried 245 Hz but it made the motor too loud.
; Supposedly, anything above 20kHz is above
; human hearing
IF PortEngDir = 0 THEN
HPWM 2, MotorRPM, 20000 ' Port engine (motor 2), fwd (CCW)
ELSE
HPWM 2, (255-MotorRPM), 20000 ' Port engine (motor 2), rev (CW)
ENDIF
RETURN
end
' ***************************************************************
' [IOC - interrupt handler]
' ***************************************************************
RotEncAdjust:
New_Bits = PORTA & (%00000011)
IF (New_Bits & %00000011) = (Old_Bits & %00000011) Then DoneRotEnc
RotEncDir = New_Bits.1 ^ Old_Bits.0
IF RotEncDir = 1 Then
; CW rotation - increase speed but only to a max of 255
IF MotorRPM < 255 then MotorRPM = MotorRPM + 1
Else
' CCW rotation - decrease speed to a min of 0
IF MotorRPM > 0 Then MotorRPM = MotorRPM - 1
EndIF
@ EE_write_var _MotorRPM ; save the new number to EEPROM
DoneRotEnc:
Old_Bits = New_Bits
IOCAF.0 = 0 ' Clear interrupt flags
IOCAF.1 = 0
@ INT_RETURN
' ***************************************************************
' [INT - interrupt handler]
' ***************************************************************
;RotEncBtnPress:
' Restore MotorRPM to default value
;@ EE_write_default _MotorRPM
; INTCON.1 = 0 ' Clear RA2/INT External Interrupt Flag
;@ INT_RETURN
Bookmarks