PIGPIO has a tick timer but it is only 32 bits.
I decide to implement the 64 bits internal free running timer
This is the C code to create the python module.
freeRunningCounter.c
Code: Select all
#include <stdio.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <Python.h>
#define ST_BASE (0x20003000)
#define TIMER_OFFSET (4)
static PyObject *freeRunningCounterError;
long long int *counter; // 64 bit timer
void *st_base;
int fd;
static PyObject * freeRunningCounter(PyObject *self, PyObject * args);
static PyMethodDef freeRunningCounterMethods[] = {
{ "getCounter", freeRunningCounter,METH_NOARGS, "Get free running counter"},
{ NULL,NULL,0,NULL}
};
PyMODINIT_FUNC
initfreeRunningCounter(void)
{
PyObject *m;
m = Py_InitModule("freeRunningCounter", freeRunningCounterMethods);
if ( m == NULL)
return;
// get access to system core memory
if (-1 == (fd = open("/dev/mem", O_RDONLY))) {
fprintf(stderr, "open() failed.\n");
return;
}
// map a specific page into process's address space
if (MAP_FAILED == (st_base = mmap(NULL, 4096,
PROT_READ, MAP_SHARED, fd, ST_BASE))) {
fprintf(stderr, "mmap() failed.\n");
return ;
}
close(fd);
// set up pointer, based on mapped page
counter = (long long int *)((char *)st_base + TIMER_OFFSET);
freeRunningCounterError = PyErr_NewException("freeRunningCounter.error",NULL,NULL);
Py_INCREF(freeRunningCounterError);
PyModule_AddObject(m, "error", freeRunningCounterError);
}
static PyObject * freeRunningCounter(PyObject *self, PyObject * args)
{
return PyLong_FromUnsignedLongLong((unsigned long long )*counter);
}
I use python 2.7 and I compile the code like this
Code: Select all
gcc -I/usr/include/python2.7 -lpython2.7 -c freeRunningCounter.c
gcc -shared freeRunningCounter.o -o freeRunningCounter.so
To check it just try
Code: Select all
[email protected] ~ $ sudo python
Python 2.7.3 (default, Mar 18 2014, 05:13:23)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import freeRunningCounter
>>> print freeRunningCounter.getCounter()
17054570755
>>> print freeRunningCounter.getCounter()
17055602152
>>> quit()
[email protected] ~ $
And now if we return to the stepper I just create a small program to show you how to implement it.
I use print and you shouldn't since printing will be very slow.
PrecisePulse.py
Code: Select all
#!/usr/bin/env python
import freeRunningCounter
stepTiming = input('enter time step in micro-second ? ')
Target = freeRunningCounter.getCounter() + stepTiming;
while True:
Current = freeRunningCounter.getCounter()
print Current,
if Current > Target:
Target= Target + stepTiming
print "Move stepper"
else:
print "\r",
[email protected] ~ $
P.S. you need to run "sudo" to get access to the free running counter
N.B. the timing between step is not exact but the overall pulse count will be precise. (crystal resolution). If each step of your stepper is not noticeable on the image capture, that will work fine.