Please help configure 16F616
I'm having trouble getting a 16F616 to work correctly, and I'm pretty sure the problem is with how I am configuring the various registers.
These are my peripheral connections:
A0 - push button (digital input)
A1 - potentiometer (analog input)
A2 - potentiometer (analog input)
A3 - push button (digital input/MCLRE is off)
A4 - relay (digital output)
A5 - SPI connection (digital output)
C0 - LED (digital output)
C1 - SPI connection (digital output)
C2 - SPI connection (digital output)
C3 - relay (digital output)
C4 - LED (digital output)
C5 - relay (digital output)
I am also using the TRM0 interrupt. What am I doing wrong?
Code:
#config
__CONFIG _CP_OFF & _WDTE_OFF & _BOREN_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF
#endconfig
ADCON0 = %00000000
ANSEL = %00000110
CM1CON0 = %00000000
CM2CON0 = %00000000
TRISA = %00001111
TRISC = %00000000
' Set TMR0 to interrupt every 16.384 milliseconds
OPTION_REG = %10000101 ' Set TMR0 configuration
INTCON = %10100000 ' Enable TMR0 interrupts
On Interrupt Goto tickint
Re: Please help configure 16F616
Quote:
#config
__CONFIG _CP_OFF & _WDTE_OFF & _BOREN_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF
#endconfig
is only setting a partial number of config bits for that chip ,the bits that are omitted will revert to their default state , it may cause your [totally unspecified] problem, or it may be in the unposted code or both
this is the device info file from your ?:\PBP3\DEVICE_REFERENCE folder
Code:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; File: PIC16F616.INFO
; Date: 05/18/16
; Generated by melabs File Manager
;
; PICBASIC PRO(tm) Compiler version: 3.0.9
;
; Copyright 2016 microEngineering Labs, Inc. All Rights Reserved
; The content herein is intended to facilitate embedded development using
; PICBASIC PRO Compiler. Reproduction or utilization for other purposes
; is prohibited without written permission from microEngineering Labs, Inc..
;
; microEngineering Labs, Inc.
; 2845 Ore Mill Road STE 4
; Colorado Springs, CO 80904
; 719-520-5323
; fax: 719-520-1867
; http://melabs.com
; [email protected]
;
; Modifications to this file in the \DEVICE_REFERENCE folder will be
; overwritten when you install future upgrades.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;MPASM __CONFIG Directive Options
;
; The PBP default configuration for the PIC16F616 is:
;
; #CONFIG
; __config _INTRC_OSC_NOCLKOUT & _WDT_ON & _MCLRE_ON & _IOSCFS_4MHZ & _CP_OFF
; #ENDCONFIG
;
; You may use the information below to construct your own configuration
; directives for the PIC16F616. Please note that ALL DEFAULT
; CONFIGURATION SETTINGS WILL BE OVERWRITTEN when you include a #CONFIG
; block in your program.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Available __CONFIG labels for PIC16F616:
;
;CONFIG Options
;
; Oscillator Selection bits
; _FOSC_EXTRCCLK ;RC oscillator: CLKOUT function on RA4/OSC2/CLKOUT pin, RC on RA5/OSC1/CLKIN
; _EXTRC_OSC_CLKOUT ;RC oscillator: CLKOUT function on RA4/OSC2/CLKOUT pin, RC on RA5/OSC1/CLKIN
; _EXTRC ;RC oscillator: CLKOUT function on RA4/OSC2/CLKOUT pin, RC on RA5/OSC1/CLKIN
; _FOSC_EXTRCIO ;RCIO oscillator: I/O function on RA4/OSC2/CLKOUT pin, RC on RA5/OSC1/CLKIN
; _EXTRC_OSC_NOCLKOUT ;RCIO oscillator: I/O function on RA4/OSC2/CLKOUT pin, RC on RA5/OSC1/CLKIN
; _EXTRCIO ;RCIO oscillator: I/O function on RA4/OSC2/CLKOUT pin, RC on RA5/OSC1/CLKIN
; _FOSC_INTOSCCLK ;INTOSC oscillator: CLKOUT function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN
; _INTRC_OSC_CLKOUT ;INTOSC oscillator: CLKOUT function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN
; _INTOSC ;INTOSC oscillator: CLKOUT function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN
; _FOSC_INTOSCIO ;INTOSCIO oscillator: I/O function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN
; _INTRC_OSC_NOCLKOUT ;INTOSCIO oscillator: I/O function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN
; _INTOSCIO ;INTOSCIO oscillator: I/O function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN
; _FOSC_EC ;EC: I/O function on RA4/OSC2/CLKOUT pin, CLKIN on RA5/OSC1/CLKIN
; _EC_OSC ;EC: I/O function on RA4/OSC2/CLKOUT pin, CLKIN on RA5/OSC1/CLKIN
; _FOSC_HS ;HS oscillator: High-speed crystal/resonator on RA4/OSC2/CLKOUT and RA5/OSC1/CLKIN
; _HS_OSC ;HS oscillator: High-speed crystal/resonator on RA4/OSC2/CLKOUT and RA5/OSC1/CLKIN
; _FOSC_XT ;XT oscillator: Crystal/resonator on RA4/OSC2/CLKOUT and RA5/OSC1/CLKIN
; _XT_OSC ;XT oscillator: Crystal/resonator on RA4/OSC2/CLKOUT and RA5/OSC1/CLKIN
; _FOSC_LP ;LP oscillator: Low-power crystal on RA4/OSC2/CLKOUT and RA5/OSC1/CLKIN
; _LP_OSC ;LP oscillator: Low-power crystal on RA4/OSC2/CLKOUT and RA5/OSC1/CLKIN
;
; Watchdog Timer Enable bit
; _WDTE_ON ;WDT enabled
; _WDT_ON ;WDT enabled
; _WDTE_OFF ;WDT disabled and can be enabled by SWDTEN bit of the WDTCON register
; _WDT_OFF ;WDT disabled and can be enabled by SWDTEN bit of the WDTCON register
;
; Power-up Timer Enable bit
; _PWRTE_OFF ;PWRT disabled
; _PWRTE_ON ;PWRT enabled
;
; MCLR Pin Function Select bit
; _MCLRE_ON ;MCLR pin function is MCLR
; _MCLRE_OFF ;MCLR pin function is digital input, MCLR internally tied to VDD
;
; Code Protection bit
; _CP_OFF ;Program memory code protection is disabled
; _CP_ON ;Program memory code protection is enabled
;
; Internal Oscillator Frequency Select bit
; _IOSCFS_8MHZ ;8 MHz
; _IOSCFS8 ;8 MHz
; _IOSCFS_4MHZ ;4 MHz
; _IOSCFS4 ;4 MHz
;
; Brown-out Reset Selection bits
; _BOREN_ON ;BOR enabled
; _BOD_ON ;BOR enabled
; _BOR_ON ;BOR enabled
; _BOREN_NSLEEP ;BOR enabled during operation and disabled in Sleep
; _BOD_NSLEEP ;BOR enabled during operation and disabled in Sleep
; _BOR_NSLEEP ;BOR enabled during operation and disabled in Sleep
; _BOREN_OFF ;BOR Disabled
; _BOREN_OFF ;BOR Disabled
; _BOD_OFF ;BOR Disabled
; _BOR_OFF ;BOR Disabled
;
;
;/MPASM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Re: Please help configure 16F616
Quote:
Originally Posted by
richard
is only setting a partial number of config bits for that chip ,the bits that are omitted will revert to their default state , it may cause your [totally unspecified] problem, or it may be in the unposted code or both
this is the device info file from your ?:\PBP3\DEVICE_REFERENCE folder
Thanks for your help, Richard. Yes, that's the device. I'll post the code and a schematic. I was reluctant to because it's pretty long and I'm not sure I can fully explain all the things I'm trying to do.
2 Attachment(s)
Re: Please help configure 16F616
Here's the schematic. PDF is attached as well.
Attachment 8311
Re: Please help configure 16F616
So I've started a new program that does not have all the features I want. I figured it's best to start with the base and then add things once I get those working properly. The schematic is for an echo/delay sound effects unit. Right now, I'm just trying to get the on/off (bypass/trails) switch and the "DELAY TIME" potentiometer to work.
The 2 x PT2399 ICs are the delay chips. They are in series. Their delay time is controlled by the MCP4251 digital potentiometer, which is controlled by the 16F616 (note that the schematic says 16F676, but I am using the 16F616), which interfaces with the user via an analog potentiometer.
The on/off feature has two modes of operation - normal bypass and trails bypass. Normal bypass is just an on/off switch for the effect. When "ON", junction A and B are set high to allow signal to pass through the switching JFETs and junction C is low to block signal. When "OFF", junction A and B are low and junction C is high. "Trails mode" is a feature that allows the echoes to continue repeating after you turn the effect "off", but doesn't allow any new echoes to be created. So when the effect is on, it is the same as when in normal mode, but when the effect is off, junction A is low, cancelling new signal that feeds into the delay chips and the dry side of the crossfader, but junction B and C are high allowing the complete dry signal to pass and any signal that is already in the feedback loop of the delay chip.
The user can toggle between normal and trails modes by pressing and holding the bypass switch for 3 seconds. The tempo LED will blink 5 times to let the user know that the mode has changed. When the effect is on, the bypass LED is high. When it is off, the bypass LED is low.
In the code below, the bypass feature seems to work just fine. It is the delay time control that I'm having problems with. The analog potentiometer does control the delay time as it should. However, it modulates wildly, i.e., the digital potentiometer will not settle into one position once you stop turning the analog potentiometer. I have a feeling the way I've done the config or set the registers has something to do with it.
Code:
#config
__CONFIG _CP_OFF & _WDTE_OFF & _BOREN_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _IOSCFS_4MHZ
#endconfig
ADCON0 = %00000000
ADCON1 = %01100000
ANSEL = %00000110
CM1CON0 = %00000000
CM2CON0 = %00000000
TRISA = %00001111
TRISC = %00000000
'
' Hardware connection
' ===================
CS VAR PORTA.5
SCK VAR PORTC.2
SDI VAR PORTC.1
tempoLED var PORTC.0
tempobutton var PORTA.0
bypassbutton var PORTA.3
bypassLED var PORTC.4
fetA var PORTC.5
fetB var PORTA.4
fetC var PORTC.3
'
' Variables definition
' ===================
w var word ' division toggle switch
x var word ' delay time knob
xprevious var word
z var word
binaryvalue var word
ticks var word
tapcount var word
LEDcounter var word
LEDcounterlimit var word
LEDrate var word
trailsmode var byte
trailsmodecounter var word
LEDon var byte
LEDoff var byte
LEDon = 1
LEDoff = 0
'
' begin in bypass
' ===============
tempoLED = 0
fetA = 0
fetB = 0
fetC = 1
bypassLED = LEDoff
trailsmode = 0
main:
gosub readpot
if bypassBUTTON = 0 then
gosub bypasspress
gosub bypassbuttonrelease
ENDif
pause 100
gosub movedigipot
goto main
bypasspress: ' subroutine that occurs when bypass button is pressed
trailsmodecounter = 0 ' waits to see if you want to switch between normal or trails mode
do until trailsmodecounter = 400
if bypassbutton = 1 then exit
pause 10
trailsmodecounter = trailsmodecounter + 1
loop
if trailsmodecounter = 400 then ' if bypass button was held long enough then change mode
goto trailmodechange
endif
if trailsmode = 1 then ' if bypass button was not held long enough go to sub to toggle between on/off
gosub trailsbypass
elseif trailsmode = 0 then
gosub normalbypass
endif
return
trailmodechange: ' subroutine that occurs when bypass button is held long enough to change between normal or trails mode
if trailsmode = 1 then
trailsmode = 0
elseif trailsmode = 0 then
trailsmode = 1
endif
for z = 1 to 5
tempoLED = 1
pause 100
tempoLED = 0
pause 100
next z
goto main
normalbypass: ' subroutine for normal bypass
if bypassLED = 0 then
fetA = 1
fetB = 1
fetC = 0
bypassLED = LEDon
elseif bypassLED = 1 then
fetA = 0
fetB = 0
fetC = 1
bypassLED = 0
endif
return
trailsbypass: 'subroutine for trails bypass
if bypassLED = 0 then
fetA = 1
fetB = 1
fetC = 0
bypassLED = LEDon
elseif bypassLED = 1 then
fetA = 0
fetB = 1
fetC = 1
bypassLED = LEDoff
endif
return
bypassbuttonrelease: ' debounce subroutine when bypass button is pressed
do until bypassbutton = 1
pause 10
loop
return
movedigipot:
CS=0
shiftout SDI, SCK, 1, [00000000,x] ' move wiper A
shiftout SDI, SCK, 1, [00010000,x] 'move wiper B
CS=1
return
readpot:
adcin 2,x 'read voltage of "delay time" pot
return
end
Re: Please help configure 16F616
Haven't checked anything in detail but I see you're using ADCIN to read the pot but you're not telling the compiler anything about how you want it read.
I suspect you're either sample time is way to low or you have mismatch between the expected number of bits and the left/right justification. I don't know what PBP defaults to when you don't tell it anything with the DEFINEs.
Check the manual for the DEFINEs belonging to ADCIN.
You have x decalred as a WORD which makes me Think you WANT 10 bits from the ADC but the digipot you're using expects 8bits only. From memory I don't know how SHIFTOUT handles WORD variables like in this case. Is it actually shifting out 16 bits or is it only shifting out 8 of the 16bits and if that's the case is it the lower or higher byte.
/Henrik.
Re: Please help configure 16F616
Quote:
Originally Posted by
HenrikOlsson
Haven't checked anything in detail but I see you're using ADCIN to read the pot but you're not telling the compiler anything about how you want it read.
I suspect you're either sample time is way to low or you have mismatch between the expected number of bits and the left/right justification. I don't know what PBP defaults to when you don't tell it anything with the DEFINEs.
Check the manual for the DEFINEs belonging to ADCIN.
You have x decalred as a WORD which makes me Think you WANT 10 bits from the ADC but the digipot you're using expects 8bits only. From memory I don't know how SHIFTOUT handles WORD variables like in this case. Is it actually shifting out 16 bits or is it only shifting out 8 of the 16bits and if that's the case is it the lower or higher byte.
/Henrik.
Thanks, Henrik. I added "define ADC_SAMPLEUS 100" and "define ADC_BITS 8". That didn't seem to help any.
How do my ADCONx and CMxCON0 registers look?
Re: Please help configure 16F616
Hi,
CMxCON looks fine to me, bit 7 = 0 which means the comparator is disabled (which it is by default on this device so no real need to add that but can't hurt).
ANSEL sets RA1 and RA2 to analog, I suppose that's what you want.
ADCON0 looks fine except possibly for bit 7 (I can NEVER remember when to use which setting). It should be in one state when using 8 bits and the other when usign 10 bits.
ADCON1 sets the ADC clock to FOsc/64 which makes it run REALLY slow if the oscillator is 4MHz, try the RC mode instead.
I checked the manual, if not told otherwise SHIFTOUT sends 8 bits even if the variable is of another size. You have mode 1 selected (MSB first) so my question then is if it shifts out the high byte of your word, MSB first or the low byte of your word, MSB first?
I don't know, perhaps you've already done this, but I would make sure I had full control over that pot-chip first and THEN focus on the ADC.
/Henrik.
Re: Please help configure 16F616
I think I've got it working well now. FWIW, tweaking the CONFIG or registers didn't really help much. Neither did setting the ADC sample rate to ridiculously long times. What seems to have fixed it was adding a "buffer" or tolerance limit. Subroutine movedigipot sets xprevious to the ADC reading that was used to last move the digital pot. Subroutine checkpot checks to see if the current ADC reading is within +/- 2.56% of xprevious. If it is, it doesn't allow the digital pot to move. I made it so that x could never equal zero because that causes trouble further down the road. There's no obvious reason at the moment.
Now it's time to implement the interrupt.....ugh.
Code:
#config
__CONFIG _CP_OFF & _WDTE_OFF & _BOREN_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _IOSCFS_8MHZ
#endconfig
ADCON0 = %00000000
ADCON1 = %00110000
ANSEL = %00000110
define ADC_SAMPLEUS 50
define ADC_BITS 8
CM1CON0 = %00000000
CM2CON0 = %00000000
TRISA = %00001111
TRISC = %00000000
'
' Hardware connection
' ===================
CS VAR PORTA.5
SCK VAR PORTC.2
SDI VAR PORTC.1
tempoLED var PORTC.0
tempobutton var PORTA.0
bypassbutton var PORTA.3
bypassLED var PORTC.4
fetA var PORTC.5
fetB var PORTA.4
fetC var PORTC.3
'
' Variables definition
' ===================
w var byte ' division toggle switch
x var byte ' delay time knob
xprevious var byte
z var byte
ticks var word
tapcount var word
LEDcounter var word
LEDcounterlimit var word
LEDrate var word
trailsmode var byte
trailsmodecounter var word
LEDon var byte
LEDoff var byte
LEDon = 1
LEDoff = 0
'
' begin in bypass
' ===============
tempoLED = 0
fetA = 0
fetB = 0
fetC = 1
bypassLED = LEDoff
trailsmode = 0
gosub readpot
gosub movepot
if xprevious <= 0 then
xprevious = 1
endif
main:
if bypassBUTTON = 0 then
gosub bypasspress
gosub bypassbuttonrelease
ENDif
gosub potcheck
goto main
' subroutine that occurs when bypass button is pressed
bypasspress:
trailsmodecounter = 0 ' waits to see if you want to switch between normal or trails mode
do until trailsmodecounter = 400
if bypassbutton = 1 then exit
pause 10
trailsmodecounter = trailsmodecounter + 1
loop
if trailsmodecounter = 400 then
goto trailmodechange
endif
if trailsmode = 1 then
gosub trailsbypass
elseif trailsmode = 0 then
gosub normalbypass
endif
return
trailmodechange: ' subroutine that occurs when bypass button is held long enough to change between normal or trails mode
if trailsmode = 1 then
trailsmode = 0
elseif trailsmode = 0 then
trailsmode = 1
endif
for z = 1 to 5
tempoLED = 1
pause 100
tempoLED = 0
pause 100
next z
goto main
normalbypass: ' subroutine for normal bypass
if bypassLED = 0 then
fetA = 1
fetB = 1
fetC = 0
bypassLED = LEDon
elseif bypassLED = 1 then
fetA = 0
fetB = 0
fetC = 1
bypassLED = 0
endif
return
trailsbypass: 'subroutine for trails bypass
if bypassLED = 0 then
fetA = 1
fetB = 1
fetC = 0
bypassLED = LEDon
elseif bypassLED = 1 then
fetA = 0
fetB = 1
fetC = 1
bypassLED = LEDoff
endif
return
bypassbuttonrelease: ' debounce subroutine when bypass button is pressed
do until bypassbutton = 1
pause 10
loop
return
potcheck:
gosub readpot
if x <= 0 then
x = 1
endif
if x >= xprevious + 5 or x <= xprevious - 5 then
gosub movepot
endif
return
movepot:
CS = 0
shiftout SDI, SCK, 1, [00000000,x]
shiftout SDI, SCK, 1, [00010000,x]
CS = 1
xprevious = x
return
readpot
adcin 2,x
pause 100
return
end
Re: Please help configure 16F616
So I added the interrupt. The idea is to make the tempo LED blink in time with the echoes, so that if you turn the delay time knob clockwise, the echoes go slower and the LED blinks slower, and if you turn the delay time knob counter clockwise, the echoes go faster and the LED blinks faster. It's working pretty well but there is one thing it is doing that is weird, and I can't figure out why.
If you have the delay time pot full turn counter clockwise when you power on, the tempo LED gets stuck. If you turn the delay time knob full turn counter clockwise quickly, the tempo LED gets stuck and does not blink. However, if you turn the delay time knob full turn counter clockwise slowly, it works OK.
I'm sure the problem is in my code. Probably has something to do with the potentiometer debounce, but I can't figure out what I'm doing wrong. I remove the code that pertains to the bypass switching to make it easier to read.
Code:
#config
__CONFIG _CP_OFF & _WDTE_OFF & _BOREN_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _IOSCFS_8MHZ
#endconfig
ADCON0 = %00000000
ADCON1 = %00110000
ANSEL = %00000110
define ADC_SAMPLEUS 50
define ADC_BITS 8
CM1CON0 = %00000000
CM2CON0 = %00000000
TRISA = %00001111
TRISC = %00000000
' Set TMR0 interrupt prescaler to 1:64
OPTION_REG = %10000101 ' Set TMR0 configuration and enable PORTB pullups
INTCON = %10100000 ' Enable TMR0 interrupts
On Interrupt Goto tickint
'
' Hardware connection
' ===================
CS VAR PORTA.5
SCK VAR PORTC.2
SDI VAR PORTC.1
tempoLED var PORTC.0
tempobutton var PORTA.0
bypassbutton var PORTA.3
bypassLED var PORTC.4
fetA var PORTC.5
fetB var PORTA.4
fetC var PORTC.3
'
' Variables definition
' ===================
w var byte ' division toggle switch
x var byte ' delay time knob
xprevious var byte
z var byte
ticks var word
tapcount var word
LEDcounter var word
LEDcounterlimit var word
LEDrate var word
trailsmode var byte
trailsmodecounter var word
LEDon var byte
LEDoff var byte
LEDon = 1
LEDoff = 0
'
' begin in bypass
' ===============
tempoLED = 0
fetA = 0
fetB = 0
fetC = 1
bypassLED = LEDoff
trailsmode = 0
gosub readpot
gosub movepot
if xprevious <= 0 then
xprevious = 1
endif
main:
if LEDcounter > LEDrate then
tempoLED = 1
pause 5
tempoLED = 0
endif
gosub potcheck
goto main
potcheck:
gosub readpot
if x <= 0 then
x = 1
endif
if x >= xprevious + 5 or x <= xprevious - 5 then ' analog potentiometer debounce tolerance
gosub movepot
endif
return
movepot:
CS = 0
shiftout SDI, SCK, 1, [00000000,x]
shiftout SDI, SCK, 1, [00010000,x]
CS = 1
xprevious = x
gosub tempoLEDadjust
return
readpot
adcin 2,x
pause 10
return
tempoLEDadjust: ' compensate for TMR0 not being 1:1 with actual delay time
LEDrate = x + 10
LEDcounterlimit = LEDrate + 1 'counterlimit must always be 1 greater than rate
LEDcounter = 0 ' reset LED counter
return
Disable ' Disable interrupts during interrupt handler
tickint: ' Interrupt routine to handle each timer tick
LEDcounter = LEDcounter + 1 ' add 1 to LEDcounter on every interrupt
if LEDcounter > LEDcounterlimit then ' prevent LEDcounter from overflowing
LEDcounter = 0
endif
tiexit:
INTCON.2 = 0 ' Reset timer interrupt flag
Resume
enable
end
Re: Please help configure 16F616
try something like this
slightly altered for a pic16f1825
Code:
;pic16f1825
#CONFIG
__config _CONFIG1, _FOSC_INTOSC & _CP_OFF & _WDTE_OFF & _PWRTE_ON & _MCLRE_ON & _CLKOUTEN_OFF
__config _CONFIG2, _PLLEN_OFF & _LVP_OFF
#ENDCONFIG
ADCON0 = %00000000
ADCON1 = %00110000
'ANSEL = %00000110 ;pic16f1825
ANSELA = %00000100 ;pot is on porta.2 an2
define ADC_SAMPLEUS 50
define ADC_BITS 8
DEFINE ADC_CLOCK 3
'CM1CON0 = %00000000 ;pic16f1825
'CM2CON0 = %00000000 ;pic16f1825
TRISA = %00001110 ;porta.0 used for debug
TRISC = %00000000
porta.0=1 ;porta.0 used for debug
DEFINE DEBUG_REG PORTA
DEFINE DEBUG_BIT 0 ; if not used for pwr
DEFINE DEBUG_BAUD 9600
DEFINE DEBUG_MODE 0
' Set TMR0 interrupt prescaler to 1:128
OPTION_REG = %10000110 ' Set TMR0 configuration and enable PORTB pullups
INTCON = %10100000 ' Enable TMR0 interrupts
osccon=$68 ;pic16f1825
On Interrupt Goto tickint
'
' Hardware connection
' ===================
CS VAR PORTA.5
SCK VAR PORTC.2
SDI VAR PORTC.1
tempoLED var PORTC.0
' tempobutton var PORTA.0 ;porta.0 used for debug
' bypassbutton var PORTA.3 ;mclr used on pic16f1825
bypassLED var PORTC.4
fetA var PORTC.5
fetB var PORTA.4
fetC var PORTC.3
;pot is on porta.2 an2
'
' Variables definition
' ===================
' w var byte ' division toggle switch
x var byte ' delay time knob
xprevious var byte
' z var byte
' ticks var word
tapcount var word
LEDcounter var word
' LEDcounterlimit var word
LEDrate var byte
' trailsmode var byte
' trailsmodecounter var word
' LEDon var byte
' LEDoff var byte
pause 2000
Debug "Start",13 ,10
'
' begin in bypass
' ===============
tempoLED = 0
fetA = 0
fetB = 0
fetC = 1
bypassLED = 0
' trailsmode = 0
gosub readpot
gosub movepot
if xprevious <= 0 then
xprevious = 1
endif
main:
if (LEDcounter // LEDrate) > (LEDrate>>1) then
tempoLED = 1
else
tempoLED = 0
endif
gosub potcheck
if ! LEDcounter//4==0 then
Debug 13 ,10 , #LEDcounter ,9,#(LEDcounter // LEDrate),9,#LEDrate
endif
goto main
potcheck:
gosub readpot
' if x <= 0 then why ??????????????????????????????????
' x = 1
' endif
;if x >= xprevious + 5 or x <= xprevious - 5 then ' analog potentiometer debounce tolerance
if abs ( xprevious-x) > 4 then
gosub movepot
endif
return
movepot:
CS = 0
shiftout SDI, SCK, 1, [00000000,x]
shiftout SDI, SCK, 1, [00010000,x]
CS = 1
xprevious = x
gosub tempoLEDadjust
return
readpot
adcin 2,x
x = 8 max x ;stop led from shutting down completely
' pause 10 why ??????
return
tempoLEDadjust: ' compensate for TMR0 not being 1:1 with actual delay time
LEDrate = x/2
' LEDcounterlimit = LEDrate + 1 'counterlimit must always be 1 greater than rate
' LEDcounter = 0 ' reset LED counter
return
Disable ' Disable interrupts during interrupt handler
tickint: ' Interrupt routine to handle each timer tick
LEDcounter = LEDcounter + 1 ' add 1 to LEDcounter on every interrupt
' if LEDcounter > LEDcounterlimit then ' prevent LEDcounter from overflowing
' LEDcounter = 0
' endif
tiexit:
INTCON.2 = 0 ' Reset timer interrupt flag
Resume
enable
end
Re: Please help configure 16F616
Richard,
Thanks so much! That helped a lot. I made a few tweaks. I changed x = 8 max x to x = 1 max x in the readpot sub because that gave it a shorter minimum delay time. I added 7 to the LEDrate variable in the LEDtempoadjust sub because it was blinking just a slightly faster than the echoes. Then, of course I added back some of the variables and subs that pertain to the bypass switching.
So now everything works perfectly with the switching, the delay time pot, and the blinking tempo LED. There is still another hurdle for me (and hopefully, this is the last one). The last feature I need to implement is the tap tempo button. This allows the user to tap out the rate of the echoes with the button rather than using the delay time knob. So that when the end user taps out the rate with the tempo button, it overrides the delay time pot....until the pot is actually moved again. That might be why some of the things in my previous code seemed weird.
As it is now in the code below, the checkpot sub is constantly writing to the digital potentiometer. If I use the tap tempo button, it will change the tempo for a split second, but then the analog potentiometer immediately overwrites it. The checkpot sub is only supposed to check and see if the pot has been moved. I thought that by adding the if xprevious != to x and abs (xprevious - x) > 4 statement would do the trick, but it doesn't.
The way your code handles the pot is obviously way more efficient since you've pared what used to take up 1024+ words to down to 682, but it's also a little over my head. How would I make the check pot sub just check the pot to see if the pot has been moved, and move the digital pot only when the pot has been moved?
Code:
#config
__CONFIG _CP_OFF & _WDTE_OFF & _BOREN_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _IOSCFS_8MHZ
#endconfig
ADCON0 = %00000000
ADCON1 = %00110000
ANSEL = %00000110
define ADC_SAMPLEUS 50
define ADC_BITS 8
DEFINE ADC_CLOCK 3
CM1CON0 = %00000000
CM2CON0 = %00000000
TRISA = %00001111
TRISC = %00000000
' Set TMR0 interrupt prescaler to 1:128
OPTION_REG = %10000110 ' Set TMR0 configuration and enable PORTB pullups
INTCON = %10100000 ' Enable TMR0 interrupts
On Interrupt Goto tickint
'
' Hardware connection
' ===================
CS VAR PORTA.5
SCK VAR PORTC.2
SDI VAR PORTC.1
tempoLED var PORTC.0
tempobutton var PORTA.0
bypassbutton var PORTA.3
bypassLED var PORTC.4
fetA var PORTC.5
fetB var PORTA.4
fetC var PORTC.3
;pot is on porta.2 an2
'
' Variables definition
' ===================
w var byte ' division toggle switch
x var byte ' delay time knob
xprevious var byte
z var byte
ticks var word
tapcount var word
LEDcounter var word
LEDrate var byte
trailsmode var byte
trailsmodecounter var word
LEDon var byte
LEDoff var byte
'
' begin in bypass
' ===============
tempoLED = 0
fetA = 0
fetB = 0
fetC = 1
bypassLED = 0
trailsmode = 0
gosub readpot
gosub movepot
main:
tapcount = ticks
if (LEDcounter // LEDrate) > (LEDrate>>1) then
tempoLED = 1
else
tempoLED = 0
endif
gosub potcheck
if bypassBUTTON = 0 then
gosub bypasspress
gosub bypassbuttonrelease
ENDif
if tempobutton = 0 then
goto tempopress
endif
goto main
tempopress: ' subroutine that occurs when tempo button is tapped
if tapcount > 180 then ' if longer than 3 seconds between taps, ignore the previous tap.
ticks = 0
gosub tempobuttonrelease
else
x = tapcount
gosub movepot
ticks = 0
gosub tempobuttonrelease
endif
goto main
tempobuttonrelease: ' debounce subroutine for tempo button
tempoLED = 1
do until tempobutton = 1
pause 10
loop
tempoLED = 0
return
potcheck:
gosub readpot
if xprevious != x and abs (xprevious-x) > 4 then
gosub movepot
endif
return
movepot:
CS = 0
shiftout SDI, SCK, 1, [00000000,x]
shiftout SDI, SCK, 1, [00010000,x]
CS = 1
xprevious = x
gosub tempoLEDadjust
return
readpot
adcin 2,x
x = 1 max x ;stop led from shutting down completely
return
tempoLEDadjust: ' compensate for TMR0 not being 1:1 with actual delay time
LEDrate = (x/2) + 7
return
bypasspress:
trailsmodecounter = 0 ' waits to see if you want to switch between normal or trails mode
do until trailsmodecounter = 400
if bypassbutton = 1 then exit
pause 10
trailsmodecounter = trailsmodecounter + 1
loop
if trailsmodecounter = 400 then
goto trailmodechange
endif
if trailsmode = 1 then
gosub trailsbypass
elseif trailsmode = 0 then
gosub normalbypass
endif
return
trailmodechange: ' subroutine that occurs when bypass button is held long enough to change between normal or trails mode
if trailsmode = 1 then
trailsmode = 0
elseif trailsmode = 0 then
trailsmode = 1
endif
for z = 1 to 5
tempoLED = 1
pause 100
tempoLED = 0
pause 100
next z
goto main
normalbypass: ' subroutine for normal bypass
if bypassLED = 0 then
fetA = 1
fetB = 1
fetC = 0
bypassLED = LEDon
elseif bypassLED = 1 then
fetA = 0
fetB = 0
fetC = 1
bypassLED = 0
endif
return
trailsbypass: 'subroutine for trails bypass
if bypassLED = 0 then
fetA = 1
fetB = 1
fetC = 0
bypassLED = LEDon
elseif bypassLED = 1 then
fetA = 0
fetB = 1
fetC = 1
bypassLED = LEDoff
endif
return
bypassbuttonrelease: ' debounce subroutine when bypass button is pressed
do until bypassbutton = 1
pause 10
loop
return
Disable ' Disable interrupts during interrupt handler
tickint: ' Interrupt routine to handle each timer tick
LEDcounter = LEDcounter + 1 ' add 1 to LEDcounter on every interrupt
ticks = ticks + 1
if ticks > 300 then 'prevent overflow when long periods of time pass between taps
ticks = 240
endif
tiexit:
INTCON.2 = 0 ' Reset timer interrupt flag
Resume
enable
end
Re: Please help configure 16F616
I realized what the problem was. xprevious =x was in the movepot subroutine, so anytime either the analog pot or tempo button changed x, xprevious would change.
This seems to have fixed it.
Code:
#config
__CONFIG _CP_OFF & _WDTE_OFF & _BOREN_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _IOSCFS_8MHZ
#endconfig
ADCON0 = %00000000
ADCON1 = %00110000
ANSEL = %00000110
define ADC_SAMPLEUS 50
define ADC_BITS 8
DEFINE ADC_CLOCK 3
CM1CON0 = %00000000
CM2CON0 = %00000000
TRISA = %00001111
TRISC = %00000000
' Set TMR0 interrupt prescaler to 1:128
OPTION_REG = %10000110 ' Set TMR0 configuration and enable PORTB pullups
INTCON = %10100000 ' Enable TMR0 interrupts
On Interrupt Goto tickint
'
' Hardware connection
' ===================
CS VAR PORTA.5
SCK VAR PORTC.2
SDI VAR PORTC.1
tempoLED var PORTC.0
tempobutton var PORTA.0
bypassbutton var PORTA.3
bypassLED var PORTC.4
fetA var PORTC.5
fetB var PORTA.4
fetC var PORTC.3
;pot is on porta.2 an2
'
' Variables definition
' ===================
w var byte ' division toggle switch
x var byte ' delay time knob
xprevious var byte
z var byte
ticks var word
tapcount var word
LEDcounter var word
LEDrate var byte
trailsmode var byte
trailsmodecounter var word
LEDon var byte
LEDoff var byte
override var bit
analogpot var bit
footswitch var bit
analogpot = 1
footswitch = 0
'
' begin in bypass
' ===============
tempoLED = 0
fetA = 0
fetB = 0
fetC = 1
bypassLED = 0
trailsmode = 0
gosub readpot
gosub movepot
pause 100
main:
tapcount = ticks
gosub potcheck
if LEDcounter < 1 then
tempoLED = 1
else
tempoLED = 0
endif
if bypassBUTTON = 0 then
gosub bypasspress
gosub bypassbuttonrelease
ENDif
if tempobutton = 0 then
goto tempopress
endif
goto main
potcheck:
gosub readpot
if abs (xprevious-x) > 4 then
override = analogpot
gosub movepot
endif
return
tempopress: ' subroutine that occurs when tempo button is tapped
if tapcount > 180 then ' if longer than 3 seconds between taps, ignore the previous tap.
ticks = 0
gosub tempobuttonrelease
else
x = tapcount + 10
override = footswitch
gosub movepot
ticks = 0
gosub tempobuttonrelease
endif
goto main
tempobuttonrelease: ' debounce subroutine for tempo button
tempoLED = 1
do until tempobutton = 1
pause 10
loop
tempoLED = 0
return
movepot:
CS = 0
shiftout SDI, SCK, 1, [00000000,x]
shiftout SDI, SCK, 1, [00010000,x]
CS = 1
if override = analogpot then
xprevious = x
endif
gosub tempoLEDadjust
return
readpot
adcin 2,x
x = 1 max x ;stop led from shutting down completely
return
tempoLEDadjust: ' compensate for TMR0 not being 1:1 with actual delay time
LEDrate = (x/2) + 6
return
bypasspress:
trailsmodecounter = 0 ' waits to see if you want to switch between normal or trails mode
do until trailsmodecounter = 400
if bypassbutton = 1 then exit
pause 10
trailsmodecounter = trailsmodecounter + 1
loop
if trailsmodecounter = 400 then
goto trailmodechange
endif
if trailsmode = 1 then
gosub trailsbypass
elseif trailsmode = 0 then
gosub normalbypass
endif
return
trailmodechange: ' subroutine that occurs when bypass button is held long enough to change between normal or trails mode
if trailsmode = 1 then
trailsmode = 0
elseif trailsmode = 0 then
trailsmode = 1
endif
for z = 1 to 5
tempoLED = 1
pause 100
tempoLED = 0
pause 100
next z
goto main
normalbypass: ' subroutine for normal bypass
if bypassLED = 0 then
fetA = 1
fetB = 1
fetC = 0
bypassLED = LEDon
elseif bypassLED = 1 then
fetA = 0
fetB = 0
fetC = 1
bypassLED = 0
endif
return
trailsbypass: 'subroutine for trails bypass
if bypassLED = 0 then
fetA = 1
fetB = 1
fetC = 0
bypassLED = LEDon
elseif bypassLED = 1 then
fetA = 0
fetB = 1
fetC = 1
bypassLED = LEDoff
endif
return
bypassbuttonrelease: ' debounce subroutine when bypass button is pressed
do until bypassbutton = 1
pause 10
loop
return
Disable ' Disable interrupts during interrupt handler
tickint: ' Interrupt routine to handle each timer tick
LEDcounter = LEDcounter + 1 ' add 1 to LEDcounter on every interrupt
if LEDcounter > LEDrate then
LEDcounter = 0
endif
ticks = ticks + 1
if ticks > 300 then 'prevent overflow when long periods of time pass between taps
ticks = 240
endif
tiexit:
INTCON.2 = 0 ' Reset timer interrupt flag
Resume
enable
end
Now I just need to make some fine adjustments so that the tempopress subroutine changes x so that the echoes are actually in time with the tempo that is tapped out. And I also need to add the division toggle switch. That's pretty simple though. It just divides x in half for double time or thirds for triplets.
Re: Please help configure 16F616
I'm having one weird problem now that I can't figure out. The tap tempo works well except when the delay time pot is at about 20% of its rotation or less. If it's at 20% or less, the tempo button still works, but it makes the echoes go too fast....about 4 echoes for every one tap. If I have the delay time pot at 25% or higher, the tempo button works as expected with a 1 to 1 ratio.
The way it's supposed to work is 2 is added to the tapcount variable upon each interrupt. It's supposed to be irrelevant as to whether or not you tap twice, 3, 4, or however many times. It just looks at the interval between the last to taps. It determines what the "first" tap is by looking at how long it was since your last tap. At the beginning of the tempopress subroutine, if it's been longer than 3 seconds, it assumes that this is your first tap, so it clears the tapcount variable. The interrupt then starts counting by adding 2 to the tapcount variable. On the second tap, it looks at the tapcount variable and uses that to set the delay time in the movepot subroutine. It then clears the tapcount variable and starts again.
I can't figure out why the delay time pot is having an effect on this only when it is below a certain threshold.
Re: Please help configure 16F616
I figured out what my biggest problem was. It was a hardware problem. It was SW3. The on-off-on toggle switch. I should have had the pole connected to a voltage divide. For some reason, it worked the way it was supposed to until the pot was below 20%. I don't know why the position of the pot made a difference, but it did. Anyhow....added a voltage divide and it works perfectly.
The missing voltage divide aside, the pot still needed to be "debounced". Thank you so much, Richard for the massive improvement you made to the way the ADC reads the pot. Thanks for your help too, Henrik.
Re: Please help configure 16F616