7 7
Larry Bank

ArmbianIO API proposal

Recommended Posts

13 minutes ago, StuxNet said:

@Larry Bank hit up this guy >>> https://github.com/rm-hull <<< He has very similar projects to what your working on, ie: universal SBC's wrappers, except mainly for screens. He has one repo "OPi.GPIO" that aims to accomplish something similar to ArmbianIO project but is limited to OPi as you can imagine. He has recent commits that suggest branching out into NanoPi (Duo) territory though.

 

I talked to him awhile back, pretty cool dude but seems pretty busy and the OPi.GPIO isn't his main focus. In any case this is all to say, without looking at your source and knowing what you do/don't have, maybe he has some goods you can snag.

All in all. Awesome work. Had this idea for a long time, but lack the hardware/expertise to do it (this was as far as I could go) but it's awesome to see you follow up bitbank with ArmbianIO. Keep it up. I'll absolutely be sending you some beer money when I get the chance.

Hi Stuxnet,

Thanks for the encouragement. Richard Hull's project is pure python and doesn't have any additional useful info for me. In fact, his project takes a very simplistic approach to the GPIO numbering and won't work properly on all boards. I'll keep improving ArmbianIO with the goal of it being easy to use and having support for all boards supported by Armbian.

Share this post


Link to post
Share on other sites

@StuxNet I've committed the pin mappings for NanoPi Duo https://github.com/rm-hull/OPi.GPIO/tree/master/nanopi to OPi.GPIO only because the Luma libraries depend on RPi.GPIO API and there wasn't a good alternative (unless you want to use the one off hacked up FriendlyElec junk). Larry's library already spans many more SBCs and has I2C and SPI access as part of the API. OPi.GPIO is only for GPIO and only supports Python (by design). I believe Luma uses Python's spidev for SPI and I'm not sure about I2C.  ArmbianIO supports C, Python and Java using pretty much the same method/function signatures. I plan on creating a RP.iGPIO wrapper that maps Pi pins to specific SBCs, so I can use Luma without having to hack in a new GPIO replacement for each SBC. I might be able to leverage @Larry Bank's pin mappings in C and just create the BOARD/BCM dicts. The only reason for this is so many projects rely on crappy RPi.GPIO instead of some type of abstraction :(

Share this post


Link to post
Share on other sites

OK, I tried https://github.com/nativelibs4java/JNAerator to generate the JNA wrapper, but it generates a bunch of BirdJ and other dependencies that are really not required for a simple and clean Java API. The Java interface file I created was easy enough to hand edit (in fact I just copied the C header and changed a few types and dealt with the function pointer). The Swig requirement has been totally removed from the project! I just need to port the rest of the demo programs over to Java.

Share this post


Link to post
Share on other sites
14 hours ago, sgjava said:

Not sure about JavaScript yet, but if I can find a generator that deals with pointers well then maybe I'll try that next.

Just do be clear. I'm not really interested in a 'JavaScript' port at all (it's IMHO a terrible 'language'). But it could be cool to have nodes to execute GPIO stuff from a node (in case you don't know nodeRed you should install it on one of your SBCs to understand the concept a little bit). If it's just about toggeling a pin I can easy write a python script doing this and execute this script with node-reds excec node (running shell commands). But having an ArmbianIO-Node in which msg.topic defines pin and msg.payload defines pinstate (high/low) as read/write opportunity could be really nice. I'm sure this isn't an easy task and probably a little bit to much of work. But in case you're interested this could be a nice project. :) 

 

Edit:

Just as an example what's needed for creating such 'custom' nodes: http://opensourceforu.com/2017/07/writing-custom-add-ons-node-red/ 

 

Share this post


Link to post
Share on other sites

@chwe I've looked at the Node-Red demo and it looks interesting to make work flows, but if you look at https://github.com/monteslu/node-red-contrib-gpio you'll see it's pretty involved. The nice thing though is it would support many more SBCs by ArmbianIO's very nature. @Larry Bank and I were discussing adding PWM yesterday, board name detection (see @tkaiser's comments above), etc., so there's still some core functionality to add at the C level and then to the wrappers. Of course being an Open Source project any one can contribute :)

Share this post


Link to post
Share on other sites

OK, I started on the RPi.GPIO wrapper https://github.com/bitbank2/ArmbianIO/blob/master/python/RPi/GPIO.py which basically supports reading and writing to the pins. None of the event stuff is coded yet, but you can see where I'm going. No pin mappings yet. Just keeping it the way ArmbianIO does it for now. The Led test works :)

import time
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
# Pin 12 set to output
GPIO.setup(12,GPIO.OUT)
# LED on
GPIO.output(12,GPIO.LOW)
time.sleep(3)
# LED off
GPIO.output(12,GPIO.HIGH)
GPIO.cleanup()

 

Share this post


Link to post
Share on other sites

Holy smokes, I didn't think the RPi.GPIO clone would be such a pain, but the bonus is I fixed some bugs in the C code and changed how callbacks work a bit. AIOAddGPIOCallback no longer sets pin direction, so you must call AIOAddGPIO and set the pin direction to GPIO_IN. I also added AIORemoveGPIOCallback which sets edge to "none" and causes the pthread to exit. This operated more like RPi.GPIO by leaving the pin set the way it was before the callback and only changes edge. I also fixed AIORemoveGPIO yesterday as it was using the literal pin number and not the mapped pin, so the pin was left in it's previous state (i.e. /sys/class/gpio/gpio123 was still there).

 

I was able to implement most of the RPi.GPIO event methods:

  • add_event_detect
  • remove_event_detect
  • add_event_callback

I still need to work on:

  • wait_for_edge
  • event_detected

Once this is done I should be able to test Luma.OLED on a few different model SBCs without code changes if I use the same pins. This will be the ultimate test. No more hacked up RPi.GPIO for each SBC! I had to have a custom RPi.GPIO for Odroid C1, Pine A64, the various Nano Pis, etc.

Share this post


Link to post
Share on other sites

Pull request pending for NanoPi Neo 2 and made the demo slightly more verbose.

 

Just wondering, does it might make sense to put all the boards and their pin mappings at the top of armbianio.c into structs? The current system of having to change multiple arrays seems a bit fragile.

Share this post


Link to post
Share on other sites

Today I had some time playing with GPIOs once again.. and I thought I should give ArmbianIO a try. :) 

 

Unfortunately,  wrapper.sh failed on the very last step:

opi@orangepizero:~/ArmbianIO/python$ sudo ./wrapper.sh
/usr/local/bin/pip
Status: Preprocessing /tmp/tmp9Kozky.h
Status: gcc -E -U __GNUC__ -dD "-Dinline=" "-D__inline__=" "-D__extension__=" "-D_Bool=uint8_t" "-D__const=const" "-D__asm__(x)=" "-D__asm(x)=" "-DCTYPESGEN=1" /tmp/tmp9Kozky.h
Status: Parsing /tmp/tmp9Kozky.h
Status: Processing description list.
Status: Writing to armbianio/armbianio.py.
Status: Wrapping complete.
Directory '.' is not installable. File 'setup.py' not found.

the files are generated but I saw that you removed setup.py from your github on feb.  What did I wrong? :)

Calling the libary from command line (as long as I'm in the right folder) works, but it's not registered as a library to call it from scripts.. 

 

System: OPi0, Debian stretch mainline (4.14.18)

Share this post


Link to post
Share on other sites

super fast, like a drive-in service. :) (and it works!)

btw. there's a small mistake in the ledtest example:

    # Pin 12 set to output
    AIOAddGPIO(12, GPIO_OUT)
    # LED on
    AIOWriteGPIO(12, 0)
    time.sleep(3)
    # LED off
    AIOWriteGPIO(12, 1)
    AIORemoveGPIO(12)
    AIOShutdown()
...

led on should be 1 and led off should be 0.. :) As it is written now, the pin stays high after finishing the script.

Share this post


Link to post
Share on other sites

ahh saw my mistake.. I drive the LED directly from the GPIO (I know this not recommended, but it's sunday and I'm lazy :lol:).. 

@TonyMac32 would be upset when he see how I treat my boards.. :D  

 

Edit: note to myself, I should read the comments people write to their code before complaining... :P 

@martinayotte J'ai choisi la première voie.. 

Share this post


Link to post
Share on other sites
3 hours ago, chwe said:

I drive the LED directly from the GPIO (I know this not recommended

For simple LED, there is no issue driving it directly, simply check the sink or source capabilities of your SoC or chips.

Some have higher sink capabilities than source, such as TTL chips, or even worst the PCF8574 GPIO Expander, but according to H3 datasheet, GPIOs has a "buffer strenth" of max 20mA in both sink/source mode.

 

 

Share this post


Link to post
Share on other sites

** Update **

I just added support to the ArmbianIO project for accessing the on-board IR receiver (connected to GPIO PL11 on many Orange Pi boards). Use the macro "IR_PIN" when reading the signal from the receiver (instead of specifying the header pin number). I will be releasing a demo app shortly which receives NEC ir codes without the use of the LIRC driver. My demo app will allow you to connect any IR receiver to any available GPIO pin or use the built-in one if present. The IR codes can be received with a simple 1-bit port without the use of a UART by simply timing the on/off signal to a reasonable margin of error using the Linux clock functions.

 

Share this post


Link to post
Share on other sites

I just published a simple C project to make use of the IR receiver (either on-board or connected to an arbitrary GPIO):

 

https://github.com/bitbank2/ir_receiver

 

It's basically the simplest C code to receive IR codes without the use of external libraries or kernel drivers. It depends on a reasonably accurate system clock. This works fine on Armbian running on OrangePi boards, but doesn't work on my RPI3B.

Share this post


Link to post
Share on other sites

Hello Larry,

 

i tried to use your ArmbianIO library now for an Orange Pi PC2 with H5 CPU.

But it seems not to be supported:

# ./demo
Unrecognized board type, aborting...
Problem initializing ArmbianIO library

How can i help to add this board that your library can be used?

 

That numbers in armbianio.c are not so easy to compose.

I will create an template with the GPIO-description and PIN-Numbers.

Share this post


Link to post
Share on other sites

 

 

Yes - i found this explanation in the sourcecode - but it is not so easy to translate it into the needed numbers. ;)

 

And there are mistakes in the GPIO-assignment that has been published ... :(

 

Correct should be

 

 

GPIO-Orange-Pi.png

Share this post


Link to post
Share on other sites

O.K. Then the assignment for an Orange Pi PC 2 should be

iOPIPC2Pins[] = {
355,-1,-1,12,-1,11,-1,6,69,-1,
70,1,110,0,-1,3,68,-1,71,15,
-1,16,2,14,13,-1,21,19,18,7,
-1,8,200,9,-1,10,201,107,198,-1,
199 };

The Pin for IR-RX is 363 (PL11)

 

Here is the complete file that compiles armbianio.c.zip

 

What must be else done to add this new board?

 

Share this post


Link to post
Share on other sites

Thanks for this wonderful lib!

I attached a TSOP34838 to my Tinker Board, and am using ArmbianIO to decode the IR signals. At first in JAVA. This worked better than I thought. However to get the signal when it's done sending (and not ~87 ms later) I needed to change the C library. Apart from that, I think it's more stable under heavier load.

My initial try is here:

https://github.com/bitbank2/ArmbianIO/compare/master...zeekoe:master

 

@Larry Bank Is this a direction you'd like to go with the library, or do you like to keep it more light-weight? If it is, I can clean up stuff a bit. An option would be putting the variable timeout mechanism inside the callback, and the decoding mechanism outside.

Note that it currently supports at least one specific remote with 800/1600 microsecond codes and 90 ms wait time. I plan to extend it for another remote I have with 600/1200 microsecond codes. Both seem to be RC5 (-ish).

 

edit: aha, I knew I read about manual IR decoding for NEC codes somewhere, just didn't remember it was here and written by you :blink:. Well, I took a slightly different approach, making use of the interrupt thingy and it seems to work reasonably reliable. Let me know what you think of it. But if you didn't go that way, perhaps I would need to move on to a hard-polling mechanism too, if I want perfect reception...

Share this post


Link to post
Share on other sites
On 11/11/2018 at 10:51 AM, zeekoe said:

Thanks for this wonderful lib!

I attached a TSOP34838 to my Tinker Board, and am using ArmbianIO to decode the IR signals. At first in JAVA. This worked better than I thought. However to get the signal when it's done sending (and not ~87 ms later) I needed to change the C library. Apart from that, I think it's more stable under heavier load.

My initial try is here:

https://github.com/bitbank2/ArmbianIO/compare/master...zeekoe:master

 

@Larry Bank Is this a direction you'd like to go with the library, or do you like to keep it more light-weight? If it is, I can clean up stuff a bit. An option would be putting the variable timeout mechanism inside the callback, and the decoding mechanism outside.

Note that it currently supports at least one specific remote with 800/1600 microsecond codes and 90 ms wait time. I plan to extend it for another remote I have with 600/1200 microsecond codes. Both seem to be RC5 (-ish).

 

edit: aha, I knew I read about manual IR decoding for NEC codes somewhere, just didn't remember it was here and written by you :blink:. Well, I took a slightly different approach, making use of the interrupt thingy and it seems to work reasonably reliable. Let me know what you think of it. But if you didn't go that way, perhaps I would need to move on to a hard-polling mechanism too, if I want perfect reception...

I'm glad you found it useful. Your additions look worthwhile. Please do a pull request and I'll merge it into the main branch.

 

I'm not sure about the bigger direction of ArmbianIO, but if it helps solve problems and more than 1 person finds it useful, then it should be added.

Share this post


Link to post
Share on other sites

https://github.com/bitbank2/ArmbianIO/pull/14

Note that there's still a bug somewhere: after exactly 38 codes received, I get nothing through in the JAVA method. The poller is still running though; I get "Code timeout" messages every three seconds (from C) and "Tick" messages every second (from the JAVA main sleep thread).

 

This translates generally to: after 38 times of executing the call back after creating it, it doesn't execute the callback anymore. I tried removing & re-adding the callback periodically, and in that case the callback is executed again. Does anyone know why this is? I don't think I changed anything to the C code that could've caused this. But my C isn't very wonderful.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
7 7