0

I'm trying to measure the power level of the signal captured by rtl sdr dongle and then compare several measurements to get the best level of power, but I don't know exactly how to return instantly the power level to my main function.

Here is my code:

import asyncio
from rtlsdr import RtlSdr
import numpy as np
import time

global power

async def streaming():
    #SDR CONFIGURATION
    sdr = RtlSdr()
    sdr.rs = 2.4e6
    sdr.fc = 801e6

    async for samples in sdr.stream(512):
        global power
        samples = samples - np.mean(samples)
        calibrate = 3.2
        power = np.mean(np.abs(samples ** 2))

        #print('Relative power:', calibrate * 10 * np.log10(power), 'dB')
    await sdr.stop()
    sdr.close()
    #return power
# i traied this function to return the result from streaming() but it didn't work !!
async def get_result():
    global power
    while True:
        yield power

async def main():
    global power
    nb_config = 100
    fpower = -100
    for i in range(nb_config):
        # Get the current event loop.
        loop = asyncio.get_running_loop()
        #try to get the power value from the loop
        task = streaming()
        power = loop.run_until_complete(asyncio.gather(*task))
        loop.close()
        if power > fpower :
            fpower = power
            print(10*np.log10(fpower))

asyncio.run(main(), debug=True)
Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
  • A side note: That `global power` statement in the global scope really doesn't do anything... – Tomerikoo Jun 27 '22 at 10:39
  • There are some conflicting ideas here. You set a global var to pass state around, and then overwrite `power` with the result of `loop.run_until_complete`. You're also using asyncio.gather to await a single task inside an async function, which doesn't make sense. All of which points to spending some time with the python tutorial on asyncio: it's really quite good. – 2e0byo Jun 27 '22 at 10:41

1 Answers1

0

The short answer is that if you want an async function to yield up multiple values, just yield them:

async def powers(): # was 'streaming', but that doesn't seem to describe it
    ...

    async for samples in sdr.stream(512):
        samples = samples - np.mean(samples)
        calibrate = 3.2
        power = np.mean(np.abs(samples ** 2))
        yield power

    await sdr.stop()
    sdr.close()

But then you need to get these values inside main:

async def main():
    ...
    async for power in powers():
        print(power)

Since this is cooperative multithreading, any time python is in main() (or anything else), it won't be in powers(). Whether that matters depends on how the tools in question are built, but you might need to be careful not to full up buffers once your code gets longer, if your SDR is still putting out data.

2e0byo
  • 5,305
  • 1
  • 6
  • 26
  • Thanks a lot for your answer, now the script starts printing some results, then I'm getting this message : `Executing .callback() at ... took 0.141 seconds Executing :28> result=None created at ... took 0.265 seconds` i couldn't understand what does it mean exactly ! – Mohammed Ayoub Toubal Jun 27 '22 at 11:20
  • Something is telling you it's running a coroutine; if everything works ignore it. I really recommend spending some time learning asyncio: it will help a lot in the long run, and well let you dig in to how your particularl library is written---whence this message, probably. In any case SO isn't a forum; you might be better asking for help elsewhere with the particular problems of interacting with rtlsdr. – 2e0byo Jun 27 '22 at 11:27
  • solved by removing DEBUG from asyncio.run(main(), debug=True) but i'm still having a `RuntimeError: Event loop is closed` when i stop the script which is something weird to me !! – Mohammed Ayoub Toubal Jun 27 '22 at 11:30
  • yep, if you ask it to debug it will be pretty verbose. The error is exactly what ought to happen: if you close the event loop without exiting `main()` you've created a (probably harmless) error condition. – 2e0byo Jun 27 '22 at 11:44
  • Thanks a lot for helping, in fact, I have another question please, i did some tests on the script and i noticed that `async for power in powers()` never stops when the `for i in range(nb_config)` ends, ideally i want to excute `powers` async function in parallel to my `main()` function and grap the power value from `powers()` whenever i need it in `main()` but i didn't know how to close the `async for power in powers()` loop !, is that possible ? – Mohammed Ayoub Toubal Jun 27 '22 at 12:41
  • @MohammedAyoubToubal questions don't belong in comments. But this is just a python thing: if you want to get out of the `async for` loop you need either to have the iterator finish, or keep track of the number of iterations yourself and break out of it. Wrapping the whole loop in another loop will just multiply them. As it is I think your `powers()` will end after 512 samples: it might make more sense to pass the the number through as a parameter (`asyunc for x in powers(100)`). But this really is another q. – 2e0byo Jun 27 '22 at 12:56