2

I'm currently trying to make a NRF24L01 module work by using Java. I found this library that makes use of the JNI, but I can't get it to work.

When I try to run the provided example code the Raspberry Pi just hangs and the CPU rises to 100% after (or rather while) running rf24.begin().

I digged a little bit into the code and found out that the reason it hangs is due to an endless while loop inside the bcm2835_spi_transfernb() function of this file.

The function is the following:

void bcm2835_spi_transfernb(char* tbuf, char* rbuf, uint32_t len)
{
    volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4;
    volatile uint32_t* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO/4;
    uint32_t TXCnt=0;
    uint32_t RXCnt=0;

    // This is Polled transfer as per section 10.6.1
    // BUG ALERT: what happens if we get interupted in this section, and someone else
    // accesses a different peripheral?

    // Clear TX and RX fifos
    bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR);

    // Set TA = 1
    bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA);

    // Use the FIFO's to reduce the interbyte times
    while((TXCnt < len)||(RXCnt < len))
    {
        // TX fifo not full, so add some more bytes
        while( (bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD )  && (TXCnt < len )  && !(bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXR) )
        {
           bcm2835_peri_write_nb(fifo, tbuf[TXCnt]);
           TXCnt++;

        }   
        //Rx fifo not empty, so get the next received bytes     
        while(((bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD))&&( RXCnt < len )){        
           rbuf[RXCnt] = bcm2835_peri_read_nb(fifo);
           RXCnt++;    
        }
    }
    while(! (bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_DONE) ){}
    if(TXCnt == len){ bcm2835_peri_set_bits(paddr, 0, BCM2835_SPI0_CS_TA);}
}

The problem is that the two while loops inside the outer while loop are never entered and therefore the exit-condition cannot occur turning this into an endless while loop.

Unfortunately I have no idea why that happens. Is it possible that this is due to a SPI related problem, like me forgetting to setup something? I did enable the SPI interface and validated it multiple times and also tested it. It seems to be working correctly. I also checked my wiring multiple times and I'm confident that its correct.

I would appreciate a little input, since I am really lost regarding this right now.

Gereon99
  • 141
  • 3
  • Well, there are a couple of reasons that the SPI transfer goes into an infinite loop. Usually first thing first is to use a *SPI loopback test* to make sure the SPI software and hardware are properly setup and the wiring is good. In case you are not familiar with SPI loopback in general and nRFL2401+ specifically, you might like to skim the following chat record: https://chat.stackexchange.com/rooms/107068/discussion-between-tlfong01-and-sideways8. – tlfong01 Apr 24 '20 at 02:40
  • Your references are out of date. You need to update the tools: (1) anvo/rf24-bcm-java Java wrapper for the nRF24L01 library - 2014 https://github.com/anvo/rf24-bcm-java

    (2) TMRh20 RF24/RPi/RF24/bcm2835.c - Mike McCauley 2013 https://github.com/stanleyseow/RF24/blob/92f598cf70bb85fc1470a359d8eed38a7b28e393/RPi/RF24/bcm2835.c#L589

    (3) Arduino and Raspberry Pi driver/libraries for nRF24L01 http://github.com/stanleyseow/RF24 - 2014 https://github.com/stanleyseow/RF24

    (4) Optimized high speed nRF24L01+ driver class documentaion V1.3.4 - TMRh20 2020 http://tmrh20.github.io/RF24/.

    – tlfong01 Apr 24 '20 at 02:42
  • 1
    I actually performed a SPI loopback test and it was successful. Could you please elaborate though what you mean with "updating" my tools? I saw that the submodule the Java wrapper uses is very old, since someone else is now maintaining the library. Do you mean I have to use that newer code? If so, how am I supposed to do it? I think "simply" changing the submodule will mess with the rest of the code. – Gereon99 Apr 24 '20 at 10:32
  • Just a couple of quick comments: (1) SPI loopback: I usually first do SPI loopback. As you might know, SPI loopback only makes sure MOSI and MISO is working more or less properly, but CE0 or CE1 is not tested. To make sure all three signals are tested, I usually do the ping test. For nRF24L01+, I do the following: (2) Read the nRF24L01+'s config register at address 0x00, to see if the POR value is 0x04. (3) I sometimes also do the read-after-write test: write random values 0x00, 0xff, 0x55, 0xas, 0x5a, 0xa5 etc to make sure I can read after write OK. – tlfong01 Apr 24 '20 at 12:31
  • (4) Lower SPI speed. I read that your code initializes SPI speed to 5MHz. One answer of the following questions says problem solved after lowering speed to 4MHz: (5) "Rpi SPI nRF24L01+ 2.4GHz Transceiver Module Send Message to Arduino Problem" https://raspberrypi.stackexchange.com/questions/107608/rpi-spi-nrf24l01-2-4ghz-transceiver-module-send-message-to-arduino-problem. I do read from time to time tutorials recommending to lower speed from 5MHz. When debugging, I usually lower SPI speed to 1Mhz, and sometimes even 10kHz. – tlfong01 Apr 24 '20 at 12:32
  • (6) About outdated SPI and python modules: My recent experience on nRF24 and NFC modules are all python I2C/SPI/UART. So my python cases might not well applied to Java. You might like to skim some of my recent troubleshooting experience on messing around outdated SPIU and python modules:

    (a) CHAT Record of Rpi SPI nRF24L01+ 2.4GHz Transceiver Module Send Message to Arduino Problem https://chat.stackexchange.com/transcript/103645/2020/1/24 / to continue, ...

    – tlfong01 Apr 24 '20 at 12:50
  • (b) CHAT Record of lib_nrf24 throws OSError (Errno 9) Bad file descriptor on radio.available(0) https://chat.stackexchange.com/rooms/107068/discussion-between-tlfong01-and-sideways8

    (c) CHAT record on on How can Rpi python read a MFRC522/PN532 NFC/RFID MIFARE smart card/tag? https://chat.stackexchange.com/transcript/106073/2020/3/29

    (d) How can Rpi python read a MFRC522/PN532 NFC/RFID MIFARE smart card/tag? https://raspberrypi.stackexchange.com/questions/109773/how-can-rpi-python-read-a-mfrc522-pn532-nfc-rfid-mifare-smart-card-tag/110791#110791

    – tlfong01 Apr 24 '20 at 12:50
  • (e) CHAT record on on How can Rpi python read a MFRC522/PN532 NFC/RFID MIFARE smart card/tag? https://chat.stackexchange.com/transcript/106073/2020/3/29. This is the end of my brainstorming comments on troubleshooting out dated software. I will read your Java code and see I can suggest something, perhaps tomorrow or day after. Cheers. – tlfong01 Apr 24 '20 at 12:53
  • Question: Do you have any experience in Pi4j? You can use Pi4j SPI to read and write nRF24L01's config register to make sure Java SPI API is OK. This is what I am doing with python for libnrf24.py. Reference: https://pi4j.com/1.2/index.html – tlfong01 Apr 24 '20 at 13:36
  • One more thing. I think your problem is at the Java level NOT at the SPI transfer level. This is what I commented on another similar questioner using python SPI for nRF24L01. As you suggested, the problem is around/before the while loops, not related to SPI transfer. But I am not knowledgeable enough to go further. Good luck and cheers. – tlfong01 Apr 24 '20 at 13:52
  • 1
    Thank you for your effort. I might try reading e.g. the config register with Pi4J as suggested by you. Thats a good idea. – Gereon99 Apr 24 '20 at 14:16
  • You are welcome. As I indicated earlier, my Java knowledge is rather rusty. I only remeber the funny name JavaBeans but forgot what it is. I recommend Pi4J because only know this and not JNI. I also remember that I did NOT try Oracle because it is not open source. Perhaps I should spend some time this weekend to polish my rusty Java stuff. Just now I casually googled and found Java is more confusing and messy than Python 2/3. References: (1) "Installing Java on the Rpi (Rpi4 buster OK) - Emmet, PiMyLifeUp 2019dec12": https://pimylifeup.com/raspberry-pi-java/, / to continue, ...

    :

    – tlfong01 Apr 25 '20 at 01:50
  • (2) "Efficient Java Development for the Raspberry Pi - GregF10 2018": https://www.instructables.com/id/Efficient-Development-of-Java-for-the-Raspberry-Pi/,

    (3) "How to Install Java on Raspberry Pi - 2020feb24": https://linuxize.com/post/install-java-on-raspberry-pi/.

    – tlfong01 Apr 25 '20 at 01:50
  • I forgot to mention that it is important to most up to date software packages, because say, if your jdk/jni/ etc is out of date, some modules might be missing, cause infinite waiting. So you see now I am starting to install the most up to date Java stuff. – tlfong01 Apr 25 '20 at 09:50
  • I know I can run develop Java stuff using Eclipse or NetBean. I am thinking of installing NetBean in my Win10 PC (CORE i5, 6GB) as the developer workstation, and Rpi4B 4GB buster as the remote platform. Any comments or counter suggestions please? – tlfong01 Apr 25 '20 at 10:02
  • On second thought, perhaps I should start small and use BlueJ or GreenFoot IDE to refresh my memory on Java. Both these IDEs are small, and already preinstalled in Rpi4B buster, so I think they should be as newbie friendly and python Thonny or Geany. – tlfong01 Apr 25 '20 at 11:29
  • I skimmed the Wiki's on BlueJ and GreenFoot and found BlueJ is better for my current toy program, because GreenFoot seems mainly for 2D graphical things. So I will go BlueJ. – tlfong01 Apr 25 '20 at 11:39
  • So I googled a couple of reviews by Java beginners and programmers. My conclusion is that BlueJ is definitely good for newbies to learn Java as a new language. I also read the 2003 paper by M Kölling, who "invented" BlueJ, on how to teach Java with BlueJ. Of course I am not going to teach Java, but this paper is indeed helpful for me the newbie to know how to learn Java, using BlueJ. This paper is 17 years old. I hope BlueJ should be much improved now, and so should be worth my time testing the waters. – tlfong01 Apr 25 '20 at 13:10
  • One thing I am surprised to hear from Kölling, is that he does not suggest to start with "Hello World", but instead encourages students to (1) use of case studies in programming learning, (2) to read, study, modify and extend existing programs. So I am thinking of using the existing nRF24L01+ Python/Java library as a case study, and learn how to expand the libraries with more features. – tlfong01 Apr 25 '20 at 13:15
  • I dived deeper and found the following article is best to start with Rpi Java SPI programming: (1) "Rpi Java & Pi4J SPI Programming with Pi-Face - Robert Savage 2013feb25": http://www.savagehomeautomation.com/projects/raspberry-pi-programming-pi-face-with-java-pi4j.html

    The author Savage says the following: "The good news is that if you use the *Pi4J libraries all the nitty-gritty hard work (SPI communication protocol for the chipset and state change monitoring threads) is already done for you.*". Ah bed time!. I call it a day and see you tomorrow.

    – tlfong01 Apr 25 '20 at 13:50

2 Answers2

3

Answer

(1) After googling a bit, I have decided to start with Rpi BlueJ Java IDE, and the first Java programs will be on:

(a) GPIO LED/Button programming,

(b) SPI programming.

(2) Next step is to study existing nRF24L01+ Python/Java libraries and see how to expand the libraries with more features.

(3) I also found that Pi4J libraries include SPI. So I guess I should jump start to Pi4J and see if I can just use it to read nRF24L01's config register, which is what I wanted to do in the very beginning.

(4) I think I can first try to use Pi4J to read the nRF2410+'s config register at address 0x00, hopefully getting the POR (Power On Reset) value of 0x00.

If no luck, I will fall back to do SPI loopback test, to check if I need to adjust the SPI speed to a lower value, say from 5MHz to 1MHz.

If still no luck I will give up SPI for now and try to do the easier Ri4J GPIO, testing GPIO read/write of the nRF24L01+'s Reset pin and Interrupt pin.

rf module 1

rf module 2

(5) Now I am following the BlueJ and Pi4J tutorials (Refs 8 ~ 14) to do my newbie Java GPIO and SPI programming exercises.


ERRATA

I found the tutorials referred above are much out of date. So I googled harder and found a couple of very up to date tutorials, and other too good to be true things including the following:

(1) BlueJ already includes Pi4J, therefore no need to install.

(2) Rpi buster already includes JDK, therefore no need to install.

(3) BlueJ also includes GPIO classes for Rpi.

(4) BlueJ already includes tutorials on LED, button, servos, analogue sensors, including MCP3008.

In other words, my tentative plans in Sections 1 to 4 above are all rubbish!

bluej rpi


(6) If BlueJ already includes Pi4J which in turn includes SPI, I think they are very mature or stable and should have very little teething problem, so is not much need to do any feasibility study. In other words, we can just do a incremental/continuous TTD (Test Driven Development) starting from the very bottom, GPIO control of the NRF24 Reset and Interrupt pins, using BlueJ's LED and Button tutorials as a reference. Here is a top down schematic of the overall test plan.

nrf24 schematic

(7) I found a more updated 2016 tutorial also by Kölling, Educational Programming on the Raspberry Pi - M Kölling, Electronics, 5 (3) 2016

I skimmed this tutorial and found it very useful to know the basic idea of creating the tools GreenFoot and BlueJ.

(8) Now I am reading the Pi4J SPI Class. The documentation looks good:

pi4j spi class

(9) Java JNI learning notes

JNI


/ to continue, ...


References

(1) Installing Java on the Raspberry Pi (OK for Rpi4 buster) - Emmet, PiMyLifeUp 2019dec12

(2) Efficient Java Development for the Raspberry Pi - GregF10 2018

(3) How to Install Java on Raspberry Pi - 2020feb24

(4) BlueJ - Wikipedia

(5) GreenFoot

(6) The BlueJ system and its pedagogy - M Kölling etal 2003dec

(7) BlueJ on the Raspberry Pi - BlueJ.org

(8) BlueJ LED Tutorial - BlueJ.org

(9) Raspberry Pi - Programming Pi-Face with Java & Pi4J (SPI)

(10) Java SPI using com.pi4j.wiringpi Class

(11) The BlueJ Tutorial Version 2.0.1 for BlueJ Version 2.0.x - Michael Kölling

(12) The BlueJ Environment Reference Manual Version 2.0 for BlueJ Version 2.0

(13) Pi4J Java I/O library for the Rpi (Rpi3B+ OK, but no guarntee for Rpi4B)

(14) Getting Started with BlueJ, Creating and Running programs in BlueJ - UT CS

(15) Educational Programming on the Raspberry Pi - M Kölling, Electronics, 5 (3) 2016

(16) BlueJ on the Raspberry Pi

(17) Pi4J Overview

(18) Java Programming Tutorial Java Native Interface (JNI) - www3.ntu.edu.sg


Appendices

Appendix A - Install OpenJdk v11.0.6

(1) Installing Java on the Raspberry Pi (OK for Rpi4 buster) - Emmet, PiMyLifeUp 2019dec12

openjdk install


Appendix B - Using MicroSoft Visual Studio Code

magpi java 1

magpi java 2

/ to continue, ...


tlfong01
  • 4,665
  • 3
  • 10
  • 24
1

A few days have passed and I decided to kinda "rewrite" this lib. (I copied a lot)

Its not as extensive, but it works well for me. If anyone is interested to try it out: Here.

I didn't add tons of documentation though, so be warned.

Gereon99
  • 141
  • 3