PDA

View Full Version : Please help me figure out the flaw in my logic



keithv
- 5th July 2016, 23:57
I'm trying to make a tap tempo for an echo sound effect. The delay time (length of time between echoes) is set by a digital potentiometer. The user interfaces with the PIC either by an actual analog potentiometer (using the ADC of the PIC16F676) or by tap tempo. Tap tempo is when you press a button to tap out the beat of how fast or slow you want the echoes to occur.

The PIC checks to see first if the analog potentiometer has been moved. If the analog pot has been moved, then it moves the digital pot to mimic the analog pot. If it hasn't been moved, it waits for a button press.

If the button has been pressed, it then begins counting the time between the first button press and the second. When it detects the second button press, it moves the digital potentiometer according to how much time has elapsed between the two button presses. It's using the TMR0 interrupt to count, so the "ticks" variable is always counting whether or not the PIC is waiting for a second button press. The ticks variable is simply reset to zero when it receives its first button press.

The one complicated part about this program is handling the waiting time between when the program begins running and the first button press, and the waiting time between the last time the user used the tap tempo the next time the user uses the tap tempo. I don't want the echo time to change on the first button press, only on the second button press or subsequent button presses that occur before 265 ticks have elapsed.

I tried to handle this by making the ticks variable loop between 256 and 900 once it counts up to 900, so that when the first button press occurs, it knows that if tapcount is greater than 255, then this is the "first" tap and not the second tap.

Everything is working perfectly except I cannot get it to reset ticks on the "first" tap. For some reason it always goes to the movedigipot1 subroutine on the first tap, so when I press the button for the first time, it changes the echo time. It works correctly on the second buttonpress and all subsequent buttonpresses, but it should not move the digipot on the first press.

Any ideas as to what it is I'm doing wrong here?





#config
__CONFIG _CP_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT& _MCLRE_OFF
#endconfig


ADCON1 = %00000000
ANSEL = %00000111
CMCON = %00000111


TRISA = %00001111
TRISC = %00000000


' Set TMR0 to interrupt every 16.384 milliseconds
OPTION_REG = $55 ' Set TMR0 configuration and enable PORTB pullups
INTCON = $a0 ' Enable TMR0 interrupts
On Interrupt Goto tickint

'
' Hardware connection
' ===================
' lug 1 of pot to Vdd, lug 3 of pot to Vss
CS VAR PORTC.0
SCK VAR PORTC.1
SDI VAR PORTC.2
pushbutton var PORTA.3 'tap tempo button
buttonON var PORTC.5 'tap tempo press LED

'
' Variables definition
' ===================
x var byte
xprevious var byte
tapcount var byte
ticks var byte
'
' Software/Hardware initialisation
' ================================
cs = 1 ' disable MCP
PAUSE 100 ' safe settle time
gosub readpot
gosub movedigipot1
xprevious = x
buttonON = 0


main:
tapcount = ticks
gosub readpot
xprevious = x
pause 10
if pushbutton = 0 then
goto tappress
endif
gosub readpot
if xprevious != x then 'check to see if potentiometer has moved. If it has moved...
gosub movedigipot1 'change delay time
endif
pause 10
if tapcount > 900 then 'prevent tapcount/ticks variables from becoming too big while waiting for buttonpress
ticks = 256 '256 is maximum number of ticks between taps before resetting
endif
goto main






tappress:
if tapcount > 255 then 'if more then 255 ticks have elapsed since last tap....
ticks = 0 '.....clear oddtap and return to main
gosub debounce

else
x = tapcount
gosub movedigipot1 'change delay time to tap tempo
ticks = 0 'clear tapcount and return to main
gosub debounce

endif
goto main


debounce:
buttonON = 1
do until pushbutton = 1
pause 10
loop
buttonON = 0
return

movedigipot1: ' subroutine to move 127 step MCP4232 SPI digital potentiometer
CS=0
shiftout SDI, SCK, 1, [010001, x + 7] ' move wiper A
CS=1
return




readpot:
adcin 0,x 'read voltage of "delaytime" pot
x = x/2 ' convert to 7 bit
return


' Interrupt routine to handle each timer tick
Disable ' Disable interrupts during interrupt handler


tickint:
ticks = ticks + 1 ' Count 1/60 of second on every interrupt
endif



tiexit:
INTCON.2 = 0 ' Reset timer interrupt flag
Resume




end

HenrikOlsson
- 6th July 2016, 08:21
For starters, IF tapcount > 900 is never going to be true and ticks = 256 will result in ticks being set to 0 since both tapcount and ticks are declared as BYTEs.

/Henrik.

keithv
- 6th July 2016, 17:35
DUH!!!!!

Thanks, Henrik! I knew it had to be something obvious that I was overlooking. Changed those to word and it works flawlessly now!