I'm using a trim pot to control a motor's speed via PWM on a PIC16F1825 but instead of the usual 0-100% duty cycles (corresponding to 0-255 from the ADCIN function with 8-bit resolution) I want to scale the adjustment of the duty to be around a set value. For example, if I determine that the typical duty cycle I want to provide in my application is 75% then I'd like to use the trim pot to adjust the value from 50-100% with 75% being the middle point of the pot. I can do this on an Arduino with the Map function but I can't seem to figure out how to do that similarly with PBP. Any guidance offered would be much appreciated.
Code:#DEFINE USE_LCD_FOR_DEBUG ; comment out for non-debug use ' *************************************************************** ' Pin Connections ' *************************************************************** ' Vdd -> pin 1 -> +5V ' RC4/Tx -> pin 6 -> EUSART transmit (LCD) ' RC2 -> pin 8 -> Port motor direction signal (motor 2) ' RC1/CCP4 -> pin 9 -> Port motor PWM output (motor 2) ' RC0 -> pin 10 -> Stbd motor direction signal (motor 1) ' RA2/CCP3 -> pin 11 -> Stbd motor PWM output (motor 1) ' RA1 -> pin 12 -> trim pot input ' Vss -> pin 14 -> GND DEFINE OSC 16 ; Set oscillator 16Mhz DEFINE ADC_BITS 8 ; Set number of bits in result DEFINE ADC_SAMPLEUS 50 ; Set sampling time in uS (was 5) DEFINE ADC_CLOCK 3 ; Set clock source (3=rc) DEFINE HSER_TXSTA 20h ; Set transmit status and control register DEFINE HSER_BAUD 2400 ; Set baud rate ' *************************************************************** ' Device Fuses ' *************************************************************** #CONFIG __config _CONFIG1, _FOSC_INTOSC & _WDTE_ON & _PWRTE_ON & _MCLRE_OFF & _CP_OFF & _CPD_OFF __config _CONFIG2, _PLLEN_OFF & _STVREN_ON & _BORV_LO & _LVP_OFF #ENDCONFIG ' *************************************************************** ' Initialization ' *************************************************************** OSCCON = %01111000 ; 16MHz internal osc APFCON0.2 = 0 ; Tx on RC4 for LCD display BAUDCON.4 = 1 ; Transmit inverted data to the Tx pin FVRCON = 0 ; Fixed Voltage Reference is disabled ANSELA = %00000010 ; Analog on PORTA.1 (AN1) only ADCON0 = %00000101 ; ADC (analog-to-digital) is enabled on AN1 (RA1) only ADCON1.7 = 0 ; Left-justified results in 8-bits TRISA = %00000010 ; Make all pins output except for RA1 (trim pot input) ANSELC = 0 ; Digital only for all PortC pins TRISC = 0 ; Make all PORTC pins output MOTOR_1_DIR VAR PORTC.0 ; Alias PORTC.0 as "MOTOR_1_DIR" MOTOR_1_PWM VAR PORTA.2 ; Alias PORTA.2 as "MOTOR_1_PWM" MOTOR_2_DIR VAR PORTC.2 ; Alias PORTC.2 as "MOTOR_2_DIR" MOTOR_2_PWM VAR PORTC.1 ; Alias PORTC.1 as "MOTOR_2_PWM" #IFDEF USE_LCD_FOR_DEBUG LCD_INST CON 254 ' instruction LCD_CLR CON 1 ' Clear screen LCD_L1 CON 128 ' LCD line 1 LCD_L2 CON 192 ' LCD line 2 #ENDIF ' *************************************************************** ' Set up registers for PWM on CCP3 & CCP4 ' *************************************************************** CCP3CON = %00001100 ; Use CCP3 in PWM mode CCP4CON = %00001100 ; Use CCP4 in PWM mode ' Use Mister E's PICMultiCalc_1.3.1.exe application (Windows only) ' to determine prescaler and PR2 values for given OSC frequency (e.g. 16Mhz) ' and duty cycle (use 100% to see highest actual value) T2CON = %00000101 ; Timer2 on with 1:4 prescaler PR2 = 62 ; For 16Mhz OSC the desired output freq of 15,873Hz is ; achieved with this PR2 value (8-bit resolution ; with 1:4 prescaler) ; PWM freq must be ~ 16-20kHz to reduce noise PreSpinVal CON 17 ; value to subtract from MinDuty for motor spin up MinDuty CON 75 ; 75 when max duty = 252 (8-bit resolution) ;SpinUpPause CON 17 ; Pause during motor spin up SpinUpPause VAR BYTE ; Pause during motor spin up SpinUpPause = 99 #IFDEF USE_LCD_FOR_DEBUG SpinUpPause = 17 ; Less pause is needed when using LCD #ENDIF MaxDuty VAR WORD ; According to Darrel: ; MaxDuty = (PR2 + 1) * 4 MaxDuty = (PR2 + 1) * 4 ; 252 but with prescaler resolution it's actually 250 DutyVar VAR WORD ; temp variable to store duty variable for CCP3/4 MotorRPM VAR BYTE adcVal VAR BYTE ; stores ADCIN results ' *************************************************************** ' Set default values ' *************************************************************** ADCIN 1, adcVal ' Read channel 1 to adval MotorRPM = adcVal ' (set speed for motors to spin up to) ' TODO: want to use trim pot to adjust motor speed but only within a ' a certain range; midpoint of the pot should be the typical speed ' observed from 'The Tholian Web' and the min/max adjustment accordingly ' (i.e. max is 100% duty cycle but if mid is 75% then min would be 50%) LOW MOTOR_1_DIR ' Set stbd motor (motor 1) to fwd (CW) LOW MOTOR_2_DIR ' Set port motor (motor 2) to fwd (CCW) ' Spin up motors to saved value of _MotorRPM ' (Below a value of 'MinDuty', the motors don't move at all) FOR DutyVar = (MinDuty - PreSpinVal) to MotorRPM 'DutyVar4 = i CCP3CON.4 = DutyVar.0 CCP3CON.5 = DutyVar.1 CCPR3L = DutyVar >> 2 CCP4CON.4 = DutyVar.0 CCP4CON.5 = DutyVar.1 CCPR4L = DutyVar >> 2 pause SpinUpPause #IFDEF USE_LCD_FOR_DEBUG HSEROUT [LCD_INST, LCD_CLR] pause 5 HSEROUT ["RPM=", DEC DutyVar, " ", 13, 10] ' Send text followed by carriage return and linefeed #ENDIF NEXT DutyVar #IFDEF USE_LCD_FOR_DEBUG HSEROUT [LCD_INST, LCD_CLR] pause 5 HSEROUT ["RPM=", DEC MotorRPM, " ", 13, 10] ' Send text followed by carriage return and linefeed #ENDIF Main: ' Check if motor RPM has changed ADCIN 1, adcVal ' Read channel 0 to adval #IFDEF USE_LCD_FOR_DEBUG HSEROUT [LCD_INST, LCD_CLR] pause 5 HSEROUT ["adcVal=", DEC adcVal, " ", 13, 10] ' Send text followed by carriage return and linefeed #ENDIF ' TODO: only change motor speed if reading is changed by +/- 2 since the ' value can change by +/- 1. ' If (adcVal - prevVal) > 1 Then ' gosub ChngMotorHPWM ' EndIf GOTO Main ChngMotorHPWM: DutyVar = MotorRPM CCP3CON.4 = DutyVar.0 CCP3CON.5 = DutyVar.1 CCPR3L = DutyVar >> 2 CCP4CON.4 = DutyVar.0 CCP4CON.5 = DutyVar.1 CCPR4L = DutyVar >> 2 RETURN





Bookmarks