I remember that when I was studying, I also made a radio. I used the Redmi 1S mobile phone packaging box to make it. The finished product is as follows:
The radio module uses RDA5807, and the main control chip uses a 51 microcontroller. Together with the OLED12864 display and infrared receiver, it realizes remote station search and frequency display. Combined with the mobile phone box made of kraft paper, the overall look is fresh and fresh.
After graduation, I kept this little radio with me. After a person leaves his hometown and moves several times to a strange city, some important things are gradually lost. So I planned to make another version of this radio, as a nostalgic reminder of my college days.
Xiaomi mobile phones no longer use kraft paper packaging boxes, and it seems impossible to reproduce them 100%. In order to make the materials for making radios easier to obtain, I plan to use PCB boards as the casing and collect a handful of wool from the board factory. If other friends are interested, it will be easier for them to copy.
The finished product is as shown below:
The new design uses ESP8266 as the main control chip, the display uses a 240*240 LCD, and WS2812 is used as a signal indicator. It is also equipped with a CD42 charging and discharging module, which can be used even when the charging cable is disconnected. The detailed network connection is as shown below:
8266 pin | connected module |
---|---|
0 | Encoder buttons |
2 | Encoder knob phase A |
4 | RDA5807 -->SCL |
5 | RDA5807 -->SDA |
12 | WS2812_IN |
13 | LCD_SPI_MOSI |
14 | LCD_SPI_SCL |
15 | LCD_DC |
16 | Encoder knob B phase |
In order to facilitate development and modification, the software is implemented using MicroPython. The core code is as follows:
main.py
import time
from machine import Timer,Pin
from ST7789V import LCD_240_240
from biliflow import BiliFlow
from RDA58XX import RDA5807
from neopixel import NeoPixel
tim = Timer(-1)
bf = BiliFlow() #b站粉丝数量显示
lcd = LCD_240_240()#显示屏驱动
rda = RDA5807() #收音机启动
np = NeoPixel(Pin(12, Pin.OUT) , 1) #WS2812驱动
lcd.Disp_Pic(0x320000) #显示背景图片
def bilibili(t): #定时刷新B站的粉丝数
r, g, b = np[0]
np[0] = (50, g, b)
np.write()
lcd.Disp_Str(90,140,str(bf.get_follower()).encode('utf-8'))
np[0] = (0, g, b)
np.write()
tim.init(period=10000, mode=Timer.PERIODIC, callback=bilibili)
key0 = Pin(0, Pin.IN, Pin.PULL_UP)
key0_statue = key0.value()
key1 = Pin(2, Pin.IN, Pin.PULL_UP)
key1_statue = key1.value()
need_re = 0
while True:
if not key0_statue == key0.value(): #按下编码器 静音
key0_statue = key0.value()
time.sleep_ms(10)
if key0.value() == 0:
print("mute")
rda.mute()
if not key1_statue == key1.value(): #右旋编码器,向下搜台
key1_statue = key1.value()
if key1.value() == 0:
print("next")
rda.next_sta()
time.sleep_ms(3000)
need_re = 1
if need_re == 1: #刷新当前电台的频率
rda.refresh_info()
need_re = 0
lcd.Disp_Str(0,0,b' ')
lcd.Disp_Str(0,0,("FM:" + str(rda.tune)).encode('utf-8'))
print("FM:", rda.tune ,"RSSI:", rda.rssi)
In addition, radio chip driver, LCD display driver and fan number display related codes are also required.
RDA58XX.py
radio driver code
from machine import Pin, SoftI2C
import time
import machine
class RDA5807(object):
def __init__(self):
self.i2c = SoftI2C(scl=Pin(4), sda=Pin(5), freq=10000)
self.i2c_buf = bytearray(2)
self.i2c_buf4 = bytearray(4)
self.is_mute = 0
self.rssi = 0
self.tune = 0
def next_sta(self): #向下搜台
self.i2c_buf[0] = 0xd3
self.i2c_buf[1] = 0x81
self.i2c.writeto(0x10, self.i2c_buf)
def pro_sta(self): #向上搜台
self.i2c_buf[0] = 0xd1
self.i2c_buf[1] = 0x81
self.i2c.writeto(0x10, self.i2c_buf)
def set_ch(self, ch): #设置频率eg. 965 unit 100KHz
self.i2c_buf4[0] = 0xd0
self.i2c_buf4[1] = 0x01
ch -= 870
self.i2c_buf4[2] = ((ch >> 2) & 0xff)
self.i2c_buf4[3] = ((ch << 5) & 0xff)
self.i2c.writeto(0x10, self.i2c_buf4)
def refresh_info(self): #获取当前频率,信号强度等
self.i2c.readfrom_into(0x11, self.i2c_buf4)
self.tune = 870 + self.i2c_buf4[1]
self.rssi = self.i2c_buf4[2] >> 1
def mute(self): #静音/取消静音
if self.is_mute == 1:
self.i2c_buf[0] = 0xd0
self.is_mute = 0
else:
self.i2c_buf[0] = 0x90
self.is_mute = 1
self.i2c_buf[1] = 0x01
self.i2c.writeto(0x10, self.i2c_buf)
ST7789V.py
Display driver
from machine import Pin, SPI
import time
import machine
import esp
class LCD_240_240(object):
def __init__(self):
self.hspi = SPI(1, 40000000)
self.lcd_dc = Pin(15, Pin.OUT)
self.lcd_dc.off()
self.hspi.write(b'x11')
time.sleep(0.05)
self.LCD_Cmd_Data(b'x36',b'x00')
self.LCD_Cmd_Data(b'x3A',b'x05')
self.LCD_Cmd_Data(b'xB2',b'x0Cx0Cx00x33x33')
self.LCD_Cmd_Data(b'xB7',b'x35')
self.LCD_Cmd_Data(b'xBB',b'x19')
self.LCD_Cmd_Data(b'xC0',b'x2C')
self.LCD_Cmd_Data(b'xC2',b'x01')
self.LCD_Cmd_Data(b'xC3',b'x12')
self.LCD_Cmd_Data(b'xC4',b'x20')
self.LCD_Cmd_Data(b'xC6',b'x0F')
self.LCD_Cmd_Data(b'xD0',b'xA4xA1')
self.LCD_Cmd_Data(b'xE0',b'xD0x04x0Dx11x13x2Bx3Fx54x4Cx18x0Dx0Bx1Fx23')
self.LCD_Cmd_Data(b'xE1',b'xD0x04x0Cx11x13x2Cx3Fx44x51x2Fx1Fx1Fx20x23')
self.lcd_dc.off()
self.hspi.write(b'x21x29')
def LCD_Cmd_Data(self,cmd, data):
self.lcd_dc.off()
self.hspi.write(cmd)
self.lcd_dc.on()
self.hspi.write(data)
def SetDisArea(self,xStart,yStart,xEnd,yEnd):
buf = bytearray(4)
buf[0] = 0
buf[1] = xStart
buf[2] = 0
buf[3] = xEnd
self.LCD_Cmd_Data(b'x2A',buf)
buf[1] = yStart
buf[3] = yEnd
self.LCD_Cmd_Data(b'x2B',buf)
self.lcd_dc.off()
self.hspi.write(b'x2C')
def Disp_Color(self,Color): #整屏填充某个颜色
self.SetDisArea(0,0,239,239)
self.lcd_dc.on()
buf = bytearray(480)
for j in range(240):
buf[j*2] = Color >> 8
buf[j*2+1] = Color & 0xFF
for i in range(240):
self.hspi.write(buf)
def DrawPoint(self,x,y,color):#在指定位置打点
buf = bytearray(2)
buf[0] = 0
buf[1] = x
self.LCD_Cmd_Data(b'x2A',buf)
buf[1] = y
self.LCD_Cmd_Data(b'x2B',buf)
buf[0] = color >> 8
buf[1] = color &0xFF
self.LCD_Cmd_Data(b'x2C',buf)
def Disp_Pic(self, star_addr): #显示图像,从Flash固定位置读取图像并显示在屏幕上
self.SetDisArea(0,0,239,239)
self.lcd_dc.on()
buf = bytearray(480)
byte_offset = star_addr
for i in range(240):
esp.flash_read(byte_offset, buf)
self.hspi.write(buf)
byte_offset += 480
def Disp_Str(self,x,y,str_datda):#显示字符串,需提前将字库烧录到0x300000位置
font_buf = bytearray(64)
for c in str_datda:
start_addr = 0x300000 + 65*(c - 0x20)
esp.flash_read(start_addr, font_buf)
self.SetDisArea(x,y,x+15,y+31)
x+=16
self.lcd_dc.on()
for j in range(64):
for k in range(8):
if (font_buf[j] & (0x01<<k)) == (0x01 << k):
self.hspi.write(b'xf8x00')
else:
self.hspi.write(b'xffxff')
bilibiliflow.py
Get the number of fans of station B
import network
import json # 导入json功能模块
import urequests #导入urequests功能模块
class BiliFlow(object):
def __init__(self):
wifi = network.WLAN(network.STA_IF) # 将模块设为STA模式
wifi.active(True) # 开启WIFI
if not wifi.isconnected(): # 如果wifi模块未连接到热点
print('WiFi 连接中...')
wifi.connect('your_wifi' , 'xx123456') #连接自己的手机热点
while not wifi.isconnected(): #等待wifi连接
pass
print('WiFi 连接成功' , wifi.ifconfig()) #连接成功
def get_follower(self):#获取粉丝数,将下列vmid修改成自己的即可
r = urequests.get('http://api.bilibili.com/x/relation/stat?vmid=604244921')
p = json.loads(r.text)
return p['data']['follower']
If you like, you can also make a copy. If you encounter any problems during the production process, please leave a message in the comment area!
Search Station B I am Teacher Peng, find more surprises!
All reference designs on this site are sourced from major semiconductor manufacturers or collected online for learning and research. The copyright belongs to the semiconductor manufacturer or the original author. If you believe that the reference design of this site infringes upon your relevant rights and interests, please send us a rights notice. As a neutral platform service provider, we will take measures to delete the relevant content in accordance with relevant laws after receiving the relevant notice from the rights holder. Please send relevant notifications to email: bbs_service@eeworld.com.cn.
It is your responsibility to test the circuit yourself and determine its suitability for you. EEWorld will not be liable for direct, indirect, special, incidental, consequential or punitive damages arising from any cause or anything connected to any reference design used.
Supported by EEWorld Datasheet