??? 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 |