Your formula works, Henrik - not that should come as a surprise. Knowing how you arrived at that constant in the expression would help me me adjust for different resolutions.
Here's the code I used to test Henrik's formula:
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)
' RA1 -> pin 12 -> trim pot input
' Vss -> pin 14 -> GND
DEFINE OSC 16 ; Set oscillator 16Mhz
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
APFCON0.7 = 0 ; Rx on RC5
BAUDCON.4 = 1 ; Transmit inverted data to the Tx pin
ANSELC = 0 ; Digital only for all PortC pins
TRISC = 0 ; Make all PORTC pins output
TRISA = %00000010 ; Make all pins output except for RA1 (trim pot input)
ANSELA = %00000010 ; Analog on PORTA.1 (AN1) only
FVRCON = 0 ; Fixed Voltage Reference is disabled
ADCON0 = %00000101 ; ADC enabled on AN1 (RA1) only; ADC conversion enabled
PAUSEUS 20 ; wait for the analog switch 'glitch' to die down
ADCON1 = %00110000 ; Left-justified results in 8-bits; Frc as timer
#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
MotorDuty VAR BYTE ; Actual duty cycle for motor
ADCInVal VAR BYTE ; stores ADCIN result read from trim pot
MinDuty CON 100 ; Minimum speed to rotate motor for this application
Main:
gosub Do_ADC
pause 100
GOSUB Map_ADC_Val_to_PWM_Duty
GOTO Main
Do_ADC:
PAUSEUS 50 ' Wait for A/D channel acquisition time
ADCON0.1 = 1 ' Start conversion
WHILE ADCON0.1 = 1 ' Wait for it to complete
WEND
ADCInVal = ADRESH
return
Map_ADC_Val_to_PWM_Duty:
' Arduino Map function to emulate:
' ===============================
' map(value, fromLow, fromHigh, toLow, toHigh)
' long map(long x, long in_min, long in_max, long out_min, long out_max)
' {
' return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
' }
' MotorDuty = (ADCInVal - 0) * (MaxDuty - MinDuty)/(MaxADCVal - 0) + MinDuty
MotorDuty = (ADCInVal ** 39322) + MinDuty ' Same as 100 + ADCInValue * 0.600006 but likely faster than 100+ADCInValue*6/10
#IFDEF USE_LCD_FOR_DEBUG
HSEROUT [LCD_INST, LCD_CLR]
pause 5
' HSEROUT ["ADCInVal=", DEC ADCInVal, " ", 13, 10] ; Send text followed by carriage return and linefeed
HSEROUT ["ADCInVal=", DEC ADCInVal, " ", 13, 10, "MotorDuty=", DEC MotorDuty]
' pause 5
' HSEROUT ["MotorDuty=", DEC MotorDuty, " "] ; Send text followed by carriage return and linefeed
#ENDIF
RETURN
Here's the annoying part - no matter how many searches I do here I can't find the syntax to print on the 2nd line of the LCD. With the above the screen just seems to flicker (which also doesn't make sense - with the ADC method here it usually results in a rock-solid value; in other words, it doesn't change until I actually move the wiper arm. I know it's unrelated to the original post, but any ideas?
Bookmarks