Since I started reviewing different boards (i.e. those other than the Raspberry Pi), one thing that has always stood out a mile has been lack of GPIO support. Well, that’s now history – at least for Node-Red users.
I cannot being to express how sick and tired I am of hearing about not being able to access GPIO without ROOT access. On the one hand you're not supposed to use root - on the other hand if you are not root you can't do this... you can't do that... the Raspberry Pi and other devices are learning tools for heaven's sake - it's as if some folk don't want us to succeed until we're as clever as them!!! GRRR.
So you can imagine how pleased I was as this learning exercise started to unfold. It turns out - that there IS a way... read on...
Let me explain: For the Raspberry Pi there are a number of means of accessing GPIO – not least the standard GPIO nodes in Node-Red. These nodes however generally do not work with other boards and there are a lot of very good other boards out there. This solution seems to work with the Raspberry Pi AND other boards too. I've tested Orange Pi Zero, FriendlyArm Nanopi Plus2 - and I feel pretty sure it will work with many other boards too.
I think one of the first to get third party support was the Orange Pi (not from the company – I’m unaware of anyone getting direct help). But until recently, the likes of the FriendlyArm boards really had very little support – and what there was, was C code which needed to be operated by the ROOT user and that can pose problems for some programs.
Recently after certainly requests from me and no doubt others, FriendlyArm made the WIRINGNP utility (there’s a WIRINGOP version for Orange Pi) which comes with GPIO and though this still requires root – you can access the ports from Node-Red via the EXEC node using a SUDO call to the GPIO utility. It isn’t ideal or fast – but then normal Raspberry Pi GPIO isn’t fast either. Thanks to the changes that FA have made I’ve been able to use the LUMA Python library to easily access for example SD1306 OLED I2c displays from Node-Red.
As many Linux power users will know – the GPIO can be accessed as files at /sys/class/gpio – again – root access by default – just not as easy as dropping a box into Node-Red.
Well, now it is – I invite you to read https://flows.nodered.org/node/node-red-contrib-opi-gpio
So now it is possible to select a GPIO pin and turn it on or off – and read it - even with interrupts. In some cases via a drop down box, in others, via a simple gpio manual selector. Either way it is EASY.
In the instructions you'll see in that link above, you may have to run some code to ensure that your PI user has access to the GPIO – well, that was too messy for me so I asked Antonio for a little help and we’ve just added this to “the script” - you can run it stand alone – though the logging won’t work – and that’s fine - or.
getent group gpio || sudo groupadd gpio 2>&1 | tee -a $LOGFILE
getent group gpio | grep -w -l pi || sudo adduser pi gpio 2>&1 | tee -a $LOGFILE
[ ! -f /etc/udev/rules.d/99-com.rules ] && echo "KERNEL==\"gpio*\", RUN=\"/bin/sh -c 'chgrp -R gpio /sys/%p /sys/class/gpio && chmod -R g+w /sys/%p /sys/class/gpio'\"" | sudo tee -a /etc/udev/rules.d/99-com.rules > /dev/null
If the editor screws that up you’ll find it near the end of “the script”. So that takes care of making sure you have access.
So I added the Node-Red node which uses a library called ONOFF which in turn allows access – and sure enough – the NanoPi M3 was NOT on the dropdown list of boards – how was I going to add a pin from the M3 so I could toggle it up and down and read it.
Turns out it is easy – there is a formula for calculating the actual port of a GPIO pin based on it’s given name. It may not surprise you to know that Pin GPIOA0 is port 0. But what of B,C,D etc… GPIOC1 for example…
For every letter after A, add 32 – then the actual number. So C1 is 32+32+2 - i.e. port 66 – it is THAT easy. On the Pi you just use the GPIO numbers.
I can’t guaranteed this works on all boards but it works on the ones I’ve tried!! And I now have fast access to GPIO! The author is keen to develop this – and if you sent the author a list of pin names, actual physical pin numbers and the calculated port along with which board you are using – he’ll add them into the list of predefined boards but he IS looking for someone to take on this project. I don't think it is that complex so on the lookout for a budding programmer as this could do with some frills.
This is great news for Node-Red users who need port access.
So the setup and the node are now in “the script” but there is nothing to stop you adding this in manually as you would any node and running the above code (as Pi user) to add permissions.
Oh yes I tried the Nanopi M3 as well and THAT worked.
For the adventurous – the fellow who made this node relies on a NODEJS package called ONOFF for his Node-Red Node – if you go to the source of THAT you’ll find other general nodejs packages for i2c and SPI – not had time to look at SPI yet but the I2c library works a TREAT - I have it running in another blog entry with my Nano peripheral - but could it be that we’re about to be able to make full use of GPIO on the various boards out there – at last?
The only caviat at this point is that I found one board that only partly works. The Neo PLUS2 at first insisted that the user does not have permission as seen here
29 Jul 11:12:43 - [info] [opi_out:PA6] Pin: 6
29 Jul 11:12:43 - [error] [opi_out:a9041de2.0d817] Error: EACCES: permission denied, open '/sys/class/gpio/gpio6/value'
I rebooted the machine and now it worked but some other bits said
29 Jul 12:17:16 - [error] [opi_out:a9041de2.0d817] Error: EBUSY: resource busy or locked, write
Maybe I just happened to pick pins that had other uses already.
Using the node I had no problem with some of the other bits – and to make life easy, FriendlyArm in their WIKIs so specify the actual Linux port numbers. This example being for the Plus 2
I had no problem with ports 12, 11,2,0,2,3, 64,65,66,67 (0 is currently entered as 00 due to a bug in the node which does not store the last setting but defaults to 0) but 201, 203 and 1 gave me problems.
Meanwhile for that particular board, for those who’ve use FriendlyArm’s own software, there is of course the GPIO software which can be used by any user. However there’s a bug in that which I’ve reported.. gpio write 6 1 should turn on physical pin 6 – instead it turns on physical pin 22 (even the gpio number doesn’t match). I suspect they’ve copied the table over from another board and forgotten to update it. Physical pin 7 works. Of course it could be that they’ve messed something up in GPIO that is affecting other attempts to get to these ports.
On the Raspberry Pi it is important not to wipe out the existing 99-rule.com because in the latest version, that already has some rules to get around the (sometimes somewhat inappropriate) tight security regarding gpio – Github contributor FIVDI sent this which is found in the Raspberry Pi.
SUBSYSTEM=="input", GROUP="input", MODE="0660" SUBSYSTEM=="i2c-dev", GROUP="i2c", MODE="0660" SUBSYSTEM=="spidev", GROUP="spi", MODE="0660" SUBSYSTEM=="bcm2835-gpiomem", GROUP="gpio", MODE="0660" SUBSYSTEM=="gpio*", PROGRAM="/bin/sh -c '\ chown -R root:gpio /sys/class/gpio && chmod -R 770 /sys/class/gpio;\ chown -R root:gpio /sys/devices/virtual/gpio && chmod -R 770 /sys/devices/virtual/gpio;\ chown -R root:gpio /sys$devpath && chmod -R 770 /sys$devpath\ '"
IF ANYONE IS FEELING AMBITIOUS – if you could test the gpio ports on a board you have – and return the results here - board type – pins tested by name and actual pin number – these could be fed back to the author – everyone wins… !!!!
Testing – if you need a quick toggle to test a GPIO – I just realised I could use my own Node-Red node for the job… node-red-contrib-timeout. Set the warning to 1, the countdown to 1, the unsafe state payload to 0 and the safe state and warning states to 1… and that’s it.. you have a toggle once a second. node-red-contrib-timeout
Incidentally, in getting excited about this new ability to easily access GPIO, I got a bit frustrated with my FriendlyArm M3 board – there’s a 2mm connector on there called LVDS and no-where on their website could I find information. I thought there might be some useful GPIO I could use. I wrote off to FA and they sent me some data. Here’s the LVDS connector – I notice some potentially useful GPIO therein and possibly even another I2c channel?