VS1053 asynchronous socket read

Discussion about programs, libraries and tools that work with MicroPython. Mostly these are provided by a third party.
Target audience: All users and developers of MicroPython.
Post Reply
User avatar
cemox
Posts: 34
Joined: Mon Oct 08, 2018 5:31 pm
Location: Turkey

VS1053 asynchronous socket read

Post by cemox » Tue Apr 28, 2020 11:28 am

I am building a simple internet radio with my ESP8266 Lolin Board + VS1053 board. The code below works (I removed irrelevant parts of the code):

Code: Select all

from machine import Pin, SPI
import utime
import socket
hspi = SPI(1, baudrate=2000000) #2M is good

url = 'http://mp3channels.webradio.antenne.de/chillout'

def writeData(buf): #sends data to VS1053
    waitDREQ()
    XDCS.off()
    hspi.write(buf)
    XDCS.on()

def http_get(url):
    _, _, host, path = url.split('/', 3)
    addr = socket.getaddrinfo(host, 80)[0][-1]
    s = socket.socket()
    s.connect(addr)
    s.send(bytes('GET /%s HTTP/1.1\r\nHost: %s\r\n\r\n' % (path, host), 'utf8'))
    while True:
        data = s.recv(32)
        if data:
            writeData(data)
        else:
            break
    s.close()

But, when I try the code with 128kb streams, there are lots of lags in the sound. (I set the clock multiplier to the highest in VS1053 also tried higher SPI rates).

Then I decided to use Asyncio (of which I have limited understanding) with the plan of using two buffer (say size of 128 bytes each), while sending first buffer to VS1053, asynchronous socket fills the second buffer (I am not sure if this is a good approach though).

But in my first attempt with Asyncio, even 32kb stream does not sound ok (laggy). Here is the code:

Code: Select all

import socket, utime
import uasyncio as asyncio
import vs1053 as vs

url = 'http://mp3channels.webradio.antenne.de/chillout'

def writeData(buf): #sends data to VS1053
    waitDREQ()
    XDCS.off()
    hspi.write(buf)
    XDCS.on()

async def get_stream_data(url):
    _, _, host, path = url.split('/', 3)
    print(host,path)
    reader, writer = yield from asyncio.open_connection(host, 80)
    print(reader, writer)
    print("================")
    query = bytes('GET /%s HTTP/1.1\r\nHost: %s\r\n\r\n' % (path, host), 'utf8')
    print(query)
    yield from writer.awrite(query)
    
    while True:
        line = yield from reader.read(32)

        if line:
            writeData(line)

loop = asyncio.get_event_loop()
loop.create_task(get_stream_data(url))
loop.run_forever()

VS1053 receives 32 byte packets safely. Reading 128 byte packets from stream and sending it to VS1053 in 32 bytes packets can be good approach, but I could not figure out how to do it yet.

I am stuck in the middle of the project now.

gyroing
Posts: 3
Joined: Thu Apr 23, 2020 5:46 pm

Re: VS1053 asynchronous socket read

Post by gyroing » Thu Apr 30, 2020 1:20 pm

here is my internet radio code:

Code: Select all

from machine import Pin, SPI
from vs1053 import vs1053
import uasyncio as asyncio

sck = Pin(14) 
miso = Pin(12)
mosi = Pin(13)



spi = SPI(1, 160000 , sck=sck, mosi=mosi, miso=miso)

player = vs1053.Player(
    spi,
    xResetPin = 27,
    dReqPin = 34,
    xDCSPin = 33,
    xCSPin = 32,
    CSPin = None
)

async def play_radio(url):
    import socket
    _, _, host, path = url.split('/', 3)
    addr = socket.getaddrinfo(host, 80)[0][-1]
    s = socket.socket()
    s.connect(addr)
    s.send(bytes('GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n' % (path, host), 'utf8'))
    while True:
        data = s.recv(1024)
        if data:
            player.writeData(data)
        else:
            break
        await asyncio.sleep(0)  
    s.close()
    
player.setVolume(1)    
loop = asyncio.get_event_loop()
loop.create_task(play_radio('http://mp3channels.webradio.antenne.de/chillout'))
loop.run_forever()
please consider vs1053 can accept buffer up to 2k byte byte and it is perfect in 1024 byte , also the you should set the baudrate experimentally :)

User avatar
tve
Posts: 216
Joined: Wed Jan 01, 2020 10:12 pm
Location: Santa Barbara, CA
Contact:

Re: VS1053 asynchronous socket read

Post by tve » Thu Apr 30, 2020 5:11 pm

Couple of comments:
  • You're not really using asyncio 'cause you're not using asyncio.open_conncetion to get streams, so all the socket code you have is blocking.
  • You have a single activity, so asyncio would bring no benefit. there's nothing to switch between.
  • You are ignoring the return values of send and recv, these functions do not guarantee to send or receive the whole buffer!
Personal opinion: using an esp8266 with MP is asking for frustration ;-)
Last edited by tve on Sat May 02, 2020 6:34 am, edited 1 time in total.

User avatar
cemox
Posts: 34
Joined: Mon Oct 08, 2018 5:31 pm
Location: Turkey

Re: VS1053 asynchronous socket read

Post by cemox » Sat May 02, 2020 5:06 am

Thank you. I am using

Code: Select all

reader, writer = await asyncio.open_connection(host, port)
in my function now.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: VS1053 asynchronous socket read

Post by pythoncoder » Sat May 02, 2020 8:02 am

I am currently working on an asynchronous VS1053 driver. It accepts an MP3 stream and plays it as an asynchronous task.
Peter Hinch
Index to my micropython libraries.

Didtho
Posts: 6
Joined: Thu Apr 29, 2021 11:03 pm

Re: VS1053 asynchronous socket read

Post by Didtho » Sat May 01, 2021 9:39 am

Hello,
Where is the vs1053 library you are using in the above code available?
Because the one I find (peterhinch) does not have the vs1053.Player, the setVolume. I want to listen to a webradio and I cannot find an example with the peterhinch library.
Thank you.

Post Reply