Full Version : 1Khz Synchronous Detector (AVR ASM)
avr >>PROJECTS (AVR) >>1Khz Synchronous Detector (AVR ASM)


Admin5- 04-27-2006
Cappel's Experimental 1 KHz Synchronous Detector

Overview

This circuit employs a synchronous demodulator to separate a 1 KHz signal from noise and measures the amplitude of the 1 kHz signals once a second at about 60 microvolts per count then sends the measurements via an RS-232 interface for further processing or display. An LED on the board also lights when the measured signal exceeds a preset threshold.

This experiment was started when I took an interest in receiving ELF wireless signals. It also has applictions in optics and high frequency RF, or for that matter, any place one needs to measure a tiny signal, of which the frequency and phase are known, in the presence of noise.

With the addition of a preamplifier based on the LM324, the sensitivity of this circuit was easily extended to a sensitivity to 160 nanovolts per count. That an LM324 is used with little in the way of noise on the output testifies to the value of using this kind of detector.

How it works


The detector is a multiplier fillowed by an integrator.
A single slope analog to digital conversion process measures the
detected signal with 7 bit resolution.


There are several sophisticated references on the web that describe how synchronous detectors work, so here I will only give a light overview and go into some specifics of this implementation.

The idea is to multiply the input signal by the output of a local oscillator that is synchronized with the expected signal, and integrate the result. Imagine a square wave being fed into the signal input of the multiplier and a synchronized square wave being fed into the local oscillator input of the multiplier. If the local oscillator is synchronized such that they are perfectly matched in phase, then the output of the multiplier will be positive when the incoming signal and the local oscillator are positive and the output will also be positive when the inputs are negative (negative x negative = positive) this is actually a full wave rectifier when both signals are synchronized and in the proper phase with one another.

In theory, signals at the proper frequency are presented as DC to the integrator and all other frequencies average out to zero. In practice, this circuituses square waves to perform the modulation, so it is susceptible to odd harmonics of the sampling frequency, so it is sensitive to 3 kHz, 5 kHz, 7 kHz..., so an analog filter ahead of the detector can be useful if it is important to reject these frequencies.

The circuit

All the analog circuits are biased to operate around a 1.8v reference.

The incoming signal is buffered by U2A (there is on U1 in this schematic as U1 was moved to a separate preamp assembly), which provides a noniverted signal to the integrator when U3A is switched on. U2B inverts the buffered signal from U2A and provides an inverted version of the signal to the integrator when U3B is switched on. To increase the charging rate, either decrease the 100k resistor on the input of U2C or decrease the .047 uf integrating capacitor.


On the output of the integrator, input noise tends to average out.


The signals fed into the integrator charge the .047 uf capacitor in the integrator. After 999 cycles of the 1 kHz sampling signal, U3C is turned on and the capacitor is discharged with a constant current (1.8V/7.5K = 240 microamps), producing a linear positive-going ramp at 5,106 volts/second on the output of U2C. While the output of U2 is ramping up toward the 1.8 volt reference, the AT90S2313 sits in a loop, incrementing a counter every 1.25 microseconds, until the comparitor on the AT90S2313 changes state, indicating that the ramp on U2C has reached the 1.8 volt reference voltage. The maximum count for this measurement is 127 to limit the time spent in the measurement to less than the 250 microsecond interrupt interval. Thus, a 7 bit measurement is made in 160 microseconds or less, and is completed within a single 250 microsecond interrupt interval.

The rate of discharge of the integrating capacitor during the measurement phase is set by the current into the node, 1.8 volts/7.5 k =240 microamps, divided by the .047 uf capacitance, which gives a 5100 volt/second voltage ramp. The A/D conversion sensitivity is therefore 1.25 us/count X 5100 volts/second = 6.375 millivolts per count.

After the count is completed, which occurs when the pseudo 7 bit counter overflows or the ramp reaches the 1.8 volt reference, U3C is switched off and U3D is switched on to clamp the of the integrator to the 1.8 volt reference and to make sure the capacitor is discharged to a consistent state for 1 millisecond before starting signal measurement again,

The entire measurement cycle takes 999 milliseconds for integration + 1 millisecond to clamp the capacitor to zero, for a total of 1 second per measurement.

The gian of the integrator is ( ( Peak input Voltage/ 100 k Ohm) X 0.999 seconds ) )/ .047 microfarads = 212.5 volts out/volt in. The sensitivity of the detector is therefore 6.375 mv/212.5 = 30 microvolts peak per count, or since peak-to-peak = 2 x peak, 60 microvolts peak-to-peak per count.

After the measurement is completed, the measured value is formatted into BCD and sent via the UART at 9600 baud, two stop bits, no parity. The transmission of the data does not occur during interrupt time.

An LED is turned on by the microcontroller during the integration and measurement cycle following a measurement in which the measured value exceeded 64 decimal.

The sensitivity of this particular hardware assembly is 5 millivolts/(87 counts - 18 counts) = 72.4 microvolts per count. This number is reasonable close to the calculated sensitivitiy of 60 microvolts per count. The error might be becasue the input signal was larger than I thought.

This sensitivity, 72 microvolts per count, is for square waves. The sensitivity for sine waves will be 63.7% of the sensitivity for square waves. Also note that if the incoming signal is not perfectly phased with respect to the sampling signal, the amplifude will be reduce.

The circuit can be made more sensitive by decreasing the 100k resistor connected to pin 9 of U2C, by reducing the ,047 uf integrating capacitor, or increasing the integration time, which is currently set to 999 cycles. Reducing the resistor or capacitor will reduce the circuit's ability to reject interfering signals at frequenices not at the sampling frequency. Increasing the integration time will raise the senstitivity without affecting the ability to reject interfering signals, but the offset control becomes very touchy with integration times of more than a few thousand cycles.


Link: http://cappels.org/dproj/syncdet/syncdet.html

Admin5- 04-27-2006
CODE

;******************************************************
.include "2313def.inc"
;******************************************************

; User timer 1 to make a 4 khz interrupt and put a square wave sampling pulse on pin 16.
; Firmware expects a 4 Mhz AT90S2313
; Keep other I/O pins low, except when outpulse is greater than $C0, hold reset pin high

.def chargecount = r2;Value of measuered charge in integrator
.def counterlow = r3;Lower byte of the preload for 4 kHz interrupt. Usaed for programmability
.def oldchargecount = r4;Value of charge on prior measurement
.def quarterycles = r5;Value to change timer low
.def meascount = r6;Count of measurements modulus 256. Used for alternative meas output

.def temp  =r16;Scratch register
.def temp2  =r17;Second scratch register
.def outpulse =r18;Interrupt counter
.def datab  =r19;Temporary data for PORTB, to be output every interrupt time (only 4 lsb available).
;.def resetcounter =r20;Counter to determine reset time
.def flagreg  =r21;Flags stored here
.def H  = r22;Used to send decimal ascii
.def T  = r23;Used to send decimal ascii
.def U  = r24;Used to send decimal ascii
;NOTE: Y register is used as integration timer


;definition of I/O
;B0 COMPARITOR NONINVERTING
;B1 COMPARITOR INVERTING
;B2
;B3 SAMPLE CLOCK PHASE 1 ON EVEN MEASUREMENTS
;B4 SAMPLE CLOCK PHASE 1
;B5 SAMPLE CLOCK PHASE 2
;B6 SAMPLE CLOCK PHASE 3
;B7 SAMPLE CLOCK PHASE 4


;D0 USED FOR UART RECEIVE
;D1 USED FOR UART TRANSMIT
;D2
;D3 LED - SIGNAL ABOVE THRESOLD
;D4 CLAMP INTEGRATOR TO ZERO
;D5 MEASURE
;D6
;D7

;definition of flagreg bit assignments
.equ meastaken =0;Set after new measurement taken. Cleared by servo
;1
;2
;3
;4
;5
;6
;7

.equ counterhigh =$03;High byte of the perolaod for 4 kHz interrupt
.equ measuretime =$E7;Point detector cycle that measurement takes place
.equ measuretimeH =$03
.equ resettime =$E8
.equ resettimeH =$03
.equ detthreshold =$40;Threshold above which a signal is said to have been detected
.equ outpulsepattern =0b00110011;Note: As used here, the high and low nybble are used sequentially,and
;repeats every two cycles. For odd and even cycles to be identicle, both nybbles should be identicle.
;The pattern "0b00110011 would result in a 50% duty cycle at 1 kHz.


;UART baud rate calculation
.equ clock = 4000000;clock frequency
.equ baudrate = 9600 ;choose a baudrate
.equ baudconstant = (clock/(16*baudrate))-1



.cseg ; Main program entry point on reset
.ORG $0000
rjmp start
.ORG $0004
rjmp timerservice;Timer/counter compare interrupt handler

start:
 
ldi r16,RAMEND;Init Stack Pointer
out spl,r16

 ldi     temp,baudconstant    
 out     ubrr,temp      ;Load baudrate.
; sbi ucr,rxen ;Enable WAUT receive;Uart receive not used so not enabled bere.
 sbi ucr,txen ;Enable UART Transmit


ldi outpulse,outpulsepattern;Initial pulse ouput pattern
ldi flagreg, 0b00000000;Initialize all flags

clr YL  ;Initialize integration cycle counter
clr YH

ldi temp,$04;Initialize quarter cycle counter
mov quarterycles,temp

ldi temp,$E8;Initialize the variable for interrupt timer
mov counterlow,temp

ldi temp,$00;Set data on PORTD and PORTB low.
out PORTD,temp
out PORTB,temp


ldi temp,0b11111100;Make pins on PORTB, except comparitor pins, ouputs.
out DDRB,temp
ldi temp,0b11111111;Make all pins on PORTD
out DDRD,temp

ldi temp,$09;Set timer 1 to reset 0000 after compare match. Prescaler = 1X
out TCCR1B,temp

ldi temp,counterhigh;Set compare register to $03E8 for 4 khZ interrupt
out OCR1AH,temp
mov temp,counterlow
out OCR1AL,temp

ldi temp,$40;Enable interrupt on compare match
out TIMSK,temp

sei  ;Enable interrupts
rjmp Main ;Go to main loop and wait for interrupt



locklight:

mov temp,chargecount
cpi temp,detthreshold
brmi ledoff
sbi PORTD,3
ret

ledoff: cbi PORTD,3
ret




servo:
sbrs flagreg,meastaken
ret   ;Return if this is not first call after signal measurement
andi flagreg,$FE

mov temp,chargecount;Send the latest measuremnet followed by a CR and LF.
rcall sendnumber  
rcall crlf  

rcall locklight
ret

;Code below is not executed
mov temp,chargecount
cpi temp,$10
brpl nosignal
inc counterlow
ldi temp,counterhigh;Set compare register
out OCR1AH,temp
mov temp,counterlow
out OCR1AL,temp

nosignal:
ret  
 

 
Main:  
rcall servo
rjmp Main





sendnumber:;Enter with value to be sent in temp, sends as three digit ascii
 ;via serial port.
 mov U,temp  ;Enter with 8 bit value in U, Exits with numerals in H,T,U
 clr H  ;(Hundreds, Tens, and Units).
 clr T
anotherh:
 subi  U,100  ;Find out how many hundreds in U.
 brcs hdone
 inc H
 rjmp anotherh
hdone:
 subi U,-100  ;Subtracted one too many -add back.
anothert:
 subi U,10
 brcs tdone
 inc T
 rjmp anotherT
tdone:
 subi U,-10  
 cpi H,0  
 breq dontsendh
 subi H,-48
 mov temp,H
 rcall emitchar
 cpi t,0
 brne dontsendh
 ldi temp,$30 ;If U=0 then don't emit this zero
 rcall emitchar
dontsendh:
 cpi t,0
 breq dontsendt
 subi T,-48
 mov temp,T
 rcall emitchar
dontsendt:
 subi U,-48
 mov temp,U
 rcall emitchar
 ret
 
 
crlf:  ;Send return and linefeed
 ldi temp,$0A ;Send return and line feed
 rcall emitchar
 ldi temp,$0D
 rcall emitchar
 ret



emitchar:;Send character contained in temp with two stop bits.
 sbis usr,udre   ;wait until the register is cleared.
 rjmp emitchar    
 cbi ucr,0  ;Set 9th bit to zero (second stop bit).
 sbi ucr,2  ;Set to send 9 data bits.
 out udr,temp ;send the character.
 ret


measurecharge:  ;Measure time it takes to zero integrator. Output range is $80 to $00,
ldi temp,$81;which is later adjusted to 0 to $127 in timerservice and sendnumber.
mov chargecount,temp;Set chargevalue to $81 so it will only spend 127 cycles in this routine.
ori flagreg,1;Set meastaken flag.
cbi PORTB,4 ;Make both phase 1 and phase 3 low during the measurement
cbi PORTB,6 ;so incoming signals don't affect measurement accuracy.
sbi PORTD,5 ;Turn on discharge resistor.   ;(Discharge resistor turned off after return).
sbic acsr,aco;If comparitor is high, then charge is zero or negative. In this case.
ret  ;skip measurement and go on to discharge capacitor.
morch:
inc chargecount;Stay in a counting loop until the comparitor goes high.
breq saturated
sbis acsr,aco
rjmp morch
saturated:
ret  ;(Discharge resistor turned off after return)


writeportb:;Output outpulse combined with datab lower 4 bits to PORTB
mov temp,datab
andi temp,$0F
mov temp2,outpulse
andi temp2,$F0
or temp,temp2
out PORTB,temp
ret

timerservice: ;Timer 1 interrupt service

push temp
push temp2
clc
rol outpulse ;Rotate bit image and output to PORTB.
brcc B1  ;If carry set, set bit 0.
ori outpulse,$01  
B1:
   ;If meascount is even, copy PORTB bit 4 to PORTB bit 3
   ;so that pulses are sent from B3 on alternate measurements
mov temp,meascount
andi temp,0b00000001
brne noclockout ;If meascount lsb is not zero, skip to noclockout
   ;If meascount is zero, then copy outputle bit 4 into datab bit 3
mov temp,datab
andi temp,0b11110111
mov datab,temp
mov temp,outpulse
lsr temp
andi temp,0b00001000
or datab,temp

noclockout:
rcall writeportb

dec quarterycles ;If four quarter cycles haven't passed, then don't
brne notfullcycle ;increment resetcounter or see if its time to measure charge.
ldi temp,$04
mov quarterycles,temp


adiw YL,1  ;There will be a glitch on D4 during resets.
mov temp,YL
mov temp2,YH
subi temp,measuretime
sbci temp2,measuretimeH

; cpi resetcounter,measuretime;See if its time to measure charge and reset the integrator.
brcs noreset
brne nomeasure ;If this is the first time through, measure the charge (250 us).
rcall measurecharge ;First time is when resercounter = measuretime.
inc meascount ;Increment measurement count
mov temp,chargecount;After measuring charge, adjust offset and save previoius charge
subi temp,$81 ;for possible future use.
mov oldchargecount,chargecount;Save old charge value before replacing.
mov chargecount,temp;Remove offset from count.
nomeasure:

mov temp,YL
mov temp2,YH
subi temp,resettime
sbci temp2,resettimeH
brne nozeroY
clr YL
clr YH
nozeroY:
cbi PORTD,5  ;Turn off discharge resistor.
sbi PORTD,4  ;Turn on dump resistor.
rcall writeportb ;Restore PORTB
rjmp finishedinterupt
noreset:
cbi PORTD,4  ;Turn off dump resistor.
 

notfullcycle:   ;Skip to here if this is not at the end of a full cycle.

finishedinterupt:
pop temp2
pop temp
reti





.exit   ;don't assemble past here.


Forumer™ is Voted #1 Free Forum Hosting provider
Build your own community today with the largest message board hosting company.