GPIO control for realtime machine

Moderators: odroid, mdrjr

GPIO control for realtime machine

Unread postby brad » Tue Sep 20, 2016 3:42 pm

Hello,
im currently researching and investigating the possibilities of machine control with the C2 in particular using LinuxCNC to control a 3 axis router and possibly a spindle motor. For this I need a number of outputs for 3 stepper motor controllers and 1 spindle (or a PWM) control. I also need maybe 4 inputs for emergency stop, and limit switches on each axis.

I have been able to get LinuxCNC compiled up on the C2 Ubuntu Mate image and have a working realtime kernel for testing although there are a few bugs to iron out in the kernel. Realtime latency seems stable enough from my initial testing and I suspect I can maybe get it down some more. I currently have approx 110000ns max jitter latency on both servo and base threads at the moment.

Next step is to investigate controlling the GPIO's to do what I need.

There are currently many motion controllers out there that work well for stepper motors which have a Parallel LPT port interface. This is 1 option, emulate a parallel port on the C2's GPIO's so I can plug in one of these and off I go.

The next option is to throw away the motion controller LPT interface and create a new layout on the GPIO to interface directly with the stepper motor controllers, switches and the PWM controller on the C2. This is a much better solution as I now have a PWM to control the high speed spindle. I can then create a shield which can directly interface with the stepper controllers and PWM power supply for the spindle. I could even do some communication to the shield by i2c or uart connection to expand further.

All sounds great but there are a few hills to climb first and I am unsure about a few things.
1) PWM control on the odroid and if they can support the resolutions I would need to control and PWM power supply for spindle motor.
2) In regards to driving the GPIO I would need to create a new HAL driver which can be used with LinuxCNC, I am investigating the possibilities on how to do and have looked at what others have done with different boards.

- Beaglebone black - HAL driver exists which is an example of a driver driving GPIO pins...(https://github.com/LinuxCNC/linuxcnc/bl ... _bb_gpio.c)
- Pi2 has 2 lots of attempted drivers both incomplete mainly for other reasons of not enough cpu processing power but there are examples of the GPIO's pins being controlled via both WiringPi interface and also one apparently using DMA both written as HAL drivers. I get the feeling from reading over other forums that Wiring Pi works but was a little slow, remembering that all we really care about is real-time performance of the GPIO's.

Which path should I attempt to take? WiringPi or DMA, can anyone think of pro's and cons for each?

Initially I will be setting up for stepper motors which does not require I have a full loop with the C2, I can simply send the outputs out the pins the router will follow. Down the track I will be replacing these with servo motors and would like to bring the C2 into the loop, ie C2 (LinuxCNC) knows exactly the potions of the router servo motors via optical sensors sent back through gpio pins and can be more accurate and potentially faster as it can control the motors much better and essentially much quicker.

Brad.
brad
 
Posts: 686
Joined: Tue Mar 29, 2016 1:22 pm
Location: Australia
languages_spoken: english
ODROIDs: C2

Re: GPIO control for realtime machine

Unread postby odroid » Tue Sep 20, 2016 6:22 pm

I think the DMA driven GPIO HAL is more feasible to implement the stepper signal generator because 110usec of tolerance is too big.
But we don't have any experience of the DMA (Memory to GPIO data register) programming. :(
User avatar
odroid
Site Admin
 
Posts: 27973
Joined: Fri Feb 22, 2013 11:14 pm
languages_spoken: English
ODROIDs: ODROID

Re: GPIO control for realtime machine

Unread postby paulcrawford » Tue Sep 20, 2016 8:18 pm

brad, you may want to have a look at http://abyz.co.uk/rpi/pigpio/cif.html. Although designed for rpi, it definitely uses DMA and there is a reference https://github.com/richardghirst/PiBits/tree/master/ServoBlaster that may help you.
paulcrawford
 
Posts: 112
Joined: Tue May 10, 2016 11:51 am
languages_spoken: english
ODROIDs: odroid c2

Re: GPIO control for realtime machine

Unread postby brad » Wed Sep 21, 2016 10:05 am

Thank you gentlemen, I shall take a further look
brad
 
Posts: 686
Joined: Tue Mar 29, 2016 1:22 pm
Location: Australia
languages_spoken: english
ODROIDs: C2

Re: GPIO control for realtime machine

Unread postby brad » Thu Oct 06, 2016 11:34 am

Trying to work out what options are possible with the hardware mappings on the c2 and the multiplexer in the S905. I have come up with my wishlist, forgetting about drivers for the moment would this layout be physically possible? I am still looking into what is being used and what is available.

For a realtime CNC machine it would give me options of at least 7 General purpose logic pins (input or output), 4 PWM's, an in and out PCM & 2 ADC's

For a realtime Digital Audio Workstation it would give me at least 7 general purpose logic pins, PCM in and out, 4 PWM's, an I2S interface with at least 2 input and 2 output pins, 2 ADC's and a Digital Mic interface.

The uart & i2c interfaces on the pins would remain as they are but would be nice if PWM_AO_A was possible on the 7 pin header which I suspect it is

40 Pin Header
- Pin1 - +3.3v
- Pin2 - +5v
- Pin3 - I2CA_SDA
- Pin4 - +5v
- Pin5 - I2CA_SCL
- Pin6 - Ground
- Pin7 - GP I/O
- Pin8 - TXD1
- Pin9 - Ground
- Pin10 - RDX1
- Pin11 - PWM_E
- Pin12 - PCM_FS_A
- Pin13 - PCM_CLK_A
- Pin14 - Ground
- Pin15 - PCM_IN_A
- Pin16 - PCM_OUT_A
- Pin17 - +3.3v
- Pin18 - GP I/O
- Pin19 - PWM_F
- Pin20 - Ground
- Pin21 - GP I/O
- Pin22 - GP I/O
- Pin23 - GP I/O
- Pin24 - GP I/O
- Pin25 - Ground
- Pin26 - DMIC_CLK_OUT
- Pin27 - I2CB_SDA
- Pin28 - I2CB_SCL
- Pin29 - GP I/O
- Pin30 - Ground
- Pin31 - I2SOUT_CH23
- Pin32 - DMIC_IN
- Pin33 - PWM_A
- Pin34 - Ground
- Pin35 - I2SIN_CH67
- Pin36 - I2SIN_CH23
- Pin37 - ADC.AIN1 0~1.8v
- Pin38 - 1.8v rail reference voltage
- Pin39 - Ground
- Pin40 - ADC.AIN0 0~1.8v

7 Pin Header
- Pin1 - Ground
- Pin2 - PWM_AO_A
- Pin3 - +5v
- Pin4 - I2S_AM_CLK
- Pin5 - I2S_LR_CLK_OUT
- Pin6 - I2S_AO_CLK_OUT
- Pin7 - I2SOUT_CH01
brad
 
Posts: 686
Joined: Tue Mar 29, 2016 1:22 pm
Location: Australia
languages_spoken: english
ODROIDs: C2

Re: GPIO control for realtime machine

Unread postby brad » Sun Oct 09, 2016 5:18 pm

I have been looking into the GPIO control further and my lack of understanding seems to be causing me some confusion. Im trying to read registers via a C program to see how it is all setup but have conflicting results.

I produced some code which is attached (rough/development/alpha) to go off and find the register bits for the GPIO bits which from testing seems to be working well based on information I found from the datasheet, wiringpi and beaglebone linuxcnc driver. Both 40P and 7P are showing and I can physically pull input GPIO's set high on both headers to a low by earthing the GPIO and see the result in the registers

I also went off to find the pin multiplexer registers as per the datasheet but I think I am wrong with the offsets as coded as the data does not make sense. All bits seem off with the PERIPHS and same with the RTI. Shortly after boot the 7P AO gpio pin multiplexer registers start flapping but then stop a few mins afterwards and settle down, they dont appear to be the right registers from what I can tell.

I have too many bits in my head at the moment, there has to be a better way to work out the register offsets to hit them on the mark, can anyone offer suggestions? I suspect im doing something silly.
4
test program can be compiled using "gcc test.c" and probably has some errors, it needs much work.

and can be run as root using "sudo ./a.out"
Attachments
test.c
Test GPIO registers read
(17.91 KiB) Downloaded 79 times
brad
 
Posts: 686
Joined: Tue Mar 29, 2016 1:22 pm
Location: Australia
languages_spoken: english
ODROIDs: C2

Re: GPIO control for realtime machine

Unread postby crashoverride » Mon Oct 10, 2016 4:51 am

brad wrote:can anyone offer suggestions?

I found the program on this page to be the greatest help to me:
http://odroid.com/dokuwiki/doku.php?id=en:c2_gpio_default
crashoverride
 
Posts: 3526
Joined: Tue Dec 30, 2014 8:42 pm
languages_spoken: english
ODROIDs: C1

Re: GPIO control for realtime machine

Unread postby brad » Tue Oct 11, 2016 6:58 pm

crashoverride wrote:I found the program on this page to be the greatest help to me:
http://odroid.com/dokuwiki/doku.php?id= ... io_default


Thank you I missed that, it is most helpful :)

Id now like to work the patterns out for a few more registers. Do you know if a SIGBUS ((SI_USER) ie: a kill) signal when reading is more likely a private area of memory i cannot access directly? Maybe its a sign im accessing an invalid address? The datasheet speaks of 32 bit for EE registers and 16 bit x 4 CBUS registers to make up a full 64bit register for the AO domain which sort of confuses the whole matter for me.
brad
 
Posts: 686
Joined: Tue Mar 29, 2016 1:22 pm
Location: Australia
languages_spoken: english
ODROIDs: C2

Re: GPIO control for realtime machine

Unread postby brad » Wed Oct 12, 2016 6:12 pm

I've just spotted quiet a few RFC's for mainline kernel including the below 2 which is helping me gain a better understanding. Im really interested in knowing longer term plans for 3.14.y on C2 in regards to spending time on the drivers

https://patchwork.kernel.org/patch/9361981/
https://patchwork.kernel.org/patch/9361983/
brad
 
Posts: 686
Joined: Tue Mar 29, 2016 1:22 pm
Location: Australia
languages_spoken: english
ODROIDs: C2

Re: GPIO control for realtime machine

Unread postby brad » Sat Oct 15, 2016 11:19 am

Im doing some initial measuring on the standard kernel for bit banging the GPIO for PWM / duty cycle output

Test 1
- PWM (50us off & 50us on)
- chrt to FIFO scheduler with priority 85 (sudo chrt -f 85 ./a.out)
- Oscilloscope set to 50us scale for each line
50us.jpg
PWM 50 50
(231.78 KiB) Downloaded 553 times


Test 2
- Switch Pins fast with no waiting
- chrt to FIFO scheduler with priority 85 (sudo chrt -f 85 ./a.out)
- Oscilloscope set to 10us scale for each line
fast_pin.jpg
Fast Pin
(366.3 KiB) Downloaded 553 times


Test 3
- Duty Cycle (20us on, 80us off)
- chrt to FIFO scheduler with priority 85 (sudo chrt -f 85 ./a.out)
- Oscilloscope set to 20us scale for each line
20_duty.jpg
20 % duty
(297.68 KiB) Downloaded 553 times


Some quick code for testing by changing the high_time and low_time for the sleeps
Code: Select all
    #include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <errno.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>

int main(int argc, char **argv)
{
        // write delay
        int delay = 13000;

        // high time
        int high_time = 20000;
        // low time
        int low_time = 80000;

        // Open a fd to the gpio export pin
        int fd_gpio_export;

        if ((fd_gpio_export = open ("/sys/class/gpio/export", O_WRONLY)) < 0) {
                printf ("Unable to open : /sys/class/gpio/export %s\n", strerror(errno));
        }

        // Export pint 249 (Odroid Pin 7)
        if(dprintf(fd_gpio_export, "%s" , "249") < 0) {
                printf ("Unable to write : /sys/class/gpio/export %s\n", strerror(errno));
        }

        // Open a fd to gpio pin direction
        int fd_gpio_direction;

        if ((fd_gpio_direction = open ("/sys/class/gpio/gpio249/direction", O_WRONLY)) < 0) {
                printf ("Unable to open : /sys/class/gpio/gpio249/direction %s\n", strerror(errno));
        }

        // Set  pin 249 (Odroid Pin 7) as out pin
        if(dprintf(fd_gpio_direction, "%s" , "out") < 0) {
                printf ("Unable to write : /sys/class/gpio/gpio249/direction %s\n", strerror(errno));
        }

        // Open a fd to gpio pin direction
        int fd_gpio_249_value;

        if ((fd_gpio_249_value = open ("/sys/class/gpio/gpio249/value", O_WRONLY)) < 0) {
                printf ("Unable to open : /sys/class/gpio/gpio249/value %s\n", strerror(errno));
        }

        while(1==1) {
                dprintf(fd_gpio_249_value, "%s" , "1");
                nanosleep((const struct timespec[]){{0, high_time - delay}}, NULL);
                dprintf(fd_gpio_249_value, "%s" , "0");
                nanosleep((const struct timespec[]){{0, low_time - delay}}, NULL);
        }
}


I will try a similar test against the realtime kernel and try to track the jitter, in the standard kernel I need to take off approx 13us delay from the nanosleep functions to get timing approx right when running with the FIFO scheduler at a priority of 85. Shorter sleeps than 20us make output start to look messy.
brad
 
Posts: 686
Joined: Tue Mar 29, 2016 1:22 pm
Location: Australia
languages_spoken: english
ODROIDs: C2

Re: GPIO control for realtime machine

Unread postby brad » Sun Sep 03, 2017 11:38 am

Ive been working further on this little project with the 2 main goals..

- Well performing Realtime kernel
- Parallel Realtime GPIO support (in / out)

In regards to Real-time kernel version hardkernel 3.10.y works quiet well if USB and USB PHY driver is disabled. Mainline 4.11 Realtime kernel has missing HDMI support but I found USB did not impact performance but heavy Ethernet or emmc work did. I seen some massive improvements in emmc performance and design in 4.12.x so I am waiting for 4.12 version of realtime kernel to be released. The Ethernet issues were exaggerated for me as due to no HDMI I was running my X11 sessions via ssh and Ethernet. GBit Ethernet helped considerably.

In regards to IO for realtime machine control I have been looking at the GPIO and how best to control it from a userspace application. In my case the application will be LinuxCNC or MachineKit which I am working on a Hardware Abstration Layer (HAL) driver. Its based loosely on the driver for the beaglebone https://github.com/machinekit/machineki ... _bb_gpio.c

Im still working on the HAL driver but the aim is to have it called from a realtime thread running from machinekit. It initially picks up GPIO reserved pins which have been configured in the device tree (3.10.y or 4.x), individually memory maps each ports control registers (GPIOX, GPIOY & GPIOAO) and provides realtime compatible abstraction layer to Machinekit to allow it to interface with the GPIO. If we mmap the GPIO via ports in the S905 (ie all pins in the GPIOX port together) we can execute an operation to update and then read all pins on the port in one hit as they are all contained in the same registers. This same operation allows us to write (to output pins) and read (from input pins) quickly in a parallel operation within the real-time thread. There will be another control module in the hal driver which will configure the ports. real-time performance is not as critical here its mostly used for initial configuration, ie determine if a pin is input / output, should it be pulled up / down or even later enable a pin mux function to provide PWM output or GPIO interupts. Im not sure if I should be using the sysfs for this part as performance is not critical. Problem is the sysfs is different between 3.10.y and 4.x and I was hoping to make something compatible with both so mmap the registers directly might be a better solution for a userspace application.

LinuxCNC compiles and runs on Ubuntu with with hardkernel 3.10.y realtime kernel or 4.11.y real-time kernel. Im having some troubles compiling Machine kit on aarch64 at the moment but hope to overcome this shortly.

Plan is to emulate the GPIO to be compatible with parallel port stepper controller such as http://www.ebay.com.au/itm/Upgrade-5-Ax ... 544e2653da

I have a few types of 3.3v - 5v interface adaptors to try to make it work quickly and be compatible with C2's GPIO.
brad
 
Posts: 686
Joined: Tue Mar 29, 2016 1:22 pm
Location: Australia
languages_spoken: english
ODROIDs: C2

Re: GPIO control for realtime machine

Unread postby Herbk » Wed Jan 31, 2018 6:44 am

Hi Brad,
are there any new's from this project?
I'm realy interessted in it, because PC's with parport getting rare...

brad wrote:Ive been working further on this little project with the 2 main goals..

- Well performing Realtime kernel
- Parallel Realtime GPIO support (in / out)

In regards to Real-time kernel version hardkernel 3.10.y works quiet well if USB and USB PHY driver is disabled. Mainline 4.11 Realtime kernel has missing HDMI support but I found USB did not impact performance but heavy Ethernet or emmc work did. I seen some massive improvements in emmc performance and design in 4.12.x so I am waiting for 4.12 version of realtime kernel to be released. The Ethernet issues were exaggerated for me as due to no HDMI I was running my X11 sessions via ssh and Ethernet. GBit Ethernet helped considerably.

In regards to IO for realtime machine control I have been looking at the GPIO and how best to control it from a userspace application. In my case the application will be LinuxCNC or MachineKit which I am working on a Hardware Abstration Layer (HAL) driver. Its based loosely on the driver for the beaglebone https://github.com/machinekit/machineki ... _bb_gpio.c

Im still working on the HAL driver but the aim is to have it called from a realtime thread running from machinekit. It initially picks up GPIO reserved pins which have been configured in the device tree (3.10.y or 4.x), individually memory maps each ports control registers (GPIOX, GPIOY & GPIOAO) and provides realtime compatible abstraction layer to Machinekit to allow it to interface with the GPIO. If we mmap the GPIO via ports in the S905 (ie all pins in the GPIOX port together) we can execute an operation to update and then read all pins on the port in one hit as they are all contained in the same registers. This same operation allows us to write (to output pins) and read (from input pins) quickly in a parallel operation within the real-time thread. There will be another control module in the hal driver which will configure the ports. real-time performance is not as critical here its mostly used for initial configuration, ie determine if a pin is input / output, should it be pulled up / down or even later enable a pin mux function to provide PWM output or GPIO interupts. Im not sure if I should be using the sysfs for this part as performance is not critical. Problem is the sysfs is different between 3.10.y and 4.x and I was hoping to make something compatible with both so mmap the registers directly might be a better solution for a userspace application.

LinuxCNC compiles and runs on Ubuntu with with hardkernel 3.10.y realtime kernel or 4.11.y real-time kernel. Im having some troubles compiling Machine kit on aarch64 at the moment but hope to overcome this shortly.

Plan is to emulate the GPIO to be compatible with parallel port stepper controller such as http://www.ebay.com.au/itm/Upgrade-5-Ax ... 544e2653da

I have a few types of 3.3v - 5v interface adaptors to try to make it work quickly and be compatible with C2's GPIO.
Herbk
 
Posts: 1
Joined: Tue May 30, 2017 4:13 pm
languages_spoken: german, english


Return to Hardware and peripherals

Who is online

Users browsing this forum: No registered users and 2 guests