This commit is contained in:
joan 2014-01-12 21:31:59 +00:00
parent a58a98d17b
commit 7f0cf5a014
11 changed files with 1602 additions and 766 deletions

47
MakeRemote Normal file
View File

@ -0,0 +1,47 @@
CC = gcc
AR = ar
RANLIB = ranlib
SIZE = size
CFLAGS = -O3 -Wall
ALL = libpigpiod_if.a pigs
all: $(ALL)
pigs: command.o
$(CC) -o pigs pigs.c command.c
clean:
rm -f *.o *.i *.s *~ $(ALL)
install: $(LIB)
sudo install -m 0755 -d /usr/local/include
sudo install -m 0644 pigpio.h /usr/local/include
sudo install -m 0644 pigpiod_if.h /usr/local/include
sudo install -m 0755 -d /usr/local/lib
sudo install -m 0644 libpigpiod_if.a /usr/local/lib
sudo install -m 0755 -d /usr/local/bin
sudo install -m 0755 pigs /usr/local/bin
sudo python setup.py install
uninstall:
sudo rm -f /usr/local/include/pigpio.h
sudo rm -f /usr/local/lib/libpigpiod_if.a
sudo rm -f /usr/local/bin/pigs
LIB = libpigpiod_if.a
OBJ = pigpiod_if.o command.o
$(LIB): $(OBJ)
$(AR) rcs $(LIB) $(OBJ)
$(RANLIB) $(LIB)
$(SIZE) $(LIB)
# generated using gcc -MM *.c
command.o: command.c pigpio.h command.h
pigpiod.o: pigpiod.c pigpio.h command.h
pigpiod_if.o: pigpiod_if.c pigpio.h pigpiod_if.h
pigs.o: pigs.c pigpio.h command.h

View File

@ -5,61 +5,74 @@ SIZE = size
CFLAGS = -O3 -Wall CFLAGS = -O3 -Wall
ALL = libpigpio.a checklib demolib pig2vcd pigpiod pigs LIB1 = libpigpio.a
OBJ1 = pigpio.o command.o
LIB2 = libpigpiod_if.a
OBJ2 = pigpiod_if.o command.o
LIB = $(LIB1) $(LIB2)
ALL = $(LIB) checklib pig2vcd pigpiod pigs
LL = -L. -lpigpio -lpthread -lrt
all: $(ALL) all: $(ALL)
checklib: checklib.o libpigpio.a checklib: checklib.o $(LIB1)
$(CC) -o checklib checklib.c -L. -lpigpio -lpthread -lrt $(CC) -o checklib checklib.c $(LL)
demolib: demolib.o libpigpio.a pigpiod: pigpiod.o $(LIB1)
$(CC) -o demolib demolib.c -L. -lpigpio -lpthread -lrt $(CC) -o pigpiod pigpiod.c $(LL)
pigs: pigs.o command.o
$(CC) -o pigs pigs.c command.c
pig2vcd: pig2vcd.o pig2vcd: pig2vcd.o
$(CC) -o pig2vcd pig2vcd.c $(CC) -o pig2vcd pig2vcd.c
pigpiod: pigpiod.o libpigpio.a
$(CC) -o pigpiod pigpiod.c -L. -lpigpio -lpthread -lrt
pigs: command.o
$(CC) -o pigs pigs.c command.c
clean: clean:
rm -f *.o *.i *.s *~ $(ALL) rm -f *.o *.i *.s *~ $(ALL)
install: $(LIB) install: $(LIB)
sudo install -m 0755 -d /usr/local/include sudo install -m 0755 -d /usr/local/include
sudo install -m 0644 pigpio.h /usr/local/include sudo install -m 0644 pigpio.h /usr/local/include
sudo install -m 0755 -d /usr/local/lib sudo install -m 0644 pigpiod_if.h /usr/local/include
sudo install -m 0644 libpigpio.a /usr/local/lib sudo install -m 0755 -d /usr/local/lib
sudo install -m 0755 -d /usr/local/bin sudo install -m 0644 libpigpio.a /usr/local/lib
sudo install -m 0755 pig2vcd /usr/local/bin sudo install -m 0644 libpigpiod_if.a /usr/local/lib
sudo install -m 0755 pigpiod /usr/local/bin sudo install -m 0755 -d /usr/local/bin
sudo install -m 0755 pigs /usr/local/bin sudo install -m 0755 pig2vcd /usr/local/bin
sudo install -m 0755 pigpiod /usr/local/bin
sudo install -m 0755 pigs /usr/local/bin
sudo python setup.py install sudo python setup.py install
uninstall: uninstall:
sudo rm -f /usr/local/include/pigpio.h sudo rm -f /usr/local/include/pigpio.h
sudo rm -f /usr/local/include/pigpiod_if.h
sudo rm -f /usr/local/lib/libpigpio.a sudo rm -f /usr/local/lib/libpigpio.a
sudo rm -f /usr/local/lib/libpigpiod_if.a
sudo rm -f /usr/local/bin/pig2vcd sudo rm -f /usr/local/bin/pig2vcd
sudo rm -f /usr/local/bin/pigpiod sudo rm -f /usr/local/bin/pigpiod
sudo rm -f /usr/local/bin/pigs sudo rm -f /usr/local/bin/pigs
LIB = libpigpio.a $(LIB1): $(OBJ1)
OBJ = pigpio.o command.o $(AR) rcs $(LIB1) $(OBJ1)
$(RANLIB) $(LIB1)
$(SIZE) $(LIB1)
$(LIB): $(OBJ) $(LIB2): $(OBJ2)
$(AR) rcs $(LIB) $(OBJ) $(AR) rcs $(LIB2) $(OBJ2)
$(RANLIB) $(LIB) $(RANLIB) $(LIB2)
$(SIZE) $(LIB) $(SIZE) $(LIB2)
# generated using gcc -M *.c # generated using gcc -MM *.c
checklib.o: checklib.c pigpio.h checklib.o: checklib.c pigpio.h
command.o: command.c pigpio.h command.h command.o: command.c pigpio.h command.h
demolib.o: demolib.c pigpio.h
pig2vcd.o: pig2vcd.c pigpio.h pig2vcd.o: pig2vcd.c pigpio.h
pigpio.o: pigpio.c pigpio.h command.h pigpio.o: pigpio.c pigpio.h command.h
pigpiod.o: pigpiod.c pigpio.h command.h pigpiod.o: pigpiod.c pigpio.h command.h
pigpiod_if.o: pigpiod_if.c pigpio.h command.h pigpiod_if.h
pigs.o: pigs.c pigpio.h command.h pigs.o: pigs.c pigpio.h command.h

72
README
View File

@ -9,13 +9,16 @@ Enter the following two commands (in this order)
make make
make install make install
This will install: This will install
the library (libpigpio.a) in /usr/local/lib
the header file (pigpio.h) in /usr/local/include o the library (libpigpio.a) in /usr/local/lib
the daemon (pigpiod) in /usr/local/bin o the library (libpigpiod_if.a) in /usr/local/lib
the socket interface (pigs) in /usr/local/bin o the header file (pigpio.h) in /usr/local/include
the utility pig2vcd in /usr/local/bin o the header file (pigpiod_if.h) in /usr/local/include
the Python module pigpio.py o the daemon (pigpiod) in /usr/local/bin
o the socket interface (pigs) in /usr/local/bin
o the utility pig2vcd in /usr/local/bin
o the Python module pigpio.py
TEST TEST
@ -23,8 +26,13 @@ To test the library do
sudo ./checklib sudo ./checklib
checklib.c, demolib.c, pig2vcd.c, pigpiod.c, pigs.c, and pigpio.py EXAMPLE CODE
show examples of interfacing with the library.
checklib.c, pig2vcd.c, and pigpiod.c
show examples of interfacing with the pigpio library.
pigs.c, pigpio.py, and test_pigpiod_if.c
show examples of interfacing with the pigpiod daemon.
DAEMON DAEMON
@ -39,7 +47,7 @@ When the library starts it locks
/var/run/pigpio.pid /var/run/pigpio.pid
The file should be deleted when the library terminates. The file should be automatically deleted when the library terminates.
SOCKET INTERFACE SOCKET INTERFACE
@ -62,16 +70,16 @@ echo "help" >/dev/pigpio
PYTHON MODULE PYTHON MODULE
By default the Python pigpio module is installed to the The Python pigpio module is installed to the default python location.
default python location. You can install it for additional
Python versions by You can install it for additional Python versions by
pythonx.y setup.py install pythonx.y setup.py install
where x.y is the Python version. where x.y is the Python version.
If the pigpiod daemon is running you can test the Python If the pigpiod daemon is running you can test the Python module
module by entering the following commands. by entering the following commands.
python python
@ -95,3 +103,37 @@ To stop the pigpiod daemon
sudo killall pigpiod sudo killall pigpiod
RUNNING ON NON Pi's
You can access the pigpiod daemon running on the Pi from any machine which
can access it over the network. This access is via the socket interface.
In particular this allows you to use the following on non-Pi's.
o pigs
o the pigpio Python module
o the C socket I/F using libpigpiod_if (header file pigpiod_if.h)
On a Linux machine
make -f MakeRemote clean
make -f MakeRemote
make -f MakeRemote install
This will install
o the library (libpigpiod_if.a) in /usr/local/lib
o the header file (pigpio.h) in /usr/local/include
o the header file (pigpiod_if.h) in /usr/local/include
o the socket interface (pigs) in /usr/local/bin
o the Python module pigpio.py
On Windows machines (and possibly Macs)
The Python module should install with
python setup.py install
pigs and pigpiod_if.c will need minor mods to reflect the
Window's/Mac's socket interface.

View File

@ -26,7 +26,7 @@ For more information, please refer to <http://unlicense.org/>
*/ */
/* /*
This version is for pigpio version 7+ This version is for pigpio version 10+
*/ */
#include <stdio.h> #include <stdio.h>
@ -74,6 +74,7 @@ cmdInfo_t cmdInfo[]=
{PI_CMD_TICK, "T", 1, 4}, {PI_CMD_TICK, "T", 1, 4},
{PI_CMD_HELP, "HELP", 6, 5}, {PI_CMD_HELP, "HELP", 6, 5},
{PI_CMD_HELP, "H", 6, 5}, {PI_CMD_HELP, "H", 6, 5},
{PI_CMD_PIGPV, "PIGPV", 1, 4},
}; };
char * cmdUsage = "\ char * cmdUsage = "\
@ -93,6 +94,7 @@ NC h close notification\n\
PWM/P u d set PWM value for gpio\n\ PWM/P u d set PWM value for gpio\n\
PFS u d set PWM frequency for gpio\n\ PFS u d set PWM frequency for gpio\n\
PFG u get PWM frequency for gpio\n\ PFG u get PWM frequency for gpio\n\
PIGPV return pigpio version\n\
PRS u d set PWM range for gpio\n\ PRS u d set PWM range for gpio\n\
PRG u get PWM range for gpio\n\ PRG u get PWM range for gpio\n\
PRRG u get PWM real range for gpio\n\ PRRG u get PWM real range for gpio\n\
@ -159,6 +161,8 @@ static errInfo_t errInfo[]=
{PI_TOO_MANY_PULSES , "waveform has too many pulses"}, {PI_TOO_MANY_PULSES , "waveform has too many pulses"},
{PI_TOO_MANY_CHARS , "waveform has too many chars"}, {PI_TOO_MANY_CHARS , "waveform has too many chars"},
{PI_NOT_SERIAL_GPIO , "no serial read in progress on gpio"}, {PI_NOT_SERIAL_GPIO , "no serial read in progress on gpio"},
{PI_BAD_SERIAL_STRUC , "bad (null) serial structure parameter"},
{PI_BAD_SERIAL_BUF , "bad (null) serial buf parameter"},
{PI_NOT_PERMITTED , "no permission to update gpio"}, {PI_NOT_PERMITTED , "no permission to update gpio"},
{PI_SOME_PERMITTED , "no permission to update one or more gpios"}, {PI_SOME_PERMITTED , "no permission to update one or more gpios"},
}; };
@ -200,7 +204,7 @@ int cmdParse(char * buf, cmdCmd_t * cmd)
switch (cmdInfo[idx].vt) switch (cmdInfo[idx].vt)
{ {
case 1: /* BR1 BR2 HWVER NO TICK */ case 1: /* BR1 BR2 HWVER PIGPV NO TICK */
f = sscanf(buf, " %7s %c", str, &t); f = sscanf(buf, " %7s %c", str, &t);
if (f == 1) valid = 1; if (f == 1) valid = 1;
break; break;

673
demolib.c
View File

@ -1,673 +0,0 @@
/*
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>
*/
/*
This version is for pigpio version 3+
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/i2c-dev.h>
#include <sys/ioctl.h>
#include "pigpio.h"
/* ===========================================================================
THIS PROGRAM NEEDS THE I2C DEVICE AND DEVELOPMENT LIBRARY
TO GET THE NEEDED FILES DO
sudo apt-get install libi2c-dev
BEFORE RUNNING THE PROGRAM ENSURE THAT THE I2C DEVICE IS PRESENT
sudo modprobe i2c-bcm2708
sudo modprobe i2c-dev
sudo chmod o+rw /dev/i2c*
=========================================================================== */
/*
P1 Name gpio used for
3 SDA 0/2 i2c
5 SCL 1/3 i2c
7 --- 4 LASER
8 TXD 14 LED1
10 RXD 15 LED2
11 --- 17 SERVO 1
12 --- 18 SERVO 2
13 --- 21/27 SERVO 3
15 --- 22 LED3
16 --- 23 TI Launchpad
18 --- 24 Sonar trigger
19 MOSI 10 Sonar echo
21 MISO 9 Motor B In 1
22 --- 25 LDR
23 SCLK 11 Motor B In 2
24 CE0 8 Motor A In1
26 CE1 7 Motor A In2
*/
#define LASER 4
#define MOTOR_A_IN2 7
#define MOTOR_A_IN1 8
#define MOTOR_B_IN1 9
#define SONAR_ECHO 10
#define MOTOR_B_IN2 11
#define LED1 14
#define LED2 15
#define SERVO1 17
#define SERVO2 18
#define SERVO3 21
#define LED3 22
#define LAUNCHPAD 23
#define SONAR_TRIGGER 24
#define LDR 25
#define LEDS 4
short rawAcc[3];
short rawGyr[3];
short rawMag[3];
#define ROLL 0
#define PITCH 1
#define YAW 2
#define ACC_ORIENTATION(X, Y, Z) \
{rawAcc[ROLL] = -X; rawAcc[PITCH] = -Y; rawAcc[YAW] = Z;}
#define GYRO_ORIENTATION(X, Y, Z) \
{rawGyr[ROLL] = Y; rawGyr[PITCH] = -X; rawGyr[YAW] = -Z;}
#define MAG_ORIENTATION(X, Y, Z) \
{rawMag[ROLL] = X; rawMag[PITCH] = Y; rawMag[YAW] = -Z;}
#define CALIBRATIONS 200
#define ADXL345_I2C_ADDR 0x53
#define ITG3200_I2C_ADDR 0x68
static int version, micros=5, millis=100;
static volatile unsigned long launchpadPulses;
static volatile unsigned long launchpad5;
static volatile unsigned long launchpad10;
static volatile unsigned long launchpad15;
static volatile unsigned long launchpadOutRange;
static volatile int launchpadErr;
static volatile uint32_t LDRrechargeTick;
/* forward prototypes */
void LEDlaserTick (void);
void motorTick(void);
void i2cTick (void);
void servoTick (void);
void sonarLDRtick(void);
void launchpadAlert(int gpio, int level, uint32_t tick);
void sonarAlert(int gpio, int level, uint32_t tick);
void LDRalert(int gpio, int level, uint32_t tick);
void putTTY(char * buf);
void putTTYstr(int row, int col, char * buf);
int main(int argc, char *argv[])
{
char str[256];
if (argc > 1) micros = atoi(argv[1]);
if (argc > 2) millis = atoi(argv[2]);
putTTY("\033c"); /* clear console */
gpioCfgBufferSize(millis);
gpioCfgClock(micros, PI_CLOCK_PCM, PI_CLOCK_PLLD);
/* before using the library you must call gpioInitialise */
version = gpioInitialise();
if (version >= 0)
{
/* initialise pins, only gpio numbers are supported */
gpioSetMode(SERVO1, PI_OUTPUT);
gpioSetMode(SERVO2, PI_OUTPUT);
gpioSetMode(SERVO3, PI_OUTPUT);
gpioSetMode(LASER, PI_OUTPUT);
gpioSetMode(LED1, PI_OUTPUT);
gpioSetMode(LED2, PI_OUTPUT);
gpioSetMode(LED3, PI_OUTPUT);
gpioSetMode(MOTOR_A_IN1, PI_OUTPUT);
gpioSetMode(MOTOR_A_IN2, PI_OUTPUT);
gpioSetMode(MOTOR_B_IN1, PI_OUTPUT);
gpioSetMode(MOTOR_B_IN2, PI_OUTPUT);
gpioSetMode(SONAR_TRIGGER, PI_OUTPUT);
gpioWrite (SONAR_TRIGGER, PI_OFF);
gpioSetMode(SONAR_ECHO, PI_INPUT);
gpioSetMode(LAUNCHPAD, PI_INPUT);
gpioSetMode(LDR, PI_INPUT);
/* update i2c fifty times a second, timer #0 */
gpioSetTimerFunc(0, 20, i2cTick);
//gpioSetTimerFunc(0, 1000, servoTick);
/* update LEDs and laser once a second, timer #1 */
gpioSetTimerFunc(1, 1000, LEDlaserTick);
/* update motors every three seconds, timer #2 */
gpioSetTimerFunc(2, 3000, motorTick);
/* update sonar/LDR 10 times a second, timer #3 */
gpioSetTimerFunc(3, 100, sonarLDRtick);
/* an attachecd TI launchpad is transmitting high pulses of
15, 35, 55, 75, ..., 975, 995 microseconds repeating with 50
microseconds off between each pulse */
gpioSetAlertFunc(LAUNCHPAD, launchpadAlert);
/* monitor sonar echos */
gpioSetAlertFunc(SONAR_ECHO, sonarAlert);
/* monitor LDR level changes */
gpioSetAlertFunc(LDR, LDRalert);
while (1)
{
sleep(1);
sprintf(str, "TI pulses %8ld", launchpadPulses);
putTTYstr(9, 1, str);
sprintf(str, "+/-5 %8ld", launchpad5);
putTTYstr(10, 6, str);
sprintf(str, "+/-10 %8ld", launchpad10);
putTTYstr(11, 5, str);
sprintf(str, "+/-15 %8ld", launchpad15);
putTTYstr(12, 5, str);
sprintf(str, "Others %8ld (last %d) ",
launchpadOutRange, launchpadErr);
putTTYstr(13, 4, str);
}
}
gpioTerminate();
return 0;
}
void LEDlaserTick(void)
{
static int gpio[LEDS]={LED1, LED2, LED3, LASER};
static int pos [LEDS]={ 0, 3, 6, 9};
static int inc [LEDS]={ 1, 1, 1, 1};
static int vals[] = {0, 1, 2, 4, 8, 16, 32, 64, 128, 249};
int i;
for (i=0; i<LEDS; i++)
{
gpioPWM(gpio[i], vals[pos[i]]);
pos[i] += inc[i];
if ( (pos[i]>=(sizeof(vals)/4)) || (pos[i]<0) )
{
inc[i] = -inc[i];
pos[i] += inc[i];
}
}
}
void sonarLDRtick(void)
{
/* trigger a sonar reading */
gpioWrite(SONAR_TRIGGER, PI_ON);
usleep(20);
gpioWrite(SONAR_TRIGGER, PI_OFF);
/* trigger a LDR reading */
gpioSetMode(LDR, PI_OUTPUT); /* drain capacitor */
gpioWrite(LDR, PI_OFF);
usleep(200);
LDRrechargeTick = gpioTick();
gpioSetMode(LDR, PI_INPUT); /* start capacitor recharge */
}
void motorTick(void)
{
static int gpio_in1[2]={MOTOR_A_IN1, MOTOR_B_IN1};
static int gpio_in2[2]={MOTOR_A_IN2, MOTOR_B_IN2};
static int speed [2]={ 80, 80};
static int inc [2]={ -50, 50};
int i;
char str[256];
for (i=0; i<2; i++)
{
speed[i]+=inc[i];
if (speed[i]<0)
{
gpioPWM(gpio_in1[i], -speed[i]);
gpioPWM(gpio_in2[i], 0);
if (speed[i] < -205) inc[i] = -inc[i];
sprintf(str, "MOT%d IN1=%3d IN2=%3d", i+1, -speed[i], 0);
}
else
{
gpioPWM(gpio_in2[i], speed[i]);
gpioPWM(gpio_in1[i], 0);
if (speed[i] > 205) inc[i] = -inc[i];
sprintf(str, "MOT%d IN1=%3d IN2=%3d", i+1, 0, speed[i]);
}
if (i) putTTYstr(7, 1, str); else putTTYstr(5, 1, str);
}
}
/* loads of code to read/write i2c */
void selectDevice(int i2c, int addr, char * name)
{
if (ioctl(i2c, I2C_SLAVE, addr) < 0)
{
fprintf(stderr, "%s not present\n", name);
}
}
void writeToDevice(int i2c, char * buf, int len)
{
static int reported = 0;
if (write(i2c, buf, len) != len)
{
if (!reported)
{
fprintf(stderr, "Can't write to device\n");
reported = 1;
}
}
else reported = 0;
}
void readADXL345(int i2c)
{
char buf[8];
static int reported = 0;
selectDevice(i2c, ADXL345_I2C_ADDR, "ADXL345");
writeToDevice(i2c, "\x32", 1);
if (read(i2c, buf, 6) != 6)
{
if (!reported)
{
fprintf(stderr, "Unable to read from ADXL345\n");
reported = 1;
}
}
else
{
reported = 0;
ACC_ORIENTATION (
((buf[1]<<8) | buf[0]),
((buf[3]<<8) | buf[2]),
((buf[5]<<8) | buf[4]) );
}
}
void readITG3200(int i2c)
{
char buf[8];
static int reported = 0;
selectDevice(i2c, ITG3200_I2C_ADDR, "ITG3200");
writeToDevice(i2c, "\x1D", 1);
if (read(i2c, buf, 6) != 6)
{
if (!reported)
{
fprintf(stderr, "Unable to read from ITG3200\n");
reported = 1;
}
}
else
{
reported = 0;
GYRO_ORIENTATION (
((buf[0]<<8) | buf[1]),
((buf[2]<<8) | buf[3]),
((buf[4]<<8) | buf[5]) );
}
}
int initI2Cdevices(void)
{
int i2c;
if ((i2c = open("/dev/i2c-0", O_RDWR)) < 0)
{
perror("Failed to open i2c bus");
exit(1);
}
/* initialise ADXL345 */
selectDevice(i2c, ADXL345_I2C_ADDR, "ADXL345");
writeToDevice(i2c, "\x2d\x00", 2);
writeToDevice(i2c, "\x2d\x10", 2);
writeToDevice(i2c, "\x2d\x08", 2);
writeToDevice(i2c, "\x31\x00", 2);
writeToDevice(i2c, "\x31\x0b", 2);
/* initialise ITG3200 */
selectDevice(i2c, ITG3200_I2C_ADDR, "ITG3200");
writeToDevice(i2c, "\x16\b00011000", 2);
return i2c;
}
/* an attached IMU (GY-85) supplies orientation information which
is used to position the servos */
float estimateAngle(int acc, int gyro, float oldAng, int elapsed)
{
float angleAcc, angleInc, estAngle;
float secs;
secs = (float) elapsed / 1e6f;
angleAcc = (float) acc * 90.0f / 256.0f;
angleInc = (float) gyro * secs * 2000.0f / 32768.0f;
estAngle = 0.75 * (oldAng + angleInc) + 0.25 * angleAcc;
return estAngle;
}
void servoTick(void)
{
static int wid1=1500, wid2=1500, wid3=1500;
static int inc1=50, inc2=75, inc3=100;
gpioServo(SERVO1, wid1);
gpioServo(SERVO2, wid2);
gpioServo(SERVO3, wid3);
wid1+=inc1; if ((wid1<1000) || (wid1>2000)) {inc1 = -inc1; wid1+=inc1;}
wid2+=inc2; if ((wid2<1000) || (wid2>2000)) {inc2 = -inc2; wid2+=inc2;}
wid3+=inc3; if ((wid3<1000) || (wid3>2000)) {inc3 = -inc3; wid3+=inc3;}
}
void i2cTick(void)
{
static int inited = 0;
static int calibrated = 0;
static int calibrations = 0;
static int accCalibX = 0, accCalibY = 0, accCalibZ = 0;
static int gyroCalibX = 0, gyroCalibY = 0, gyroCalibZ = 0;
static int i2c;
static float X=0.0, Y=0.0, Z=0.0;
static uint32_t lastTick;
uint32_t tick;
int elapsed;
int pulse;
char str[256];
if (inited)
{
tick = gpioTick();
elapsed = tick - lastTick;
lastTick = tick;
readADXL345(i2c);
readITG3200(i2c);
if (calibrated)
{
X = estimateAngle(
rawAcc[ROLL], rawGyr[ROLL] -gyroCalibX, X, elapsed);
Y = estimateAngle(
rawAcc[PITCH], rawGyr[PITCH] - gyroCalibY, Y, elapsed);
Z = estimateAngle(
rawAcc[YAW], rawGyr[YAW] - gyroCalibZ, Z, elapsed);
pulse = 1500 + (Y * 1000 / 90);
if (pulse < 500) pulse = 500;
if (pulse > 2500) pulse = 2500;
gpioServo(SERVO1, pulse);
pulse = 1500 - (X * 500 / 90);
if (pulse < 1000) pulse = 1000;
if (pulse > 2000) pulse = 2000;
gpioServo(SERVO2, pulse);
/* prefer Z but that doesn't change much */
pulse = 1500 - (Y * 500 / 90);
if (pulse < 800) pulse = 800;
if (pulse > 2200) pulse = 2200;
gpioServo(SERVO3, pulse);
sprintf(str, "X=%4.0f Y=%4.0f Z=%4.0f ", X, Y, Z);
putTTYstr(1, 1, str);
}
else
{
accCalibX+=rawAcc[ROLL];
accCalibY+=rawAcc[PITCH];
accCalibZ+=rawAcc[YAW];
gyroCalibX+=rawGyr[ROLL];
gyroCalibY+=rawGyr[PITCH];
gyroCalibZ+=rawGyr[YAW];
if (++calibrations >= CALIBRATIONS)
{
accCalibX /= CALIBRATIONS;
accCalibY /= CALIBRATIONS;
accCalibZ /= CALIBRATIONS;
gyroCalibX /= CALIBRATIONS;
gyroCalibY /= CALIBRATIONS;
gyroCalibZ /= CALIBRATIONS;
calibrated = 1;
}
}
}
else
{
i2c = initI2Cdevices();
gpioServo(SERVO1, 1500);
gpioServo(SERVO2, 1500);
gpioServo(SERVO3, 1500);
inited = 1;
}
}
void sonarAlert(int gpio, int level, uint32_t tick)
{
static uint32_t startTick;
int diffTick;
char str[256];
if (level == PI_ON)
{
startTick = tick;
}
else if (level == PI_OFF)
{
diffTick = tick - startTick;
if (diffTick < 26100)
{
sprintf(str, "Sonar %3d cms", (diffTick+29)/58);
putTTYstr(15, 1, str);
}
}
}
void LDRalert(int pin, int level, uint32_t tick)
{
int diffTick;
char str[256];
if (level == PI_ON)
{
diffTick = tick - LDRrechargeTick;
sprintf(str, "LDR %4d micros", diffTick);
putTTYstr(17, 1, str);
}
}
void launchpadAlert(int pin, int level, uint32_t tick)
{
static int inited = 0, lastTick, lastPulseLen;
int pulseLen, pulseDif;
if (inited)
{
pulseLen = tick - lastTick;
lastTick = tick;
if (level==0)
{
if (lastPulseLen)
{
pulseDif = pulseLen - lastPulseLen;
/* allow for wrap around */
if (pulseDif < 0) pulseDif += 1096;
/* now centre around expected value */
pulseDif -= 33;
if (pulseDif < 0) pulseDif = -pulseDif;
launchpadPulses++;
if (pulseDif <= 5)
{
launchpad5++;
}
else if (pulseDif <= 10)
{
launchpad10++;
}
else if (pulseDif <= 15)
{
launchpad15++;
}
else
{
launchpadOutRange++;
launchpadErr = pulseDif;
}
}
lastPulseLen = pulseLen;
}
}
else
{
lastTick = tick;
lastPulseLen = 0;
launchpadPulses = 0;
launchpad5 = 0;
launchpad10 = 0;
launchpad15 = 0;
launchpadOutRange = 0;
inited = 1;
}
}
void putTTY(char * buf)
{
write(1, buf, strlen(buf));
}
void putTTYstr(int row, int col, char * buf)
{
char str[256];
sprintf(str, "\033[%d;%dH%s", row, col, buf);
putTTY(str);
}

120
pigpio.c
View File

@ -25,7 +25,7 @@ OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/> For more information, please refer to <http://unlicense.org/>
*/ */
/* pigpio version 9 */ /* pigpio version 10 */
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -198,6 +198,31 @@ bit 0 READ_LAST_NOT_SET_ERROR
} \ } \
while (0) while (0)
#define CHECK_INITED_RET_NULL_PTR \
do \
{ \
if (!libInitialised) \
{ \
fprintf(stderr, \
"%s %s: pigpio uninitialised, call gpioInitialise()\n",\
myTimeStamp(), __FUNCTION__); \
return (NULL); \
} \
} \
while (0)
#define CHECK_INITED_RET_NIL \
do \
{ \
if (!libInitialised) \
{ \
fprintf(stderr, \
"%s %s: pigpio uninitialised, call gpioInitialise()\n",\
myTimeStamp(), __FUNCTION__); \
} \
} \
while (0)
#define CHECK_NOT_INITED \ #define CHECK_NOT_INITED \
do \ do \
{ \ { \
@ -322,16 +347,16 @@ bit 0 READ_LAST_NOT_SET_ERROR
/* DMA CS Control and Status bits */ /* DMA CS Control and Status bits */
#define DMA_CHANNEL_RESET (1<<31) #define DMA_CHANNEL_RESET (1<<31)
#define DMA_WAIT_ON_WRITES (1<<28) #define DMA_WAIT_ON_WRITES (1<<28)
#define DMA_PANIC_PRIORITY(x) ((x)<<20) #define DMA_PANIC_PRIORITY(x) ((x)<<20)
#define DMA_PRIORITY(x) ((x)<<16) #define DMA_PRIORITY(x) ((x)<<16)
#define DMA_INTERRUPT_STATUS (1<< 2) #define DMA_INTERRUPT_STATUS (1<< 2)
#define DMA_END_FLAG (1<< 1) #define DMA_END_FLAG (1<< 1)
#define DMA_ACTIVATE (1<< 0) #define DMA_ACTIVATE (1<< 0)
/* DMA control block "info" field bits */ /* DMA control block "info" field bits */
#define DMA_NO_WIDE_BURSTS (1<<26) #define DMA_NO_WIDE_BURSTS (1<<26)
#define DMA_PERIPHERAL_MAPPING(x) ((x)<<16) #define DMA_PERIPHERAL_MAPPING(x) ((x)<<16)
#define DMA_BURST_LENGTH(x) ((x)<<12) #define DMA_BURST_LENGTH(x) ((x)<<12)
#define DMA_SRC_IGNORE (1<<11) #define DMA_SRC_IGNORE (1<<11)
#define DMA_SRC_DREQ (1<<10) #define DMA_SRC_DREQ (1<<10)
#define DMA_SRC_INC (1<< 8) #define DMA_SRC_INC (1<< 8)
@ -981,7 +1006,8 @@ static void myDoCommand(cmdCmd_t * cmd)
if (gpioMask & (uint64_t)(1<<p1)) res = gpioSetPullUpDown(p1, p2); if (gpioMask & (uint64_t)(1<<p1)) res = gpioSetPullUpDown(p1, p2);
else else
{ {
PERM_ERROR("gpioSetPullUpDown: gpio %d, no permission to update", p1); PERM_ERROR(
"gpioSetPullUpDown: gpio %d, no permission to update", p1);
res = PI_NOT_PERMITTED; res = PI_NOT_PERMITTED;
} }
break; break;
@ -1012,7 +1038,8 @@ static void myDoCommand(cmdCmd_t * cmd)
if (gpioMask & (uint64_t)(1<<p1)) res = gpioSetPWMrange(p1, p2); if (gpioMask & (uint64_t)(1<<p1)) res = gpioSetPWMrange(p1, p2);
else else
{ {
PERM_ERROR("gpioSetPWMrange: gpio %d, no permission to update", p1); PERM_ERROR(
"gpioSetPWMrange: gpio %d, no permission to update", p1);
res = PI_NOT_PERMITTED; res = PI_NOT_PERMITTED;
} }
break; break;
@ -1021,7 +1048,8 @@ static void myDoCommand(cmdCmd_t * cmd)
if (gpioMask & (uint64_t)(1<<p1)) res = gpioSetPWMfrequency(p1, p2); if (gpioMask & (uint64_t)(1<<p1)) res = gpioSetPWMfrequency(p1, p2);
else else
{ {
PERM_ERROR("gpioSetPWMfrequency: gpio %d, no permission to update", p1); PERM_ERROR(
"gpioSetPWMfrequency: gpio %d, no permission to update", p1);
res = PI_NOT_PERMITTED; res = PI_NOT_PERMITTED;
} }
break; break;
@ -1054,7 +1082,8 @@ static void myDoCommand(cmdCmd_t * cmd)
if ((mask | p1) != mask) if ((mask | p1) != mask)
{ {
PERM_ERROR("gpioWrite_Bits_0_31_Clear: bad levels %08X (permissions %08X)", PERM_ERROR(
"gpioWrite_Bits_0_31_Clear: bad levels %08X (permissions %08X)",
p1, mask); p1, mask);
res = PI_SOME_PERMITTED; res = PI_SOME_PERMITTED;
} }
@ -1067,7 +1096,8 @@ static void myDoCommand(cmdCmd_t * cmd)
if ((mask | p1) != mask) if ((mask | p1) != mask)
{ {
PERM_ERROR("gpioWrite_Bits_32_53_Clear: bad levels %08X (permissions %08X)", PERM_ERROR(
"gpioWrite_Bits_32_53_Clear: bad levels %08X (permissions %08X)",
p1, mask); p1, mask);
res = PI_SOME_PERMITTED; res = PI_SOME_PERMITTED;
} }
@ -1080,7 +1110,8 @@ static void myDoCommand(cmdCmd_t * cmd)
if ((mask | p1) != mask) if ((mask | p1) != mask)
{ {
PERM_ERROR("gpioWrite_Bits_0_31_Set: bad levels %08X (permissions %08X)", PERM_ERROR(
"gpioWrite_Bits_0_31_Set: bad levels %08X (permissions %08X)",
p1, mask); p1, mask);
res = PI_SOME_PERMITTED; res = PI_SOME_PERMITTED;
} }
@ -1093,7 +1124,8 @@ static void myDoCommand(cmdCmd_t * cmd)
if ((mask | p1) != mask) if ((mask | p1) != mask)
{ {
PERM_ERROR("gpioWrite_Bits_32_53_Set: bad levels %08X (permissions %08X)", PERM_ERROR(
"gpioWrite_Bits_32_53_Set: bad levels %08X (permissions %08X)",
p1, mask); p1, mask);
res = PI_SOME_PERMITTED; res = PI_SOME_PERMITTED;
} }
@ -1138,6 +1170,10 @@ static void myDoCommand(cmdCmd_t * cmd)
case PI_CMD_HELP: case PI_CMD_HELP:
break; break;
case PI_CMD_PIGPV:
res = gpioVersion();
break;
} }
cmd->res = res; cmd->res = res;
@ -4731,6 +4767,56 @@ int gpioSetTimerFuncEx(unsigned id, unsigned ms, gpioTimerFuncEx_t f,
return 0; return 0;
} }
/* ----------------------------------------------------------------------- */
pthread_t *gpioStartThread(ThreadFunc_t func, void *arg)
{
pthread_t *pth;
pthread_attr_t pthAttr;
DBG(DBG_USER, "func=%08X, arg=%08X", (uint32_t)func, (uint32_t)arg);
CHECK_INITED_RET_NULL_PTR;
pth = malloc(sizeof(pthread_t));
if (pth)
{
if (pthread_attr_init(&pthAttr))
{
free(pth);
SOFT_ERROR(NULL, "pthread_attr_init failed");
}
if (pthread_attr_setstacksize(&pthAttr, STACK_SIZE))
{
free(pth);
SOFT_ERROR(NULL, "pthread_attr_setstacksize failed");
}
if (pthread_create(pth, &pthAttr, func, arg))
{
free(pth);
SOFT_ERROR(NULL, "pthread_create failed");
}
}
return pth;
}
/* ----------------------------------------------------------------------- */
void gpioStopThread(pthread_t *pth)
{
DBG(DBG_USER, "pth=%08X", (uint32_t)pth);
CHECK_INITED_RET_NIL;
if (pth)
{
pthread_cancel(*pth);
pthread_join(*pth, NULL);
}
}
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
@ -4959,6 +5045,16 @@ uint32_t gpioTick(void)
} }
/* ----------------------------------------------------------------------- */
unsigned gpioVersion(void)
{
DBG(DBG_USER, "");
return PIGPIO_VERSION;
}
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
unsigned gpioHardwareRevision(void) unsigned gpioHardwareRevision(void)

119
pigpio.h
View File

@ -26,7 +26,7 @@ For more information, please refer to <http://unlicense.org/>
*/ */
/* /*
This version is for pigpio version 9 This version is for pigpio version 10
*/ */
#ifndef PIGPIO_H #ifndef PIGPIO_H
@ -51,6 +51,7 @@ This version is for pigpio version 9
/ output gpio level changes. / / output gpio level changes. /
/ 9) rudimentary permission control through the socket and pipe interfaces / / 9) rudimentary permission control through the socket and pipe interfaces /
/ so users can be prevented from "updating" inappropriate gpios. / / so users can be prevented from "updating" inappropriate gpios. /
/ 10) a simple interface to start and stop new threads. /
/ / / /
/ NOTE: / / NOTE: /
/ / / /
@ -83,8 +84,9 @@ This version is for pigpio version 9
****************************************************************************/ ****************************************************************************/
#include <stdint.h> #include <stdint.h>
#include <pthread.h>
#define PIGPIO_VERSION 9 #define PIGPIO_VERSION 10
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
@ -154,6 +156,9 @@ gpioSetGetSamplesFuncEx Requests a gpio samples callback, extended.
gpioSetTimerFunc Request a regular timed callback. gpioSetTimerFunc Request a regular timed callback.
gpioSetTimerFuncEx Request a regular timed callback, extended. gpioSetTimerFuncEx Request a regular timed callback, extended.
gpioStartThread Start a new thread.
gpioStopThread Stop a previously started thread.
gpioSetSignalFunc Request a signal callback. gpioSetSignalFunc Request a signal callback.
gpioSetSignalFuncEx Request a signal callback, extended. gpioSetSignalFuncEx Request a signal callback, extended.
@ -175,6 +180,8 @@ gpioTick Get current tick (microseconds).
gpioHardwareRevision Get hardware version. gpioHardwareRevision Get hardware version.
gpioVersion Get the pigpio version.
gpioCfgBufferSize Configure the gpio sample buffer size. gpioCfgBufferSize Configure the gpio sample buffer size.
gpioCfgClock Configure the gpio sample rate. gpioCfgClock Configure the gpio sample rate.
gpioCfgDMAchannel Configure the DMA channel (DEPRECATED). gpioCfgDMAchannel Configure the DMA channel (DEPRECATED).
@ -264,11 +271,15 @@ typedef void (*gpioGetSamplesFuncEx_t) (const gpioSample_t * samples,
int numSamples, int numSamples,
void * userdata); void * userdata);
typedef void *(ThreadFunc_t) (void *);
/* /*
All the functions which return an int return < 0 on error. All the functions which return an int return < 0 on error.
If the library isn't initialised all but the gpioCfg* functions If the library isn't initialised all but the gpioCfg*, gpioVersion,
will return error PI_NOT_INITIALISED. and gpioHardwareRevision functions will return error PI_NOT_INITIALISED.
If the library is initialised the gpioCfg* functions will If the library is initialised the gpioCfg* functions will
return error PI_INITIALISED. return error PI_INITIALISED.
@ -381,9 +392,9 @@ int gpioSetPullUpDown(unsigned gpio,
/* pud: 0-2 */ /* pud: 0-2 */
#define PI_PUD_OFF 0 #define PI_PUD_OFF 0
#define PI_PUD_DOWN 1 #define PI_PUD_DOWN 1
#define PI_PUD_UP 2 #define PI_PUD_UP 2
@ -406,14 +417,14 @@ int gpioRead (unsigned gpio);
/* level: 0-1 */ /* level: 0-1 */
#define PI_OFF 0 #define PI_OFF 0
#define PI_ON 1 #define PI_ON 1
#define PI_CLEAR 0 #define PI_CLEAR 0
#define PI_SET 1 #define PI_SET 1
#define PI_LOW 0 #define PI_LOW 0
#define PI_HIGH 1 #define PI_HIGH 1
/* level: only reported for gpio timeout, see gpioSetWatchdogTimeout */ /* level: only reported for gpio timeout, see gpioSetWatchdogTimeout */
@ -1255,6 +1266,68 @@ int gpioSetTimerFuncEx(unsigned timer,
/* ----------------------------------------------------------------------- */
pthread_t *gpioStartThread(ThreadFunc_t func, void *arg);
/*-------------------------------------------------------------------------*/
/* Starts a new thread of execution with func as the main routine.
Returns a pointer to pthread_t if OK, otherwise NULL.
The function is passed the single argument arg.
The thread can be cancelled by passing the pointer to pthread_t to
gpioStopThread().
EXAMPLE:
#include <stdio.h>
#include <pigpio.h>
void *myfunc(void *arg)
{
while (1)
{
printf("%s\n", arg);
sleep(1);
}
}
int main(int argc, char *argv[])
{
pthread_t *p1, *p2, *p3;
if (gpioInitialise() < 0) return 1;
p1 = gpioStartThread(myfunc, "thread 1"); sleep(3);
p2 = gpioStartThread(myfunc, "thread 2"); sleep(3);
p3 = gpioStartThread(myfunc, "thread 3"); sleep(3);
gpioStopThread(p3); sleep(3);
gpioStopThread(p2); sleep(3);
gpioStopThread(p1); sleep(3);
gpioTerminate();
}
*/
/* ----------------------------------------------------------------------- */
void gpioStopThread(pthread_t *pth);
/*-------------------------------------------------------------------------*/
/* Cancels the thread pointed at by pth.
No value is returned.
The thread to be stopped should have been started with gpioStartThread().
*/
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
int gpioSetSignalFunc(unsigned signum, int gpioSetSignalFunc(unsigned signum,
gpioSignalFunc_t f); gpioSignalFunc_t f);
@ -1518,9 +1591,17 @@ unsigned gpioHardwareRevision(void);
EXAMPLES: EXAMPLES:
for "Revision : 0002" the function returns 2. for "Revision : 0002" the function returns 2.
for "Revision : 000f" the function returns 15. for "Revision : 000f" the function returns 15.
for "Revision : 000g" the function returns 0. for "Revision : 000g" the function returns 0.
*/
/*-------------------------------------------------------------------------*/
unsigned gpioVersion(void);
/*-------------------------------------------------------------------------*/
/* Returns the pigpio version.
*/ */
@ -1734,6 +1815,7 @@ void gpioWaveDump(void);
#define PI_CMD_PFG 23 #define PI_CMD_PFG 23
#define PI_CMD_PRRG 24 #define PI_CMD_PRRG 24
#define PI_CMD_HELP 25 #define PI_CMD_HELP 25
#define PI_CMD_PIGPV 26
/* /*
The following command only works on the socket interface. The following command only works on the socket interface.
@ -1792,8 +1874,8 @@ after this command is issued.
#define PI_TOO_MANY_PULSES -36 /* waveform has too many pulses */ #define PI_TOO_MANY_PULSES -36 /* waveform has too many pulses */
#define PI_TOO_MANY_CHARS -37 /* waveform has too many chars */ #define PI_TOO_MANY_CHARS -37 /* waveform has too many chars */
#define PI_NOT_SERIAL_GPIO -38 /* no serial read in progress on gpio */ #define PI_NOT_SERIAL_GPIO -38 /* no serial read in progress on gpio */
#define PI_BAD_SERIAL_STRUC -39 /* bad null serial structure parameter */ #define PI_BAD_SERIAL_STRUC -39 /* bad (null) serial structure parameter */
#define PI_BAD_SERIAL_BUF -40 /* bad null serial buf parameter */ #define PI_BAD_SERIAL_BUF -40 /* bad (null) serial buf parameter */
#define PI_NOT_PERMITTED -41 /* gpio operation not permitted */ #define PI_NOT_PERMITTED -41 /* gpio operation not permitted */
#define PI_SOME_PERMITTED -42 /* one or more gpios not permitted */ #define PI_SOME_PERMITTED -42 /* one or more gpios not permitted */
@ -1816,3 +1898,4 @@ after this command is issued.
#define PI_DEFAULT_UPDATE_MASK_R2 0xFBC6CF9C #define PI_DEFAULT_UPDATE_MASK_R2 0xFBC6CF9C
#endif #endif

View File

@ -76,7 +76,7 @@ import threading
import os import os
import atexit import atexit
VERSION = "1.0" VERSION = "1.1"
# gpio levels # gpio levels
@ -92,9 +92,9 @@ TIMEOUT = 2
# gpio edges # gpio edges
EITHER_EDGE = 0 RISING_EDGE = 0
RISING_EDGE = 1 FALLING_EDGE = 1
FALLING_EDGE = 2 EITHER_EDGE = 2
# gpio modes # gpio modes
@ -338,12 +338,14 @@ class _callback_thread(threading.Thread):
def __init__(self): def __init__(self):
"""Initialises notifications.""" """Initialises notifications."""
threading.Thread.__init__(self) threading.Thread.__init__(self)
self.go = False
self.daemon = True self.daemon = True
self.monitor = 0 self.monitor = 0
self.callbacks = [] self.callbacks = []
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.connect((_host,_port)) self.sock.connect((_host,_port))
self.handle = _pigpio_command(self.sock, _PI_CMD_NOIB, 0, 0) self.handle = _pigpio_command(self.sock, _PI_CMD_NOIB, 0, 0)
self.go = True
self.start() self.start()
def stop(self): def stop(self):
@ -376,13 +378,23 @@ class _callback_thread(threading.Thread):
notify_begin(self.handle, self.monitor) notify_begin(self.handle, self.monitor)
def run(self): def run(self):
"""Execute the notification thread.""" """Execute the notification thread."""
self.go = True
lastLevel = 0 lastLevel = 0
MSG_SIZ = 12
while self.go: while self.go:
seq_no, flags, tick, level = (
struct.unpack('HHII', self.sock.recv(12, socket.MSG_WAITALL))) buf = self.sock.recv(MSG_SIZ)
while self.go and len(buf) < MSG_SIZ:
buf += self.sock.recv(MSG_SIZ-len(buf))
if self.go: if self.go:
seq, flags, tick, level = (struct.unpack('HHII', buf))
if flags == 0: if flags == 0:
changed = level ^ lastLevel changed = level ^ lastLevel
lastLevel = level lastLevel = level
@ -391,9 +403,7 @@ class _callback_thread(threading.Thread):
newLevel = 0 newLevel = 0
if cb.bit & level: if cb.bit & level:
newLevel = 1 newLevel = 1
if (cb.edge == EITHER_EDGE or if (cb.edge ^ newLevel):
cb.edge == RISING_EDGE and newLevel == 1 or
cb.edge == FALLING_EDGE and newLevel == 0):
cb.func(cb.gpio, newLevel, tick) cb.func(cb.gpio, newLevel, tick)
else: else:
gpio = flags & 31 gpio = flags & 31
@ -404,6 +414,7 @@ class _callback_thread(threading.Thread):
self.sock.close() self.sock.close()
class _wait_for_edge: class _wait_for_edge:
"""A class to encapsulate waiting for gpio edges.""" """A class to encapsulate waiting for gpio edges."""
def __init__(self, gpio, edge, timeout): def __init__(self, gpio, edge, timeout):
@ -1553,20 +1564,18 @@ def start(host = os.getenv("PIGPIO_ADDR", ''),
else: else:
h = _host h = _host
errStr = "Can't connect to pigpio on " + str(h) + "(" + str(_port) + ")" errStr = "Can't connect to pigpio on " + str(h) + "(" + str(_port) + ")"
print("********************************************************") print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%")
print(errStr) print(errStr)
print("") print("")
print("Did you start the pigpio daemon?") print("Did you start the pigpio daemon? E.g. sudo pigpiod")
print("(sudo pigpiod)")
print("") print("")
print("Did you specify the correct Pi host/port in the environment") print("Did you specify the correct Pi host/port in the environment")
print("variables PIGPIO_ADDR/PIGPIO_PORT?") print("variables PIGPIO_ADDR/PIGPIO_PORT?")
print("(e.g. export PIGPIO_ADDR=soft, export PIGPIO_PORT=8888)") print("E.g. export PIGPIO_ADDR=soft, export PIGPIO_PORT=8888")
print("") print("")
print("Did you specify the correct Pi host/port in the") print("Did you specify the correct Pi host/port in the")
print("pigpio.start() function") print("pigpio.start() function? E.g. pigpio.start('soft', 8888))")
print("(e.g. pigpio.start('soft', 8888))") print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%")
print("********************************************************")
raise raise
def stop(): def stop():

688
pigpiod_if.c Normal file
View File

@ -0,0 +1,688 @@
/*
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>
*/
/* PIGPIOD_IF_VERSION 1 */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include <netdb.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <arpa/inet.h>
#include "pigpio.h"
#include "command.h"
#include "pigpiod_if.h"
#define PISCOPE_MAX_REPORTS_PER_READ 4096
#define STACK_SIZE (256*1024)
typedef void (*CBF_t) ();
struct callback_s
{
int id;
int gpio;
int edge;
CBF_t f;
void * user;
int ex;
callback_t *prev;
callback_t *next;
};
/* GLOBALS ---------------------------------------------------------------- */
static gpioReport_t gReport[PISCOPE_MAX_REPORTS_PER_READ];
static int gPigCommand = -1;
static int gPigHandle = -1;
static int gPigNotify = -1;
static uint32_t gNotifyBits;
callback_t *gCallBackFirst = 0;
callback_t *gCallBackLast = 0;
static int gPigStarted = 0;
static pthread_t *pthNotify;
/* PRIVATE ---------------------------------------------------------------- */
static int pigpio_command(int fd, int command, int p1, int p2)
{
cmdCmd_t cmd;
cmd.cmd = command;
cmd.p1 = p1;
cmd.p2 = p2;
cmd.res = 0;
if (send(fd, &cmd, sizeof(cmdCmd_t), 0) != sizeof(cmdCmd_t))
return pigif_bad_send;
if (recv(fd, &cmd, sizeof(cmdCmd_t), MSG_WAITALL) != sizeof(cmdCmd_t))
return pigif_bad_recv;
return cmd.res;
}
static int pigpioOpenSocket(char *addr, char *port)
{
int sock, err;
struct addrinfo hints, *res, *rp;
const char *addrStr, *portStr;
if (!addr)
{
addrStr = getenv(PI_ENVADDR);
if ((!addrStr) || (!strlen(addrStr)))
{
addrStr = PI_DEFAULT_SOCKET_ADDR_STR;
}
}
else addrStr = addr;
if (!port)
{
portStr = getenv(PI_ENVPORT);
if ((!portStr) || (!strlen(portStr)))
{
portStr = PI_DEFAULT_SOCKET_PORT_STR;
}
}
else portStr = port;
memset (&hints, 0, sizeof (hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags |= AI_CANONNAME;
err = getaddrinfo (addrStr, portStr, &hints, &res);
if (err) return pigif_bad_getaddrinfo;
for (rp=res; rp!=NULL; rp=rp->ai_next)
{
sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (sock == -1) continue;
if (connect(sock, rp->ai_addr, rp->ai_addrlen) != -1) break;
}
freeaddrinfo(res);
if (rp == NULL) return pigif_bad_connect;
return sock;
}
static void dispatch_notification(gpioReport_t *r)
{
static uint32_t lastLevel = 0;
callback_t *p;
uint32_t changed;
int l, g;
/*
printf("s=%d f=%d l=%8X, t=%10u\n",
r->seqno, r->flags, r->level, r->tick);
*/
if (r->flags == 0)
{
changed = (r->level ^ lastLevel) & gNotifyBits;
lastLevel = r->level;
p = gCallBackFirst;
while (p)
{
if (changed & (1<<(p->gpio)))
{
if ((r->level) & (1<<(p->gpio))) l = 1; else l = 0;
if ((p->edge) ^ l)
{
if (p->ex) (p->f)(p->gpio, l, r->tick, p->user);
else (p->f)(p->gpio, l, r->tick);
}
}
p = p->next;
}
}
else
{
g = (r->flags) & 31;
p = gCallBackFirst;
while (p)
{
if ((p->gpio) == g)
{
if (p->ex) (p->f)(g, PI_TIMEOUT, r->tick, p->user);
else (p->f)(g, PI_TIMEOUT, r->tick);
}
p = p->next;
}
}
}
static void *pthNotifyThread(void *x)
{
static int got = 0;
int bytes, r;
while (1)
{
bytes = read(gPigNotify, (char*)&gReport+got, sizeof(gReport)-got);
if (bytes > 0) got += bytes;
else break;
r = 0;
while (got >= sizeof(gpioReport_t))
{
dispatch_notification(&gReport[r]);
r++;
got -= sizeof(gpioReport_t);
}
/* copy any partial report to start of array */
if (got && r) gReport[0] = gReport[r];
}
return 0;
}
static void findNotifyBits(void)
{
callback_t *p;
uint32_t bits = 0;
p = gCallBackFirst;
while (p)
{
bits |= (1<<(p->gpio));
p = p->next;
}
if (bits != gNotifyBits)
{
gNotifyBits = bits;
pigpio_command(gPigCommand, PI_CMD_NB, gPigHandle, gNotifyBits);
}
}
static void _wfe(int gpio, int level, uint32_t tick, void *user)
{
*(int *)user = 1;
}
static int intCallback(int gpio, int edge, void *f, void *user, int ex)
{
static int id = 0;
callback_t *p;
if ((gpio >=0) && (gpio < 32) && (edge >=0) && (edge <= 2) && f)
{
/* prevent duplicates */
p = gCallBackFirst;
while (p)
{
if ((p->gpio == gpio) && (p->edge == edge) && (p->f == f))
{
return pigif_duplicate_callback;
}
p = p->next;
}
p = malloc(sizeof(callback_t));
if (p)
{
if (!gCallBackFirst) gCallBackFirst = p;
p->id = id++;
p->gpio = gpio;
p->edge = edge;
p->f = f;
p->user = user;
p->ex = ex;
p->next = 0;
p->prev = gCallBackLast;
if (p->prev) (p->prev)->next = p;
gCallBackLast = p;
findNotifyBits();
return p->id;
}
return pigif_bad_malloc;
}
return pigif_bad_callback;
}
/* PUBLIC ----------------------------------------------------------------- */
double time_time(void)
{
struct timeval tv;
double t;
gettimeofday(&tv, 0);
t = (double)tv.tv_sec + ((double)tv.tv_usec / 1E6);
return t;
}
void time_sleep(double seconds)
{
struct timespec ts, rem;
if (seconds > 0.0)
{
ts.tv_sec = seconds;
ts.tv_nsec = (seconds-(double)ts.tv_sec) * 1E9;
while (clock_nanosleep(CLOCK_REALTIME, 0, &ts, &rem))
{
/* copy remaining time to ts */
ts.tv_sec = rem.tv_sec;
ts.tv_nsec = rem.tv_nsec;
}
}
}
const char *pigpio_error(int error)
{
if (error > -1000) return cmdErrStr(error);
else
{
switch(error)
{
case pigif_bad_send:
return "failed to send to pigpiod";
case pigif_bad_recv:
return "failed to receive from pigpiod";
case pigif_bad_getaddrinfo:
return "failed to find address of pigpiod";
case pigif_bad_connect:
return "failed to connect to pigpiod";
case pigif_bad_socket:
return "failed to create socket";
case pigif_bad_noib:
return "failed to open noib";
case pigif_duplicate_callback:
return "identical callback exists";
case pigif_bad_malloc:
return "failed to malloc";
case pigif_bad_callback:
return "bad callback parameter";
case pigif_notify_failed:
return "failed to create notification thread";
case pigif_callback_not_found:
return "callback not found";
default:
return "unknown error";
}
}
}
unsigned pigpiod_if_version(void)
{
return PIGPIOD_IF_VERSION;
}
pthread_t *start_thread(ThreadFunc_t func, void *arg)
{
pthread_t *pth;
pthread_attr_t pthAttr;
pth = malloc(sizeof(pthread_t));
if (pth)
{
if (pthread_attr_init(&pthAttr))
{
perror("pthread_attr_init failed");
free(pth);
return NULL;
}
if (pthread_attr_setstacksize(&pthAttr, STACK_SIZE))
{
perror("pthread_attr_setstacksize failed");
free(pth);
return NULL;
}
if (pthread_create(pth, &pthAttr, func, arg))
{
perror("pthread_create socket failed");
free(pth);
return NULL;
}
}
return pth;
}
void stop_thread(pthread_t *pth)
{
if (pth)
{
pthread_cancel(*pth);
pthread_join(*pth, NULL);
}
}
int pigpio_start(char *addrStr, char *portStr)
{
if (!gPigStarted)
{
gPigCommand = pigpioOpenSocket(addrStr, portStr);
if (gPigCommand >= 0)
{
gPigNotify = pigpioOpenSocket(addrStr, portStr);
if (gPigNotify >= 0)
{
gPigHandle = pigpio_command(gPigNotify, PI_CMD_NOIB, 0, 0);
if (gPigHandle < 0) return pigif_bad_noib;
else
{
pthNotify = start_thread(pthNotifyThread, 0);
if (pthNotify)
{
gPigStarted = 1;
return 0;
}
else return pigif_notify_failed;
}
}
else return gPigNotify;
}
else return gPigCommand;
}
return 0;
}
void pigpio_stop(void)
{
gPigStarted = 0;
if (pthNotify)
{
stop_thread(pthNotify);
pthNotify = 0;
}
if (gPigNotify >= 0)
{
if (gPigHandle >= 0)
{
pigpio_command(gPigNotify, PI_CMD_NC, gPigHandle, 0);
gPigHandle = -1;
}
close(gPigNotify);
gPigNotify = -1;
}
if (gPigCommand >= 0)
{
if (gPigHandle >= 0)
{
pigpio_command(gPigCommand, PI_CMD_NC, gPigHandle, 0);
gPigHandle = -1;
}
close(gPigCommand);
gPigCommand = -1;
}
}
int set_mode(int gpio, int mode)
{
return pigpio_command(gPigCommand, PI_CMD_MODES, gpio, mode);
}
int get_mode(int gpio)
{
return pigpio_command(gPigCommand, PI_CMD_MODEG, gpio, 0);
}
int set_pull_up_down(int gpio, int pud)
{
return pigpio_command(gPigCommand, PI_CMD_PUD, gpio, pud);
}
int read_gpio(int gpio)
{
return pigpio_command(gPigCommand, PI_CMD_READ, gpio, 0);
}
int write_gpio(int gpio, int level)
{
return pigpio_command(gPigCommand, PI_CMD_WRITE, gpio, level);
}
int set_PWM_dutycycle(int user_gpio, int dutycycle)
{
return pigpio_command(gPigCommand, PI_CMD_PWM, user_gpio, dutycycle);
}
int set_PWM_range(int user_gpio, int range_)
{
return pigpio_command(gPigCommand, PI_CMD_PRS, user_gpio, range_);
}
int get_PWM_range(int user_gpio)
{
return pigpio_command(gPigCommand, PI_CMD_PRG, user_gpio, 0);
}
int get_PWM_real_range(int user_gpio)
{
return pigpio_command(gPigCommand, PI_CMD_PRRG, user_gpio, 0);
}
int set_PWM_frequency(int user_gpio, int frequency)
{
return pigpio_command(gPigCommand, PI_CMD_PFS, user_gpio, frequency);
}
int get_PWM_frequency(int user_gpio)
{
return pigpio_command(gPigCommand, PI_CMD_PFG, user_gpio, 0);
}
int set_servo_pulsewidth(int user_gpio, int pulsewidth)
{
return pigpio_command(gPigCommand, PI_CMD_SERVO, user_gpio, pulsewidth);
}
int notify_open(void)
{
return pigpio_command(gPigCommand, PI_CMD_NO, 0, 0);
}
int notify_begin(int handle, uint32_t bits)
{
return pigpio_command(gPigCommand, PI_CMD_NB, handle, bits);
}
int notify_pause(int handle)
{
return pigpio_command(gPigCommand, PI_CMD_NB, handle, 0);
}
int notify_close(int handle)
{
return pigpio_command(gPigCommand, PI_CMD_NC, handle, 0);
}
int set_watchdog(int user_gpio, int timeout)
{
return pigpio_command(gPigCommand, PI_CMD_WDOG, user_gpio, timeout);
}
uint32_t read_bank_1(void)
{
return pigpio_command(gPigCommand, PI_CMD_BR1, 0, 0);
}
uint32_t read_bank_2(void)
{
return pigpio_command(gPigCommand, PI_CMD_BR2, 0, 0);
}
int clear_bank_1(uint32_t levels)
{
return pigpio_command(gPigCommand, PI_CMD_BC1, levels, 0);
}
int clear_bank_2(uint32_t levels)
{
return pigpio_command(gPigCommand, PI_CMD_BC2, levels, 0);
}
int set_bank_1(uint32_t levels)
{
return pigpio_command(gPigCommand, PI_CMD_BS1, levels, 0);
}
int set_bank_2(uint32_t levels)
{
return pigpio_command(gPigCommand, PI_CMD_BS2, levels, 0);
}
uint32_t get_current_tick(void)
{
return pigpio_command(gPigCommand, PI_CMD_TICK, 0, 0);
}
uint32_t get_hardware_revision(void)
{
return pigpio_command(gPigCommand, PI_CMD_HWVER, 0, 0);
}
unsigned get_pigpio_version(void)
{
return pigpio_command(gPigCommand, PI_CMD_PIGPV, 0, 0);
}
int callback(int gpio, int edge, CBFunc_t f)
{
return intCallback(gpio, edge, f, 0, 0);
}
int callback_ex(int gpio, int edge, CBFuncEx_t f, void *user)
{
return intCallback(gpio, edge, f, user, 1);
}
int callback_cancel(int id)
{
callback_t *p;
p = gCallBackFirst;
while (p)
{
if (p->id == id)
{
if (p->prev) p->prev->next = p->next;
else gCallBackFirst = p->next;
if (p->next) p->next->prev = p->prev;
else gCallBackLast = p->prev;
free(p);
findNotifyBits();
return 0;
}
p = p->next;
}
return pigif_callback_not_found;
}
int wait_for_edge(int gpio, int edge, double timeout)
{
int triggered = 0;
int id;
double due;
if (timeout <= 0.0) return 0;
due = time_time() + timeout;
id = callback_ex(gpio, edge, _wfe, &triggered);
while (!triggered && (time_time() < due)) time_sleep(0.1);
callback_cancel(id);
return triggered;
}

527
pigpiod_if.h Normal file
View File

@ -0,0 +1,527 @@
/*
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>
*/
#ifndef PIGPIOD_IF_H
#define PIGPIOD_IF_H
#include "pigpio.h"
#define PIGPIOD_IF_VERSION 1
typedef enum
{
pigif_bad_send = -2000,
pigif_bad_recv = -2001,
pigif_bad_getaddrinfo = -2002,
pigif_bad_connect = -2003,
pigif_bad_socket = -2004,
pigif_bad_noib = -2005,
pigif_duplicate_callback = -2006,
pigif_bad_malloc = -2007,
pigif_bad_callback = -2008,
pigif_notify_failed = -2009,
pigif_callback_not_found = -2010,
} piscopeError_t;
typedef void (*CBFunc_t) (int gpio, int level, uint32_t tick);
typedef void (*CBFuncEx_t)(int gpio, int level, uint32_t tick, void * user);
typedef struct callback_s callback_t;
#define RISING_EDGE 0
#define FALLING_EDGE 1
#define EITHER_EDGE 2
double time_time(void);
/* Return the current time in seconds since the Epoch.*/
void time_sleep(double seconds);
/* Delay execution for a given number of seconds */
const char *pigpio_error(int error);
/* Return a string for a pigpio library error. */
unsigned pigpiod_if_version(void);
/* Return the pigpiod_if version. */
pthread_t *start_thread(ThreadFunc_t func, void *arg);
/* Starts a new thread of execution with func as the main routine.
Returns a pointer to pthread_t if OK, otherwise NULL.
The function is passed the single argument arg.
The thread can be cancelled by passing the pointer to pthread_t to
gpioStopThread().
*/
void stop_thread(pthread_t *pth);
/* Cancels the thread pointed at by pth.
No value is returned.
The thread to be stopped should have been started with gpioStartThread().
*/
int pigpio_start(char *addrStr, char *portStr);
/* Connect to the pigpio daemon. Reserving command and
notification streams.
addrStr specifies the host or IP address of the Pi running
the pigpio daemon. It may be NULL in which case localhost
is used unless overriden by the PIGPIO_ADDR environment
variable.
portStr specifies the port address used by the Pi running
the pigpio daemon. It may be NULL in which case "8888"
is used unless overriden by the PIGPIO_PORT environment
variable.
*/
void pigpio_stop(void);
/*
Terminates the connection to the pigpio daemon and releases
resources used by the library.
*/
int set_mode(int gpio, int mode);
/* Set the gpio mode.
gpio: 0-53.
mode: INPUT, OUTPUT, ALT0, ALT1, ALT2, ALT3, ALT4, ALT5.
Returns 0 if OK, otherwise PI_BAD_GPIO, PI_BAD_MODE,
or PI_NOT_PERMITTED.
*/
int get_mode(int gpio);
/* Get the gpio mode.
Returns the gpio mode if OK, otherwise PI_BAD_GPIO.
gpio: 0-53.
*/
int set_pull_up_down(int gpio, int pud);
/* Set or clear the gpio pull-up/down resistor.
Returns 0 if OK, otherwise PI_BAD_GPIO, PI_BAD_PUD,
or PI_NOT_PERMITTED.
gpio: 0-53.
pud: PUD_UP, PUD_DOWN, PUD_OFF.
*/
int read_gpio(int gpio);
/* Read the gpio level.
Returns the gpio level if OK, otherwise PI_BAD_GPIO.
gpio:0-53.
*/
int write_gpio(int gpio, int level);
/*
Write the gpio level.
Returns 0 if OK, otherwise PI_BAD_GPIO, PI_BAD_LEVEL,
or PI_NOT_PERMITTED.
gpio: 0-53.
level: 0, 1.
Notes
If PWM or servo pulses are active on the gpio they are switched off.
*/
int set_PWM_dutycycle(int user_gpio, int dutycycle);
/* Start (non-zero dutycycle) or stop (0) PWM pulses on the gpio.
Returns 0 if OK, otherwise PI_BAD_USER_GPIO, PI_BAD_DUTYCYCLE,
or PI_NOT_PERMITTED.
user_gpio: 0-31.
dutycycle: 0-range (range defaults to 255).
Notes
The set_PWM_range() function can change the default range of 255.
*/
int set_PWM_range(int user_gpio, int range_);
/* Set the range of PWM values to be used on the gpio.
Returns 0 if OK, otherwise PI_BAD_USER_GPIO, PI_BAD_DUTYRANGE,
or PI_NOT_PERMITTED.
user_gpio: 0-31.
range_: 25-40000.
Notes
If PWM is currently active on the gpio its dutycycle will be
scaled to reflect the new range.
The real range, the number of steps between fully off and fully on
for each of the 18 available gpio frequencies is
25(#1), 50(#2), 100(#3), 125(#4), 200(#5), 250(#6), 400(#7),
500(#8), 625(#9), 800(#10), 1000(#11), 1250(#12), 2000(#13),
2500(#14), 4000(#15), 5000(#16), 10000(#17), 20000(#18)
The real value set by set_PWM_range is
(dutycycle * real range) / range.
*/
int get_PWM_range(int user_gpio);
/* Get the range of PWM values being used on the gpio.
Returns the dutycycle range used for the gpio if OK,
otherwise PI_BAD_USER_GPIO.
user_gpio: 0-31.
*/
int get_PWM_real_range(int user_gpio);
/* Get the real underlying range of PWM values being used on the gpio.
Returns the real range used for the gpio if OK,
otherwise PI_BAD_USER_GPIO.
user_gpio: 0-31.
*/
int set_PWM_frequency(int user_gpio, int frequency);
/*
Set the frequency (in Hz) of the PWM to be used on the gpio.
Returns the numerically closest frequency if OK, otherwise
PI_BAD_USER_GPIO or PI_NOT_PERMITTED.
user_gpio: 0-31.
frequency: 0- (Hz).
The selectable frequencies depend upon the sample rate which
may be 1, 2, 4, 5, 8, or 10 microseconds (default 5). The
sample rate is set when the C pigpio library is started.
Each gpio can be independently set to one of 18 different
PWM frequencies.
If PWM is currently active on the gpio it will be switched
off and then back on at the new frequency.
1us 40000, 20000, 10000, 8000, 5000, 4000, 2500, 2000, 1600,
1250, 1000, 800, 500, 400, 250, 200, 100, 50
2us 20000, 10000, 5000, 4000, 2500, 2000, 1250, 1000, 800,
625, 500, 400, 250, 200, 125, 100, 50, 25
4us 10000, 5000, 2500, 2000, 1250, 1000, 625, 500, 400,
313, 250, 200, 125, 100, 63, 50, 25, 13
5us 8000, 4000, 2000, 1600, 1000, 800, 500, 400, 320,
250, 200, 160, 100, 80, 50, 40, 20, 10
8us 5000, 2500, 1250, 1000, 625, 500, 313, 250, 200,
156, 125, 100, 63, 50, 31, 25, 13, 6
10us 4000, 2000, 1000, 800, 500, 400, 250, 200, 160,
125, 100, 80, 50, 40, 25, 20, 10, 5
*/
int get_PWM_frequency(int user_gpio);
/*
Get the frequency of PWM being used on the gpio.
Returns the frequency (in hertz) used for the gpio if OK,
otherwise PI_BAD_USER_GPIO.
user_gpio: 0-31.
*/
int set_servo_pulsewidth(int user_gpio, int pulsewidth);
/*
Start (500-2500) or stop (0) servo pulses on the gpio.
Returns 0 if OK, otherwise PI_BAD_USER_GPIO, PI_BAD_PULSEWIDTH or
PI_NOT_PERMITTED.
user_gpio: 0-31.
pulsewidth: 0 (off), 500 (most anti-clockwise) - 2500 (most clockwise).
The selected pulsewidth will continue to be transmitted until
changed by a subsequent call to set_servo_pulsewidth().
The pulsewidths supported by servos varies and should probably be
determined by experiment. A value of 1500 should always be safe and
represents the mid-point of rotation.
You can DAMAGE a servo if you command it to move beyond its limits.
OTHER UPDATE RATES:
This function updates servos at 50Hz. If you wish to use a different
update frequency you will have to use the PWM functions.
Update Rate (Hz) 50 100 200 400 500
1E6/Hz 20000 10000 5000 2500 2000
Firstly set the desired PWM frequency using set_PWM_frequency().
Then set the PWM range using set_PWM_range() to 1E6/Hz.
Doing this allows you to use units of microseconds when setting
the servo pulse width.
E.g. If you want to update a servo connected to gpio 25 at 400Hz
set_PWM_frequency(25, 400);
set_PWM_range(25, 2500);
Thereafter use the set_PWM_dutycycle() function to move the servo,
e.g. set_PWM_dutycycle(25, 1500) will set a 1500 us pulse.
*/
int notify_open(void);
/*
Get a free notification handle.
Returns a handle greater than or equal to zero if OK,
otherwise PI_NO_HANDLE.
A notification is a method for being notified of gpio state
changes via a pipe.
Pipes are only accessible from the local machine so this function
serves no purpose if you are using the library from a remote machine.
The in-built (socket) notifications provided by callback()
should be used instead.
Notifications for handle x will be available at the pipe
named /dev/pigpiox (where x is the handle number).
E.g. if the function returns 15 then the notifications must be
read from /dev/pigpio15.
*/
int notify_begin(int handle, uint32_t bits);
/*
Start notifications on a previously opened handle.
Returns 0 if OK, otherwise PI_BAD_HANDLE.
handle: 0-31 (as returned by notify_open())
bits: a mask indicating the gpios to be notified.
The notification sends state changes for each gpio whose
corresponding bit in bits is set.
Notes
Each notification occupies 12 bytes in the fifo as follows:
H (16 bit) seqno
H (16 bit) flags
I (32 bit) tick
I (32 bit) level
*/
int notify_pause(int handle);
/*
Pause notifications on a previously opened handle.
Returns 0 if OK, otherwise PI_BAD_HANDLE.
handle: 0-31 (as returned by notify_open())
Notifications for the handle are suspended until
notify_begin() is called again.
*/
int notify_close(int handle);
/*
Stop notifications on a previously opened handle and
release the handle for reuse.
Returns 0 if OK, otherwise PI_BAD_HANDLE.
handle: 0-31 (as returned by notify_open())
*/
int set_watchdog(int user_gpio, int timeout);
/*
Sets a watchdog for a gpio.
Returns 0 if OK, otherwise PI_BAD_USER_GPIO
or PI_BAD_WDOG_TIMEOUT.
user_gpio: 0-31.
timeout: 0-60000.
The watchdog is nominally in milliseconds.
Only one watchdog may be registered per gpio.
The watchdog may be cancelled by setting timeout to 0.
If no level change has been detected for the gpio for timeout
milliseconds any notification for the gpio has a report written
to the fifo with the flags set to indicate a watchdog timeout.
The callback() and callback_ex functions interpret the flags and will
call registered callbacks for the gpio with level TIMEOUT.
*/
uint32_t read_bank_1(void);
/*
Read the levels of the bank 1 gpios (gpios 0-31).
The returned 32 bit integer has a bit set if the corresponding
gpio is logic 1. Gpio n has bit value (1<<n).
*/
uint32_t read_bank_2(void);
/*
Read the levels of the bank 2 gpios (gpios 32-53).
The returned 32 bit integer has a bit set if the corresponding
gpio is logic 1. Gpio n has bit value (1<<(n-32)).
*/
int clear_bank_1(uint32_t levels);
/*
Clears gpios 0-31 if the corresponding bit in levels is set.
Returns 0 if OK, otherwise PI_SOME_PERMITTED.
A status of PI_SOME_PERMITTED indicates that the user is not
allowed to write to one or more of the gpios.
levels: a bit mask with 1 set if the corresponding gpio is
to be cleared.
*/
int clear_bank_2(uint32_t levels);
/*
Clears gpios 32-53 if the corresponding bit (0-21) in levels is set.
Returns 0 if OK, otherwise PI_SOME_PERMITTED.
A status of PI_SOME_PERMITTED indicates that the user is not
allowed to write to one or more of the gpios.
levels: a bit mask with 1 set if the corresponding gpio is
to be cleared.
*/
int set_bank_1(uint32_t levels);
/*
Sets gpios 0-31 if the corresponding bit in levels is set.
Returns 0 if OK, otherwise PI_SOME_PERMITTED.
A status of PI_SOME_PERMITTED indicates that the user is not
allowed to write to one or more of the gpios.
levels: a bit mask with 1 set if the corresponding gpio is
to be set.
*/
int set_bank_2(uint32_t levels);
/*
Sets gpios 32-53 if the corresponding bit (0-21) in levels is set.
Returns 0 if OK, otherwise PI_SOME_PERMITTED.
A status of PI_SOME_PERMITTED indicates that the user is not
allowed to write to one or more of the gpios.
levels: a bit mask with 1 set if the corresponding gpio is
to be set.
*/
uint32_t get_current_tick(void);
/*
Gets the current system tick.
Tick is the number of microseconds since system boot.
As tick is an unsigned 32 bit quantity it wraps around after
2**32 microseconds, which is approximately 1 hour 12 minutes.
*/
uint32_t get_hardware_revision(void);
/*
Get the Pi's hardware revision number.
It is unfortunate that Pi boards have been named Revision.1 and
Revision.2. That use of the word revision is distinct from the
Pi's hardware revision number.'
The hardware revision is the last 4 characters on the Revision line
of /proc/cpuinfo.
The revision number can be used to determine the assignment of gpios
to pins.
There are at least two types of board.
Type 1 has gpio 0 on P1-3, gpio 1 on P1-5, and gpio 21 on P1-13.
Type 2 has gpio 2 on P1-3, gpio 3 on P1-5, gpio 27 on P1-13, and
gpios 28-31 on P5.
Type 1 boards have hardware revision numbers of 2 and 3.
Type 2 boards have hardware revision numbers of 4, 5, 6, and 15.
If the hardware revision can not be found or is not a valid
hexadecimal number the function returns 0.
*/
int callback(int gpio, int edge, CBFunc_t f);
/*
*/
int callback_ex(int gpio, int edge, CBFuncEx_t f, void *user);
/*
*/
int callback_cancel(int id);
/*
*/
int wait_for_edge(int gpio, int edge, double timeout);
/*
*/
#endif

View File

@ -3,7 +3,7 @@
from distutils.core import setup from distutils.core import setup
setup(name='pigpio', setup(name='pigpio',
version='1.0', version='1.1',
author='joan', author='joan',
author_email='joan@abyz.me.uk', author_email='joan@abyz.me.uk',
maintainer='joan', maintainer='joan',