Cornell University ECE4760
Audio over UDP from PicoW to PIcoW

Pi Pico RP2040

 

UDP on direct Wifi link from PicoW to PicoW
The Picow has a WIFI module that can be used to connect to the internet, using the LWIP package running on the rp2040. This project uses the UDP protocol to send/receive data between two picoW's on their own subnet. The sender is configured as a WIFI access point to which the other picow attaches. This configuration allows for performance measurements on send/receive functions, with minimal interference from other network traffic. An ISR on the sending end generates a double-buffered DDS sine wave at a fixed sample rate, which varied from 4000 to 100000 samples per second for testing. An ISR on the receiving end double buffers the data for playback through a SPI, 12-bit, DAC. The code simulates a real application with a blinky thread, serial thread, UDP send thread, and UDP receive thread. There is also the receive ISR required for async packet arrival by LWIP. The threads and ISRs are segregated onto two cores, with core-0 doing all the network work, and core-1 doing the audio work. Since we have complete control of the network IP addresses are assigned statically. Weirdly, the LWIP library appears to require that an access point assign IP addresses using DHCP, so that feature is used, but the IP address assigned in not used.

A serial connection from the send pico to a laptop is used for control and debugging. There is an option to use serial to set up the send/receive functions, but the auto-setup is easier. When using auto-setup you need to connect gpio2 to Vdd on the sending picow, and leave it unattached on the receiving picow. The sending end (access point) has to boot up before the receiving end tries to join the network. In auto-setup mode, once the receiving end attaches, there are just two commands available on the sending end:
-- play frequency (example: play 400) sends the specified frequency of sine wave on the send side, and plays it on the receive side.
-- stop just turns off the DDS on the send side, and zeros the DAC on the receive side.

UDP send/recv code is slightly modified to run in Protothreads and is from :
-- Pico examples https://github.com/raspberrypi/pico-examples/tree/master/pico_w/wifi/udp_beacon
-- lwip contrib apps: https://github.com/lwip-tcpip/lwip/tree/master/contrib/apps

The structure of the program is built around Protothreads, with a thread to send a packet, and a thread to process a received command packet, but note that the actual low level packet receive is performed by an ISR required by LWIP. The ISR is a short as possible and just copies the receive buffer, then signals a semaphore to run the receive thread, if it is a command. If the receive buffer is data, then it is handled by the audio ISR.

Performance
A short packet sent from send to receive and back takes from 10 to 50 mSec or so. Sustained throughput of 1000 byte audio data packets is at least 800 kbits/sec. At 50,000 (or lower) samples/sec, with two byte samples, there is essentially no packet loss and no LWIP errors. However, since both the data source and sink are running in ISRs on separate machines, the mismatch in cpu frequencies (up to 30 ppm) will cause a missed or duplicated packet every few minutes. A rate 50,000 samples corresponds to 800 kbits/sec. At 60,000 samples/sec the sine wave wiggles a few times/sec, implying an occasional packet loss, but also there is a steady stream of error/warning from LWIP: [CYW43] got unexpected packet -9. The cyw43 driver code suggests that this is due to a bad status bit in the UDP header. Modifying the file in the pico SDK called lib/cyw43-driver/src/cyw43_ll.c by removing the line CYW43_WARN("got unexpected packet %d\n", ret); kills the message, which one version of the SDK says is an artifact of the SPI interface.

The following tests are done in a quiet WIFI environment. At 40,000 samples/sec (640 kbits/sec), and with the two picow's are two meters apart, there are very few missed packets. The audio artifact of a missed packet is either a click, or a brief burst of buzzing edge noise at 80 Hz, the packet rate. A sine wave played for several minutes between noise bursts. When the picow's are 5 meters apart, and not line-of-sight behind a wood wall, the sine wave is stable for a while, then bursty for several seconds, then stable again.

Code, Project ZIP


 


Copyright Cornell University November 11, 2023