ShadowLight8 / Dynamic_RDS

Dynamic_RDS - Plugin for Falcon Player (FPP) to manage an FM transmitter and custom RDS (radio data system) messages similar to what is seen from typical FM stations. Reads multiple fields from media metadata and playlist. Runs on Raspberry Pi and BBB. Supports the QN8066 chip.
GNU General Public License v3.0
9 stars 1 forks source link

HifiBerry or alternative DAC for Dynamic_RDS #23

Open TomasRa1 opened 9 months ago

TomasRa1 commented 9 months ago

On https://www.aliexpress.com/item/1005005393398013.html is possible to buy very cheap but with relatively good audio quality DAC for Rpi with IC PCM5102A. HifiBerryPCM5102A_DAC It works nicely as good quality audio driver for FM transmitter as I tested. For Rpi connection it needs these Rpi GPIOs: +5V/pin2, GND/pin6, BCK/pin12, LCK/pin35, Din/pin40 You can see on picture mutual connection and also 4 PCB jumpers, which must be soldered as on this picture: PCM5102_jumpers For to use this or similar Rpi HifiBerry DAC or also for to use Rpi built-in PCM DAC we need reconnect Dynamic_RDS PWM output from pin32 (GPIO12) PWM0 to any other free pin, because built-in Rpi audio or external HifiBerry DAC needs this pin PWM0. For more detailed informations regarding Rpi implementation of this HifiBerry DAC module, please visit eg. https://blog.himbeer.me/2018/12/27/how-to-connect-a-pcm5102-i2s-dac-to-your-raspberry-pi/. I decided to use RPi pin11 (GPIO17) for PWM output.

It needs to modify "Dynamic_RDS_Engine.py".

  1. Delete (or comment by "#") all regarding PWM0.
  2. Added on the beginning of file to the end of IMPORT loads (from line 17):
    
    ~~~~~~
    import smbus
    import subprocess
    import unicodedata
    from time import sleep
    from datetime import date, datetime, timedelta
    from urllib.request import urlopen
    from urllib.parse import quote
    import RPi.GPIO as GPIO     # RPi GPIO for transmitter output power set
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(17, GPIO.OUT)    # Set GPIO17/pin11 as PWM2 OUTPUT
    pwm_2 = GPIO.PWM(17, 18000) # PWM2 set to GPIO17/pin11,PWMf=18kHz
    pwm_2.start(0)              # PWM2 duty cycle=0 (0V on pin11)

@atexit.register def cleanup(): try: logging.debug('Cleaning up fifo') os.unlink(fifo_path) except: pass logging.info('Exiting')

===============

Basic I2C Class


```
3. Add under "**class QN80xx(Transmitter):**/**def update(self):**/**# TX gain changes and input impedance**" and above "**def shutdown(self):**"(from line 271):
```
    # TX output power update
    pwm_2.ChangeDutyCycle(int(config['DynRDSQN8066AmpPower']))
    logging.info('PWM2 duty cycle updated to {}%'.format(config['DynRDSQN8066AmpPower']))
    self.activePWM = True
```
4. Modify  **# With everything stopped, disable PWM** (from line 279):
```
     # With everything stopped, disable PWM
    if self.activePWM:
      logging.debug('Stopping PWM2')
      pwm_2.ChangeDutyCycle(0)
      logging.debug('PWM2 duty cycle = 0')
      GPIO.cleanup()
      logging.debug('GPIO cleanup')
      self.activePWM = False
```
__________________________________________________________________________________

MODIFY **Dynamic_RDS.php**:

1. Delete or comment by "**//**" PWM0 detection on lines 97-99
2. Modify line 100 to: `PrintSettingGroup("DynRDSPowerSettings", "", "", 1, "Dynamic_RDS", "DynRDSFastUpdate");`
3. Modify end of file lines 116-124:

```
> <h2>PWM and audio hardware setup</h2>
> <div class="container-fluid settingsTable settingsGroupTable">
> For output power control of 
> Transmitter board: <li>Connect Transmitter board PWM input pin -> to RPi pin11 (GPIO17)</li> <li>Use ferrite bead around cable 
> between RPi and Transmitter board.</li> For HiFiBerry DAC: <li>Add line to /boot/config.txt:</li> <li>dtoverlay=hifiberry-dac</li> 
> <li>HiFiBerry/RPi connection: +5V/pin2, GND/pin6, BCK/pin12, LCK/pin35, Din/pin40</li> </div> </div>                                         
> <div class="container-fluid settingsTable settingsGroupTable">
> </div>
> </div>
```

__________________________________________________________________________________

MODIFY **settings.json** from line 115 (to 140):

```
>         "DynRDSQN8066ChipPower": {
>             "name": "DynRDSQN8066ChipPower",
>             "description": "Chip Power (92-122)",
>             "tip": "Adjust the power output from the transmitter chip",
>             "restart": 0,
>             "reboot": 0,
>             "type": "number",
>             "min": 92,
>             "max": 122,
>             "step": 1,
>             "suffix": "dB&mu;V <i class='fas fa-fw fa-bolt fa-nbsp ui-level-1'></i>",
>             "default": 120
>   },
>         "DynRDSQN8066AmpPower": {
>             "name": "DynRDSQN8066AmpPower",
>             "description": "Amp Power (0-100)",
>             "tip": "Adjust the power output for the amplifier after the transmitter chip.",
>             "suffix": "% <i class='fas fa-fw fa-bolt fa-nbsp ui-level-1'></i>",
>             "restart": 0,
>             "reboot": 0,
>             "type": "number",
>             "min": 0,
>             "max": 100,
>             "step": 1,
>             "default": 0
>   },
```
I am not so proffesional as Mr. Nick Anderson. I think that my code for Dynamic_RDS_Engine.py needs tunning, because I am only amateur. Eg. I was also not sucessful with attempt to not send PWM value repeatedly when not changed. But I tested this my solution in longer transmitter's operation sucessfuly.
I also think that when we will sucessful with improve i2c I/O errors during communication by replace SMBUS with "SOFTWARE I2C" than we can change all values setting on Plugin FPP web page to change for immediately update without need any restart (as I already realized above on PWM and chip power set).
I hope that Nick will be understanding :-) 
ShadowLight8 commented 8 months ago

Ability to switch which PWM is being used will be part of #27, but it is just the framework at the moment

ShadowLight8 commented 8 months ago

I decided to keep #27 to be the basic enable/disable for PWM. I'll start a new pull request to allow changing which pins are being used for PWM and I2C.

ShadowLight8 commented 8 months ago

@TomasRa1 I've had some time to read through all the info you posted. I've ordered, what looks like, the same I2S board so I have a way to test. (https://www.amazon.com/gp/product/B08SLPHY2Z/)

I did find https://forums.raspberrypi.com/viewtopic.php?t=220082 mentioned being able to use i2s and hardware pwm at the same time by moving pwm to Pin 32 / GPIO 12, so I'm going to give that a try first. That would allow the hardware pwm to still be used, just on a different pin.

I saw your use of RPi.GPIO so I looked into it more as an option for software PWM. That which lead me to https://pythonhosted.org/RPIO/. RPIO can do PWM by using DMA, so it's the middle ground between hardware PWM and software PWM. Something I can look into, especially if the hardware pwm pin change doesn't work.

I've started work on being able to change hardware PWM pins. It's up as a draft PR #28

TomasRa1 commented 8 months ago

Thank you very much Nick! HiFiBerry DAC needs these Rpi GPIOs: +5V/pin2, GND/pin6, BCK/pin12, LCK/pin35, Din/pin40. There are GPIO pins 18, 19, 21. I would like to prefer configure any free pin for PWM, because it is universal at all cases. Pin 11 (Gpio17) is located next to GND pin and it is thanks this position shielded from other i2c pins, which we use for Transmitter module and at the same time pin11 is next to these i2c pins, we can easy use flat 6pin connector for RPi and Transmitter interconnection. I think it is favorable to use pin11 for PWM.

It is also possible to update PWM value dynamically in time, we do not need restart FPPD or any reboot for to change PWM value (the same as power of TX chip 8066). I changed Dynamic_RDS.php and settings.json source files (as I already described here above) for this dynamic set of PWM value. And also tested OK.

ShadowLight8 commented 8 months ago

I've got the hardware PWM pin selection done in #28 Next, I'll follow your idea and make the PWM value dynamic so restarts are not needed. After that, I'll start looking into using RPIO so any gpio pin can be PWM.

ShadowLight8 commented 8 months ago

@TomasRa1 I've merged #28, but it required an FPP change that has been merged, but only to master/fpp. I've guessing the next release will have it. Until then, the hardware pwm pin change won't work.

I'll start looking into using RPIO next!

chrkov commented 8 months ago

I have been looking for a nice DAC that has RCA outputs. I found this (https://www.amazon.com/Decoder-Amplifier-PCM5102-PCM5102A-Headphone/dp/B0C7KQPR7S/ref=sr_1_50?crid=KTYBTOFN5CGZ&keywords=PCM5102&qid=1704083256&s=industrial&sprefix=pcm5102%2Cindustrial%2C104&sr=1-50) and just wondering if you think this would work also? It seems to have the same connections.

TomasRa1 commented 8 months ago

Yes, it is the same chip PCM5102A, it must also works. I hope that connection could be: AltDAC_PCM5102A BCK = BCK DATA = DIN LRCK = LCK GND = GND VCC = VIN

FLT=N = SCK jumper soldered (ICpin12=GND) FMT=I2S

Please, test it and inform us regarding result if my ideas above are correct. Thank you.

TomasRa1 commented 8 months ago

@TomasRa1 I've merged #28, but it required an FPP change that has been merged, but only to master/fpp. I've guessing the next release will have it. Until then, the hardware pwm pin change won't work.

I'll start looking into using RPIO next!

It will be nice to implement PWM via RPIO, thank you very much! https://pythonhosted.org/RPIO/

from RPIO import PWM

# Setup PWM and DMA channel 0
PWM.setup()
PWM.init_channel(0)

# Add some pulses to the subcycle
PWM.add_channel_pulse(0, 17, 0, 50)
PWM.add_channel_pulse(0, 17, 100, 50)

# Stop PWM for specific GPIO on channel 0
PWM.clear_channel_gpio(0, 17)

# Shutdown all PWM and DMA activity
PWM.cleanup()
ShadowLight8 commented 8 months ago

The merge of #31 makes it so the dynamic changing of the pwm amp power works. I'm continuing work on RPIO

ShadowLight8 commented 8 months ago

Draft pull request of work in progress is up #34

ShadowLight8 commented 7 months ago

RPIO is pretty old and no longer maintained, so it doesn't have support already in place for the newer Pi's. I'm looking into options to update it or finding a similar PWM via DMA library. A key part is finding something that is light weight.

chrkov commented 7 months ago

I dont know if it helps, but maybe look at WLED and what they are doing? It seems they have the ability to move pins around so they must be using something. Maybe it would work for PI. Again, I am no programmer, just tossing ideas out.

chrkov commented 7 months ago

Should the DAC be able to work now without affecting this plugin? Because I have the DAC hooked up and it is working (outputs sound), but now I am seeing issues with this plugin. I believe PWM is not working as I can no longer adjust the power. I have the PWM set to "PIN 32 / GPIO 12". The only reason I am thinking this is because my range is no where near what it was before.

ShadowLight8 commented 7 months ago

I'll check that pin's output and try to add in my DAC this weekend to test.

ShadowLight8 commented 7 months ago

@chrkov I've not physically hooked up the DAC yet, but I did setup everything on the PI for it (confirmed that is show up with aplay -l). Using my logic analyzer, I can see PWM output on Pin 32. Something might change when I actually connect the DAC and play audio, so I'll check again once I'm to that point. PWM-Pin32

ShadowLight8 commented 7 months ago

PWM via DMA Notes Seems that no single option would cover everything, but seems like bringing together parts of each might be an option.

https://github.com/jbentham/rpi

https://github.com/besp9510/dma_pwm

https://github.com/metachris/RPIO

https://sourceforge.net/projects/raspberry-gpio-python/

chrkov commented 7 months ago

Is there any logs or anything I can do to help troubleshoot the issue? I am not sure if there is any feedback given when the change is made to see if its taken. I can see in the logs when I make a change to the power: 03:36:46 INFO Config {'DynRDSEnableRDS': '1', 'DynRDSPSUpdateRate': '2', 'DynRDSPSStyle': 'Merry|Christ-|-mas!', 'DynRDSRTUpdateRate': '6', 'DynRDSRTSize': '32', 'DynRDSRTStyle': 'Christmas on 124th Ave|{T}[ / {A}]|[Track {N} of {C}]|See you for the 2024 Show!', 'DynRDSPty': '22', 'DynRDSPICode': '3DC6', 'DynRDSTransmitter': 'QN8066', 'DynRDSFrequency': '88.9', 'DynRDSPreemphasis': '75us', 'DynRDSQN8066Gain': '0', 'DynRDSQN8066SoftClipping': '1', 'DynRDSQN8066AGC': '0', 'DynRDSQN8066ChipPower': '122', 'DynRDSQN8066PIHardwarePWM': '1', 'DynRDSQN8066AmpPower': '100', 'DynRDSStart': 'FPPDStart', 'DynRDSStop': 'Never', 'DynRDSCallbackLogLevel': 'INFO', 'DynRDSEngineLogLevel': 'INFO', 'DynRDSmpcEnable': '1', 'DynRDSAdvPISoftwareI2C': '1', 'DynRDSAdvPIPWMPin': '12,4', 'DynRDSQN8066DigitalGain': 0, 'DynRDSQN8066InputImpedance': 1, 'DynRDSQN8066BufferGain': 1}

TomasRa1 commented 7 months ago

Nick, please, try to use RPi.GPIO solution and adapt it, please. I tested it sucessfully. Yes, it is SW emulation, but we do not need extrem speed resp. PWM frequency 18kHz is low and RPi manage it without any problem or any overload. It is good to block PWM pin on the transmitter board by small ceramic capacitor 22n against GND. This capacitor round the edges of the pulses and remove noise from the PWM wire and capacitive coupling PWM signal to other wires. I also tested sucessfully.

Chrkov: (if I understand correctly) PWM signal is only transmited signal from RPi to transmitter (TX) board. On the TXboard is analog OP which convert digital PWM signal to analog level, which regulate voltage to PA driver. It is simple passive analog solution, not digital. Due to PWM signal cannot be validated by CPU as backward received data for secondary validation. We can only set PWM frequency and duty cycle and regarding duty cycle we can display percentual level of regulated voltage - eg. 100% = 10V and 10% = 1V, etc. We cannot validate how to data were set. We can only display actual set value of duty cycle. But you can connect SWR metter between RF output connector and antenna and you can see forward (and reflected) output power directly.

chrkov commented 7 months ago

So two things. 1. Can I put a voltage meter on the PWM pin then and measure the voltage out to verify if its working then? If so, was your example about 1V = 10% and 10V = 100% just an example or what I should really see?

Is there a cheap SWR meter? I would only need it for this, so I dont want to spend a lot on it. Does something like this (https://www.amazon.com/Astatic-PDC1-100-Watt-Meter/dp/B004ULN610) do the trick for basic testing? It says for CB, but I know those frequencies are different than FM.

ShadowLight8 commented 7 months ago

Is there any logs or anything I can do to help troubleshoot the issue? I am not sure if there is any feedback given when the change is made to see if its taken. I can see in the logs when I make a change to the power:....

@chrkov Can you run grep -i dt /boot/config.txt? That will list the dtparam and dtoverlay lines. It's possible that something got messed up since the code to edit that file is not very fancy.

You can also see what the PWM settings are with cat /sys/class/pwm/pwmchip0/pwm0/period Should be 18300 cat /sys/class/pwm/pwmchip0/pwm0/duty_cycle Varies with Amp Power setting cat /sys/class/pwm/pwmchip0/pwm0/enable Should be 1

Also, I just merged #34 which gets the other 2 hardware pwm pins working. You might give that a try.

ShadowLight8 commented 7 months ago

Nick, please, try to use RPi.GPIO solution and adapt it, please. I tested it sucessfully. Yes, it is SW emulation, but we do not need extrem speed resp. PWM frequency 18kHz is low and RPi manage it without any problem or any overload. It is good to block PWM pin on the transmitter board by small ceramic capacitor 22n against GND. This capacitor round the edges of the pulses and remove noise from the PWM wire and capacitive coupling PWM signal to other wires. I also tested sucessfully.

@TomasRa1 I'll take a look at this route with software PWM as much as I don't like it :) Since you've had success with it, it does give me confidence that it is a reasonable option.

chrkov commented 7 months ago

Here is the outputs of those commands. None of the cat commands found a file? Is there a typo there or is that my problem? If I do a 'ls' under /sys/class/pwm' I dont see any subdirs...

fpp@cmk-od-fpp01:~ $ grep -i dt /boot/config.txt

framebuffer_width=1280

sdtv_mode=2

dtparam=i2c_arm=on

dtoverlay=i2c-gpio,i2c_gpio_sda=2,i2c_gpio_scl=3,i2c_gpio_delay_us=4,bus=1

dtparam=i2s=on

dtparam=spi=on

dtoverlay=gpio-ir,gpio_pin=17

dtoverlay=gpio-ir-tx,gpio_pin=18

dtparam=audio=on

dtoverlay=vc4-kms-v3d

dtparam=spi=on

dtparam=i2c_arm=on

dtoverlay=i2c-gpio,i2c_gpio_sda=2,i2c_gpio_scl=3,i2c_gpio_delay_us=4,bus=1

dtparam=audio=on

dtoverlay=pwm dtparam=i2s=on dtoverlay=hifiberry-dac dtparam=i2c_arm=on

fpp@cmk-od-fpp01:~ $ cat /sys/class/pwm/pwmchip0/pwm0/period cat: /sys/class/pwm/pwmchip0/pwm0/period: No such file or directory fpp@cmk-od-fpp01:~ $ cat /sys/class/pwm/pwmchip0/pwm0/duty_cycle cat: /sys/class/pwm/pwmchip0/pwm0/duty_cycle: No such file or directory fpp@cmk-od-fpp01:~ $ cat /sys/class/pwm/pwmchip0/pwm0/enable cat: /sys/class/pwm/pwmchip0/pwm0/enable: No such file or directory

ShadowLight8 commented 7 months ago

@chrkov For the cat commands, that tells me the hardware pwm didn't get setup correctly for some reason. A few things in your config.txt that might be part of it: dtoverlay=pwm dtparam=i2c_arm=on While neither are wrong, the plugin updates the pwm line with pin and func (otherwise it defaults to Pin 12 / GPIO 18). The i2c_arm=on is hardware i2c where the i2c-gpio is the software i2c. I'm surprised to see both.

If you haven't already, update the plugin to get the latest.

To see if we can get it out of this state using the plugin, on the Dynamic_RDS config page, change the PI PWM Pin to Pin 12 / GPIO 18, uncheck Enable Pi PWM, uncheck Use PI Software I2C. That should clean up things in the /boot/config.txt. You can check with the grep -i dt /boot/config.txt to see the changes. Next, you can re-enable PWM, re-enable software I2C, and set your PWM pin again. Run the grep command again and you should see lines like: dtoverlay=i2c-gpio,i2c_gpio_sda=2,i2c_gpio_scl=3,i2c_gpio_delay_us=4,bus=1 without an uncommented dtparm=i2c_arm=on dtoverlay=pwm,pin=12,func=4 After that reboot and see if that clears things up.


For comparison, here's what the grep -i dt /boot/config.txt looks like for me:

fpp@FPP-DevPi:~/media/plugins/Dynamic_RDS $ grep -i dt /boot/config.txt
#framebuffer_width=1280
#sdtv_mode=2
#dtparam=i2c_arm=on
dtparam=i2s=on
dtoverlay=hifiberry-dac
#dtparam=spi=on
#dtoverlay=gpio-ir,gpio_pin=17
#dtoverlay=gpio-ir-tx,gpio_pin=18
#dtparam=audio=on
dtoverlay=pwm,pin=18,func=2
#dtoverlay=vc4-kms-v3d
dtparam=spi=on
dtparam=i2c_arm=on,i2c_arm_baudrate=400000
#dtparam=audio=on
#dtoverlay=pwm,pin=13,func=4
dtoverlay=pi3-miniuart-bt
dtoverlay=dwc2
chrkov commented 7 months ago

So I did the following. Change PWM pin to 12, disabled PWM and disabled Software I2C. Rebooted. Ran check on config.txt with output.

fpp@cmk-od-fpp01:~ $ grep -i dt /boot/config.txt

framebuffer_width=1280

sdtv_mode=2

dtparam=i2c_arm=on

dtparam=i2s=on

dtparam=spi=on

dtoverlay=gpio-ir,gpio_pin=17

dtoverlay=gpio-ir-tx,gpio_pin=18

dtparam=audio=on

dtoverlay=vc4-kms-v3d

dtparam=spi=on dtparam=i2c_arm=on

dtparam=audio=on

dtparam=i2s=on dtparam=i2c_arm=on dtparam=i2s=on dtparam=i2s=on dtoverlay=hifiberry-dac dtparam=i2s=on

Not sure why I see so many dtparam=i2c=on now.

Go back in to config and reenable PWM, Software I2C and set pin to 32. Reboot.

Run check on config.txt and it is now:

fpp@cmk-od-fpp01:~ $ grep -i dt /boot/config.txt

framebuffer_width=1280

sdtv_mode=2

dtparam=i2c_arm=on

dtoverlay=i2c-gpio,i2c_gpio_sda=2,i2c_gpio_scl=3,i2c_gpio_delay_us=4,bus=1

dtparam=i2s=on

dtparam=spi=on

dtoverlay=gpio-ir,gpio_pin=17

dtoverlay=gpio-ir-tx,gpio_pin=18

dtparam=audio=on

dtoverlay=vc4-kms-v3d

dtparam=spi=on

dtparam=i2c_arm=on

dtoverlay=i2c-gpio,i2c_gpio_sda=2,i2c_gpio_scl=3,i2c_gpio_delay_us=4,bus=1

dtparam=audio=on

dtparam=i2s=on

dtparam=i2c_arm=on

dtoverlay=i2c-gpio,i2c_gpio_sda=2,i2c_gpio_scl=3,i2c_gpio_delay_us=4,bus=1 dtparam=i2s=on dtparam=i2s=on dtoverlay=hifiberry-dac dtparam=i2s=on

and the Config page says this:

image

and still nothing under the directory /sys/class/pwm

I also did upgrade to 7.5. and after the upgrade the DAC was gone. I checked before I did anything and the /sys/class/pwm directory was populated and the cat commands all came back as you said. Then I ran the Enable_HiFiBerry.sh script and the /sys/class/pwm directory went blank again. I am starting to thing that script does something to cause me issues. Is that the script you guys are using to enable the DAC also?

ShadowLight8 commented 7 months ago

@chrkov I'm still not sure what is happening that's causing the issue. The first config.txt output shows me that the i2c setting updated in the config.txt from software to hardware as expected. As expected, the pwm line was removed, but it should have uncommented #dtparam=audio=on as well, but that doesn't appear to be the case.

In the second config.txt output, again, it looks like the i2c settings worked as expected, but no pwm line appears. It should be right after the #dtparam=audio=on lines.

I'm not familiar with the Enable_HiFiBerry.sh script, but I'll take a look. I'm guessing it adds the dtparam=i2s=on and dtverlay=hifiberry-dac lines. I had just followed https://blog.himbeer.me/2018/12/27/how-to-connect-a-pcm5102-i2s-dac-to-your-raspberry-pi/ and manually updated the /boot/config.txt.

You can manually add the following to your /boot/config.txt to setup PWM on Pin 32 / GPIO 12: dtoverlay=pwm,pin=12,func=4 I'd put it right after one of the #dtparam=audio=on lines

chrkov commented 7 months ago

ok. Pretty sure that using the Enable_HiFiBerry.sh script did something bad to my system. I have noticed several oddities since I did that (Like my UserCallbackHook.sh script no long runs either). I grabbed a new SD card and reinstalled a fresh copy of FPP 7.5 and installed everything and its working perfect (like before I added the DAC) but using your directions above for adding the DAC. I think we are all good now.

ShadowLight8 commented 7 months ago

This morning, after rebooting my Pi, I noticed that pwm wasn't working. Looking into the syslog to see why, I discovered that there is a race condition in startup between the hardware pwm0 on pin 18 and i2s when both are enabled. While I know they both want pin 18, it seems like it is random who gets it. I'm not using the DAC yet, so that's why I still have pin 18 set. It should be easy enough to check for, so I'll add a warning about it.

ShadowLight8 commented 7 months ago

@TomasRa1 I've got my first version of software PWM in #36 now. Once I split out the PWM functionality to a new class, it went pretty quick to get it added. More testing is needed to make sure it works well.

I've been looking at the software PWM output with my logic analyzer. Here's what I have observed so far - While I set the base frequency to 10kHz, I'm seeing something closer to ~4-6kHz. Trying an Amp Power of 30, which sets a 10% duty cycle, I'm seeing much higher (25-35%) on my analyzer. While I haven't try it on the transmitter yet, I expect it will increase the output power, but the control of it won't be as good as the hardware PWM (which runs at 54.6kHz).

I'll spend some more time to see if I can get this to be better.

ShadowLight8 commented 7 months ago

I've merged #36 to the main branch, so you can update the plugin. To use the software PWM, enable PWM, then select a Software pin in the advanced options.

chrkov commented 7 months ago

Testing out Pin 11 right now and everything seems to be working well.

I am guessing Duty Cycles are different?

ShadowLight8 commented 7 months ago

@chrkov The frequency of the software PWM is an order of magnitude slower than hardware PWM (5 kHz vs 50 kHz). The duty cycle with software PWM is not as granular either, so you might find an Amp Power of 1 and an Amp Power of 30 have about the same effect on the transmitter.

I don't have enough electrical engineering knowledge to know how the slower PWM frequency impacts the amplification circuit on the transmitter board, but I'm glad to hear that it seems to do something :)

TomasRa1 commented 7 months ago

Hello Nick, thank you very much for your great work! Real measured frequency of PWM could be outside of audible frequencies, which is used for FM transmitting, which is up to 15kHz and also outside of all FM subcarrier frequencies: 19kHz-pilot stereo, 38kHz-L/R switching, 56-58kHz-RDS. I think that optimal real measured output PWM frequency, which cannot interfere in FM radio chain is around 18kHz, because audible frequencies around 19kHz are suppressed in stereocoder on transmitter side and also on FM receiver side. Frequency 5kHz could be audible as whistling. I recommend to set PWM frequency to output frequency around 18kHz eg. 17-18kHz. Thank you again for all!

ShadowLight8 commented 7 months ago

@TomasRa1 I'll do some more testing and tweaking to see if I can get a higher frequency out of the software pwm. I might also see about making the software pwm period/frequency a configurable advanced option as well.

ShadowLight8 commented 7 months ago

@TomasRa1 @chrkov I've spent sometime testing different things with Software PWM and the results are disappointing. For reference, this was all tested on a Raspberry Pi 3B+. The short version is that no matter what I've set, the actual PWM output is significantly different than expected and is effectively providing more power to the transmitter than desired. I'm not even factoring in the jitter and other inconsistencies in timing I saw. I tried to get the best, most consistent numbers, while testing.

Set Freq - What I used in the code to initialize RPi.GPIO Set Amp Power - From config screen T1 Duty Cycle - Measured the time of the high part of the pwm T2 Period - Measured from the start of high to the next start of high Calc Freq - Calculated the frequency from T2 Calc Amp Power - What the equivalent Amp Power setting would be based on the pwm measurements

image As the pwm frequency goes up, the actual frequency measured gets further from expected. At 2000Hz, it's pretty close, but even 5000Hz is only managing 3000Hz and it continues to get worse from there. Amp Power basically corresponds to the Duty Cycle, but you can see that at low amp power setting, the measured amp power (derived from the duty cycle) is much higher than it should be. At the higher frequencies, it is much worse, but even at 2000Hz it isn't great.

I'm going to look over the code in RPi.GPIO to see if anything looks odd, especially around the frequency.

TomasRa1 commented 7 months ago

I tested with set frequency to 18kHz (as I wrote in the code) and not registered inconsistency in power regulation. Maybe it was not perfect, but in real operation the regulation was consistent. When I will have a time I try to measure PWM signal with osciloscope. I understand that set frequency is different (lower with dependency on the frequency) than real transmitted PWM frequency. I used blocking capacitor 22n connected from PWM pin to GND on the transmitter board and check on osciloscope that edges of pulses are rounded. I also check that PWM frequency from original china's CPU controller was around 54kHz. I will inform later.