I'm currently trying to do some real-time signal-processing and I would like to use "gnuradio". I will be processing multiple channels of EEG which come in trough a custom interface (namely "Lab Streaming Layer"; LSL) in python.
Now my question is if there is an existing block already where you can kind of "push" samples into the signal-processing-graph during run-time? The only blocks I've found so far offer support for audio hardware, TCP-streams and files.
You will have to write your own block; that can be done in Python or C++, whatever is better for your case.
The GNU Radio Guided Tutorials (you should really read them in order from 1 to 5, at least) do explain how to do that.
Because we all know that people are lazy at reading, here's a rough preview of what you'll learn:
make a new Out-of-tree module: gr_modtool newmod sensorinterface, change into the newly generated directory: cd gr-sensorinterface
add a new source block: gr_modtool add eeg_sensor_source; the block type you'll want is "source"; you will be asked to fill in some block details.
edit the generated source file (in lib/ or python/, depending on which language you chose:
add a proper io signature: your output will probably have the size of float
edit the central work function; add code to get new samples, and copy those to the output_items buffer.
The guided tutorials are really nice!
The most flexible method is to write your own GNU Radio block, but there are several options for getting data into a flow graph without using any custom blocks. (Naming from the Python perspective.)
gnuradio.blocks.message_source, which takes data from a gnuradio.gr.msg_queue.
You can use a gnuradio.blocks.file_descriptor_source where the file descriptor is one end of a pipe.
Related
I'm working with gnuradio 3.10.4 and usrp B200mini.
My flowgraph is very simple:
usrp source -> head block -> file sink
I want to store a fixed amount of data to file sink, then reconfigure usrp and start it to store again.
My Python program likes:
tb.start()
tb.wait()
tb.lock()
...reconfigure usrp...
tb.unlock()
tb.start()
...
But the second time when tb.start() is used, the file can be created successfully but no data is written to it.
Can anyone tell me what's wrong with the program or provide any relevant docmutation becaouse I find little about it.
Thanks for your support.
When you're not sure how to get a block to do what you want, or if it can, it can be useful to consult the source code of the block, because GNU Radio blocks are not always thoroughly documented.
Starting from this wiki page on Head we can see all the code. It's C++, but fairly simple, and you can ignore all the setup and just look at the lines that seem to be doing the work.
In head_impl::work in head_impl.cc, we can see that the way the block works is counting the number of items it has passed in d_ncopied_items and comparing that against d_nitems (the value you provided). There's nothing here that restarts the count.
We have to also check the header file, head_impl.h, because code may be there too. And there we find what you need:
void reset() override { d_ncopied_items = 0; }
So, call reset() on the head block and it will forget about how many items it has already copied.
I am trying to create a synchronized usrp source block in gnu radio consisting of multiple B210 USRP devices. Lang: C++.
From what I have found I need to:
Instantiate multiple multi_usrp_sptr as each B210 requires one and multiple B210 devices cannot be addressed by using single sptr
Use external frequency and PPS sources - an option that can be selected from block or set programmatically
Synchronize re/tuning to achieve repeatable phase offset between nodes - this can be achieved using timed commands API https://kb.ettus.com/Synchronizing_USRP_Events_Using_Timed_Commands_in_UHD
Synchronize sample streams using time_spec property issue_stream cmd
The problem is how should I insert these timed commands and set time_spec of stream in GNU radio block or gr-uhd libs?
I looked into the gr-uhd folder where the sink/source code resided and found functions that could be altered.
Unfortunately I don't know how to copy or export this library to do these modifications and later compile to insert my custom blocks to GNU Radio, because gr-uhd seems to be built in and compiled at GR installation.
I attempted coping and then making the lib but that's not the way - it didn't succeed. Should I add my own source block via gr_modtool and insert only the commands I need?
Compatibility with uhd and its functions apart from just adding a few lines would be advantageous not to write the source from scratch.
Please advise
Edit
Experimental flowchart, based on Marcus Müller suggestion:
Experimental usrp synchronization flow
The problem is how should I insert these timed commands and set time_spec of stream in GNU radio block or gr-uhd libs?
For a USRP sink: add tags containing dictionaries with the correct command times to the streams. The GNU Radio API docs have information on how these dictionaries need to look like. The time field is what you need to set with an appropriate value.
For a USRP source: Use the set_start_time on the uhd_usrp_source block; use the same dictionaries described above to issue commands like tuning, gain setting at a coordinated time.
I was trying to find a proper way of synchronizing the USRPs via tags.
There are a few issues I came across in this approach:
Timed commands require the knowledge of the current moment in time, which is done via usrp.get_time_now(), even though I would request the USRP to give the time through tags I would have to somehow extract it from the output. (make some kind of loop and proper triggering) (source: https://kb.ettus.com/Synchronizing_USRP_Events_Using_Timed_Commands_in_UHD) or maybe plan everything not in a relative way - using absolute values instead of offsets. I have seen an approach to regularly reset the sense of time each PPS (set it to 0.0) and maybe then setting time of commands within range of 0.0-1.0 would be acceptable. Then the loop for reading and inserting time into commands would also be redundant.
I didn't found a way to create dicts in GR via blocks to make the solution scalable (without writing a few lines of code in textbox) or writing OOT block
In the end there is so little information to tell what kind of solution is most appropriate (PDU, events, are tags still relevant in GR
?), and the docs are so very scarce, that after some mailing I decided to add a simple class that inherits from the main top_bock.py and after instantiation of top_block it calls a few functions to synchronize the devices. This kind of solution is not the most flexible one, and the parent class top_block.py has to be called through the inheriting one, but it enables an easy programming interface.
Soon I will add an example of the code used in inheriting class just in case.
If there is any more neat, dynamic or scalable solution please let me know or point me to sources.
I need to drive a testbench with labview.
The test scenarios are written in a languages that can be automaticaly translated into labview diagrams.
Is this an API that allow to create "labview diagrams" from another software ? or with labview itself ?
I agree that LabVIEW scripting is one approach, but let me throw out another option.
If you are planning to do a one time migration from your test code to LabVIEW than scripting is great, but if you plan to regularly update your test code (because it's easier to use the "test" language than LabVIEW) than it could become quite painful to constantly perform the migration every time your test code has changed.
I've had great success with simply putting my state machine inside of a for loop and then reading in "commands" from a text file that was generated using my "test" language (see pic).
For example, to do an IV sweep my text file might say something like:
SourceV, 5
ReadI
Wait, 1
SourceV, 6
ReadI
This image is greatly simplified - I'm not using a state machine and I don't show how to use "parameters," but I can provide a more comprehensive example if needed. Again, I've had great success doing this with around 30 "commands" controlling multiple instruments and then I generated the text input using VBA or Python.
It's called LabVIEW scripting. You will need to enable an option in the VI Server page in the options dialog to see the relevant features.
A few things to note:
Scripting isn't complicated, but you do need to be aware of how LV code is built.
While scripting is public, it was initially created as an internal tool. There are still corners of it which are incomplete.
Scripting code can be tedious. If you can get away with it, try creating templates of code.
NI has something called CodeGen, which I believe are a series of functions which make some scripting easier, although I never really looked into it.
I am reading a file datafile at the launch of my application.This is just self learning drill.
On apple developers website under the heading Minimize File Access at Launch Time
it says
If you must read a file at launch time, do so only once.
So my question is that is there a standard or preferred way of doing this. At the moment I have an instance varible NSArray and I populate that in - (void)viewDidUnloadand never garbage collect it. Is that good enough ? or Should I be making use of application Object (I am not even sure if it is logical to say this.).
There is no standard way to optimize. But there are some guidelines.
One basic idea of optimization is to do less. E.g. as the advice you cited where the data of a file may be needed at multiple points in your code, it is better to read it from disk once and then distribute a data pointer within your program.
If the file is big enough to cause a stutter when you start your application, i.e. it takes more than 20ms to read and parse the file, you should consider reading the file in a background thread/task and adding a ‘loading…’-state to display to the user.
this is my first post, and it covers something which I've been trying to get working on and off for about a year now.
Essentially it boils down to the following: I have a copy of newlib which I'm trying to get working on an LPC2388 (an ARM7TDMI from NXP). This is on a linux box using arm-elf-gcc
The question I have is that I've been looking at a lot of the tutorials talking about porting newlib, and they all talk about the stubs (like exit, open, read/write, sbrk), and I have a pretty good idea of how to implement all of these functions. But where should I put them?
I have the newlib distribution from sources.redhat.com/pub/newlib/newlib-1.18.0.tar.gz and after poking around I found "syscalls.c" (in newlib-1.18.0/newlib/libc/sys/arm) which contains all of the stubs which I have to update, but they're all filled in with rather finished looking code (which does NOT seem to work without the crt0.S, which itself does not work with my chip).
Should I just be wiping out those functions myself, and re-writing them? Or should I write them somewhere else. Should I make a whole new folder in newlib/libc/sys with the name of my "architecture" and change the target to match?
I'm also curious if there's proper etiquette on distribution of something like this after releasing it as an open source project. I currently have a script which downloads binutils, arm-elf-gcc, newlib, and gdb, and compiles them. If I am modifying files which are in the newlib directory, should I hand a patch which my script auto-applies? Or should I add the modified newlib to the repository?
Thanks for bothering to read! Following this is a more detailed breakdown of what I'm doing.
For those who want/need more info about my setup:
I'm building a ARM videogame console based loosely on the Uzebox project ( http://belogic.com/uzebox/ ).
I've been doing all sorts of things pulling from a lot of different resources as I try and figure it out. You can read about the start of my adventures here (sparkfun forums, no one responds as I figure it out on my own): forum.sparkfun.com/viewtopic.php?f=11&t=22072
I followed all of this by reading through the Stackoverflow questions about porting newlib and saw a few of the different tutorials (like wiki.osdev.org/Porting_Newlib ) but they also suffer from telling me to implements stubs without mentioning where, who, what, when, or how!
But where should I put them?
You can put them where you like, so long as they exist in the final link. You might incorporate them in the libc library itself, or you might keep that generic, and have the syscalls as a separate target specific object file or library.
You may need to create your own target specific crt0.s and assemble and link it for your target.
A good tutorial by Miro Samek of Quantum Leaps on getting GNU/ARM development up and running is available here. The examples are based on an Atmel AT91 part so you will need to know a little about your NXP device to adapt the start-up code.
A ready made Newlib porting layer for LPC2xxx was available here, but the links ot teh files appear to be broken. The same porting layer is used in Martin Thomas' WinARM project. This is a Windows port of GNU ARM GCC, but the examples included in it are target specific not host specific.
You should only need to modify the porting layer on Newlib, and since it is target and application specific, you need not (in fact probably should not) submit your code to the project.
When I was using newlib that is exactly what I did, blew away crt0.s, syscalls.c and libcfunc.c. My personal preference was to link in the replacement for crt0.s and syscalls.c (rolled the few functions in libcfunc into the syscalls.c replacement) based on the embedded application.
I never had an interest in pushing any of that work back into the distro, so cannot help you there.
You are on the right path though, crt0.S and syscalls.c are where you want to work to customize for your target. Personally I was interested in a C library (and printf) and would primarily neuter all of the functions to return 0 or 1 or whatever it took to get the function to just work and not get in the way of linking, periodically making the file I/O functions operate on linked in data in rom/ram. Basically without replacing or modifying any other files in newlib I had a fair amount of success, so you are on the right path.