-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
A new scanner example #714
Comments
I think this is worthy of separate discussion so I split it into a separate issue. |
|
It seems to me that this isn't a trivial example to build. There's Linux machines and Arduino boards that would both need a separate approach. On Linux it would be possible to build something appealing with C++/ncurses or Python/rich-python without a lot of effort. On an Arduino board it would theoretically be possible to use Adafruit-GFX API and it should work on a lot of displays. |
After a little testing with existing scanner example, I noticed that if I changed the channel (on a separate nRF24 module) while the Carrier Wave was transmitting, then scanning nRF24 module would show the carrier wave detected on the wrong channel. This needs more investigation, but I have a feeling the module TX-ing the carrier wave isn't modulating to the right frequency while the PLL is locked (because its transmitting)... Also I haven't tried changing the PA level while transmitting a carrier wave, but that would be harder to verify if the new PA level is achieved correctly. I'm curious if @waltbar did extensive testing before submitting #609 (which is why |
Just for reference, it was the comment from @Avamander that started this "new scanner" idea:
The youtube video's description has a link to the scanner source code |
This sounds like an useful thing to figure out. I wonder if anyone here has an SDR that could answer what piece here is incorrect. |
A lot of python people swear by the |
Rich is not just for setting colors, has quite a few nice features/UI-elements built-in that are useful when building a nice quick CLI, I can recommend it. |
interesting lib (it also requires colorama as a dep), but how do you evision the scanner output? |
I was just thinking a progress bar per-channel and just update those with signal strength. (So basically yours but rotated right 90deg) |
glad I asked. Now I just have to explore the ncursers and rich-python libs A LOT more... I'm currently tied up in doing a wireless HID hub using circuitpython (something that should mimic Logitech's Unifying dongles)... |
We need to consider improving the "frame rate" for the scanner output. I made an attempt at the Arduino+OLED (using I2C) sketch, and the "refresh rate" (using algorithm from original scanner.ino) is drastically slow (about 5 seconds). |
The timing etc of the scanner example is dictated by the hardware mostly, as the device needs to listen for a bit. Providing the user with a channel range to scan could speed it up instead of scanning the entire range. Or do you mean to display each channel as it is scanned?
… On Jan 15, 2021, at 7:37 AM, Brendan ***@***.***> wrote:
We need to consider improving the "frame rate" for the scanner output.
I made an attempt at the Arduino+OLED (using I2C) sketch, and the "refresh rate" (using algorithm from original scanner.ino) is drastically slow (about 5 seconds).
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or unsubscribe.
|
I was thinking of displaying each channel as it is scanned. Although, providing user with input options (at program start up) isn't a bad idea. Say they want to change the data rate |
I just tried using for curr_channel in range(126): # for each channel
nrf.channel = curr_channel
time.sleep(0.00013) # let the radio finish modulating to the new channel
nrf.listen = 1 # start a RX session
time.sleep(0.00013) # wait 130 microseconds
signals[curr_channel] += nrf.rpd # if interference is present
nrf.listen = 0 # end the RX session
# output the signal counts per channel
print(
hex(min(0x0F, signals[curr_channel]))[2:] if signals[curr_channel] else "-",
sep="",
end="" if curr_channel < 125 else "\r",
)
# print `signals` array 1 last time with a LF at EoL for prettiness This technique could also be used in the Linux C++ version of the scanner example (using Last time I tried doing a EDIT: Apparently the "sweeping animated cursor" for the status of the current channel being scanned is specific to using putty. 🤷🏻♂️ QuestionHow should we calculate the decay of the peak for a channel? Should it be time based or the last x number of scans on that channel? |
@Avamander printing 125 horizontal progress bars may be problematic because each progress bar in rich python is essentially 1 line and the scrolling of terminal windows. Were you thinking of averaging 2 or 3 channels per line? we can do 3 columns of 41 progress bars or something like that to utilize screen realty. 25 lines seems like a safe bet to avoid automatic scrolling. |
It'd be possible to read the amount of available lines and divide the channels between those? |
Python rich has a way of finding the dimensions of the console that we could divy up accordingly. I still haven't looked at ncurses yet... I imagine they must have an equivalent option. |
int x1 = xx1;
int y1 = yy1;
int Sc;
int x2, y2;
int BlobHeight = 4; // Blobs are 4x4 pixels
char NB[12]; // Number Buffer
char NB1[12];
char NB2[12];
char NB3[12];
char NB4[12];
char CB[100]; // COMMAND BUFFER
char fyll[] = "fill ";
char IELLOW[] = "YELLOW";
char NA[1] = ""; // blank one
for (Sc = ScanStart; Sc <= ScanEnd; Sc++) {
Radio1.setChannel(Sc);
Radio1.startListening();
x2 = x1 + (Sc * 5);
y2 = y1 + 255;
y2 = y2 - BlobHeight;
y2 = y2 - AllChannels[Sc];
delayMicroseconds(120); // Minimum!?
Radio1.stopListening();
if (Radio1.testCarrier()) {
if (AllChannels[Sc] < (250)) {
AllChannels[Sc] += BlobHeight;
/* send all channel data to the display */ // EDITED FROM OG SRC
}
}
else {
NoCarrier[Sc]++;
if (NoCarrier[Sc] > 15) { // must see no carrier >15 times before reducing the trace
if (AllChannels[Sc] >= (BlobHeight)) {
/* send all channel data to the display */ // EDITED FROM OG SRC
AllChannels[Sc] -= (BlobHeight);
NoCarrier[Sc] = 0;
}
}
}
} |
I just found out that the python std libs ship with a ncurses wrapper (for Linux platforms only). This might be a better alternative to the |
So I put together a couple examples that use the curses lib (1 in python and 1 in C++) on the promiscuous-scanners branch. The python example runs very well, but I have no idea why the C++ example doesn't pick up as many signals (practically nothing). Everything is set up almost identically for both examples... As for the Arduino example, I have an idea for using macro defines to allow using either an I2C driven display or an SPI driven display. By default, I think I'll demo the I2C driven display since getting 2 SPI devices on 1 bus can be tricky depending on the display being used. |
I'm getting pretty consistent results between the C++ and Python scanner on my RPI4. My RPi Model B provides much more active output, and I'm not sure the reason, whether it is the radio connected or the RPi version. One thing to note, if the SSH window is too small, I'm getting an error with the python example:
It may be worth trying to detect the size of the window and giving a non-cryptic error message instead, or at least adding the info to the example. |
I retract my refresh rate complaints. Turns out I had a rogue Refresh rate is rather good when I toggle a const carrier wave from another device.. Its kinda fun to watch the peak go up and down. |
Hey, I just realized that testRPD(); will only catch signals >64dBm, but radio.available(); will catch signals <64dBm, so a call to available could be added as well to increase responsiveness even more!
|
I thought any payload received had to be >64dbm. Its an interesting idea though because I think the RX FIFO may be getting filled while the RPD flag isn't asserted, so the RX FIFO doesn't seem to be getting flushed when it should be (thus blocking noise detection). In fact, I called |
@TMRh20 Are you using putty for ssh? I've switched to Windows Terminal (I think it ships with Win11 as a default app) for my SSH needs. Putty's terminal window is typically very small for every new session (using default config). The curses grid needs a 48-character width just to display the channel's labels and signal counts (that's not even including the actual progress bar which uses a dynamically calculated width). |
Per the datasheet: I'll have to check out windows terminal, I am using putty. |
You won't be disappointed. It now comes with builtin WSL and VS Dev prompt support, so now I can have a native Ubuntu bash in 1 tab and another tab to compile using VS compiler... And colors 🏳️🌈 ! |
I still get the same result with Technically, we could save ourselves the extra call to |
I get expected results when I delay a millisecond after setting the new channel. 🤷🏼 |
Yeah, somethings up with it. There is definitely some differences between Arduino behavior and RPi/Linux behavior that I can't explain yet. |
It doesn't work when I use The python curses example works fine, but there's always a slower execution due to the necessary interpreter. And I'm using the python std time lib to delay. |
I'm pretty sure they both use sys/time.h... they just use different math. Chrono is used for millis(), as other options seem to give messed up results. I'm getting good results here without extra delays. |
oh yeah, that's right. |
I've also added some extra addresses to your example, I wasn't sure what to use, but it seems to make a difference: |
I tried it (using 0xA0, 0x0A, 0x50, 0x05), but didn't seem to help any for me. My RPi4 has always seemed to suffer from timing issues (the man_ack example hasn't been 100% reliable for me). I frequently refer to my setup as the culprit, so if it is working for you, then I'm ok with it. Feel free to commit anything you want to the branch, I'm not going to do any forced git pushes or rebases while testing the branch with my RPis -- that git magic badly messes with my local clones. |
My experiences concur, but they aren't entirely specific to the RPi4 (seeing the same for my RPi2 also). I'm temped to try a different driver (been testing with SPIDEV).
I suspect that "spamming" the SPI bus too rapidly is the problem. It would make sense if a 100+ microsecond delay after setting the channel solves the inconsistencies, but an entire millisecond makes me think its the SPI bus itself. |
BTW, I have the Arduino example almost ready to commit. The |
Ok, I pushed the new Arduino "ScannerGraphic" to the branch. I left some display specific info in the commit message for aaabe5d Its a rough draft right now, but I put it up there for testing and feedback. I also made some updates to the pico and arduino (serial) scanners that conform to @TMRh20 suggestions. I removed the call to |
FYI, I'd like to have the filled portion of the bar in C++ scanner use the double horizontal line ( |
Just to add more to the confusion, I tried the C++ curses scanner with the RPi driver, and I got expected results without adding any additional delay after switching channels. I did notice the example runs a bit slower.
|
Looks like the bcm2835 uses register reads to get the system clock if the arg to delayMicroseconds is lower than 450. This requires root privilege though. The comments note that calling |
Well at least that might indicate why we need a delay with the SPIDEV driver. Originally the SPIDEV drive was much slower, until we figured out automatic CS toggling, and I think there have been some improvements over time. Now its too fast! lol |
@Avamander If I were to write a new scanner example,
startConstCarrier()
take no arguments because the PA Leveland RF channelcan/should be set independently ofstartConstCarrier()
.testRpd()
(&testCarrier()
) only detect signals "louder" than -64 dBm. The video you linked to is doing some averaging and manipulation on falling peaks. This is what makes your request interesting (to me). Furthermore, this data is only reset when entering RX mode (specifically during FALLING transitions of the CE pin when the CONFIG register's PRIM_RX bit is asserted), so add the confusion of manually manipulating the CE pin (considering thatce()
is a private function).Nonetheless, I shy away from no challenge...
Originally posted by @2bndy5 in #713 (comment)
The text was updated successfully, but these errors were encountered: