Thanks Darrel!
Thanks Darrel!
It works! I think I had a combination of problems - PBP config and a weird breadboard connection issue (I have 4 banks of +/- and when the chip was connected to the far bank the voltage potential between Vdd and Vss wasn't 4.91 volts (my 7805's 5v) - more like 1.93 v. Once I configured the chip with Darrel's code above and move the power connections to one of the other banks I can see the LED fade in and repeat.
Thanks heaps Darrel!
Now that I've got the HPWM stuff sorted (thanks to Darrel) I'm back to the original problem which is converting RBC interrupts to IOC on the 16F1825 - rotating the rotary encoder knob has no effect on MotorRPM. Here's the code I have so far:
Any ideas?Code:DEFINE OSC 20 ' Set oscillator 20Mhz ' *************************************************************** ' Device Fuses ' *************************************************************** ' PIC chip data sheets can be found here: C:\Program Files\Microchip\MPASM Suite #CONFIG __config _CONFIG1, _FOSC_HS & _WDTE_ON & _PWRTE_ON & _MCLRE_OFF & _CP_OFF & _CPD_OFF __config _CONFIG2, _PLLEN_OFF & _STVREN_ON & _BORV_LO & _LVP_OFF #ENDCONFIG ' *************************************************************** ' Initialization ' *************************************************************** DEFINE CCP3_REG PORTA DEFINE CCP3_BIT 2 ;DEFINE CCP4_REG PORTC ;DEFINE CCP4_BIT 1 ANSELA.2 = 0 ' Digital only on CCP3 pin ;ANSELC.1 = 0 ' Digital only on CCP4 pin TRISA = %00000011 ' Make PortA pins 0-1 input for rotary encoder ;TRISC = %00000000 ' Make all pins on PortC output ;INTCON.3 = 1 ' Enable interrupt-on-change (IOCIE) INTCON = %10001000 ' Global int enabled, IOCI enabled, 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 A VAR PortA.1 ' Variable to store encoder's A pin output (RA1) B VAR PortA.0 ' Variable to store encoder's B pin output (RA0) 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 ' *************************************************************** ' SETUP YOUR LCD HERE!!! ' *************************************************************** ;Define LCD_DREG PORTA ;Define LCD_DBIT 0 ;Define LCD_RSREG PORTA ;define LCD_RSBIT 4 ;DEFINE LCD_EREG PORTB ;DEFINE LCD_EBIT 7 ;define LCD_BITS 4 ;define LCD_LINES 2 ;define LCD_COMMANDUS 2000 ;define LCD_DATAUS 50 ' *************************************************************** ' Includes ' *************************************************************** INCLUDE "EE_Vars.PBP" ' Requires MPASM assembler ' Go to "View > Compile and Program Options..." ' On "Assembler" tab, check "Use MPASM" ' (no need to change any of the default settings) ' --> copy file to PBP main folder (i.e. c:\pbp) MotorRPM VAR BYTE : @ EE_var _MotorRPM, BYTE, 100 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:\pbp) ASM INT_LIST macro ; IntSource, Label, Type, ResetFlag? INT_Handler IOC_INT, _Rot_Encoder, PBP, yes endm INT_CREATE ; Creates the interrupt processor ENDASM @ INT_ENABLE IOC_INT ; Interrupt-on-Change interrupt ' Set default values Old_RPM = MotorRPM ;LCDOUT $FE, 1 ;PAUSE 1000 ' Spin up motor to saved value of _MotorRPM IF MotorRPM > 1 THEN FOR I = 0 to MotorRPM pause 30 HPWM 3, I, 20000 ; HPWM 4, I, 20000 NEXT I EndIf Main: IF MotorRPM <> Old_RPM Then Old_RPM = MotorRPM GOSUB motorhpwm @ EE_write_var _MotorRPM ; save the new number to EEPROM EndIF ; LCDOUT $FE, 2, "MotorRPM: ", #MotorRPM, " " ; pause 10 GOTO Main motorhpwm: HPWM 3, MotorRPM, 20000 ; Tried 245 Hz but it made the motor too loud. ; Supposedly, anything above 20kHz is above ; human hearing ; HPWM 4, MotorRPM, 20000 ; Tried 245 Hz but it made the motor too loud. ; Supposedly, anything above 20kHz is above ; human hearing RETURN end ' *************************************************************** ' [RBC - interrupt handler] ' *************************************************************** Rot_Encoder: RotEncDir = (A ^ B) ^ IOCAF.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 IOCAF.0 = 0 ' Clear interrupt flags IOCAF.1 = 0 @ INT_RETURN
Not bad Ross,
All you need is to clear ANSELA bits 0 and 1.
DT
That worked! At least as recognizing the IOC, but I think my logic is wrong - turning the knob one way makes the motor go faster and then slower. The idea is that a CW rotation would make it go faster but turning it CCW would slow it down:
Code:' *************************************************************** ' [RBC - interrupt handler] ' *************************************************************** Rot_Encoder: RotEncDir = (A ^ B) ^ IOCAF.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 IOCAF.0 = 0 ' Clear interrupt flags IOCAF.1 = 0 @ INT_RETURN
If I revert to the Old_Bits/New_Bits logic it now works:
Code:DEFINE OSC 20 ' Set oscillator 20Mhz ' *************************************************************** ' Device Fuses ' *************************************************************** #CONFIG __config _CONFIG1, _FOSC_HS & _WDTE_ON & _PWRTE_ON & _MCLRE_OFF & _CP_OFF & _CPD_OFF __config _CONFIG2, _PLLEN_OFF & _STVREN_ON & _BORV_LO & _LVP_OFF #ENDCONFIG ' *************************************************************** ' Initialization ' *************************************************************** DEFINE CCP3_REG PORTA DEFINE CCP3_BIT 2 ANSELA.0 = 0 ' Digital only on roatary encoder B pin ANSELA.1 = 0 ' Digital only on roatary encoder A pin ANSELA.2 = 0 ' Digital only on CCP3 pin TRISA = %00000011 ' Make PortA pins 0-1 input for rotary encoder INTCON = %10001000 ' Global int enabled, IOCI enabled, 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 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 ' *************************************************************** ' Includes ' *************************************************************** INCLUDE "EE_Vars.PBP" ' Requires MPASM assembler ' Go to "View > Compile and Program Options..." ' On "Assembler" tab, check "Use MPASM" ' (no need to change any of the default settings) ' --> copy file to PBP main folder (i.e. c:\pbp) MotorRPM VAR BYTE : @ EE_var _MotorRPM, BYTE, 100 ;PortNacelleDir VAR BYTE : @ EE_var _PortNacelleDir, BYTE, 0 ' 0 = CCW (inwards) ' 1 = CW (outwards) 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:\pbp) ASM INT_LIST macro ; IntSource, Label, Type, ResetFlag? INT_Handler IOC_INT, _Rot_Encoder, PBP, yes endm INT_CREATE ; Creates the interrupt processor ENDASM @ INT_ENABLE IOC_INT ; Interrupt-on-Change interrupt ' Set default values Old_RPM = MotorRPM Old_Bits = PORTA & (%00000011) ' Spin up motor to saved value of _MotorRPM IF MotorRPM > 1 THEN FOR I = 0 to MotorRPM pause 30 HPWM 3, I, 20000 NEXT I EndIf Main: IF MotorRPM <> Old_RPM Then Old_RPM = MotorRPM GOSUB motorhpwm @ EE_write_var _MotorRPM ; save the new number to EEPROM EndIF GOTO Main motorhpwm: HPWM 3, MotorRPM, 20000 ; Tried 245 Hz but it made the motor too loud. ; Supposedly, anything above 20kHz is above ; human hearing RETURN end ' *************************************************************** ' [IOC - interrupt handler] ' *************************************************************** Rot_Encoder: 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 DoneRotEnc: Old_Bits = New_Bits IOCAF.0 = 0 ' Clear interrupt flags IOCAF.1 = 0 @ INT_RETURN
Yay!
Well, stick with what works for you then.
Cheers.
DT
Bookmarks