Page last edited June 25, 2014
Text editor powered by tinymce.
Create your own mini radio station and rock all night
Page last edited June 25, 2014
Text editor powered by tinymce.
Page last edited June 25, 2014
Text editor powered by tinymce.
Page last edited June 25, 2014
Text editor powered by tinymce.
To begin reading sensor data, you will need to download the Adafruit si4713 library from the Arduino library manager.
Open up the Arduino library manager:
Search for the Adafruit Si4713 library and install it
We also have a great tutorial on Arduino library installation at:
http://learn.adafruit.com/adafruit-all-about-arduino-libraries-install-use
Open up File->Examples->Adafruit_Si4713->adaradio and upload to your Arduino wired up to the sensor
#define FMSTATION 10230 // 10230 == 102.30 MHzAnd change it to an unused frequency. This number is in 10KHz so for example 88.1MHz is written as 8810
// Uncomment below to scan power of entire range from 87.5 to 108.0 MHz
/*
for (uint16_t f = 8750; f<10800; f+=10) {
radio.readTuneMeasure(f);
Serial.print("Measuring "); Serial.print(f); Serial.print("...");
radio.readTuneStatus();
Serial.println(radio.currNoiseLevel);
}
*/
// Uncomment below to scan power of entire range from 87.5 to 108.0 MHz
/*
for (uint16_t f = 8750; f<10800; f+=10) {
radio.readTuneMeasure(f);
Serial.print("Measuring "); Serial.print(f); Serial.print("...");
radio.readTuneStatus();
Serial.println(radio.currNoiseLevel);
}
*/
begin()This will return true if the radio initialized, and false if the radio was not found. Check your wiring if its not 'showing up'
setTXpower(txpwr)the txpwr number is the dBμV transmission power. You can set this to 88-115dBμV or 0 (for off)
tuneFM(freq)That will set the output frequency, in 10's of KHz. So if you want to tune to 101.9 the frequency value is 10190
readTuneStatus()Whcih will set the currFreq currdBuV adnd currAntCap variables in the radio object. The first two are the frequency and power output, the third variable is the tuning antenna capacitor it set for the best output. This number will vary with antenna size and frequency.
readTuneMeasure(freq)begins the measurement, freq is in units of 10KHz so 88.1MHz is written in as 8810
readTuneStatus()which will wait until the chip has measured the data and stick it into the currNoiseLevel variable
beginRDS()Then you can set the "station name" with
setRDSstation("AdaRadio")The radio station name is up to 8 characters
setRDSbuffer( "Adafruit g0th Radio!")You can send up to 32 characters, but you can continuously send new data, just wait a few seconds before each data rewrite so the listener's radio has received all the data
setGPIOctrl(bitmask)where the bitmask has a 1 bit for each of the two pins. For example to set GPIO2 to be an output use setGPIOctrl((1<<2)) to set both outputs, use setGPIOctrl((1<<2) || (1<<1))
setGPIO(bitmask)same idea with the bitmask, to turn both on, use setGPIOctrl((1<<2) || (1<<1)). To turn GPIO2 on and GPIO1 off, setGPIOctrl(1<<2)
//setProperty(SI4713_PROP_TX_ACOMP_ENABLE, 0x02); // turn on limiter, but no dynamic rangingand uncomment the first one, and comment the second. This will turn off the AGC
setProperty(SI4713_PROP_TX_ACOMP_ENABLE, 0x0); // turn on limiter and AGC
Page last edited June 25, 2014
Text editor powered by tinymce.
It's easy to use the Si4713 FM transmitter with Python or CircuitPython, and the Adafruit CircuitPython SI4713 module. This module allows you to easily write Python code that controls the transmitter and sends RDS data.
You can use this sensor with any CircuitPython microcontroller board or with a computer that has GPIO and Python thanks to Adafruit_Blinka, our CircuitPython-for-Python compatibility library.
First wire up a Si4713 to your board exactly as shown on the previous pages for Arduino using an I2C connection. Here's an example of wiring a Feather M0 to the sensor with I2C:
Since there's dozens of Linux computers/boards you can use we will show wiring for Raspberry Pi. For other platforms, please visit the guide for CircuitPython on Linux to see whether your platform is supported.
Here's the Raspberry Pi wired with I2C:
Next you'll need to install the Adafruit CircuitPython SI4713 library on your CircuitPython board.
First make sure you are running the latest version of Adafruit CircuitPython for your board.
Next you'll need to install the necessary libraries to use the hardware--carefully follow the steps to find and install these libraries from Adafruit's CircuitPython library bundle. Our introduction guide has a great page on how to install the library bundle for both express and non-express boards.
Remember for non-express boards like the, you'll need to manually install the necessary libraries from the bundle:
Before continuing make sure your board's lib folder or root filesystem has the adafruit_si4713.mpy, and adafruit_bus_device files and folders copied over.
Next connect to the board's serial REPL so you are at the CircuitPython >>> prompt.
You'll need to install the Adafruit_Blinka library that provides the CircuitPython support in Python. This may also require enabling I2C on your platform and verifying you are running Python 3. Since each platform is a little different, and Linux changes often, please visit the CircuitPython on Linux guide to get your computer ready!
Once that's done, from your command line run the following command:
sudo pip3 install adafruit-circuitpython-si4713If your default Python is version 3 you may need to run 'pip' instead. Just make sure you aren't trying to use CircuitPython on Python 2.x, it isn't supported!
To demonstrate the usage of the sensor we'll initialize it and control the transmitter from the board's Python REPL. Run the following code to import the necessary modules and initialize the I2C connection with the sensor:
import board import busio import digitalio import adafruit_si4713 i2c = busio.I2C(board.SCL, board.SDA) si_reset = digitalio.DigitalInOut(board.D5) si4713 = adafruit_si4713.SI4713(i2c, reset=si_reset, timeout_s=0.5)
import board import busio import digitalio import adafruit_si4713 i2c = busio.I2C(board.SCL, board.SDA) si_reset = digitalio.DigitalInOut(board.D5) si4713 = adafruit_si4713.SI4713(i2c, reset=si_reset, timeout_s=0.5)
One interesting thing you can do with the Si4713 is measure the quality of an FM radio band. This is handy for example to 'scan' the entire range of FM frequencies looking for possible radio station broadcasts (i.e. frequencies with a good quality signal). This can help you find an unused frequency band to use for your transmitting.
The received_noise_level function can be called with a frequency (specified in kilohertz and only at 50khz steps) and will return the noise level, or signal quality, in dBuV units. The radio supports a range of frequencies from 87.5mhz to 108mhz and you can scan them all with this code:
for f_khz in range(87500, 108000, 50):
noise = si4713.received_noise_level(f_khz)
print('{0:0.3f} mhz = {1} dBuV'.format(f_khz/1000.0, noise))
for f_khz in range(87500, 108000, 50):
noise = si4713.received_noise_level(f_khz)
print('{0:0.3f} mhz = {1} dBuV'.format(f_khz/1000.0, noise))
The higher the dBuV noise value the stronger the signal and better chance there's a real station broadcasting there. The exact values will differ based on your area and the nearby stations but in general a small value under 32 is probably unused, and a large value above 40 is a strong radio signal. Notice in the screen shot above 107.7mhz has a strong signal with noise value of 45 dBuV, this makes sense because a nearby FM station, Seattle's 107.7mhz FM The End, is broadcasting at that frequency. However at 107.35mhz the signal has a much smaller noise value of 29 and likely indicates an unused frequency.
Once you find a frequency that's unused you can configure the transmitter to broadcast its audio input on it with the tx_frequency_khz property. Set this to a value in kilohertz, again only within the range 87.5mhz - 108mhz and at 50khz steps, to change the transmitter frequency. For example to use 107.35mhz:
You can also set the transmitter power with the tx_power property. Set this to a dBuV value from 88 - 115, or set 0 to turn off the transmitter entirely. You typically want the maximum power because these low power FM transmitters don't have much range by design. For example to set the maximum 115 dBuV transmit power:
At this point the Si4713 should be transmitting anything sent to the audio jack or LIN & RIN inputs over the configured FM frequency. Plug in an audio source and try tuning an FM radio nearby to hear the signal! Remember the range of these low power FM transmitters is limited and you might need the radio in the very same room or close by to pick up the signal.
You might need to increase or decrease the volume of your audio source to ensure it's at a high enough level for the transmitter to pick up and send (or you might need to turn it down if it's too high and 'overmodulating' the FM signal). You can actually check with the chip to see if it's getting a good audio signal and potentially overmodulating or running into other transmission issues. Simply read the input_level property to see the audio level (in dB) and the audio_signal_status property to check if there are problems with the signal:
print('Audio level: {0} dB'.format(si4713.input_level))
print('Audio signal status: 0x{0:02x}'.format(si4713.audio_signal_status))
print('Audio level: {0} dB'.format(si4713.input_level))
print('Audio signal status: 0x{0:02x}'.format(si4713.audio_signal_status))
Notice the input level is around -16 dB which is a typical value for audio (lower values mean less volume / input level and higher values up to 0 or more mean very loud input). The audio signal status is a byte that has a few bits to indicate status, in particular the 3rd bit will be turned on to indicate overmodulation (an easy way to check is if the value of the signal status is 4 or greater, that indicates bit 3 is on).
Try cranking up the audio source volume and notice the audio level value increases and the overmodulation bit turns on to indicate the volume is too high (remember a value 4 or greater means the input is overmodulating):
You should aim to keep the input level around -20 to -10 dB and ensure the overmodulation bit isn't set (if it is then the volume is too high).
Finally the RDS features of the Si4713 allow you to transmit data along with the FM audio signal. This is transferred in special side channels to the main FM broadcast and include data like the name of the station and the currently playing song. If you've ever seen a car radio that prints the name of a song being played it's probably reading it over an RDS transmission from the radio station.
You can easily configure and set the RDS transmission of the Si4713 with the configure_rds function. For example:
si4713.configure_rds(0xADAF, b'AdaFruit Radio', b'AdaFruit g0th Radio!')
si4713.configure_rds(0xADAF, b'AdaFruit Radio', b'AdaFruit g0th Radio!')
This call takes the following parameters:
Once you call configure_rds it will enable the RDS broadcast and configure itself to do so at typical North American RDS radio broadcast values (i.e. a specific frequency deviation, repeat interval, etc.). After RDS is configured you can update the station and buffer values by writing to the rds_station and rds_buffer properties respectively. Remember each is limited to a length of 96 characters and 106 characters respectively:
si4713.rds_station = b'Mosfet Jams' si4713.rds_buffer = b'Purrfect tunes!'
si4713.rds_station = b'Mosfet Jams' si4713.rds_buffer = b'Purrfect tunes!'
That's all there is to the basic Si4713 usage with CircuitPython!
Below is a complete demo that will configure the board for FM transmission at a specified frequency (see the FREQUENCY_KHZ variable at the top). It will broadcast RDS data and periodically print audio input level and signal quality status. In addition it also shows basic usage of the GPIO outputs of the Si4713 with the gpio_control and gpio_set functions--these aren't commonly used but are available if you need a couple small outputs from the board. Save this as code.py on your board.
# SPDX-FileCopyrightText: 2018 Tony DiCola for Adafruit Industries
# SPDX-License-Identifier: MIT
# Simple demo of using the SI4743 RDS FM transmitter.
import time
import board
import digitalio
import adafruit_si4713
# Specify the FM frequency to transmit on in kilohertz. As the datasheet
# mentions you can only specify 50khz steps!
FREQUENCY_KHZ = 102300 # 102.300mhz
# Initialize I2C bus.
i2c = board.I2C() # uses board.SCL and board.SDA
# i2c = board.STEMMA_I2C() # For using the built-in STEMMA QT connector on a microcontroller
# Initialize SI4713.
# si4713 = adafruit_si4713.SI4713(i2c)
# Alternatively you can specify the I2C address of the device if it changed:
# si4713 = adafruit_si4713.SI4713(i2c, address=0x11)
# If you hooked up the reset line you should specify that too. Make sure
# to pass in a DigitalInOut instance. You will need the reset pin with the
# Raspberry Pi, and probably other devices:
si_reset = digitalio.DigitalInOut(board.D5)
print("initializing si4713 instance")
si4713 = adafruit_si4713.SI4713(i2c, reset=si_reset, timeout_s=0.5)
print("done")
# Measure the noise level for the transmit frequency (this assumes automatic
# antenna capacitance setting, but see below to adjust to a specific value).
noise = si4713.received_noise_level(FREQUENCY_KHZ)
# Alternatively measure with a specific frequency and antenna capacitance.
# This is not common but you can specify antenna capacitance as a value in pF
# from 0.25 to 47.75 (will use 0.25 steps internally). If you aren't sure
# about this value, stick with the default automatic capacitance above!
# noise = si4713.received_noise_level(FREQUENCY_KHZ, 0.25)
print(f"Noise at {FREQUENCY_KHZ / 1000.0:0.3f} mhz: {noise} dBuV")
# Tune to transmit with 115 dBuV power (max) and automatic antenna tuning
# capacitance (default, what you probably want).
si4713.tx_frequency_khz = FREQUENCY_KHZ
si4713.tx_power = 115
# Configure RDS broadcast with program ID 0xADAF (a 16-bit value you specify).
# You can also set the broadcast station name (up to 96 bytes long) and
# broadcast buffer/song information (up to 106 bytes long). Setting these is
# optional and you can later update them by setting the rds_station and
# rds_buffer property respectively. Be sure to explicitly specify station
# and buffer as byte strings so the character encoding is clear.
si4713.configure_rds(0xADAF, station=b"AdaRadio", rds_buffer=b"Adafruit g0th Radio!")
# Print out some transmitter state:
print(f"Transmitting at {si4713.tx_frequency_khz / 1000.0:0.3f} mhz")
print(f"Transmitter power: {si4713.tx_power} dBuV")
print(f"Transmitter antenna capacitance: {si4713.tx_antenna_capacitance:0.2} pF")
# Set GPIO1 and GPIO2 to actively driven outputs.
si4713.gpio_control(gpio1=True, gpio2=True)
# Main loop will print input audio level and state and blink the GPIOs.
print("Broadcasting...")
while True:
# Print input audio level and state.
print(f"Input level: {si4713.input_level} dBfs")
print(f"ASQ status: 0x{si4713.audio_signal_status:02x}")
# 'Blink' GPIO1 and GPIO2 alternatively on and off.
si4713.gpio_set(gpio1=True, gpio2=False) # GPIO1 high, GPIO2 low
time.sleep(0.5)
si4713.gpio_set(gpio1=False, gpio2=True) # GPIO1 low, GPIO2 high
time.sleep(0.5)
# SPDX-FileCopyrightText: 2018 Tony DiCola for Adafruit Industries
# SPDX-License-Identifier: MIT
# Simple demo of using the SI4743 RDS FM transmitter.
import time
import board
import digitalio
import adafruit_si4713
# Specify the FM frequency to transmit on in kilohertz. As the datasheet
# mentions you can only specify 50khz steps!
FREQUENCY_KHZ = 102300 # 102.300mhz
# Initialize I2C bus.
i2c = board.I2C() # uses board.SCL and board.SDA
# i2c = board.STEMMA_I2C() # For using the built-in STEMMA QT connector on a microcontroller
# Initialize SI4713.
# si4713 = adafruit_si4713.SI4713(i2c)
# Alternatively you can specify the I2C address of the device if it changed:
# si4713 = adafruit_si4713.SI4713(i2c, address=0x11)
# If you hooked up the reset line you should specify that too. Make sure
# to pass in a DigitalInOut instance. You will need the reset pin with the
# Raspberry Pi, and probably other devices:
si_reset = digitalio.DigitalInOut(board.D5)
print("initializing si4713 instance")
si4713 = adafruit_si4713.SI4713(i2c, reset=si_reset, timeout_s=0.5)
print("done")
# Measure the noise level for the transmit frequency (this assumes automatic
# antenna capacitance setting, but see below to adjust to a specific value).
noise = si4713.received_noise_level(FREQUENCY_KHZ)
# Alternatively measure with a specific frequency and antenna capacitance.
# This is not common but you can specify antenna capacitance as a value in pF
# from 0.25 to 47.75 (will use 0.25 steps internally). If you aren't sure
# about this value, stick with the default automatic capacitance above!
# noise = si4713.received_noise_level(FREQUENCY_KHZ, 0.25)
print(f"Noise at {FREQUENCY_KHZ / 1000.0:0.3f} mhz: {noise} dBuV")
# Tune to transmit with 115 dBuV power (max) and automatic antenna tuning
# capacitance (default, what you probably want).
si4713.tx_frequency_khz = FREQUENCY_KHZ
si4713.tx_power = 115
# Configure RDS broadcast with program ID 0xADAF (a 16-bit value you specify).
# You can also set the broadcast station name (up to 96 bytes long) and
# broadcast buffer/song information (up to 106 bytes long). Setting these is
# optional and you can later update them by setting the rds_station and
# rds_buffer property respectively. Be sure to explicitly specify station
# and buffer as byte strings so the character encoding is clear.
si4713.configure_rds(0xADAF, station=b"AdaRadio", rds_buffer=b"Adafruit g0th Radio!")
# Print out some transmitter state:
print(f"Transmitting at {si4713.tx_frequency_khz / 1000.0:0.3f} mhz")
print(f"Transmitter power: {si4713.tx_power} dBuV")
print(f"Transmitter antenna capacitance: {si4713.tx_antenna_capacitance:0.2} pF")
# Set GPIO1 and GPIO2 to actively driven outputs.
si4713.gpio_control(gpio1=True, gpio2=True)
# Main loop will print input audio level and state and blink the GPIOs.
print("Broadcasting...")
while True:
# Print input audio level and state.
print(f"Input level: {si4713.input_level} dBfs")
print(f"ASQ status: 0x{si4713.audio_signal_status:02x}")
# 'Blink' GPIO1 and GPIO2 alternatively on and off.
si4713.gpio_set(gpio1=True, gpio2=False) # GPIO1 high, GPIO2 low
time.sleep(0.5)
si4713.gpio_set(gpio1=False, gpio2=True) # GPIO1 low, GPIO2 high
time.sleep(0.5)
Page last edited June 25, 2014
Text editor powered by tinymce.
Page last edited June 25, 2014
Text editor powered by tinymce.