PDA

View Full Version : AtoD - first attempts



malc-c
- 29th December 2006, 13:05
Guys, I'm getting a little out of my depth and would like some feedback here.

From my previous posts some of you (two Steves !) will remember that I'm playing with a 16F873 to come up with a better version of some disco lights based on an 16F628a. I'm now looking at hooking up the audio output from a CD player but I've never played with A - D conversion and not sure what I need to do. I've used the example varibles in the manual so I have



B0 VAR BYTE
ADCIN 0, B0 ' Read channel 0 to B0


I want to use RA0/AN0 (pin 2) for the input, and I've used a win-scope to obtain the voltage levels that the CD player is kicking out (see attached). How do I go about calibrating the A-D so that I can display the values of B0 on port B relative to the music level ?

EDIT:

I tried the obvious:


ADCIN 0, B0 ' Read channel 0 to B0
Portb=B0
RETURN


However even with no music present the first 5 bits of Port B seem to display a random pattern, rather than just PB0 being lit. There is however a noticable change of state when a music signla present, I get more LEDs light up and it extends over the full port.. but it's not seqentially lighting them up like a VU meter.

EDIT:
Sorry should of added that I copied the settings form the manual too


DEFINE ADC_BITS 8 ' Set number of bits in result
DEFINE ADC_CLOCK 3 ' Set clock source (rc = 3)
DEFINE ADC_SAMPLEUS 50 ' Set sampling time in microseconds


And have the following config:


ADCON1=$07
CMCON = 7 ' Digital inputs
CCP1CON = 0 ' PWM off
TRISA=%11111111 'set PORTA as all input

skimask
- 29th December 2006, 15:21
Guys, I'm getting a little out of my depth and would like some feedback here.

From my previous posts some of you (two Steves !) will remember that I'm playing with a 16F873 to come up with a better version of some disco lights based on an 16F628a. I'm now looking at hooking up the audio output from a CD player but I've never played with A - D conversion and not sure what I need to do. I've used the example varibles in the manual so I have

[/code]



And it's probably not going to act like a VU meter. I've tried this before. I was semi-successful in 2 ways.

The first way, I got around it by looking for and averaging the peaks of what I was sampling on the A/D port over X time. It's either that or you feed the audio in thru a diode into a capacitor across the A/D port with a small-ish resistor to ground (I wish I could do ASCII graphics). The audio 'charges' up the cap, the resistor discharges it slowly-ish (think R/C time constant), the diode keeps the cap from messing with the input signal and only let's positive voltage thru even though you do lose the .25v or .7v due to forward voltage drop (or you could use an opamp as a follower). Then you sample the A/D input.

The 2nd method was using actual FFT routines on a PIC18F4620, 128 bands per channel updated at about 13hz. Ya baby! That was neat to look at on a 128x64 graphic LCD! But the FFT routines cost me some $$$. Check my site (www.srt.com/~jdgrotte) to see what came out at the PICAlyzer link.

But just sampling the A/D of an audio input won't get you anywhere. It would be just like looking at audio on an o'scope. Doesn't look like anything useful...

malc-c
- 29th December 2006, 16:33
Yeah I 'spose when you think of it I would need to rectify the AC signal in some way so that there is something for the pic to read.

I'll try the diode / capacitor thing and see what happens.. thanks for the input

skimask
- 29th December 2006, 17:51
Yeah I 'spose when you think of it I would need to rectify the AC signal in some way so that there is something for the pic to read.

I'll try the diode / capacitor thing and see what happens.. thanks for the input

Oh it works pretty good, once you get the caps/resistors all set up to the right numbers. I don't remember the values that I used, but I do know I ended up buffering the input with an opamp before going into the diode. I've got a decent pdf of what I did around somewhere. If I find it, I'll link it.

charudatt
- 22nd January 2008, 12:43
Hello Skimask / Malc-c,

I also want to pursue this project and was wondering, what was the overall results of Malc-c project.

In abscence of some design guidelines (Schematic) from Malc-c side towards the project, I would like to share my idea.
1. I also wish to make a dancing light controller with musical input on a ADC port or a PIC 16F72 / 16F873A to make PORTB dance to the music. REALTIME
2. I am also interested in digitizing the pattern of the music , so that it could be replayed without any music source. STORE/PLAY

I would first like to work upon the REALTIME idea and then jump over to the STORE/PLAY version.

Could anyone please guide me thru this.

regards

p.s. Wonder it this thread is still alive

Acetronics2
- 22nd January 2008, 13:06
[QUOTE=malc-c;30210] Guys, I'm getting a little out of my depth and would like some feedback here.

> I really thought you'd left it aside ... too bad !

EDIT:

I tried the obvious:


ADCIN 0, B0 ' Read channel 0 to B0
Portb=B0
RETURN


> What about Trying this



ADCIN 0, B0 ' Read channel 0 to B0
Portb= DCD B0
RETURN


> AND Using ONLY ADC Channel 0 as an input ...

However even with no music present the first 5 bits of Port B seem to display a random pattern, rather than just PB0 being lit.

> Did you think to place a pulldown resistor at the Channel 0 input ( I suspect a capacitive input coupling ...)


by the way ... a scheme could be useful !!! ( as we're used to your designs ... )

a Happy new year to you ...

Alain

charudatt
- 22nd January 2008, 19:04
Nice to see the thread revive.

Any inputs on the second idea. Storing the sample and playing it back. I wonder if its as simple as reading the analog input over a period of time and saving it in a eeprom and then just playing it back !

regards

peterdeco1
- 22nd January 2008, 19:18
Here is a very crude circuit that I made for a portable cassette player to make LED's "dance" with the music. I tapped off a low level audio signal in the preamp circuit. Maybe a WRITE command to eeprom during ADC readings would allow you to store it in a PIC with eeprom. I used an 8-pin 12F675.

ANSEL = 0 'all inputs digital
CMCON = 7 'comparators off
DEFINE OSCCAL_1K 1 ' Set OSCCAL for 1K device
@ DEVICE MCLR_OFF, INTRC_OSC, WDT_ON, BOD_ON, PWRT_ON, PROTECT_ON
TRISIO = %00000001
GPIO = 0 'all outputs low
X VAR BYTE


START:
ADCIN 0, X
IF X > 2 Then High GPIO.4 : Pause 100 'on leds
IF X < 2 Then Low GPIO.4 : Pause 5 'low leds
GoTo START

charudatt
- 23rd January 2008, 02:27
thanks peterdeco,

Yes i looked upon your code in the last thread, and its for a single led. But I want PORTB to dance to the music.

I have a slight confusion in my mind, regarding the ADC Val that we sample. Does it mean that we are actually making a VU meter. How do we sample different frequencies ?

No Clue.I

skimask
- 23rd January 2008, 02:33
thanks peterdeco,

Yes i looked upon your code in the last thread, and its for a single led. But I want PORTB to dance to the music.

I have a slight confusion in my mind, regarding the ADC Val that we sample. Does it mean that we are actually making a VU meter. How do we sample different frequencies ?

No Clue.I

You don't sample different frequencies with an ADC, at least not without banks of wide- or narrow- band filters. All you sample with an ADC is analog values.

You can sample a segment of ADC values, do some complex math on it and get a spectrum display out of it (see Post #2), but it isn't easy, it's time/memory consuming with a PIC18F. There are a few graphic equalizer chips out there that'll split the audio into bands of frequencies which you could then sample individually, but again, it's not easy. I guess it depends on how many 'bands of frequencies' you're talking about...

malc-c
- 23rd January 2008, 19:08
dupliaceted post due to login errors / time out !

malc-c
- 23rd January 2008, 19:13
Struth - was it that long ago when I was messing about with this project !

Basically I ended up using a low pass filter to trigger an NE555 in mono stable mode. Its output was then fed to the PIC which ran the pre-set pattern at what ever speed the "gate" was set to. This video shows one of the first versions which used op-ams in the filter

http://www.micro-heli.co.uk/discolights2.avi

This then evolved into this,

http://www.micro-heli.co.uk/LMV.jpg

which used a simplified (but now looking at the two videos, less responsive) filtering, as can be seen in the video below

http://www.micro-heli.co.uk/lmv.avi

As far as I can tell this is the code for the PIC using the schematic above (I've had to dig it out of an archive backup so can't be 100% sure its the final version)



'************************************************* ***************
'* Name : Lightmaster V *
'* Author : M.Crabbe *
'* Notice : Copyright (c) 2007 M. Crabbe *
'* : All Rights Reserved *
'* Date : 01/01/2007 *
'* Version : 1.0 *
'* Notes : *
'* : *
'************************************************* ***************


;*************** Set up LCD *****************

DEFINE LCD_DREG PORTC ' LCD data port
DEFINE LCD_DBIT 0 ' LCD data starting bit 0 or 4
DEFINE LCD_RSREG PORTC ' LCD register select port
DEFINE LCD_RSBIT 4 ' LCD register select bit
DEFINE LCD_EREG PORTC ' LCD enable port
DEFINE LCD_EBIT 5 ' LCD enable bit
DEFINE LCD_BITS 4 ' LCD bus size 4 or 8
DEFINE LCD_LINES 2 ' Number lines on LCD
DEFINE LCD_COMMANDUS 2000 ' Command delay time in us
DEFINE LCD_DATAUS 50 ' Data delay time in us

;************* set up pattern data **********

Patt1 DATA 16,1,2,4,8,16,32,64,128,128,64,32,16,8,4,2,1
Patt2 DATA 8,129,66,36,24,24,36,66,129
Patt3 DATA 16,1,3,2,6,4,12,8,24,16,48,32,96,64,192,128,0
Patt4 DATA 16,1,128,2,64,4,32,8,16,8,32,4,64,2,128,1,0
Patt5 DATA 12,24,60,126,255,231,195,129,0,129,195,231,255
Patt6 DATA 13,1,2,4,8,17,34,68,136,16,32,64,128,0
Patt7 DATA 8,128,64,32,16,8,4,2,1

;************* set up PIC ********************

ADCON1=$07 ' PORTA all disgital
CMCON = 7 ' Digital inputs
CCP1CON = 0 ' PWM off
TRISA=%11111111 ' set PORTA as all input
TRISB=%00000000 ' set PORTB as all output
TRISC=%00000000 ' set PORTC as all output
PORTB=0
audio var PORTA.0 ;input from beat filter (+5v)
option var PORTA.2 ;music or chase option select
sequence var PORTA.3 ;pattern selection

;************* set up variables ***************

Patt var byte [8] ;used to store the sequences
Patt[1]=Patt1
Patt[2]=Patt2
Patt[3]=Patt3
Patt[4]=Patt4
Patt[5]=Patt5
Patt[6]=Patt6
Patt[7]=Patt7

C var byte ;used to advance through pattern
D var byte ;used for the speed the sequence runs at
scale var byte ;used in the POT command
Scale = 10 ;used to provide ragge with pot command
steps var byte ;used for storing the number of steps in a sequence
swcount var byte ;used to select the required sequence required
swcount=1 ;set default sequence at start
sel var byte ;used to select music or chase
sel=1 ;used to select mode

;**************** main program ********************
main:

Pot PORTA.4,scale,D ;used to read value from 10k pot and set the speed
gosub pattern ;jump out to select pattern sequence
LCDOUT $FE,$C0, "Chase Speed " ,#D 'show decimal value of D for speed of chase
if PORTA.2=0 then goto music ;if Pin A2 is low goto music
pause 60 ;debounce delay
read patt[swcount],steps ;read the first value of the selected patter and place it in the variable steps
for C = 1 to steps ;for / next loop
READ PATT[SWCOUNT]+ C,PORTB ;reads the step value for selected pattern and send it to PORTB
PAUSE D ;delay for speed
NEXT ;advance through pattern
goto main: ;go to start of main program

music:
gosub pattern ;jump to pattern sequence selection
LCDOUT $FE,$C0, "Music - selected " ;show that music has been selecterd
read patt[swcount],steps ;read the first value of the selected patter and place it in the variable steps
READ PATT[SWCOUNT]+ C,PORTB ;reads the step value for selected pattern and send it to PORTB
If audio=1 then C=C+1 ;if pin is high a beat is present, so advance pattern
If C=steps then C=1 ;check to see if end of the patetrn is reached
if PORTA.2 = 0 then goto main ;if A2 is low then goto main
pause 20 ;debounce pause
goto music: ;go back to music and start again

;*********** subs **************

pattern:
if sequence=0 then swcount=swcount+1 ;check to see if cycle button pressed, if so add 1 to SWcount
pause 40 ;debounce delay
If swcount>7 then swcount=1 ;error trap for exceeding max patterns
if swcount=1 then LCDOUT $FE, 1, "Pattern 1" 'Clear display and show sequence number
if swcount=2 then LCDOUT $FE, 1, "Pattern 2"
if swcount=3 then LCDOUT $FE, 1, "Pattern 3"
if swcount=4 then LCDOUT $FE, 1, "Pattern 4"
if swcount=5 then LCDOUT $FE, 1, "Pattern 5"
if swcount=6 then LCDOUT $FE, 1, "Pattern 6"
if swcount=7 then LCDOUT $FE, 1, "Pattern 7"
return


Hope this helps