- Blog entry posted in 'Electronics and Other Ramblings...', October 01, 2011.
- 16F690 - quite overkill for this
- std breadboard
- PICKIT2 for programming and debugging
- NS73M breakout board
- Oshonsoft PIC Basic
- Set IIC input to zero/gnd - this sets the NS73M for serial communications similar to SPI (note that I say similar and not identical)
- Make sure the communication to the NS73M follows the correct format: address first (LSB first), followed by data (LSB first)
- Make sure to drive the audio inputs with a high enough level.
Working on a few things here and there I came across the NS73M. It is a pretty nifty FM transmitter, which when used with the breakout board seems to have quite a bit of potential. Looking around the web there are a few examples for using these IC:
These, and the Sparkfun example, were my starting points. First shots at it were not really successful, mainly I did not really wire the stuff right; and the code wasn't really correct. So I re-read the code examples, read the datasheet (it's not the best piece of documentation out there - so it's a bit of a read) and attempted to talk to the IC again. The setup I used was:
The following things helped properly setup the IC for proper operation:
Originally I setup the NS73M to require 200mV for 100%modulation - why? Because I quickly scanned the datasheet without really understanding how the part works. What this truly meant was that I had to drive the NS73M inputs harder to get the modulator to work. Driving the inputs from a small MP3 player was not helping the case. So I changed the NS73M setup so that the modulator would operate at 100mV audio inputs; what a difference that made. It went from not working (i.e. not hearing anything) to wow, it works. Granted this is nothing to write your mom or grandma about, but it's a start. The following figure shows what the controller looks like.
The code defaults to 93.9MHz, and it is capable tuning the radio in 200kHz steps from 87.5MHz to 107.9MHz. Adding amplification to the audio input would surely help drive the modulator, but it does not seem to be required.
Code:
'General Configuration
'for internal 8MHz
Define CONF_WORD = 0x33c4
OSCCON = 0x71 'set for internal 8MHZ oscillator
Define CLOCK_FREQUENCY = 8
'Variable Declarations
'i/o states
Const trisa1 = %11111110
Const trisb1 = %11111111
Const trisc1 = %11111000
'ns73m frequency definitions
Const freq_default = 93900000 '93.9 MHz (half way into the U.S. FM band)
Const freq_low = 87500000 '87.5 MHz
Const freq_high = 107900000 '107.9 MHz
Const freq_incr = 200000 '200 KHz steps
'i/o definition
Symbol ns73m_ck = RC0
Symbol ns73m_da = RC1
Symbol ns73m_la = RC2
Symbol button_up = RA4
Symbol button_dn = RA5
Symbol rs232_out = RA0
'global variables
Dim frequency As Long
Dim frequency_old As Long
'global bit logic
Dim _true As Bit
Dim _false As Bit
_true = True
_false = False
'Main Program
main:
WaitMs 2500
Call init()
Call init_ns73m()
While _true
Call check_button()
Wend
End
Proc init()
AllDigital
TRISA = trisa1
TRISB = trisb1
TRISC = trisc1
'enable internal pull-ups for RA5 and RA4
OPTION.NOT_RABPU = 0
WPUA.WPUA5 = 1
WPUA.WPUA4 = 1
Low ns73m_la
Low ns73m_ck
Low ns73m_da
Serout rs232_out, 9600, "Init MCU...", CrLf
WaitMs 1000
frequency = freq_default
End Proc
Proc init_ns73m()
Call ns73m_serial(0x0e, 0x05) 'Software reset
Call ns73m_serial(0x01, 0xb4) 'Pilot on, forced subcarrier
Call ns73m_serial(0x02, 0x07) '2mW power, Unlock detect on
Call ns73m_serial(0x03, 0xea) 'Lower byte frequency (93.9 megahertz)
Call ns73m_serial(0x04, 0x2c) 'Upper byte frequency (93.9 megahertz)
Call ns73m_serial(0x08, 0x1a) 'CEX = Band 2
Call ns73m_serial(0x00, 0x21) 'Pwr on, 100mV audio for 100% modulation, 75us pre-emphasis
Call ns73m_serial(0x0e, 0x05) 'Software reset
Call ns73m_serial(0x06, 0x1e) 'Set internal charge pumps
Serout rs232_out, 9600, "Init FM Radio...", CrLf
Serout rs232_out, 9600, "FREQ = ", #frequency, CrLf
End Proc
Proc check_button()
frequency_old = frequency
'Increase Frequency on Up Button
If button_up = 0 Then 'check button_up state
'debounce switch
WaitMs 200
If button_up = 0 Then 'check button_up state again
frequency = frequency + freq_incr
Endif
Endif
'Decrease Frequency on Dn Button
If button_dn = 0 Then 'check button_dn state
WaitMs 200
If button_dn = 0 Then 'check button_dn state again
frequency = frequency - freq_incr
Endif
Endif
'CheckFreq for Min/Max values
Select Case frequency
Case < freq_low
frequency = freq_low
Case > freq_high
frequency = freq_high
Case Else
'frequency stays at calculated
EndSelect
If frequency_old <> frequency Then
Call update_ns73m()
Endif
End Proc
Proc update_ns73m()
Dim band As Byte
Dim temp As Long
'Set Frequency Band
Select Case frequency
Case <= 91720000
band = %00011011 'Band 3
Case <= 9280000
band = %00011010 'Band 2
Case <= 104000000
band = %00011001 'Band 1
Case Else
band = %00011000 'Band 0
EndSelect
Call ns73m_serial(0x08, band)
'Set Frequency Word
temp = (frequency + 304000) / 8192 'from datasheet
Call ns73m_serial(0x03, temp.LB) 'Low byte of frequency
Call ns73m_serial(0x04, temp.HB) 'High byte of frequency
Call ns73m_serial(0x0e, 0x05) 'Software reset
Call ns73m_serial(0x00, 0x21) 'Pwr on, 100mV audio for 100% modulation, 75us pre-emphasis
'Update Frequency Display
Serout rs232_out, 9600, "FREQ = ", #frequency, CrLf
End Proc
Proc ns73m_serial(address As Byte, data As Byte)
Dim cnt As Byte
Low ns73m_la
'send register address (nibble)
For cnt = 0 To 3
Low ns73m_ck
ns73m_da = address.0
address = ShiftRight(address, 1)
High ns73m_ck
ASM: nop
ASM: nop
ASM: nop
ASM: nop
ASM: nop
ASM: nop
Next cnt
Low ns73m_ck
Low ns73m_da
'send register data (byte)
For cnt = 0 To 7
Low ns73m_ck
ns73m_da = data.0
data = ShiftRight(data, 1)
High ns73m_ck
ASM: nop
ASM: nop
ASM: nop
ASM: nop
ASM: nop
ASM: nop
Next cnt
Low ns73m_ck
Low ns73m_da
High ns73m_la
WaitMs 1
Low ns73m_la
End Proc