Receptor de rádio online com Raspberry Pi - MakerHero

Receptor de rádio online com Raspberry Pi 29

Rádios online não são novidade, é verdade. Porém, constituem um meio ainda fantástico de se ouvir música e notícias do mundo todo e, por que não, conhecer novas culturas também. Quando idealizadas e popularizadas, o único dispositivo que tornava possível ouvir uma rádio online era um computador. Mas os tempos mudaram e hoje é possível fazer isso até mesmo de seu smartphone. Neste artigo, será mostrado como construir seu próprio receptor de rádio online com Raspberry Pi rodando a distribuição Linux Raspbian.

Rádio On-line com Raspberry Pi

O que é necessário comprar para reproduzir o projeto?

Para fazer o projeto de rádio online com Raspberry Pi, será necessário:

No caso, a Raspberry Pi é o “cérebro” do projeto. Uma vez que o projeto estiver rodando, a rádio-online que estiver tocando no momento irá aparecer do display OLED e será possível controlar totalmente o projeto através dos 5 botões pulsantes / push-buttons. Os botões terão as seguintes funções:

  • Play/pause
  • Aumentar volume
  • Diminuir volume
  • Ir para a próxima estação
  • Voltar à estação anterior

Neste projeto de rádio online com Raspberry Pi, podem ser utilizado qualquer modelo de placa (desde que contenham conexão com a Internet), incluindo a Raspberry Pi 3 Model B e a Raspberry Pi Zero 2 W à venda em nossa loja MakerHero.

Como funciona a rádio online com Raspberry Pi?

O princípio de funcionamento deste projeto está na comunicação entre processos no Linux. Cada aplicação executada no Linux pode ser um processo (funcionamento temporário) ou serviço (funcionamento permanente), ficando a cargo do Kernel Linux gerenciar a execução dos mesmos.

O projeto deste post será um processo, o qual se comunicará com um player de mídia do Linux para tocar as rádios online, sendo este player um outro processo em execução. O player de mídia em questão é o mplayer, um player muito leve e consagrado do Linux (já testado a exaustão, com sucesso, ao longo dos anos em várias distribuições). Este player pode tocar diferentes tipos de mídia, sendo uma solução leve e elegante para quem deseja tocar mídias no Linux.

Portanto, em termos de funcionamento, o projeto aqui desenvolvido irá se comunicar com o mplayer, enviando comandos ao mesmo através de uma técnica chamada de named pipes.  Esta técnica permite que processos distintos no Linux se comuniquem / enviem mensagens uns aos outros, ficando a cargo do Kernel Linux gerenciar a transferências destas mensagens. No caso específico deste projeto, as mensagens trafegadas entre o receptor e o mplayer são os comandos que o mplayer aceita em modo slave, e são escritas e lidas em arquivos FIFO (arquivos especiais para esta finalidade) salvos no diretório /tmp. Não se preocupe com a quantidade de I/Os nesses arquivos, pois no Linux todos os arquivos FIFO são criados/mapeados em RAM!

Preparação: instalação do mplayer e escolha das rádios online

Antes de prosseguir com o projeto, é necessário instalar o mplayer. Para isto, utilize o comando abaixo:

sudo apt-get install mplayer2

A instalação é rápida e não ocupará muito espaço na memória.

Para a escolha das rádios online, uma das formas é carregar nele arquivos do tipo playlist (.pls) da rádio on-line desejada. Portanto, ao escolher suas rádios a serem ouvidas, procure pela playlist / endereço da playlist em formato .pls. Abaixo há alguns exemplos, todos tirados do site SHOUTCast:

  • http://yp.shoutcast.com/sbin/tunein-station.pls?id=1057392
  • http://panel3.serverhostingcenter.com:2199/tunein/radiobackstage1.pls
  • http://yp.shoutcast.com/sbin/tunein-station.pls?id=142571

Ainda, você pode testar o funcionamento do mplayer ao tocar uma rádio de sua escolha com o seguinte comando:

mplayer -playlist URL_DO_ARQUIVO_PLS_DA_RADIO_ONLINE_DESEJADA

 

Circuito Esquemático

O circuito esquemático do projeto pode ser visto abaixo:

  Circuito Rádio on-line com Raspberry Pi

 

Código-fonte projeto Rádio online com Raspberry Pi

Veja abaixo o código-fonte do projeto!
Observação: para maiores informações das bibliotecas a serem instaladas para o funcionamento do display OLED na Raspberry Pi, veja este nosso artigo.

#Projeto: Radio on-line com Raspberry Pi
import os
import sys
import subprocess
import shlex
import Adafruit SSD1306

from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont

#Variaveis globais
CaminhoArquivoControle="/tmp/ControleRadio"
ComandoMPlayer = "mplayer -input file=/tmp/ControleRadio -slave -playlist "

#variaveis relacionadas ao display OLED
RST = 24
disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST)  #Display OLED 128x64 (I2C)
top = 0


#Variaveis das playlists
Playlists=[]        #Array que contem todas as playlists
NumeroPlaylists = 0 #quantidade de playlists
NomesRadios=[]      #Nomes das radios / playlists
PlaylistEscolhida=0 #Indice da playlist escolhida

#Variaveis relacionadas aos botoes de comando
PinoPlayPause = 18     # Broadcom pin 18 (no conector P1, pino 12)
PinoSobeVolume = 17    # Broadcom pin 17 (no conector P1, pino 11)
PinoDesceVolume = 22   # Broadcom pin 22 (no conector P1, pino 15)
PinoRadioAnterior = 27 # Broadcom pin 27 (no conector P1, pino 13)          
PinoProximaRadio = 23  # Broadcom pin 23 (no conector P1, pino 16)                   


NomeRadio1="Radio ShoutCast"
NomeRadio2="Radio Backstage (www.radiobackstage.com)"

#Funcao: inicia lista de playlists
#Parametros: nenhum
#Retorno: nenhum
def IniciaListaPlaylists():
	global Playlists
	global NomesRadios
	global NumeroPlaylists

	#playlist 1
	Playlists.append("http://yp.shoutcast.com/sbin/tunein-station.pls?id=1057392")
	NomesRadios.append("Radio Shoutcast")

	#playlist 2
	Playlists.append("http://panel3.serverhostingcenter.com:2199/tunein/radiobackstage1.pls")
	NomesRadios.append("Radio Backstage")

	#playlist 3
	Playlists.append("http://yp.shoutcast.com/sbin/tunein-station.pls?id=1425714")
	NomesRadios.append("Techno")

	NumeroPlaylists=3
	return

#Funcao: Toca a plsylist escolhida
#Parametros: nenhum
#Retorno: nenhum
def TocaPlaylist(PEscolhida):
	global Playlists
	global ComandoMPlayer

	os.system("pkill -f mplayer")
	ComandoPlaylist = ComandoMPlayer + Playlists[PEscolhida]
	
	#inicia processo e direciona o stdout para /dev/null
	FNULL = open(os.devnull,'w')
	args = shlex.split(ComandoPlaylist)
	InterfaceMPlayer = subprocess.Popen(args, shell=False, stdin=subprocess.PIPE, stdout=FNULL, stderr=subprocess.STDOUT)

	#ajusta volume em 50%
	os.system('echo "volume 50" >'+CaminhoArquivoControle)

	return


#Funcao: cria arquivo de controle do player (MPlayer)
#Parametros: nenhum
#Retorno: nenhum
def CriaArquivoControle():
	#se arquivo ja existe, nada e feito.
	if (os.path.exists(CaminhoArquivoControle)):
		return

	try:
		os.mkfifo(CaminhoArquivoControle)
	except:
		print "Falha ao criar arquivo de controle. Por favor, verifique o caminho de criacao do mesmo."
		exit(1)
	
	
#Funcao: escreve radio atual e estado da reproducao no display
#Parametros: nome da radio, estado de reproducao, tamanho da tela (altura e largura)
#            e objetos (draw, image e disp)
#Retorno: nenhum
def EscreveDisplay(NomeDaRadio, EstadoReproducao, AlturaDisplay, LarguraDisplay, draw, image, disp):
        global top
    
    #Apaga display desenhando um retangulo preto que ocupa toda a tela
	draw.rectangle((0,0,LarguraDisplay,AlturaDisplay), outline=0, fill=0)
	     
    font = ImageFont.load_default()
	draw.text((x, top), 'Player - radio online', font=font, fill=255)
	draw.text((x, top+20), 'Tocando:', font=font, fill=255)
	draw.text((x, top+40), NomeDaRadio, font=font, fill=255)
	draw.text((x, top+60), 'Status: ', font=font, fill=255)
	draw.text((x, top+80), EstadoReproducao, font=font, fill=255)
	disp.image(image)
	disp.display()	
	return	
	
#------------------
#Programa principal
#------------------

#inicializacoes dos GPIOs
GPIO.setmode(GPIO.BCM)
GPIO.setup(PinoPlayPause, GPIO.IN, pull_up_down=GPIO.PUD_UP)      #input c/ pull-up
GPIO.setup(PinoSobeVolume, GPIO.IN, pull_up_down=GPIO.PUD_UP)     #input c/ pull-up
GPIO.setup(PinoDesceVolume, GPIO.IN, pull_up_down=GPIO.PUD_UP)    #input c/ pull-up
GPIO.setup(PinoRadioAnterior, GPIO.IN, pull_up_down=GPIO.PUD_UP)  #input c/ pull-up
GPIO.setup(PinoProximaRadio, GPIO.IN, pull_up_down=GPIO.PUD_UP)   #input c/ pull-up

#inicializacoes do display
disp.begin()
disp.clear()
disp.display()
width = disp.width
height = disp.height
image = Image.new('1', (width, height)) 
draw = ImageDraw.Draw(image)
padding = 2
shape_width = 20
top = padding
bottom = height-padding
x = padding

#Inicializa lista de playlists
IniciaListaPlaylists()

#Cria arquivo de controle e inicia processo MPlayer
CriaArquivoControle()

#Toca playlist 1
TocaPlaylist(PlaylistEscolhida)

#escreve no display a radio que esta tocando
EscreveDisplay(NomesRadios[PlaylistEscolhida], 'Tocando', height,width, draw,image, disp)

while True:
	try:
		
		if (!GPIO.input(PinoPlayPause)):
			print "[ACAO] Play/Pause"
			os.system('echo "pause" > '+CaminhoArquivoControle)

		if (!GPIO.input(PinoSobeVolume)):
			print "[ACAO] Sobe volume"
			os.system('echo "volume +10" > '+CaminhoArquivoControle)

		if (!GPIO.input(PinoDesceVolume)):
			print "[ACAO] Desce volume"
			os.system('echo "volume -10" > '+CaminhoArquivoControle)

		if (!GPIO.input(PinoProximaRadio)):
			print "[ACAO] Proxima estacao"
			PlaylistEscolhida = PlaylistEscolhida + 1
			if (PlaylistEscolhida == NumeroPlaylists):
				PlaylistEscolhida = 0
			TocaPlaylist(PlaylistEscolhida)
			EscreveDisplay(NomesRadios[PlaylistEscolhida], 'Tocando', height,width, draw,image, disp)

		if (!GPIO.input(PinoRadioAnterior)):
			print "[ACAO] Estacao anterior"
			PlaylistEscolhida = PlaylistEscolhida - 1
			if (PlaylistEscolhida < 0):
				PlaylistEscolhida = NumeroPlaylists-1
			TocaPlaylist(PlaylistEscolhida)
			EscreveDisplay(NomesRadios[PlaylistEscolhida], 'Tocando', height,width, draw,image, disp)


	except (KeyboardInterrupt):
		print "Aplicacao sendo encerrada."
		exit(1)

Copie e cole este código em um editor de texto de sua preferência (sugestão: nano) e salve o arquivo como ReceptorRadioOnlineRasp.py. Para executar o projeto, utilize o seguinte comando:

python ReceptorRadioOnlineRasp.py

Abaixo você confere um vídeo do projeto em ação:

 

Gostou do post rádio online com Raspberry Pi? Deixe seu comentário logo abaixo.

Faça seu comentário

Acesse sua conta e participe

29 Comentários

  1. Nossa, você sabe muito cara.Parabens

    João Batista Fontanezi Moraes
  2. Parabens pelo projeto! Gostaria de saber se dá pra torná-lo como um auxiliar de Rádio em uma Tv Led atatravés do HDMI, e controlar as estações por um menu pelo próprio controle da TV?

  3. Pedro, boa noite
    Estou montando o projeto do radio e estou com dificuldade em colocar as emissoras. Quando copio o link da emissora na linha do programa, ele nao reconhece. Ele não sintoniza a emissora.

    O que será que acontece?

    1. Flavio, bom dia.

      Infelizmente, não é toda emissora que disponibiliza, de forma explícita ou não, o arquivo PLS do streaming. Se a emissora não disponibiliza isso, não há como tocá-la neste projeto.
      Procure nas rádios que deseja ouvir pelos arquivos pls para ouvir a radio online e passe o caminho deles (endereço até eles) no projeto da rádio.

      Atenciosamente,
      Pedro Bertoleti

  4. Olá, Pedro!

    Recebi esta semana a placa Raspberry e o display. Estou tentando fazer esse projeto funcionar, mas aparece a seguinte mensagem de erro no LXTerminal:

    pi@raspberrypi:~ $ python ReceptorRadioOnlineRasp.py
    File “ReceptorRadioOnlineRasp.py”, line 106
    draw.rectangle ((0,0,LarguraDisplay,AlturaDisplay), outline=0, fill=0)
    ^
    IndentationError: unindent does not match any outer indentation level

    Não consegui decifrar o que está acontecendo. Também aparece outra mensagem, no Thonny, ao clicar em Debug:

    Python 3.5.3 (/usr/bin/python3)
    >>> %Debug ReceptorRadioOnlineRasp.py
    Traceback (most recent call last):
    File “/usr/lib/python3.5/ast.py”, line 35, in parse
    return compile(source, filename, mode, PyCF_ONLY_AST)
    File “/home/pi/ReceptorRadioOnlineRasp.py”, line 106
    draw.rectangle ((0,0,LarguraDisplay,AlturaDisplay), outline=0, fill=0)
    ^
    IndentationError: unindent does not match any outer indentation level

    Agradeço qualquer auxílio.

    Um abraço!

    Marcos

    1. Marcos, bom dia.

      Este é um erro de identação. A linha “draw.rectangle ((0,0,LarguraDisplay,AlturaDisplay), outline=0, fill=0)” no seu código está ou com alguns espaços a mais ou a menos que as linhas da mesma função ou trecho de código ao qual pertence.

      Corrija esses espaços e funcionará.

      Atenciosamente,
      Pedro Bertoleti

  5. Olá, Pedro!
    Esse é um projeto que achei muito interessante, pois gosto de escutar rádios de outras partes do mundo enquanto estou na oficina. Vi outros projetos com Arduino, mas não funcionaram muito bem ao prototipar. Estou inclinado a comprar uma placa Raspberry Pi mais o display, como visto no post. O problema é que não entendo absolutamente nada de programação em Python. Gostaria de saber se posso pedir o teu auxílio, caso necessite. Um abraço e parabéns pelo projeto!

    1. Marcos, boa tarde.

      Primeiramente, obrigado pelos elogios.
      Sim, posso auxilia-lo sim. Ao surgirem dúvidas, é só postar aqui que te ajudo.

      Atenciosamente,
      Pedro Bertoleti

      1. Obrigado pela presteza, Pedro! A minha primeira dúvida é quanto ao display. Esse projeto pode ser ligeiramente modificado para utilizar um display maior, tipo de 3.5″ ou de 5″ TFT com touchscreen? Vi que existem vídeos de outros projetos que utilizam uma interface com avanço, retrocesso, pause, play e stop. Gostaria de realizar algo mais ou menos parecido, mas se for muito mais difícil vou comprar somente o display OLED. Um abraço!

        1. Marcos, bom dia.

          No caso, é possível sim utilizar um display diferente, porém o código-fonte seria consideravelmente modificado. Aconselho você a começar com o OLED e, conforme for se sentindo mais confortável com a linguagem Python, partir para algo além.

          Abraço.

  6. Boa noite!
    Parabéns pelo projeto! Estou buscando orientação para a construção de um projeto que se dará da seguinte forma: um rádio vhf irá estar ligado em uma determinada frequência, deste rádio irei pegar somente o áudio via cabo p2. Na sequência vou colocar um Raspberry Pi b+. A ideia é transformar o áudio recebido do rádio em um guetwey de áudio (oraspberry servirá como interface), sendo que eu possa acessar o raspberry remotamente via IP, e ouvir o que está passando no Rádio. Gostaria de saber se algum Voce pode me indicar qual o melhor caminho para fazer este projeto, com ideias, dicas tudo será muito bem vindo.
    Também tenho um SDR conectado no Raspberry dogo (rádio controlado por sw), pelo que disseste com a técnica mamed papis derrepente conseguiria usar o áudio da recepção desse dougo e usar para um getwey.
    Obrigado!

    1. Bruno, bom dia. Obrigado pelos elogios!

      Infelizmente não entendi sua mensagem. Poderia explicar novamente por favor?

  7. boa tarde.
    estou a usar o raspberry pi 3 e estou com dificuldade em rodar o seu projeto, será por ser o rasp3?
    Cumprimentos

    1. Boa tarde.

      Você poderia por favor dizer quais as dificuldades está passando (coloque aqui as mensagens de erro, por exemplo)? Dessa forma, eu imagino que conseguirei te ajudar de forma mais eficaz.

      Atenciosamente,
      Pedro Bertoleti

  8. Pedro tudo bem?

    Gostaria de saber se este projeto de receptor de radio internet vai funcionar num Raspberry Pi Zero W?
    Queria montar este kit e dar de presente,a pessoa que vai receber vai usar apenas como radio.

    1. valdocir.donizete,

      SIm, o projeto rodaria numa placa Raspberry Pi Zero W tranquilamente. Porém, para, isso, são precisas duas coisas:

      1) Soldar barras de pinos (a Raspberry Pi Zero W, ao contrário da Raspberry Pi 3B, não vem com as barras de pinos já soldadas)
      2) Colocar uma placa de som USB externa, já que a Raspberry Pi Zero W não contém os circuitos de áudio. Para isso, basta seguir as instruções deste artigo meu: https://www.embarcados.com.br/raspberry-pi-zero-w-placa-de-som-usb/

      Atenciosamente,
      Pedro Bertoleti

  9. Boa tarde, de alguma forma é possível programar para que mude de rádio quando entrar em comercial?

    1. Rômulo, boa tarde.

      Infelizmente desconheço uma forma de fazer isso, pois o stream de rádio não informa (ao menos desconheço isso) quando entra nos comerciais.

      Atenciosamente,
      Pedro Bertoleti

  10. Rapaz… O projeto é muito bacana e resolvi montar aqui. Meus pais, já idosos, costumam ouvir rádio AM pela madrugada afora e sempre reclamam que não pega bem (interior de Minas). Com um rádio desses eles pegariam até as estações da terra deles (interior de SP).
    Daí esbarrei no meu pouco conhecimento em programação e por ser iniciante em Raspberry. Por isso peço que desde já me desculpe pela minha ignorância, e me responda:
    a) Não sabia que existia diferenças entre Python 2 e 3. Seu código está em 2? Como faço para ele rodar em 2 no Raspberry (de cara ele rodou como se fosse 3)?
    b) Como meu conhecimento é maior em eletrônica, eu tirei os botões de controle de volume e adicionei um módulo amplificador com alto-falantes. O controle de volume com potenciômetro é bem mais cômodo e familiar para os idosos. Daí suprimi do código a parte do controle do volume (fixei em 50%). Dá problema isso?
    c) Para rodar o programa devo usar o “sudo”? No post de como usar o OLED era pra usar e aqui não… Mesmo assim, ele dá erro ao importar a biblioteca do OLED e também do GPIO.
    d) Teria que fazer o rádio iniciar assim que ligar, daí preferi a solução de iniciar após o login (arquivo profile). Dá certo?

    1. Renato, boa noite.

      Primeiramente, muito obrigado pela leitura e pelo contato! Gostei muito do uso que você dará ao projeto, adoro quando os projetos que faço ganham utilidades tão bacanas!

      Respondendo às suas dúvidas:
      a) As versões de Python presentes nas Raspberry por “default” (instaláveis sem frescuras) são a 2.7 e a 3. Eu construí o código pra versão 2.7 pois já utilizo esta versão há bastante tempo (ou seja, por questão de prática mesmo). Para rodar um programa com python 2.7, utilize o comando:

      python NomeDoSeuScript.py

      Para rodar com python 3, utilize o comando:

      python3 NomeDoSeuScript.py

      Achei esquisito rodar de cara como se fosse o 3. Qualquer coisa veja o site https://www.raspberrypi.org/documentation/usage/python/more.md e aplique as modificações necessárias para rodar em Python 3

      b) Não vejo problemas nisso.

      c) A questão do sudo é polêmica mesmo. Nesse caso, pode utilizar.
      Qual (ou quais) erros ocorreram? Poderia colocá-los aqui por favor? Dessa forma consigo te ajudar a corrigi-los.

      d) A solução que você se refere eu não conheço. O que eu conheço para tal fim (iniciar a aplicação assim que a Raspberry bootar) é acrescentar a chamada ao script no arquivo /etc/rc.local, com um & no final (por exemplo: python NomeDoSeuScript.py &).
      Por favor, mostre aqui como você fez, estou curioso.

  11. Parabéns pelo projeto. Gostaria de saber se é possível um projeto em q o py controlaria e processaria um audio e depois enviaria a um amplificador externo ???

  12. Olá Pedro…
    Montei esse projeto e funcionou perfeitamente, muito obrigado pelo projeto e dedicação.
    Gostaria de saber como faço pra ele iniciar junto a inicialização do sistema, ou seja sempre que ligar o Raspberry o sistema já vir pronto.
    Desde já fico grato pela ajuda!

    1. Sylvio, bom dia.

      Primeiramente, muito obrigado pela leitura e pelo elogio! É um prazer saber que estou fazendo projetos que estão ajudando os makers e hobbistas.
      Para iniciar o projeto junto com a inicialização do sistema, os seguintes procedimentos devem ser feitos:

      1) No script Python do projeto (código do projeto), façaum import os.time
      2) Como primeiro comando do Programa principal, executar um delay de 30 segundos (time.sleep(30)).
      Motivo: se isto não for feito, há grandes chances do script tentar usar a rede quando a mesma ainda não estiver conectada, podendo causar o fechamento “prematuro” do script ( = fechar antes mesmo de tocar alguma cosia).
      3) Siga os passos do site https://www.dexterindustries.com/howto/run-a-program-on-your-raspberry-pi-at-startup/ para inicializar o script no boot através do método do rc.local.

      Atenciosamente,
      Pedro Bertoleti

    2. Olá Pedro…

      Fiz como indicou e funcionou muito bem.
      Muito Obrigado!

  13. tem como fazer algom assim mais com Bluetooth ?
    o smart controla ele e ele so toca a radio qualquer uma ?

    1. Paulo, bom dia.

      Eu entendi que você gostaria de controlar o projeto por Bluetooth através de seu Smartphone, certo? Se sim, isso é possível ser feito (apesar de eu não ter feito algo assim ainda, não vejo impeditivo algum).

      Quanto a tocar qualquer rádio, apenas tenha um cuidado: como o artigo diz, o formato do arquivo que contém as informações de streaming (no caso deste projeto, arquivo .pls) deve ser compatível com o mplayer. Se isso for obedecido, a rádio pode ser tocada sim.

      Atenciosamente,
      Pedro Bertoleti

  14. Nelson, boa tarde.

    Não seria possível por dois motivos:

    1) Somente o Arduino Uno + display não possui conectividade com a Internet.
    2) Mesmo se existisse conectividade com a Internet neste caso, o Uno não é capaz de lidar stream e decodificação de áudio.

    Atenciosamente,
    Pedro Bertoleti

  15. TERIA COMO RODAR NUM UNO ARDUINO COM DISPLAY 1.8 TFT V1.0 SPI 128*160

    GRATO

    1. Para construir um rádio web wifi com peças baratas segue a lista
      ——————————————————————————————————
      1-ESP8266
      2-VS1053B
      3-ky-040
      4-Alto-falantes
      5-pam8403

      6-https://www.ebay.com/itm/0-96-Blue-Yellow-I2C-IIC-128X64-OLED-Serial-LCD-LED-Display-Module-for-Arduino/232472352466?hash=item36206e96d2:g:9UIAAOSw9sJZqPuc