bastibl / gr-rds

FM RDS/TMC Transceiver
http://en.wikipedia.org/wiki/Radio_Data_System
GNU General Public License v3.0
225 stars 73 forks source link

Running rds_tx.grc/.py headless on ARM64 Orange Pi? #83

Open gabba43 opened 4 weeks ago

gabba43 commented 4 weeks ago

Sorry to bother you again :)

now, I installed gnuradio on my Orange Pi Zero 3 and tried to run the script headless by changing it to 'No GUI' in the options panel and exporting it to a .py-file. It certainly runs on the OPi and doesn't give any other errors than on my Linux Mint machine but there's no MPX generated. On my desktop machine the .py-script runs perfectly fine! Any help would be greatly appreciated!

System: OPi Zero 3, 2 Gb ram, Allwinner H618/Debian bookworm server, Linux 6.1.31-sun50iw9 kernel, ARM64; version 1.0.4 (Orange Pi release)

Edit: Maybe different python versions are a problem (3.10.12 on desktop vs. 3.11.2 on opi).

rds_tx_for_opi rds_tx_for_opi.zip

bastibl commented 4 weeks ago

You seem to specify the audio devices manually (hw:4,1 and hw:3,0). Maybe the mapping is different on the different platforms, the devices support different sample rates, or you want to use a different audio subsystem (e.g. pulse)?

gabba43 commented 4 weeks ago

Thank you! Forgot to say that. I saved the installation logs of both gnuradio & deps as well as gr-rds, I can post them tomorrow. Nonetheless there were no errors when compiling & installing.

Also, I uninstalled & reinstalled gnuradio & deps after the first try but changed the repos to the official debian ones before reinstalling (they were set to a Huaweicloud from the Orange Pi devs). Maybe that helps.

I made sure that the mapping & sample rates are correct but I'll check tomorrow again. Maybe I'll add an entry to .asoundrc to make sure the USB-sound card is fixed to 192kHz. I deactivated pulse on the desktop beforehand already as I'm using jack (which only runs once started) - so when not using jack, only ALSA is running. On the debian server, I think there's also only ALSA installed but I'll make sure that this is the case tomorrow. Maybe it has pipewire or so, I'll kick that out.

bastibl commented 4 weeks ago

I don't think that this is an installation issue. Since you mentioned that you ran the same script on your desktop, I just wondered if you forgot to adapt the device name parameter of the audio source and sink.

gabba43 commented 3 weeks ago

So, after uninstalling, changing deps to official ones and reinstalling, it finally works and even with the OPis internal sound card! But... CPU load is on 95% on the Orange Pi Zero 3, 2gb. RAM usage isn't a problem, less than 100mb. RDS pops up and goes off again. So the OPi is underpowered. Luckily, I still have a couple of HP 260 G2 DMs with Pentium 4405U CPUs laying aroung which will be perfect for this job (I hope). I'll install a headless Debian on them as well. Now I just need to get the dynamic PS (changing every 3 secs) to work :D

bastibl commented 3 weeks ago

I just tested it and it really takes much more CPU than I would have expected. That's in no way optimized :-/ I hope, it works with your other device.

argilo commented 3 weeks ago

A bunch of blocks have Maxoutbuf set to 10, which forces samples to be processed in very small batches. This seems to increase CPU load a lot.

Unfortunately, removing that results in a lot more output buffer underruns. The Audio Source block has "OK to Block" set to "No" to avoid the two-clock problem, but unfortunately that setting is ignored in nearly all audio backends (except Portaudio, which is unlikely to be used because ALSA has a higher priority).

gabba43 commented 3 weeks ago

I understand. So setting a fixed, higher, buffer size and inputting audio with a fixed (e.g. 4096), higher, buffer size (-bufsize?) using ffmpeg is not a solution?

Edit: If I'm not mistaken, buffer under- over overruns can lead to pops and crackling sounds but maybe it would be worth a try to see if that helps and how bad the effects are. I think StereoTool as an MPX generator also uses a standard buffer size of 4096.

argilo commented 3 weeks ago

You could try changing the outbuffer variable from 10 to 0, and see whether that helps.

Also, for your use case (FM modulation done in hardware) there's no reason to use an internal sample rate of 380 ksps. You could use 192 ksps instead, but that would require a bunch of changes to the flow graph. (Change usrp_rate to 192000, change audio Rational Resamplers to interpolation 4 & decimation 1, change Root Raised Cosine Filter to interpolation 16, gain 11.1, sample rate 38000, num taps 16*11, add a Rational Resampler block after Root Raised Cosine Filter with interpolation 192 & decimation 38, and remove the Rational Resampler block on the output.)

I expect those changes would reduce CPU utilization quite a bit.

gabba43 commented 3 weeks ago

Awesome :D Actually tried that already but changed only the sample rate which didn't work out.

Edit: Yep, those steps reduced CPU load quite drastically to about max. 7%. It always jumps between 1 and 7. Now I just need to connect it to my tx which I sadly can't do in this exact moment but you'll hear from me later today.

argilo commented 3 weeks ago

One small correction (which I edited in above): Root Raised Cosine Filter interpolation should be 16.

gabba43 commented 3 weeks ago

Boomshakalaka! It works like a charm! CPU load is at about 5-8% when playing & resampling audio to 48kHz in FFMPEG and encoding MPX (stereo & RDS) at the same time. I'm gonna finish my tutorial and post it today, crediting you of course. I'll post a link here as well. Also, I added both of my working project files, the .grc & the .py. Thank you very much again! rds_tx_for_opi_1.0.zip

argilo commented 3 weeks ago

One last thing: from the screenshot above, it looks like you weren't using the latest version of the rds_tx.grc flow graph. You'll want to incorporate the recent changes made in #79, otherwise FM stereo channel is not going to work properly with the 192 ksps intermediate sample rate. (The left & right channels may not remain separated.)

gabba43 commented 3 weeks ago

Here's that one with latest version of the rds_tx.grc flow graph. rds_tx_for_opi_1.0.zip

Edit: Here's my tutorial on Radionecks: https://radionecks.co.uk/viewtopic.php?t=3690

argilo commented 3 weeks ago

Nice to see you got it working!

It should be possible to do dynamic RDS updates via TCP if you put back the Socket PDU block and connect it to the RDS Encoder. Some details in this issue: #44

Latency is probably going to be an issue, since a lot of RDS bits will probably build up in GNU Radio buffers. gr-rds should probably have some latency management in the style of gr-latency_manager. References:

argilo commented 3 weeks ago

84 should fix the CPU utilization problem without having to disable the output buffer limits, and it also reduces RDS latency substantially.

gabba43 commented 3 weeks ago

Did I understand it right that you basically proposed two (actually 3) things: Removing the Maxoutbuf setting for these blocks (Multiply, Add, Frequency Mod)

Also, two low-sample-rate blocks (RDS Encoder, Chunks to Symbols) do not specify a maximum output buffer size. Adding the setting to the RDS Encoder block

I've added the setting to the Chunks to Symbols block as well, but unfortunately it has no effect at the moment due to a bug

Then I'll give it a try later using the latest flowgraph (or are those specific changes already included here?).

argilo commented 3 weeks ago

The changes I proposed in #84 are:

If you make those changes in your flow graph (apart from the Frequency Mod block, which your flow graph doesn't have) you should be able to set the outbuffer variable back to 10 to keep RDS latency under control.

There will still be 20 seconds of RDS latency, which is not ideal, but it's much better than three minutes, which you'll get with the current flow graph if you set outbuffer to 0.

gabba43 commented 2 weeks ago

Sorry for my late reply, here's the updated version: rds_tx_for_opi_1.1.zip

argilo commented 2 weeks ago

Looks good.

By the way, you could shave another 7 seconds or so off the RDS latency by manually editing the .py file to replace:

self.digital_chunks_to_symbols_xx_0.set_max_output_buffer(10)

with

self.digital_chunks_to_symbols_xx_0.set_max_output_buffer(0, 10)

This is a workaround for this bug: https://github.com/gnuradio/gnuradio/issues/7534