B4R Question Simple interrupt in B4R

Discussion in 'B4R Questions' started by johnf2013, Jan 12, 2018.

  1. johnf2013

    johnf2013 Member Licensed User

    I have a C++ app running on an Arduino Nano which has at its core a fast A/D read triggered by a pin interrupt. So, a shaft running at around 3000rpm has a sensor which triggers the interrupt every revolution. I then need to save the time this occurs and then do several hundred fast A/D converter reads of each of two other sensors, noting the time of each read. The values are saved for later use.

    Sensing the interrupt is the only time critical job. Since I need better than one degree of resolution, the interrupt latency variation cannot exceed 28uS, which it appears I cannot achieve with the polled mechanism in B4R. Note, I can calibrate out the interrupt latency but I must have a latency variation of less than 28uS.

    The A/D is read as fast as possible for many revolutions and the data stashed away. After enough revolutions there is data for every degree of position. If not it doesn't matter because it is all done again the next time the interrupt is enabled at which time the stale data is updated with new. A little bit of randomness goes a long way!!

    This code works very well on an Arduino Nano, plodding along at 16MHz. It sends the data in packets on a USB link to a PC and a BC++ program does the number crunching and display. All very pretty but not very useful in a workshop environment.

    I have rewritten the PC code in B4A to run an a mobile device and use WiFi/BT. This too works very well and is almost complete. It has the data structures to receive the data, but currently fills them with simulated data. Async streams looks like the best solution since there is some other data to be packaged as well as the raw sensor data.

    I had planned to write the Arduino/ESP8266/ESP32/??? code in C++ but looking through the B4R documentation I seemed clear I could do this much more quickly with B4R - except for one problem....

    How to manage the pin interrupt. It is a simple bit of code. The ISR just gets a system uS timer value and saves it somewhere that B4R can find it. The readings of the A/D can be handled by B4R as long as the timer can be read reliably and this does not need to happen in the ISR. No B4R code will be called from the ISR - I just need to know where B4R keeps its system timer and how to get a pin interrupt to work without annoying B4R.

    So, after a lot of reading I am no closer to figuring this out than when I started. It is clear I need to use an object called pollers but I cannot work out how to use it. Reading source on GitHub is no help either. Some of the headers I searched for unsuccessfully for hours and without them I have no clue what some of the functions do, or how. Even experienced C++ programmers need a kickstart in the right direction to solve some problems.

    Does anyone have any idea how I may go about this?

    I could of course write it in C++ but that would mean figuring out how to duplicate the protocol used by B4A and AsyncStreams. Maybe this will be easier. I will take advice on this. B4R certainly makes the WiFi stuff easier to program.

    I would also like to avoid a hardware solution. It's not difficult but makes the product more expensive and seems such a waste when I have perfectly good micro.
  2. Erel

    Erel Administrator Staff Member Licensed User

    Running code inside interrupts is problematic as the interrupt could be raised at any given point and you don't have any reasonable way to control it. Its a bit like running multithreaded code without locks or any other synchronization features.

    The fastest polling mechanism is AddLooper. I'm not sure that it is fast enough for your requirements. You can see some performance numbers here: https://www.b4x.com/android/forum/threads/timers-loopers-and-callsubplus.65989/#content

    You can add an interrupt handler with inline C code.
    Store the data in a global variable and then write it in the next loop from the B4R code.
  3. bdunkleysmith

    bdunkleysmith Active Member Licensed User

    When I ported an app which I had running on a Freetronics Leostick and used an interrupt to an ESP8266 based shield, this is the skeleton of what I used in lieu of an interrupt:

    Sub Process_Globals
    Public Serial1 As Serial

    Private PIN_CLK As Pin
    Private Time As ULong

    End Sub

    'Subroutine to process fall on clock input
    Sub PIN_CLK_StateChanged (State As Boolean)
    If State = False Then                            'Clock has fallen

            Time = Micros

    End If
    End Sub
    It may not be suitable for you, but I found polling using AddLooper was problematic for me and the above worked for me.
  4. johnf2013

    johnf2013 Member Licensed User

    That's the whole point of it.

    That is what I had in mind. This is a very quick in and out - interrupt, get the system timer value, save it somewhere, and get out. At 3000rpm it does not happen very often but the response must be quick.
    How do I access B4A's system timer?
    Also, what is the pollers object and where does it fit into this problem?
  5. Erel

    Erel Administrator Staff Member Licensed User

    You don't need to do anything special with timers or pollers.

    Implement the interrupt in the C code and update a global variable with the data you want to send.

    Use AddLooper to run a sub every loop. Check the global variable(s) in this sub and send the data.

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice