| ??? 05/14/08 20:59 Modified: 05/14/08 21:01 Read: times |
#154780 - ADC smoothing assistance... |
Hi,
I'm working on a basic MIDI controller based on an LPC936 and a single pot between +3.2V and ground, with the wiper attached to pin 24 (port 0.3). This works, but with a couple of minor issues. A minor problem is that the values output jump around a fair bit. Reading some threads here suggested using moving averages, which I've implemented (I think), which has improved things enormously. The main problem is that I'm still continually sending MIDI messages that differ by one even when the pot is still. This isn't desirable - I only want to send messages on a "genuine" change. Is there anything I can add to the circuitry to stabilize things a bit? I have a 100nF cap across the pot already. Resolution isn't really a problem on a device like this, as I'm only sending 7 bits of information. I suspect I need to filter out relatively short term changes (blips and spikes), and only send relatively long term changes (intentional control movements). Any suggestions appreciated. ;******************************************************************************
;
; MIDI controller based on Linear pot & LPC935
;
;******************************************************************************
;
;
; Primary controls
$TITLE(BYTE MIDI_1)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;
;
; Variable declarations
$include(C:\asm51\LPC936.inc)
;
; Data memory
slot1 data 30h
slot2 data 31h
slot3 data 32h
slot4 data 33h
average data 34h
old_average data 35h
; Bit memory
AD_Complete Bit 00h
; Equates
slot_pointer equ R1
; Buffers for data storage
ORG 00H
CSEG
LJMP INIT
ORG 0073h
LJMP ADC_INTERRUPT
;##############################################################################
;
; Initialisation routines
;
INIT:
;//////////////////////////////////////////////////////////////////////////////
;
; configure port pins
mov P1M1, #00h ;P1 in QBD mode as we're using TxD
mov P2M1, #00h ;Ditto for P2
;//////////////////////////////////////////////////////////////////////////////
;
; configure uart for BaudRate,8,n,1
mov brgcon, #00h
mov brgr0, #0dch ;This line for 31250 (Midi)
;mov BRGR0, #30h ;This line for 115200 (PC)
mov brgr1, #00h
mov brgcon, #03h
mov scon, #50h ;mode 1
mov pcon, #0c0h ;enable fe bit & smod = 1
;//////////////////////////////////////////////////////////////////////////////
;
; Configure ADC
clr AD_Complete ;Init AD complete flag
mov ADINS, #10h ;Select ADI12 - Port 0.3 Pin 24
mov ADCON1, #45h ;Enable ADCI1, En ADC1, immediate mode
mov ADMODB, #40h ;ADC Clock divisor 3
setb EAD ;enable AD complete interrupt
setb EA
;//////////////////////////////////////////////////////////////////////////////
;
; Init variables
mov slot_pointer, #30h ;Address of slot1
mov a, #00h
;//////////////////////////////////////////////////////////////////////////////
;
; Main loop
;
LOOP1:
orl ADCON1, #01h ;Immediate start A/D conv
jnb AD_Complete, $ ;Wait for interrupt
mov a, AD1DAT0 ;Store ADC reading
clr c
rrc a ;Divide by 2 to convert reading from 0-255 to 0-127
mov @slot_pointer, a ;Store our reading in the current slot
inc slot_pointer ;Increment pointer to the next slot
cjne slot_pointer, #34h, carry_on
mov slot_pointer, #30h
carry_on:
push acc ;save a/d reading
;//////////////////////////////////////////////////////////////////////////////
;
; Calculate moving average
;
mov a, #0h
addc a, slot1
addc a, slot2
addc a, slot3
addc a, slot4 ;Add all 4 values together
rrc a ;First rotate needs to include carry
clr c
rrc a ;div by 4 to get average
mov average, a ;Store the average
clr AD_Complete ;Clear ADC Complete flag
cjne a, old_average, diff ;Are the old and new averages different?
pop acc ;dummy pop
jmp loop1
diff:
mov old_average, a ;Store average as old average
;//////////////////////////////////////////////////////////////////////////////
;
; Send data
;
pop acc ;get a/d reading back
CLR TI
mov sbuf, #0B0h ;MIDI CC
jnb ti, $
CLR TI
mov sbuf, #04h ;CC number 4
jnb ti, $
clr ti
mov sbuf, a ;Current A/D reading
jnb ti, $
mov R7, 0ffh ;Wait for a bit
TimerLoop:
nop
djnz R7, TimerLoop
jmp LOOP1 ; endless loop
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;
; ADC interrupt.
ADC_INTERRUPT:
anl ADCON1, #0F4h ;Clear conversion complete, set to stop mode
setb AD_Complete ;Set ADC Complete flag
RETI
;
; End of ADC interrupt
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
END |



