first re-commit.
This commit is contained in:
3
pigpio-master/EXAMPLES/C/COUNTER_1/README
Normal file
3
pigpio-master/EXAMPLES/C/COUNTER_1/README
Normal file
@@ -0,0 +1,3 @@
|
||||
A program showing how to use the gpioSetAlertFunc function to set a callback for gpio state changes.
|
||||
|
||||
A frequency count is generated for each monitored gpio (frequencies up to 500KHz and beyond).
|
238
pigpio-master/EXAMPLES/C/COUNTER_1/freq_count_1.c
Normal file
238
pigpio-master/EXAMPLES/C/COUNTER_1/freq_count_1.c
Normal file
@@ -0,0 +1,238 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <pigpio.h>
|
||||
|
||||
/*
|
||||
2014-08-20
|
||||
|
||||
gcc -o freq_count_1 freq_count_1.c -lpigpio -lpthread
|
||||
$ sudo ./freq_count_1 4 7 8
|
||||
|
||||
This program uses the gpioSetAlertFunc function to request
|
||||
a callback (the same one) for each gpio to be monitored.
|
||||
|
||||
EXAMPLES
|
||||
|
||||
Monitor gpio 4 (default settings)
|
||||
sudo ./freq_count_1 4
|
||||
|
||||
Monitor gpios 4 and 8 (default settings)
|
||||
sudo ./freq_count_1 4 8
|
||||
|
||||
Monitor gpios 4 and 8, sample rate 2 microseconds
|
||||
sudo ./freq_count_1 4 8 -s2
|
||||
|
||||
Monitor gpios 7 and 8, sample rate 4 microseconds, report every second
|
||||
sudo ./freq_count_1 7 8 -s4 -r10
|
||||
|
||||
Monitor gpios 4,7, 8, 9, 10, 23 24, report five times a second
|
||||
sudo ./freq_count_1 4 7 8 9 10 23 24 -r2
|
||||
|
||||
Monitor gpios 4, 7, 8, and 9, report once a second, sample rate 1us,
|
||||
generate 2us edges (4us square wave, 250000 highs per second).
|
||||
sudo ./freq_count_1 4 7 8 9 -r 10 -s 1 -p 2
|
||||
*/
|
||||
|
||||
#define MAX_GPIOS 32
|
||||
|
||||
#define OPT_P_MIN 1
|
||||
#define OPT_P_MAX 1000
|
||||
#define OPT_P_DEF 20
|
||||
|
||||
#define OPT_R_MIN 1
|
||||
#define OPT_R_MAX 10
|
||||
#define OPT_R_DEF 5
|
||||
|
||||
#define OPT_S_MIN 1
|
||||
#define OPT_S_MAX 10
|
||||
#define OPT_S_DEF 5
|
||||
|
||||
static volatile int g_pulse_count[MAX_GPIOS];
|
||||
static volatile int g_reset_counts;
|
||||
static uint32_t g_mask;
|
||||
|
||||
static int g_num_gpios;
|
||||
static int g_gpio[MAX_GPIOS];
|
||||
|
||||
static int g_opt_p = OPT_P_DEF;
|
||||
static int g_opt_r = OPT_R_DEF;
|
||||
static int g_opt_s = OPT_S_DEF;
|
||||
static int g_opt_t = 0;
|
||||
|
||||
void usage()
|
||||
{
|
||||
fprintf
|
||||
(stderr,
|
||||
"\n" \
|
||||
"Usage: sudo ./freq_count_1 gpio ... [OPTION] ...\n" \
|
||||
" -p value, sets pulses every p micros, %d-%d, TESTING only\n" \
|
||||
" -r value, sets refresh period in deciseconds, %d-%d, default %d\n" \
|
||||
" -s value, sets sampling rate in micros, %d-%d, default %d\n" \
|
||||
"\nEXAMPLE\n" \
|
||||
"sudo ./freq_count_1 4 7 -r2 -s2\n" \
|
||||
"Monitor gpios 4 and 7. Refresh every 0.2 seconds. Sample rate 2 micros.\n" \
|
||||
"\n",
|
||||
OPT_P_MIN, OPT_P_MAX,
|
||||
OPT_R_MIN, OPT_R_MAX, OPT_R_DEF,
|
||||
OPT_S_MIN, OPT_S_MAX, OPT_S_DEF
|
||||
);
|
||||
}
|
||||
|
||||
void fatal(int show_usage, char *fmt, ...)
|
||||
{
|
||||
char buf[128];
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
fprintf(stderr, "%s\n", buf);
|
||||
|
||||
if (show_usage) usage();
|
||||
|
||||
fflush(stderr);
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static int initOpts(int argc, char *argv[])
|
||||
{
|
||||
int i, opt;
|
||||
|
||||
while ((opt = getopt(argc, argv, "p:r:s:")) != -1)
|
||||
{
|
||||
i = -1;
|
||||
|
||||
switch (opt)
|
||||
{
|
||||
case 'p':
|
||||
i = atoi(optarg);
|
||||
if ((i >= OPT_P_MIN) && (i <= OPT_P_MAX))
|
||||
g_opt_p = i;
|
||||
else fatal(1, "invalid -p option (%d)", i);
|
||||
g_opt_t = 1;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
i = atoi(optarg);
|
||||
if ((i >= OPT_R_MIN) && (i <= OPT_R_MAX))
|
||||
g_opt_r = i;
|
||||
else fatal(1, "invalid -r option (%d)", i);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
i = atoi(optarg);
|
||||
if ((i >= OPT_S_MIN) && (i <= OPT_S_MAX))
|
||||
g_opt_s = i;
|
||||
else fatal(1, "invalid -s option (%d)", i);
|
||||
break;
|
||||
|
||||
default: /* '?' */
|
||||
usage();
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
return optind;
|
||||
}
|
||||
|
||||
void edges(int gpio, int level, uint32_t tick)
|
||||
{
|
||||
int g;
|
||||
|
||||
if (g_reset_counts)
|
||||
{
|
||||
g_reset_counts = 0;
|
||||
for (g=0; g<MAX_GPIOS; g++) g_pulse_count[g] = 0;
|
||||
}
|
||||
|
||||
/* only record low to high edges */
|
||||
if (level == 1) g_pulse_count[gpio]++;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int i, rest, g, wave_id, mode;
|
||||
gpioPulse_t pulse[2];
|
||||
int count[MAX_GPIOS];
|
||||
|
||||
/* command line parameters */
|
||||
|
||||
rest = initOpts(argc, argv);
|
||||
|
||||
/* get the gpios to monitor */
|
||||
|
||||
g_num_gpios = 0;
|
||||
|
||||
for (i=rest; i<argc; i++)
|
||||
{
|
||||
g = atoi(argv[i]);
|
||||
if ((g>=0) && (g<32))
|
||||
{
|
||||
g_gpio[g_num_gpios++] = g;
|
||||
g_mask |= (1<<g);
|
||||
}
|
||||
else fatal(1, "%d is not a valid g_gpio number\n", g);
|
||||
}
|
||||
|
||||
if (!g_num_gpios) fatal(1, "At least one gpio must be specified");
|
||||
|
||||
printf("Monitoring gpios");
|
||||
for (i=0; i<g_num_gpios; i++) printf(" %d", g_gpio[i]);
|
||||
printf("\nSample rate %d micros, refresh rate %d deciseconds\n",
|
||||
g_opt_s, g_opt_r);
|
||||
|
||||
gpioCfgClock(g_opt_s, 1, 1);
|
||||
|
||||
if (gpioInitialise()<0) return 1;
|
||||
|
||||
gpioWaveClear();
|
||||
|
||||
pulse[0].gpioOn = g_mask;
|
||||
pulse[0].gpioOff = 0;
|
||||
pulse[0].usDelay = g_opt_p;
|
||||
|
||||
pulse[1].gpioOn = 0;
|
||||
pulse[1].gpioOff = g_mask;
|
||||
pulse[1].usDelay = g_opt_p;
|
||||
|
||||
gpioWaveAddGeneric(2, pulse);
|
||||
|
||||
wave_id = gpioWaveCreate();
|
||||
|
||||
/* monitor g_gpio level changes */
|
||||
|
||||
for (i=0; i<g_num_gpios; i++) gpioSetAlertFunc(g_gpio[i], edges);
|
||||
|
||||
mode = PI_INPUT;
|
||||
|
||||
if (g_opt_t)
|
||||
{
|
||||
gpioWaveTxSend(wave_id, PI_WAVE_MODE_REPEAT);
|
||||
mode = PI_OUTPUT;
|
||||
}
|
||||
|
||||
for (i=0; i<g_num_gpios; i++) gpioSetMode(g_gpio[i], mode);
|
||||
|
||||
while (1)
|
||||
{
|
||||
for (i=0; i<g_num_gpios; i++) count[i] = g_pulse_count[g_gpio[i]];
|
||||
|
||||
g_reset_counts = 1;
|
||||
|
||||
for (i=0; i<g_num_gpios; i++)
|
||||
{
|
||||
printf(" %d=%d", g_gpio[i], count[i]);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
gpioDelay(g_opt_r * 100000);
|
||||
}
|
||||
|
||||
gpioTerminate();
|
||||
}
|
||||
|
6
pigpio-master/EXAMPLES/C/COUNTER_2/README
Normal file
6
pigpio-master/EXAMPLES/C/COUNTER_2/README
Normal file
@@ -0,0 +1,6 @@
|
||||
A program showing how to use the gpioSetGetSamplesFunc function to set a callback for accumulated gpio state changes over the last millisecond.
|
||||
|
||||
A frequency count is generated for each monitored gpio (frequencies up to 500KHz and beyond).
|
||||
|
||||
Generally the method used is more complicated but more efficient than frequency counter 1.
|
||||
|
257
pigpio-master/EXAMPLES/C/COUNTER_2/freq_count_2.c
Normal file
257
pigpio-master/EXAMPLES/C/COUNTER_2/freq_count_2.c
Normal file
@@ -0,0 +1,257 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <pigpio.h>
|
||||
|
||||
/*
|
||||
2014-08-20
|
||||
|
||||
gcc -o freq_count_2 freq_count_2.c -lpigpio -lpthread
|
||||
$ sudo ./freq_count_2 4 7 8
|
||||
|
||||
This program uses the gpioSetGetSamplesFunc function to request
|
||||
a callback once a millisecond for all accumulated gpio changes
|
||||
in that millisecond.
|
||||
|
||||
This tends to be more efficient then calling a callback for each
|
||||
gpio change during the millisecond.
|
||||
|
||||
EXAMPLES
|
||||
|
||||
Monitor gpio 4 (default settings)
|
||||
sudo ./freq_count_2 4
|
||||
|
||||
Monitor gpios 4 and 8 (default settings)
|
||||
sudo ./freq_count_2 4 8
|
||||
|
||||
Monitor gpios 4 and 8, sample rate 2 microseconds
|
||||
sudo ./freq_count_2 4 8 -s2
|
||||
|
||||
Monitor gpios 7 and 8, sample rate 4 microseconds, report every second
|
||||
sudo ./freq_count_2 7 8 -s4 -r10
|
||||
|
||||
Monitor gpios 4,7, 8, 9, 10, 23 24, report five times a second
|
||||
sudo ./freq_count_2 4 7 8 9 10 23 24 -r2
|
||||
|
||||
Monitor gpios 4, 7, 8, and 9, report once a second, sample rate 1us,
|
||||
generate 2us edges (4us square wave, 250000 highs per second).
|
||||
sudo ./freq_count_2 4 7 8 9 -r 10 -s 1 -p 2
|
||||
|
||||
*/
|
||||
|
||||
#define MAX_GPIOS 32
|
||||
|
||||
#define OPT_P_MIN 1
|
||||
#define OPT_P_MAX 1000
|
||||
#define OPT_P_DEF 20
|
||||
|
||||
#define OPT_R_MIN 1
|
||||
#define OPT_R_MAX 10
|
||||
#define OPT_R_DEF 5
|
||||
|
||||
#define OPT_S_MIN 1
|
||||
#define OPT_S_MAX 10
|
||||
#define OPT_S_DEF 5
|
||||
|
||||
static volatile int g_pulse_count[MAX_GPIOS];
|
||||
static volatile int g_reset_counts;
|
||||
static uint32_t g_mask;
|
||||
|
||||
static int g_num_gpios;
|
||||
static int g_gpio[MAX_GPIOS];
|
||||
|
||||
static int g_opt_p = OPT_P_DEF;
|
||||
static int g_opt_r = OPT_R_DEF;
|
||||
static int g_opt_s = OPT_S_DEF;
|
||||
static int g_opt_t = 0;
|
||||
|
||||
void usage()
|
||||
{
|
||||
fprintf
|
||||
(stderr,
|
||||
"\n" \
|
||||
"Usage: sudo ./freq_count_2 gpio ... [OPTION] ...\n" \
|
||||
" -p value, sets pulses every p micros, %d-%d, TESTING only\n" \
|
||||
" -r value, sets refresh period in deciseconds, %d-%d, default %d\n" \
|
||||
" -s value, sets sampling rate in micros, %d-%d, default %d\n" \
|
||||
"\nEXAMPLE\n" \
|
||||
"sudo ./freq_count_2 4 7 -r2 -s2\n" \
|
||||
"Monitor gpios 4 and 7. Refresh every 0.2 seconds. Sample rate 2 micros.\n" \
|
||||
"\n",
|
||||
OPT_P_MIN, OPT_P_MAX,
|
||||
OPT_R_MIN, OPT_R_MAX, OPT_R_DEF,
|
||||
OPT_S_MIN, OPT_S_MAX, OPT_S_DEF
|
||||
);
|
||||
}
|
||||
|
||||
void fatal(int show_usage, char *fmt, ...)
|
||||
{
|
||||
char buf[128];
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
fprintf(stderr, "%s\n", buf);
|
||||
|
||||
if (show_usage) usage();
|
||||
|
||||
fflush(stderr);
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static int initOpts(int argc, char *argv[])
|
||||
{
|
||||
int i, opt;
|
||||
|
||||
while ((opt = getopt(argc, argv, "p:r:s:")) != -1)
|
||||
{
|
||||
i = -1;
|
||||
|
||||
switch (opt)
|
||||
{
|
||||
case 'p':
|
||||
i = atoi(optarg);
|
||||
if ((i >= OPT_P_MIN) && (i <= OPT_P_MAX))
|
||||
g_opt_p = i;
|
||||
else fatal(1, "invalid -p option (%d)", i);
|
||||
g_opt_t = 1;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
i = atoi(optarg);
|
||||
if ((i >= OPT_R_MIN) && (i <= OPT_R_MAX))
|
||||
g_opt_r = i;
|
||||
else fatal(1, "invalid -r option (%d)", i);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
i = atoi(optarg);
|
||||
if ((i >= OPT_S_MIN) && (i <= OPT_S_MAX))
|
||||
g_opt_s = i;
|
||||
else fatal(1, "invalid -s option (%d)", i);
|
||||
break;
|
||||
|
||||
default: /* '?' */
|
||||
usage();
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
return optind;
|
||||
}
|
||||
|
||||
void samples(const gpioSample_t *samples, int numSamples)
|
||||
{
|
||||
static uint32_t state = 0;
|
||||
uint32_t high, level;
|
||||
int g, s;
|
||||
|
||||
if (g_reset_counts)
|
||||
{
|
||||
g_reset_counts = 0;
|
||||
for (g=0; g<g_num_gpios; g++) g_pulse_count[g] = 0;
|
||||
}
|
||||
|
||||
for (s=0; s<numSamples; s++)
|
||||
{
|
||||
level = samples[s].level;
|
||||
high = ((state ^ level) & g_mask) & level;
|
||||
state = level;
|
||||
/* only interested in low to high */
|
||||
if (high)
|
||||
{
|
||||
for (g=0; g<g_num_gpios; g++)
|
||||
{
|
||||
if (high & (1<<g_gpio[g])) g_pulse_count[g]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int i, rest, g, wave_id, mode;
|
||||
gpioPulse_t pulse[2];
|
||||
int count[MAX_GPIOS];
|
||||
|
||||
/* command line parameters */
|
||||
|
||||
rest = initOpts(argc, argv);
|
||||
|
||||
/* get the gpios to monitor */
|
||||
|
||||
g_num_gpios = 0;
|
||||
|
||||
for (i=rest; i<argc; i++)
|
||||
{
|
||||
g = atoi(argv[i]);
|
||||
if ((g>=0) && (g<32))
|
||||
{
|
||||
g_gpio[g_num_gpios++] = g;
|
||||
g_mask |= (1<<g);
|
||||
}
|
||||
else fatal(1, "%d is not a valid g_gpio number\n", g);
|
||||
}
|
||||
|
||||
if (!g_num_gpios) fatal(1, "At least one gpio must be specified");
|
||||
|
||||
printf("Monitoring gpios");
|
||||
for (i=0; i<g_num_gpios; i++) printf(" %d", g_gpio[i]);
|
||||
printf("\nSample rate %d micros, refresh rate %d deciseconds\n",
|
||||
g_opt_s, g_opt_r);
|
||||
|
||||
gpioCfgClock(g_opt_s, 1, 1);
|
||||
|
||||
if (gpioInitialise()<0) return 1;
|
||||
|
||||
gpioWaveClear();
|
||||
|
||||
pulse[0].gpioOn = g_mask;
|
||||
pulse[0].gpioOff = 0;
|
||||
pulse[0].usDelay = g_opt_p;
|
||||
|
||||
pulse[1].gpioOn = 0;
|
||||
pulse[1].gpioOff = g_mask;
|
||||
pulse[1].usDelay = g_opt_p;
|
||||
|
||||
gpioWaveAddGeneric(2, pulse);
|
||||
|
||||
wave_id = gpioWaveCreate();
|
||||
|
||||
/* monitor g_gpio level changes */
|
||||
|
||||
gpioSetGetSamplesFunc(samples, g_mask);
|
||||
|
||||
mode = PI_INPUT;
|
||||
|
||||
if (g_opt_t)
|
||||
{
|
||||
gpioWaveTxSend(wave_id, PI_WAVE_MODE_REPEAT);
|
||||
mode = PI_OUTPUT;
|
||||
}
|
||||
|
||||
for (i=0; i<g_num_gpios; i++) gpioSetMode(g_gpio[i], mode);
|
||||
|
||||
while (1)
|
||||
{
|
||||
for (i=0; i<g_num_gpios; i++) count[i] = g_pulse_count[i];
|
||||
|
||||
g_reset_counts = 1;
|
||||
|
||||
for (i=0; i<g_num_gpios; i++)
|
||||
{
|
||||
printf(" %d=%d", g_gpio[i], count[i]);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
gpioDelay(g_opt_r * 100000);
|
||||
}
|
||||
|
||||
gpioTerminate();
|
||||
}
|
||||
|
2
pigpio-master/EXAMPLES/C/HALL_EFFECT_SENSOR/README
Normal file
2
pigpio-master/EXAMPLES/C/HALL_EFFECT_SENSOR/README
Normal file
@@ -0,0 +1,2 @@
|
||||
Program to show status changes for a Hall effect sensor.
|
||||
|
51
pigpio-master/EXAMPLES/C/HALL_EFFECT_SENSOR/hall.c
Normal file
51
pigpio-master/EXAMPLES/C/HALL_EFFECT_SENSOR/hall.c
Normal file
@@ -0,0 +1,51 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include <pigpio.h>
|
||||
|
||||
/*
|
||||
OH3144E or equivalent Hall effect sensor
|
||||
|
||||
Pin 1 - 5V
|
||||
Pin 2 - Ground
|
||||
Pin 3 - gpio (here P1-8, gpio 14, TXD is used)
|
||||
|
||||
The internal gpio pull-up is enabled so that the sensor
|
||||
normally reads high. It reads low when a magnet is close.
|
||||
|
||||
gcc -o hall hall.c -lpigpio -lrt -lpthread
|
||||
sudo ./hall
|
||||
*/
|
||||
|
||||
#define HALL 14
|
||||
|
||||
void alert(int gpio, int level, uint32_t tick)
|
||||
{
|
||||
static uint32_t lastTick=0;
|
||||
|
||||
if (lastTick) printf("%d %.2f\n", level, (float)(tick-lastTick)/1000000.0);
|
||||
else printf("%d 0.00\n", level);
|
||||
|
||||
lastTick = tick;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int secs=60;
|
||||
|
||||
if (argc>1) secs = atoi(argv[1]); /* program run seconds */
|
||||
|
||||
if ((secs<1) || (secs>3600)) secs = 3600;
|
||||
|
||||
if (gpioInitialise()<0) return 1;
|
||||
|
||||
gpioSetMode(HALL, PI_INPUT);
|
||||
|
||||
gpioSetPullUpDown(HALL, PI_PUD_UP);
|
||||
|
||||
gpioSetAlertFunc(HALL, alert);
|
||||
|
||||
sleep(secs);
|
||||
|
||||
gpioTerminate();
|
||||
}
|
||||
|
4
pigpio-master/EXAMPLES/C/I2C_SNIFFER/README
Normal file
4
pigpio-master/EXAMPLES/C/I2C_SNIFFER/README
Normal file
@@ -0,0 +1,4 @@
|
||||
A program to passively sniff I2C transactions (100kHz bus maximum) and display the results.
|
||||
|
||||
This C program uses pigpio notifications.
|
||||
|
205
pigpio-master/EXAMPLES/C/I2C_SNIFFER/pig2i2c.c
Normal file
205
pigpio-master/EXAMPLES/C/I2C_SNIFFER/pig2i2c.c
Normal file
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "pigpio.h"
|
||||
|
||||
/*
|
||||
This software reads pigpio notification reports monitoring the I2C signals.
|
||||
|
||||
Notifications are pipe based so this software must be run on the Pi
|
||||
being monitored.
|
||||
|
||||
It should be able to handle a 100kHz bus. You are unlikely to get any
|
||||
usable results if the bus is running at 400kHz.
|
||||
|
||||
gcc -o pig2i2c pig2i2c.c
|
||||
|
||||
Do something like
|
||||
|
||||
sudo pigpiod -s 2
|
||||
|
||||
# get a notification handle, assume handle 0 was returned
|
||||
|
||||
pigs no
|
||||
|
||||
# start notifications for SCL/SDA
|
||||
|
||||
e.g. pigs nb 0 0x3 # Rev. 1 select gpios 0/1
|
||||
e.g. pigs nb 0 0xC # Rev. 2 select gpios 2/3
|
||||
e.g. pigs nb 0 0xA00 # select gpios 9/11 (1<<9|1<<11)
|
||||
|
||||
# run the program, specifying SCL/SDA and notification pipe
|
||||
|
||||
./pig2i2c SCL SDA </dev/pigpioN # specify gpios for SCL/SDA and pipe N
|
||||
|
||||
e.g. ./pig2i2c 1 0 </dev/pigpio0 # Rev.1 I2C gpios
|
||||
e.g. ./pig2i2c 3 2 </dev/pigpio0 # Rev.2 I2C gpios
|
||||
e.g. ./pig2i2c 9 11 </dev/pigpio0 # monitor external bus
|
||||
*/
|
||||
|
||||
#define RS (sizeof(gpioReport_t))
|
||||
|
||||
#define SCL_FALLING 0
|
||||
#define SCL_RISING 1
|
||||
#define SCL_STEADY 2
|
||||
|
||||
#define SDA_FALLING 0
|
||||
#define SDA_RISING 4
|
||||
#define SDA_STEADY 8
|
||||
|
||||
static char * timeStamp()
|
||||
{
|
||||
static char buf[32];
|
||||
|
||||
struct timeval now;
|
||||
struct tm tmp;
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
|
||||
localtime_r(&now.tv_sec, &tmp);
|
||||
strftime(buf, sizeof(buf), "%F %T", &tmp);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void parse_I2C(int SCL, int SDA)
|
||||
{
|
||||
static int in_data=0, byte=0, bit=0;
|
||||
static int oldSCL=1, oldSDA=1;
|
||||
|
||||
int xSCL, xSDA;
|
||||
|
||||
if (SCL != oldSCL)
|
||||
{
|
||||
oldSCL = SCL;
|
||||
if (SCL) xSCL = SCL_RISING;
|
||||
else xSCL = SCL_FALLING;
|
||||
}
|
||||
else xSCL = SCL_STEADY;
|
||||
|
||||
if (SDA != oldSDA)
|
||||
{
|
||||
oldSDA = SDA;
|
||||
if (SDA) xSDA = SDA_RISING;
|
||||
else xSDA = SDA_FALLING;
|
||||
}
|
||||
else xSDA = SDA_STEADY;
|
||||
|
||||
switch (xSCL+xSDA)
|
||||
{
|
||||
case SCL_RISING + SDA_RISING:
|
||||
case SCL_RISING + SDA_FALLING:
|
||||
case SCL_RISING + SDA_STEADY:
|
||||
if (in_data)
|
||||
{
|
||||
if (bit++ < 8)
|
||||
{
|
||||
byte <<= 1;
|
||||
byte |= SDA;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("%02X", byte);
|
||||
if (SDA) printf("-"); else printf("+");
|
||||
bit = 0;
|
||||
byte = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SCL_FALLING + SDA_RISING:
|
||||
break;
|
||||
|
||||
case SCL_FALLING + SDA_FALLING:
|
||||
break;
|
||||
|
||||
case SCL_FALLING + SDA_STEADY:
|
||||
break;
|
||||
|
||||
case SCL_STEADY + SDA_RISING:
|
||||
if (SCL)
|
||||
{
|
||||
in_data = 0;
|
||||
byte = 0;
|
||||
bit = 0;
|
||||
|
||||
printf("]\n"); // stop
|
||||
fflush(NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
case SCL_STEADY + SDA_FALLING:
|
||||
if (SCL)
|
||||
{
|
||||
in_data = 1;
|
||||
byte = 0;
|
||||
bit = 0;
|
||||
|
||||
printf("["); // start
|
||||
}
|
||||
break;
|
||||
|
||||
case SCL_STEADY + SDA_STEADY:
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
int gSCL, gSDA, SCL, SDA, xSCL;
|
||||
int r;
|
||||
uint32_t level, changed, bI2C, bSCL, bSDA;
|
||||
|
||||
gpioReport_t report;
|
||||
|
||||
if (argc > 2)
|
||||
{
|
||||
gSCL = atoi(argv[1]);
|
||||
gSDA = atoi(argv[2]);
|
||||
|
||||
bSCL = 1<<gSCL;
|
||||
bSDA = 1<<gSDA;
|
||||
|
||||
bI2C = bSCL | bSDA;
|
||||
}
|
||||
else
|
||||
{
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* default to SCL/SDA high */
|
||||
|
||||
SCL = 1;
|
||||
SDA = 1;
|
||||
level = bI2C;
|
||||
|
||||
while ((r=read(STDIN_FILENO, &report, RS)) == RS)
|
||||
{
|
||||
report.level &= bI2C;
|
||||
|
||||
if (report.level != level)
|
||||
{
|
||||
changed = report.level ^ level;
|
||||
|
||||
level = report.level;
|
||||
|
||||
if (level & bSCL) SCL = 1; else SCL = 0;
|
||||
if (level & bSDA) SDA = 1; else SDA = 0;
|
||||
|
||||
parse_I2C(SCL, SDA);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
3
pigpio-master/EXAMPLES/C/IR_RECEIVER/README
Normal file
3
pigpio-master/EXAMPLES/C/IR_RECEIVER/README
Normal file
@@ -0,0 +1,3 @@
|
||||
Function to hash a code from an IR receiver (reading an IR remote control).
|
||||
|
||||
Follow the instructions in the test file to build and run.
|
136
pigpio-master/EXAMPLES/C/IR_RECEIVER/ir_hasher.c
Normal file
136
pigpio-master/EXAMPLES/C/IR_RECEIVER/ir_hasher.c
Normal file
@@ -0,0 +1,136 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <pigpio.h>
|
||||
|
||||
#include "ir_hasher.h"
|
||||
|
||||
/*
|
||||
This code forms a hash over the IR pulses generated by an
|
||||
IR remote.
|
||||
|
||||
The remote key press is not converted into a code in the manner of
|
||||
the lirc module. No attempt is made to decode the type of protocol
|
||||
used by the remote. The hash is likely to be unique for different
|
||||
keys and different remotes but this is not guaranteed.
|
||||
|
||||
This hashing process works for some remotes/protocols but not for
|
||||
others. The only way to find out if it works for one or more of
|
||||
your remotes is to try it and see.
|
||||
*/
|
||||
|
||||
struct _Pi_Hasher_s
|
||||
{
|
||||
int gpio;
|
||||
Pi_Hasher_CB_t callback;
|
||||
int timeout;
|
||||
int in_code;
|
||||
uint32_t hash_val;
|
||||
int edges;
|
||||
int t1;
|
||||
int t2;
|
||||
int t3;
|
||||
int t4;
|
||||
};
|
||||
|
||||
|
||||
static uint32_t _hash(uint32_t hv, int old_val, int new_val)
|
||||
{
|
||||
int val;
|
||||
|
||||
if (new_val < (old_val * 0.60)) val = 13;
|
||||
else if (old_val < (new_val * 0.60)) val = 23;
|
||||
else val = 2;
|
||||
|
||||
hv ^= val;
|
||||
hv *= 16777619; /* FNV_PRIME_32 */
|
||||
|
||||
return hv;
|
||||
}
|
||||
|
||||
static void _cb(int gpio, int level, uint32_t tick, void *user)
|
||||
{
|
||||
Pi_Hasher_t * hasher;
|
||||
|
||||
hasher = user;
|
||||
|
||||
if (level != PI_TIMEOUT)
|
||||
{
|
||||
if (hasher->in_code == 0)
|
||||
{
|
||||
hasher->in_code = 1;
|
||||
|
||||
gpioSetWatchdog(gpio, hasher->timeout);
|
||||
|
||||
hasher->hash_val = 2166136261U; /* FNV_BASIS_32 */
|
||||
|
||||
hasher->edges = 1;
|
||||
|
||||
hasher->t1 = 0;
|
||||
hasher->t2 = 0;
|
||||
hasher->t3 = 0;
|
||||
hasher->t4 = tick;
|
||||
}
|
||||
else
|
||||
{
|
||||
hasher->edges++;
|
||||
|
||||
hasher->t1 = hasher->t2;
|
||||
hasher->t2 = hasher->t3;
|
||||
hasher->t3 = hasher->t4;
|
||||
hasher->t4 = tick;
|
||||
|
||||
if (hasher->edges > 3)
|
||||
{
|
||||
hasher->hash_val =
|
||||
_hash(hasher->hash_val,
|
||||
(hasher->t2)-(hasher->t1),
|
||||
(hasher->t4)-(hasher->t3));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hasher->in_code)
|
||||
{
|
||||
hasher->in_code = 0;
|
||||
|
||||
gpioSetWatchdog(gpio, 0);
|
||||
|
||||
if (hasher->edges > 12) /* Anything less is probably noise. */
|
||||
{
|
||||
(hasher->callback)(hasher->hash_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Pi_Hasher_t *Pi_Hasher(int gpio, Pi_Hasher_CB_t callback, int timeout)
|
||||
{
|
||||
Pi_Hasher_t *hasher;
|
||||
|
||||
hasher = malloc(sizeof(Pi_Hasher_t));
|
||||
|
||||
hasher->gpio = gpio;
|
||||
hasher->callback = callback;
|
||||
hasher->timeout = 5;
|
||||
|
||||
hasher->in_code = 0;
|
||||
|
||||
gpioSetMode(gpio, PI_INPUT);
|
||||
gpioSetAlertFuncEx(gpio, _cb, hasher);
|
||||
|
||||
return hasher;
|
||||
}
|
||||
|
||||
void Pi_Hasher_cancel(Pi_Hasher_t *hasher)
|
||||
{
|
||||
if (hasher)
|
||||
{
|
||||
gpioSetAlertFunc(hasher->gpio, 0);
|
||||
|
||||
free(hasher);
|
||||
|
||||
hasher = NULL;
|
||||
}
|
||||
}
|
||||
|
33
pigpio-master/EXAMPLES/C/IR_RECEIVER/ir_hasher.h
Normal file
33
pigpio-master/EXAMPLES/C/IR_RECEIVER/ir_hasher.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef IR_HASHER_H
|
||||
#define IR_HASHER_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef void (*Pi_Hasher_CB_t)(uint32_t);
|
||||
|
||||
struct _Pi_Hasher_s;
|
||||
|
||||
typedef struct _Pi_Hasher_s Pi_Hasher_t;
|
||||
|
||||
Pi_Hasher_t * Pi_Hasher(int gpio, Pi_Hasher_CB_t callback, int timeout);
|
||||
/*
|
||||
This function establishes an IR hasher on the gpio.
|
||||
|
||||
A gap of timeout milliseconds without a new bit indicates
|
||||
the end of a code.
|
||||
|
||||
When code end is detected the callback function is called
|
||||
with the code hash.
|
||||
|
||||
A pointer to a private data type is returned. This should be passed
|
||||
to Pi_Hasher_cancel if the hasher is to be cancelled.
|
||||
*/
|
||||
|
||||
|
||||
void Pi_Hasher_cancel(Pi_Hasher_t *hasher);
|
||||
/*
|
||||
This function releases the resources used by the hasher.
|
||||
*/
|
||||
|
||||
|
||||
#endif
|
47
pigpio-master/EXAMPLES/C/IR_RECEIVER/test_ir_hasher.c
Normal file
47
pigpio-master/EXAMPLES/C/IR_RECEIVER/test_ir_hasher.c
Normal file
@@ -0,0 +1,47 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include <pigpio.h>
|
||||
|
||||
#include "ir_hasher.h"
|
||||
|
||||
/*
|
||||
|
||||
REQUIRES
|
||||
|
||||
An IR receiver output pin connected to a Pi gpio.
|
||||
|
||||
TO BUILD
|
||||
|
||||
gcc -o ir_hash_c test_ir_hasher.c ir_hasher.c -lpigpio -lrt -lpthread
|
||||
|
||||
TO RUN
|
||||
|
||||
sudo ./ir_hash_c
|
||||
|
||||
*/
|
||||
|
||||
void callback(uint32_t hash)
|
||||
{
|
||||
printf("hash=%u\n", hash);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
Pi_Hasher_t *hasher;
|
||||
|
||||
if (gpioInitialise() < 0) return 1;
|
||||
|
||||
/*
|
||||
This assumes the output pin of an IR receiver is
|
||||
connected to gpio 7.
|
||||
*/
|
||||
|
||||
hasher = Pi_Hasher(7, callback, 5);
|
||||
|
||||
sleep(300);
|
||||
|
||||
Pi_Hasher_cancel(hasher);
|
||||
|
||||
gpioTerminate();
|
||||
}
|
||||
|
131
pigpio-master/EXAMPLES/C/PCF8591_YL-40/PCF8591.c
Normal file
131
pigpio-master/EXAMPLES/C/PCF8591_YL-40/PCF8591.c
Normal file
@@ -0,0 +1,131 @@
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/i2c-dev.h>
|
||||
#include <ncurses.h> /* libncurses5-dev */
|
||||
|
||||
/*
|
||||
2014-08-26 PCF8591.c
|
||||
|
||||
sudo apt-get install libncurses5-dev
|
||||
|
||||
gcc -o PCF8591 PCF8591.c -lcurses -lpigpio -lpthread
|
||||
|
||||
sudo ./PCF8591
|
||||
*/
|
||||
|
||||
/*
|
||||
Connect Pi 3V3 - VCC, Ground - Ground, SDA - SDA, SCL - SCL.
|
||||
*/
|
||||
|
||||
#define PCF8591_I2C_ADDR 0x48
|
||||
|
||||
/*
|
||||
P4 The thermister voltage is provided at AIN 1.
|
||||
P5 The photocell voltage is provided at AIN 0.
|
||||
P6 The single turn 10K ohm trim pot voltage is provided at AIN 3.
|
||||
*/
|
||||
|
||||
/*
|
||||
7 6 5 4 3 2 1 0
|
||||
0 X X X 0 X X X
|
||||
| | | | | |
|
||||
A B B C D D
|
||||
|
||||
0 1 0 0 0 1 0 0
|
||||
|
||||
A 0 D/A inactive
|
||||
1 D/A active
|
||||
|
||||
B 00 single ended inputs
|
||||
01 differential inputs
|
||||
10 single ended and differential
|
||||
11 two differential inputs
|
||||
|
||||
C 0 no auto inc
|
||||
1 auto inc
|
||||
|
||||
D 00 select channel 0
|
||||
01 select channel 1
|
||||
10 select channel 2
|
||||
11 select channel 3
|
||||
|
||||
*/
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
int r;
|
||||
int handle;
|
||||
char aout;
|
||||
unsigned char command[2];
|
||||
unsigned char value[4];
|
||||
unsigned char str[8];
|
||||
|
||||
int j;
|
||||
int key;
|
||||
|
||||
if (gpioInitialise() < 0) return 1;
|
||||
|
||||
initscr();
|
||||
noecho();
|
||||
cbreak();
|
||||
nodelay(stdscr, true);
|
||||
curs_set(0);
|
||||
|
||||
printw("PCF8591 + or - to change aout, any other key to quit.");
|
||||
|
||||
mvaddstr(10, 0, "Brightness");
|
||||
mvaddstr(12, 0, "Temperature");
|
||||
mvaddstr(14, 0, "?");
|
||||
mvaddstr(16, 0, "Resistor");
|
||||
|
||||
refresh();
|
||||
|
||||
handle = i2cOpen(1, PCF8591_I2C_ADDR, 0);
|
||||
|
||||
command[1] = 0;
|
||||
aout = 128;
|
||||
|
||||
while (1)
|
||||
{
|
||||
for (i=0; i<4; i++)
|
||||
{
|
||||
command[1] = aout;
|
||||
command[0] = 0x40 | ((i + 1) & 0x03); // output enable | read input i
|
||||
|
||||
i2cWriteDevice(handle, &command, 2);
|
||||
|
||||
usleep(20000);
|
||||
|
||||
// the read is always one step behind the selected input
|
||||
value[i] = i2cReadByte(handle);
|
||||
|
||||
sprintf(str, "%3d", value[i]);
|
||||
mvaddstr(10+i+i, 12, str);
|
||||
value[i] = value[i] / 4;
|
||||
move(10 + i + i, 16);
|
||||
|
||||
for(j = 0; j < 64; j++)
|
||||
if(j < value[i]) addch('*'); else addch(' ');
|
||||
}
|
||||
|
||||
refresh();
|
||||
|
||||
key = getch();
|
||||
|
||||
if ((key == '+') || (key == '=')) aout++;
|
||||
else if ((key == '-') || (key == '_')) aout--;
|
||||
else if (key != -1) break;
|
||||
}
|
||||
|
||||
endwin();
|
||||
|
||||
i2cClose(handle);
|
||||
|
||||
gpioTerminate();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
1
pigpio-master/EXAMPLES/C/PCF8591_YL-40/README
Normal file
1
pigpio-master/EXAMPLES/C/PCF8591_YL-40/README
Normal file
@@ -0,0 +1 @@
|
||||
A program to display readings from the (I2C) PCF8591.
|
3
pigpio-master/EXAMPLES/C/POT_CAP_RECHARGE/README
Normal file
3
pigpio-master/EXAMPLES/C/POT_CAP_RECHARGE/README
Normal file
@@ -0,0 +1,3 @@
|
||||
Function to time capacitor charging (through a resistance).
|
||||
|
||||
The time can be used to estimate the resistance.
|
94
pigpio-master/EXAMPLES/C/POT_CAP_RECHARGE/pot_cap_charge.c
Normal file
94
pigpio-master/EXAMPLES/C/POT_CAP_RECHARGE/pot_cap_charge.c
Normal file
@@ -0,0 +1,94 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include <pigpio.h>
|
||||
|
||||
/*
|
||||
Measure how long a capacitor takes to charge through a resistance.
|
||||
|
||||
A potentimeter is used to vary the resistance.
|
||||
|
||||
The time taken will be proportional to the resistance.
|
||||
|
||||
3V3 ----- Potentiometer --+-- Capacitor ----- Ground
|
||||
|
|
||||
+-- gpio
|
||||
|
||||
|
||||
gcc -o pot_cap_charge pot_cap_charge.c -lpigpio -lpthread -lrt
|
||||
sudo ./pot_cap_charge
|
||||
|
||||
*/
|
||||
|
||||
#define GPIO 25
|
||||
|
||||
#define MAX_READING 1000
|
||||
|
||||
static uint32_t rechargeTick = 0;
|
||||
|
||||
void callback(int gpio, int level, uint32_t tick)
|
||||
{
|
||||
static uint32_t smooth = 0;
|
||||
static int reading = 0;
|
||||
|
||||
uint32_t raw;
|
||||
|
||||
if (level == 1) /* measure recharge time */
|
||||
{
|
||||
++reading;
|
||||
|
||||
if (rechargeTick)
|
||||
{
|
||||
raw = tick - rechargeTick; /* set in main */
|
||||
|
||||
if (raw < MAX_READING) /* ignore outliers */
|
||||
{
|
||||
/* smooth using 0.8 * smooth + 0.2 * raw */
|
||||
|
||||
smooth = (raw + (4 * smooth)) / 5;
|
||||
|
||||
printf("%d %d %d\n", reading, raw, smooth);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ignore outlier, set dot at fixed position */
|
||||
printf("%d %d %d\n", reading, 40, smooth);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ignore reschedule, set dot at fixed position */
|
||||
printf("%d %d %d\n", reading, 20, smooth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
uint32_t t1, t2;
|
||||
int tDiff;
|
||||
|
||||
if (gpioInitialise()<0) return 1;
|
||||
|
||||
gpioSetAlertFunc(GPIO, callback); /* callback when GPIO changes state */
|
||||
|
||||
while (1)
|
||||
{
|
||||
gpioWrite(GPIO, PI_OFF); /* drain capacitor */
|
||||
|
||||
gpioDelay(200); /* microseconds */
|
||||
|
||||
t1 = gpioTick();
|
||||
|
||||
gpioSetMode(GPIO, PI_INPUT); /* start capacitor recharge */
|
||||
|
||||
t2 = gpioTick();
|
||||
|
||||
/* dump reading if rechargeTick not accurate to 3 micros */
|
||||
|
||||
if ((t2 - t1) < 3) rechargeTick = t1; else rechargeTick = 0;
|
||||
|
||||
gpioDelay(5000); /* microseconds, nominal 200 readings per second */
|
||||
}
|
||||
|
||||
gpioTerminate();
|
||||
}
|
4
pigpio-master/EXAMPLES/C/ROTARY_ENCODER/README
Normal file
4
pigpio-master/EXAMPLES/C/ROTARY_ENCODER/README
Normal file
@@ -0,0 +1,4 @@
|
||||
Function to decode a mechanical rotary encoder.
|
||||
|
||||
Follow the instructions in the test file to build and run.
|
||||
|
94
pigpio-master/EXAMPLES/C/ROTARY_ENCODER/rotary_encoder.c
Normal file
94
pigpio-master/EXAMPLES/C/ROTARY_ENCODER/rotary_encoder.c
Normal file
@@ -0,0 +1,94 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <pigpio.h>
|
||||
|
||||
#include "rotary_encoder.h"
|
||||
|
||||
struct _Pi_Renc_s
|
||||
{
|
||||
int gpioA;
|
||||
int gpioB;
|
||||
Pi_Renc_CB_t callback;
|
||||
int levA;
|
||||
int levB;
|
||||
int lastGpio;
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
+---------+ +---------+ 0
|
||||
| | | |
|
||||
A | | | |
|
||||
| | | |
|
||||
+---------+ +---------+ +----- 1
|
||||
|
||||
+---------+ +---------+ 0
|
||||
| | | |
|
||||
B | | | |
|
||||
| | | |
|
||||
----+ +---------+ +---------+ 1
|
||||
|
||||
*/
|
||||
|
||||
static void _cb(int gpio, int level, uint32_t tick, void *user)
|
||||
{
|
||||
Pi_Renc_t *renc;
|
||||
|
||||
renc = user;
|
||||
|
||||
if (gpio == renc->gpioA) renc->levA = level; else renc->levB = level;
|
||||
|
||||
if (gpio != renc->lastGpio) /* debounce */
|
||||
{
|
||||
renc->lastGpio = gpio;
|
||||
|
||||
if ((gpio == renc->gpioA) && (level == 1))
|
||||
{
|
||||
if (renc->levB) (renc->callback)(1);
|
||||
}
|
||||
else if ((gpio == renc->gpioB) && (level == 1))
|
||||
{
|
||||
if (renc->levA) (renc->callback)(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Pi_Renc_t * Pi_Renc(int gpioA, int gpioB, Pi_Renc_CB_t callback)
|
||||
{
|
||||
Pi_Renc_t *renc;
|
||||
|
||||
renc = malloc(sizeof(Pi_Renc_t));
|
||||
|
||||
renc->gpioA = gpioA;
|
||||
renc->gpioB = gpioB;
|
||||
renc->callback = callback;
|
||||
renc->levA=0;
|
||||
renc->levB=0;
|
||||
renc->lastGpio = -1;
|
||||
|
||||
gpioSetMode(gpioA, PI_INPUT);
|
||||
gpioSetMode(gpioB, PI_INPUT);
|
||||
|
||||
/* pull up is needed as encoder common is grounded */
|
||||
|
||||
gpioSetPullUpDown(gpioA, PI_PUD_UP);
|
||||
gpioSetPullUpDown(gpioB, PI_PUD_UP);
|
||||
|
||||
/* monitor encoder level changes */
|
||||
|
||||
gpioSetAlertFuncEx(gpioA, _cb, renc);
|
||||
gpioSetAlertFuncEx(gpioB, _cb, renc);
|
||||
}
|
||||
|
||||
void Pi_Renc_cancel(Pi_Renc_t *renc)
|
||||
{
|
||||
if (renc)
|
||||
{
|
||||
gpioSetAlertFunc(renc->gpioA, 0);
|
||||
gpioSetAlertFunc(renc->gpioB, 0);
|
||||
|
||||
free(renc);
|
||||
}
|
||||
}
|
||||
|
25
pigpio-master/EXAMPLES/C/ROTARY_ENCODER/rotary_encoder.h
Normal file
25
pigpio-master/EXAMPLES/C/ROTARY_ENCODER/rotary_encoder.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef ROTARY_ENCODER_H
|
||||
#define ROTARY_ENCODER_H
|
||||
|
||||
typedef void (*Pi_Renc_CB_t)(int);
|
||||
|
||||
struct _Pi_Renc_s;
|
||||
|
||||
typedef struct _Pi_Renc_s Pi_Renc_t;
|
||||
|
||||
Pi_Renc_t * Pi_Renc(int gpioA, int gpioB, Pi_Renc_CB_t callback);
|
||||
/*
|
||||
This function establishes a rotary encoder on gpioA and gpioB.
|
||||
|
||||
When the encoder is turned the callback function is called.
|
||||
|
||||
A pointer to a private data type is returned. This should be passed
|
||||
to Pi_Renc_cancel if the rotary encoder is to be cancelled.
|
||||
*/
|
||||
|
||||
void Pi_Renc_cancel(Pi_Renc_t *renc);
|
||||
/*
|
||||
This function releases the resources used by the decoder.
|
||||
*/
|
||||
|
||||
#endif
|
@@ -0,0 +1,47 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include <pigpio.h>
|
||||
|
||||
#include "rotary_encoder.h"
|
||||
|
||||
/*
|
||||
|
||||
REQUIRES
|
||||
|
||||
A rotary encoder contacts A and B connected to separate gpios and
|
||||
the common contact connected to Pi ground.
|
||||
|
||||
TO BUILD
|
||||
|
||||
gcc -o rot_enc_c test_rotary_encoder.c rotary_encoder.c -lpigpio -lrt
|
||||
|
||||
TO RUN
|
||||
|
||||
sudo ./rot_enc_c
|
||||
|
||||
*/
|
||||
|
||||
void callback(int way)
|
||||
{
|
||||
static int pos = 0;
|
||||
|
||||
pos += way;
|
||||
|
||||
printf("pos=%d\n", pos);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
Pi_Renc_t * renc;
|
||||
|
||||
if (gpioInitialise() < 0) return 1;
|
||||
|
||||
renc = Pi_Renc(7, 8, callback);
|
||||
|
||||
sleep(300);
|
||||
|
||||
Pi_Renc_cancel(renc);
|
||||
|
||||
gpioTerminate();
|
||||
}
|
||||
|
4
pigpio-master/EXAMPLES/C/WIEGAND_CODE/README
Normal file
4
pigpio-master/EXAMPLES/C/WIEGAND_CODE/README
Normal file
@@ -0,0 +1,4 @@
|
||||
Function to decode a Wiegand code.
|
||||
|
||||
Follow the instructions in the test file to build and run.
|
||||
|
42
pigpio-master/EXAMPLES/C/WIEGAND_CODE/test_wiegand.c
Normal file
42
pigpio-master/EXAMPLES/C/WIEGAND_CODE/test_wiegand.c
Normal file
@@ -0,0 +1,42 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include <pigpio.h>
|
||||
|
||||
#include "wiegand.h"
|
||||
|
||||
/*
|
||||
|
||||
REQUIRES
|
||||
|
||||
Wiegand contacts 0 and 1 connected to separate gpios.
|
||||
|
||||
TO BUILD
|
||||
|
||||
gcc -o wiegand_c test_wiegand.c wiegand.c -lpigpio -lrt
|
||||
|
||||
TO RUN
|
||||
|
||||
sudo ./wiegand_c
|
||||
|
||||
*/
|
||||
|
||||
void callback(int bits, uint32_t value)
|
||||
{
|
||||
printf("bits=%d value=%u\n", bits, value);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
Pi_Wieg_t * w;
|
||||
|
||||
if (gpioInitialise() < 0) return 1;
|
||||
|
||||
w = Pi_Wieg(14, 15, callback, 5);
|
||||
|
||||
sleep(300);
|
||||
|
||||
Pi_Wieg_cancel(w);
|
||||
|
||||
gpioTerminate();
|
||||
}
|
||||
|
137
pigpio-master/EXAMPLES/C/WIEGAND_CODE/wiegand.c
Normal file
137
pigpio-master/EXAMPLES/C/WIEGAND_CODE/wiegand.c
Normal file
@@ -0,0 +1,137 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <pigpio.h>
|
||||
|
||||
#include "wiegand.h"
|
||||
|
||||
struct _Pi_Wieg_s
|
||||
{
|
||||
int mygpio_0;
|
||||
int mygpio_1;
|
||||
int mytimeout;
|
||||
int in_code;
|
||||
int bits;
|
||||
Pi_Wieg_CB_t mycallback;
|
||||
uint32_t num;
|
||||
uint32_t code_timeout;
|
||||
};
|
||||
|
||||
void _cb(int gpio, int level, uint32_t tick, void *user)
|
||||
{
|
||||
/*
|
||||
Accumulate bits until both gpios 0 and 1 timeout.
|
||||
*/
|
||||
|
||||
Pi_Wieg_t *wieg;
|
||||
|
||||
wieg = user;
|
||||
|
||||
if (level == 0) /* a falling edge indicates a new bit */
|
||||
{
|
||||
if (!wieg->in_code)
|
||||
{
|
||||
wieg->bits = 1;
|
||||
wieg->num = 0;
|
||||
|
||||
wieg->in_code = 1;
|
||||
wieg->code_timeout = 0;
|
||||
|
||||
gpioSetWatchdog(wieg->mygpio_0, wieg->mytimeout);
|
||||
gpioSetWatchdog(wieg->mygpio_1, wieg->mytimeout);
|
||||
}
|
||||
else
|
||||
{
|
||||
wieg->bits++;
|
||||
wieg->num <<= 1;
|
||||
}
|
||||
|
||||
if (gpio == wieg->mygpio_0)
|
||||
{
|
||||
wieg->code_timeout &= 2; /* clear gpio 0 timeout */
|
||||
}
|
||||
else
|
||||
{
|
||||
wieg->code_timeout &= 1; /* clear gpio 1 timeout */
|
||||
wieg->num |= 1;
|
||||
}
|
||||
}
|
||||
else if (level == PI_TIMEOUT)
|
||||
{
|
||||
if (wieg->in_code)
|
||||
{
|
||||
if (gpio == wieg->mygpio_0)
|
||||
{
|
||||
wieg->code_timeout |= 1; /* timeout gpio 0 */
|
||||
}
|
||||
else
|
||||
{
|
||||
wieg->code_timeout |= 2; /* timeout gpio 1 */
|
||||
}
|
||||
|
||||
if (wieg->code_timeout == 3) /* both gpios timed out */
|
||||
{
|
||||
gpioSetWatchdog(wieg->mygpio_0, 0);
|
||||
gpioSetWatchdog(wieg->mygpio_1, 0);
|
||||
|
||||
wieg->in_code = 0;
|
||||
|
||||
(wieg->mycallback)(wieg->bits, wieg->num);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Pi_Wieg_t * Pi_Wieg(
|
||||
int gpio_0,
|
||||
int gpio_1,
|
||||
Pi_Wieg_CB_t callback,
|
||||
int timeout)
|
||||
{
|
||||
/*
|
||||
Instantiate with the gpio for 0 (green wire), the gpio for 1
|
||||
(white wire), the callback function, and the timeout in
|
||||
milliseconds which indicates the end of a code.
|
||||
|
||||
The callback is passed the code length in bits and the value.
|
||||
*/
|
||||
|
||||
Pi_Wieg_t *wieg;
|
||||
|
||||
wieg = malloc(sizeof(Pi_Wieg_t));
|
||||
|
||||
wieg->mygpio_0 = gpio_0;
|
||||
wieg->mygpio_1 = gpio_1;
|
||||
|
||||
wieg->mycallback = callback;
|
||||
|
||||
wieg->mytimeout = timeout;
|
||||
|
||||
wieg->in_code = 0;
|
||||
|
||||
gpioSetMode(gpio_0, PI_INPUT);
|
||||
gpioSetMode(gpio_1, PI_INPUT);
|
||||
|
||||
gpioSetPullUpDown(gpio_0, PI_PUD_UP);
|
||||
gpioSetPullUpDown(gpio_1, PI_PUD_UP);
|
||||
|
||||
gpioSetAlertFuncEx(gpio_0, _cb, wieg);
|
||||
gpioSetAlertFuncEx(gpio_1, _cb, wieg);
|
||||
|
||||
return wieg;
|
||||
}
|
||||
|
||||
void Pi_Wieg_cancel(Pi_Wieg_t *wieg)
|
||||
{
|
||||
/*
|
||||
Cancel the Wiegand decoder.
|
||||
*/
|
||||
|
||||
if (wieg)
|
||||
{
|
||||
gpioSetAlertFunc(wieg->mygpio_0, 0);
|
||||
gpioSetAlertFunc(wieg->mygpio_1, 0);
|
||||
|
||||
free(wieg);
|
||||
}
|
||||
}
|
||||
|
32
pigpio-master/EXAMPLES/C/WIEGAND_CODE/wiegand.h
Normal file
32
pigpio-master/EXAMPLES/C/WIEGAND_CODE/wiegand.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef WIEGAND_H
|
||||
#define WIEGAND_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef void (*Pi_Wieg_CB_t)(int, uint32_t);
|
||||
|
||||
struct _Pi_Wieg_s;
|
||||
|
||||
typedef struct _Pi_Wieg_s Pi_Wieg_t;
|
||||
|
||||
Pi_Wieg_t *Pi_Wieg(int gpio_0, int gpio_1, Pi_Wieg_CB_t callback, int timeout);
|
||||
/*
|
||||
This function establishes a Wiegand decoder on gpio_0 and gpio_1.
|
||||
|
||||
A gap of timeout milliseconds without a new bit indicates the
|
||||
end of a code.
|
||||
|
||||
When the code is ended the callback function is called with the code
|
||||
bit length and value.
|
||||
|
||||
A pointer to a private data type is returned. This should be passed
|
||||
to Pi_Wieg_cancel if the decoder is to be cancelled.
|
||||
*/
|
||||
|
||||
void Pi_Wieg_cancel(Pi_Wieg_t *wieg);
|
||||
/*
|
||||
This function releases the resources used by the decoder.
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
4
pigpio-master/EXAMPLES/CPP/IR_RECEIVER/README
Normal file
4
pigpio-master/EXAMPLES/CPP/IR_RECEIVER/README
Normal file
@@ -0,0 +1,4 @@
|
||||
Class to hash a code from an IR receiver (reading an IR remote control).
|
||||
|
||||
Follow the instructions in the test file to build and run.
|
||||
|
91
pigpio-master/EXAMPLES/CPP/IR_RECEIVER/ir_hasher.cpp
Normal file
91
pigpio-master/EXAMPLES/CPP/IR_RECEIVER/ir_hasher.cpp
Normal file
@@ -0,0 +1,91 @@
|
||||
#include <pigpio.h>
|
||||
|
||||
#include "ir_hasher.hpp"
|
||||
|
||||
void Hasher::_hash(int old_val, int new_val)
|
||||
{
|
||||
int val;
|
||||
|
||||
if (new_val < (old_val * 0.60)) val = 13;
|
||||
else if (old_val < (new_val * 0.60)) val = 23;
|
||||
else val = 2;
|
||||
|
||||
hash_val ^= val;
|
||||
hash_val *= 16777619; /* FNV_PRIME_32 */
|
||||
}
|
||||
|
||||
void Hasher::_callback(int gpio, int level, uint32_t tick)
|
||||
{
|
||||
if (level != PI_TIMEOUT)
|
||||
{
|
||||
if (in_code == 0)
|
||||
{
|
||||
in_code = 1;
|
||||
|
||||
gpioSetWatchdog(mygpio, mytimeout);
|
||||
|
||||
hash_val = 2166136261U; /* FNV_BASIS_32 */
|
||||
|
||||
edges = 1;
|
||||
|
||||
t1 = 0;
|
||||
t2 = 0;
|
||||
t3 = 0;
|
||||
t4 = tick;
|
||||
}
|
||||
else
|
||||
{
|
||||
edges++;
|
||||
|
||||
t1 = t2;
|
||||
t2 = t3;
|
||||
t3 = t4;
|
||||
t4 = tick;
|
||||
|
||||
if (edges > 3) _hash(t2-t1, t4-t3);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (in_code)
|
||||
{
|
||||
in_code = 0;
|
||||
|
||||
gpioSetWatchdog(mygpio, 0);
|
||||
|
||||
if (edges > 12) /* Anything less is probably noise. */
|
||||
{
|
||||
(mycallback)(hash_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Hasher::_callbackExt(int gpio, int level, uint32_t tick, void *user)
|
||||
{
|
||||
/*
|
||||
Need a static callback to link with C.
|
||||
*/
|
||||
|
||||
Hasher *mySelf = (Hasher *) user;
|
||||
|
||||
mySelf->_callback(gpio, level, tick); /* Call the instance callback. */
|
||||
}
|
||||
|
||||
Hasher::Hasher(int gpio, HasherCB_t callback, int timeout)
|
||||
{
|
||||
/*
|
||||
Initialises an IR remote hasher on a gpio. A gap of timeout
|
||||
milliseconds indicates the end of the remote key press.
|
||||
*/
|
||||
mygpio = gpio;
|
||||
mycallback = callback;
|
||||
mytimeout = timeout;
|
||||
|
||||
in_code = 0;
|
||||
|
||||
gpioSetMode(gpio, PI_INPUT);
|
||||
|
||||
gpioSetAlertFuncEx(gpio, _callbackExt, (void *)this);
|
||||
}
|
||||
|
44
pigpio-master/EXAMPLES/CPP/IR_RECEIVER/ir_hasher.hpp
Normal file
44
pigpio-master/EXAMPLES/CPP/IR_RECEIVER/ir_hasher.hpp
Normal file
@@ -0,0 +1,44 @@
|
||||
#ifndef IR_RX_HASHER_HPP
|
||||
#define IR_RX_HASHER_HPP
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef void (*HasherCB_t)(uint32_t);
|
||||
|
||||
class Hasher
|
||||
{
|
||||
|
||||
/*
|
||||
This class forms a hash over the IR pulses generated by an
|
||||
IR remote.
|
||||
|
||||
The remote key press is not converted into a code in the manner of
|
||||
the lirc module. No attempt is made to decode the type of protocol
|
||||
used by the remote. The hash is likely to be unique for different
|
||||
keys and different remotes but this is not guaranteed.
|
||||
|
||||
This hashing process works for some remotes/protocols but not for
|
||||
others. The only way to find out if it works for one or more of
|
||||
your remotes is to try it and see.
|
||||
*/
|
||||
|
||||
int mygpio, mytimeout;
|
||||
HasherCB_t mycallback;
|
||||
int in_code;
|
||||
uint32_t hash_val;
|
||||
int edges;
|
||||
uint32_t t1, t2, t3, t4;
|
||||
|
||||
void _hash(int old_val, int new_val);
|
||||
void _callback(int gpio, int level, uint32_t tick);
|
||||
|
||||
/* Need a static callback to link with C. */
|
||||
static void _callbackExt(int gpio, int level, uint32_t tick, void *user);
|
||||
|
||||
public:
|
||||
|
||||
Hasher(int gpio, HasherCB_t callback, int timeout=5);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
44
pigpio-master/EXAMPLES/CPP/IR_RECEIVER/test_ir_hasher.cpp
Normal file
44
pigpio-master/EXAMPLES/CPP/IR_RECEIVER/test_ir_hasher.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
#include <iostream>
|
||||
|
||||
#include <pigpio.h>
|
||||
|
||||
#include "ir_hasher.hpp"
|
||||
|
||||
/*
|
||||
|
||||
REQUIRES
|
||||
|
||||
An IR receiver output pin connected to a Pi gpio.
|
||||
|
||||
TO BUILD
|
||||
|
||||
g++ -o ir_hash_cpp test_ir_hasher.cpp ir_hasher.cpp -lpigpio -lrt -lpthread
|
||||
|
||||
TO RUN
|
||||
|
||||
sudo ./ir_hash_cpp
|
||||
|
||||
*/
|
||||
|
||||
void callback(uint32_t hash)
|
||||
{
|
||||
std::cout << "hash=" << hash << std::endl;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (gpioInitialise() >= 0)
|
||||
{
|
||||
/* Can't instantiate a Hasher before pigpio is initialised. */
|
||||
|
||||
/*
|
||||
This assumes the output pin of an IR receiver is
|
||||
connected to gpio 7.
|
||||
*/
|
||||
|
||||
Hasher ir(7, callback);
|
||||
|
||||
sleep(300);
|
||||
}
|
||||
}
|
||||
|
4
pigpio-master/EXAMPLES/CPP/ROTARY_ENCODER/README
Normal file
4
pigpio-master/EXAMPLES/CPP/ROTARY_ENCODER/README
Normal file
@@ -0,0 +1,4 @@
|
||||
Class to decode a mechanical rotary encoder.
|
||||
|
||||
Follow the instructions in the test file to build and run.
|
||||
|
84
pigpio-master/EXAMPLES/CPP/ROTARY_ENCODER/rotary_encoder.cpp
Normal file
84
pigpio-master/EXAMPLES/CPP/ROTARY_ENCODER/rotary_encoder.cpp
Normal file
@@ -0,0 +1,84 @@
|
||||
#include <iostream>
|
||||
|
||||
#include <pigpio.h>
|
||||
|
||||
#include "rotary_encoder.hpp"
|
||||
|
||||
/*
|
||||
|
||||
+---------+ +---------+ 0
|
||||
| | | |
|
||||
A | | | |
|
||||
| | | |
|
||||
+---------+ +---------+ +----- 1
|
||||
|
||||
+---------+ +---------+ 0
|
||||
| | | |
|
||||
B | | | |
|
||||
| | | |
|
||||
----+ +---------+ +---------+ 1
|
||||
|
||||
*/
|
||||
|
||||
void re_decoder::_pulse(int gpio, int level, uint32_t tick)
|
||||
{
|
||||
if (gpio == mygpioA) levA = level; else levB = level;
|
||||
|
||||
if (gpio != lastGpio) /* debounce */
|
||||
{
|
||||
lastGpio = gpio;
|
||||
|
||||
if ((gpio == mygpioA) && (level == 1))
|
||||
{
|
||||
if (levB) (mycallback)(1);
|
||||
}
|
||||
else if ((gpio == mygpioB) && (level == 1))
|
||||
{
|
||||
if (levA) (mycallback)(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void re_decoder::_pulseEx(int gpio, int level, uint32_t tick, void *user)
|
||||
{
|
||||
/*
|
||||
Need a static callback to link with C.
|
||||
*/
|
||||
|
||||
re_decoder *mySelf = (re_decoder *) user;
|
||||
|
||||
mySelf->_pulse(gpio, level, tick); /* Call the instance callback. */
|
||||
}
|
||||
|
||||
re_decoder::re_decoder(int gpioA, int gpioB, re_decoderCB_t callback)
|
||||
{
|
||||
mygpioA = gpioA;
|
||||
mygpioB = gpioB;
|
||||
|
||||
mycallback = callback;
|
||||
|
||||
levA=0;
|
||||
levB=0;
|
||||
|
||||
lastGpio = -1;
|
||||
|
||||
gpioSetMode(gpioA, PI_INPUT);
|
||||
gpioSetMode(gpioB, PI_INPUT);
|
||||
|
||||
/* pull up is needed as encoder common is grounded */
|
||||
|
||||
gpioSetPullUpDown(gpioA, PI_PUD_UP);
|
||||
gpioSetPullUpDown(gpioB, PI_PUD_UP);
|
||||
|
||||
/* monitor encoder level changes */
|
||||
|
||||
gpioSetAlertFuncEx(gpioA, _pulseEx, this);
|
||||
gpioSetAlertFuncEx(gpioB, _pulseEx, this);
|
||||
}
|
||||
|
||||
void re_decoder::re_cancel(void)
|
||||
{
|
||||
gpioSetAlertFuncEx(mygpioA, 0, this);
|
||||
gpioSetAlertFuncEx(mygpioB, 0, this);
|
||||
}
|
||||
|
35
pigpio-master/EXAMPLES/CPP/ROTARY_ENCODER/rotary_encoder.hpp
Normal file
35
pigpio-master/EXAMPLES/CPP/ROTARY_ENCODER/rotary_encoder.hpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#ifndef ROTARY_ENCODER_HPP
|
||||
#define ROTARY_ENCODER_HPP
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef void (*re_decoderCB_t)(int);
|
||||
|
||||
class re_decoder
|
||||
{
|
||||
int mygpioA, mygpioB, levA, levB, lastGpio;
|
||||
|
||||
re_decoderCB_t mycallback;
|
||||
|
||||
void _pulse(int gpio, int level, uint32_t tick);
|
||||
|
||||
/* Need a static callback to link with C. */
|
||||
static void _pulseEx(int gpio, int level, uint32_t tick, void *user);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
re_decoder(int gpioA, int gpioB, re_decoderCB_t callback);
|
||||
/*
|
||||
This function establishes a rotary encoder on gpioA and gpioB.
|
||||
|
||||
When the encoder is turned the callback function is called.
|
||||
*/
|
||||
|
||||
void re_cancel(void);
|
||||
/*
|
||||
This function releases the resources used by the decoder.
|
||||
*/
|
||||
};
|
||||
|
||||
#endif
|
@@ -0,0 +1,45 @@
|
||||
#include <iostream>
|
||||
|
||||
#include <pigpio.h>
|
||||
|
||||
#include "rotary_encoder.hpp"
|
||||
|
||||
/*
|
||||
|
||||
REQUIRES
|
||||
|
||||
A rotary encoder contacts A and B connected to separate gpios and
|
||||
the common contact connected to Pi ground.
|
||||
|
||||
TO BUILD
|
||||
|
||||
g++ -o rot_enc_cpp test_rotary_encoder.cpp rotary_encoder.cpp -lpigpio -lrt
|
||||
|
||||
TO RUN
|
||||
|
||||
sudo ./rot_enc_cpp
|
||||
|
||||
*/
|
||||
|
||||
void callback(int way)
|
||||
{
|
||||
static int pos = 0;
|
||||
|
||||
pos += way;
|
||||
|
||||
std::cout << "pos=" << pos << std::endl;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (gpioInitialise() < 0) return 1;
|
||||
|
||||
re_decoder dec(7, 8, callback);
|
||||
|
||||
sleep(3000);
|
||||
|
||||
dec.re_cancel();
|
||||
|
||||
gpioTerminate();
|
||||
}
|
||||
|
3
pigpio-master/EXAMPLES/CPP/WIEGAND_CODE/README
Normal file
3
pigpio-master/EXAMPLES/CPP/WIEGAND_CODE/README
Normal file
@@ -0,0 +1,3 @@
|
||||
Class to decode a Wiegand code.
|
||||
|
||||
Follow the instructions in the test file to build and run.
|
40
pigpio-master/EXAMPLES/CPP/WIEGAND_CODE/test_wiegand.cpp
Normal file
40
pigpio-master/EXAMPLES/CPP/WIEGAND_CODE/test_wiegand.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
#include <iostream>
|
||||
|
||||
#include <pigpio.h>
|
||||
|
||||
#include "wiegand.hpp"
|
||||
|
||||
/*
|
||||
|
||||
REQUIRES
|
||||
|
||||
Wiegand contacts 0 and 1 connected to separate gpios.
|
||||
|
||||
TO BUILD
|
||||
|
||||
g++ -o wiegand_cpp test_wiegand.cpp wiegand.cpp -lpigpio -lrt
|
||||
|
||||
TO RUN
|
||||
|
||||
sudo ./wiegand_cpp
|
||||
|
||||
*/
|
||||
|
||||
void callback(int bits, uint32_t value)
|
||||
{
|
||||
std::cout << "bits=" << bits << " value=" << value << std::endl;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (gpioInitialise() < 0) return 1;
|
||||
|
||||
Wiegand dec(14, 15, callback);
|
||||
|
||||
sleep(300);
|
||||
|
||||
dec.cancel();
|
||||
|
||||
gpioTerminate();
|
||||
}
|
||||
|
116
pigpio-master/EXAMPLES/CPP/WIEGAND_CODE/wiegand.cpp
Normal file
116
pigpio-master/EXAMPLES/CPP/WIEGAND_CODE/wiegand.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
#include <pigpio.h>
|
||||
|
||||
#include "wiegand.hpp"
|
||||
|
||||
Wiegand::Wiegand(int gpio_0, int gpio_1, WiegandCB_t callback, int timeout)
|
||||
{
|
||||
/*
|
||||
Instantiate with the gpio for 0 (green wire), the gpio for 1
|
||||
(white wire), the callback function, and the bit timeout in
|
||||
milliseconds which indicates the end of a code.
|
||||
|
||||
The callback is passed the code length in bits and the value.
|
||||
*/
|
||||
|
||||
mygpio_0 = gpio_0;
|
||||
mygpio_1 = gpio_1;
|
||||
|
||||
mycallback = callback;
|
||||
|
||||
mytimeout = timeout;
|
||||
|
||||
in_code = 0;
|
||||
|
||||
gpioSetMode(gpio_0, PI_INPUT);
|
||||
gpioSetMode(gpio_1, PI_INPUT);
|
||||
|
||||
gpioSetPullUpDown(gpio_0, PI_PUD_UP);
|
||||
gpioSetPullUpDown(gpio_1, PI_PUD_UP);
|
||||
|
||||
gpioSetAlertFuncEx(gpio_0, _cbEx, this);
|
||||
gpioSetAlertFuncEx(gpio_1, _cbEx, this);
|
||||
}
|
||||
|
||||
void Wiegand::_cb(int gpio, int level, uint32_t tick)
|
||||
{
|
||||
/*
|
||||
Accumulate bits until both gpios 0 and 1 timeout.
|
||||
*/
|
||||
|
||||
if (level == 0) /* a falling edge indicates a new bit */
|
||||
{
|
||||
if (!in_code)
|
||||
{
|
||||
bits = 1;
|
||||
num = 0;
|
||||
|
||||
in_code = 1;
|
||||
code_timeout = 0;
|
||||
|
||||
gpioSetWatchdog(mygpio_0, mytimeout);
|
||||
gpioSetWatchdog(mygpio_1, mytimeout);
|
||||
}
|
||||
else
|
||||
{
|
||||
bits++;
|
||||
num <<= 1;
|
||||
}
|
||||
|
||||
if (gpio == mygpio_0)
|
||||
{
|
||||
code_timeout &= 2; /* clear gpio 0 timeout */
|
||||
}
|
||||
else
|
||||
{
|
||||
code_timeout &= 1; /* clear gpio 1 timeout */
|
||||
num |= 1;
|
||||
}
|
||||
}
|
||||
else if (level == PI_TIMEOUT)
|
||||
{
|
||||
if (in_code)
|
||||
{
|
||||
if (gpio == mygpio_0)
|
||||
{
|
||||
code_timeout |= 1; /* timeout gpio 0 */
|
||||
}
|
||||
else
|
||||
{
|
||||
code_timeout |= 2; /* timeout gpio 1 */
|
||||
}
|
||||
|
||||
if (code_timeout == 3) /* both gpios timed out */
|
||||
{
|
||||
gpioSetWatchdog(mygpio_0, 0);
|
||||
gpioSetWatchdog(mygpio_1, 0);
|
||||
|
||||
in_code = 0;
|
||||
|
||||
(mycallback)(bits, num);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Wiegand::_cbEx(int gpio, int level, uint32_t tick, void *user)
|
||||
{
|
||||
/*
|
||||
Need a static callback to link with C.
|
||||
*/
|
||||
|
||||
Wiegand *mySelf = (Wiegand *) user;
|
||||
|
||||
mySelf->_cb(gpio, level, tick); /* Call the instance callback. */
|
||||
}
|
||||
|
||||
|
||||
void Wiegand::cancel(void)
|
||||
{
|
||||
/*
|
||||
Cancel the Wiegand decoder.
|
||||
*/
|
||||
|
||||
gpioSetAlertFuncEx(mygpio_0, 0, this);
|
||||
gpioSetAlertFuncEx(mygpio_1, 0, this);
|
||||
}
|
||||
|
43
pigpio-master/EXAMPLES/CPP/WIEGAND_CODE/wiegand.hpp
Normal file
43
pigpio-master/EXAMPLES/CPP/WIEGAND_CODE/wiegand.hpp
Normal file
@@ -0,0 +1,43 @@
|
||||
#ifndef WIEGAND_HPP
|
||||
#define WIEGAND_HPP
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef void (*WiegandCB_t)(int, uint32_t);
|
||||
|
||||
class Wiegand
|
||||
{
|
||||
int mygpio_0, mygpio_1, mytimeout, in_code, bits;
|
||||
|
||||
WiegandCB_t mycallback;
|
||||
|
||||
uint32_t num;
|
||||
|
||||
uint32_t code_timeout;
|
||||
|
||||
void _cb(int gpio, int level, uint32_t tick);
|
||||
|
||||
/* Need a static callback to link with C. */
|
||||
static void _cbEx(int gpio, int level, uint32_t tick, void *user);
|
||||
|
||||
public:
|
||||
|
||||
Wiegand(int gpio_0, int gpio_1, WiegandCB_t callback, int timeout=5);
|
||||
/*
|
||||
This function establishes a Wiegand decoder on gpio_0 and gpio_1.
|
||||
|
||||
A gap of timeout milliseconds without a new bit indicates
|
||||
the end of a code.
|
||||
|
||||
When the code is ended the callback function is called with the code
|
||||
bit length and value.
|
||||
*/
|
||||
|
||||
void cancel(void);
|
||||
/*
|
||||
This function releases the resources used by the decoder.
|
||||
*/
|
||||
};
|
||||
|
||||
#endif
|
||||
|
2
pigpio-master/EXAMPLES/Python/DHT11_SENSOR/README
Normal file
2
pigpio-master/EXAMPLES/Python/DHT11_SENSOR/README
Normal file
@@ -0,0 +1,2 @@
|
||||
Class to read the relative humidity and temperature from a DHT11 sensor.
|
||||
It implements the iterator python protocol.
|
163
pigpio-master/EXAMPLES/Python/DHT11_SENSOR/dht11.py
Normal file
163
pigpio-master/EXAMPLES/Python/DHT11_SENSOR/dht11.py
Normal file
@@ -0,0 +1,163 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||
|
||||
import time
|
||||
import pigpio
|
||||
|
||||
|
||||
class DHT11(object):
|
||||
"""
|
||||
The DHT11 class is a stripped version of the DHT22 sensor code by joan2937.
|
||||
You can find the initial implementation here:
|
||||
- https://github.com/srounet/pigpio/tree/master/EXAMPLES/Python/DHT22_AM2302_SENSOR
|
||||
|
||||
example code:
|
||||
>>> pi = pigpio.pi()
|
||||
>>> sensor = DHT11(pi, 4) # 4 is the data GPIO pin connected to your sensor
|
||||
>>> for response in sensor:
|
||||
.... print("Temperature: {}".format(response['temperature']))
|
||||
.... print("Humidity: {}".format(response['humidity']))
|
||||
"""
|
||||
|
||||
def __init__(self, pi, gpio):
|
||||
"""
|
||||
pi (pigpio): an instance of pigpio
|
||||
gpio (int): gpio pin number
|
||||
"""
|
||||
self.pi = pi
|
||||
self.gpio = gpio
|
||||
self.high_tick = 0
|
||||
self.bit = 40
|
||||
self.temperature = 0
|
||||
self.humidity = 0
|
||||
self.either_edge_cb = None
|
||||
self.setup()
|
||||
|
||||
def setup(self):
|
||||
"""
|
||||
Clears the internal gpio pull-up/down resistor.
|
||||
Kills any watchdogs.
|
||||
"""
|
||||
self.pi.set_pull_up_down(self.gpio, pigpio.PUD_OFF)
|
||||
self.pi.set_watchdog(self.gpio, 0)
|
||||
self.register_callbacks()
|
||||
|
||||
def register_callbacks(self):
|
||||
"""
|
||||
Monitors RISING_EDGE changes using callback.
|
||||
"""
|
||||
self.either_edge_cb = self.pi.callback(
|
||||
self.gpio,
|
||||
pigpio.EITHER_EDGE,
|
||||
self.either_edge_callback
|
||||
)
|
||||
|
||||
def either_edge_callback(self, gpio, level, tick):
|
||||
"""
|
||||
Either Edge callbacks, called each time the gpio edge changes.
|
||||
Accumulate the 40 data bits from the dht11 sensor.
|
||||
"""
|
||||
level_handlers = {
|
||||
pigpio.FALLING_EDGE: self._edge_FALL,
|
||||
pigpio.RISING_EDGE: self._edge_RISE,
|
||||
pigpio.EITHER_EDGE: self._edge_EITHER
|
||||
}
|
||||
handler = level_handlers[level]
|
||||
diff = pigpio.tickDiff(self.high_tick, tick)
|
||||
handler(tick, diff)
|
||||
|
||||
def _edge_RISE(self, tick, diff):
|
||||
"""
|
||||
Handle Rise signal.
|
||||
"""
|
||||
val = 0
|
||||
if diff >= 50:
|
||||
val = 1
|
||||
if diff >= 200: # Bad bit?
|
||||
self.checksum = 256 # Force bad checksum
|
||||
|
||||
if self.bit >= 40: # Message complete
|
||||
self.bit = 40
|
||||
elif self.bit >= 32: # In checksum byte
|
||||
self.checksum = (self.checksum << 1) + val
|
||||
if self.bit == 39:
|
||||
# 40th bit received
|
||||
self.pi.set_watchdog(self.gpio, 0)
|
||||
total = self.humidity + self.temperature
|
||||
# is checksum ok ?
|
||||
if not (total & 255) == self.checksum:
|
||||
raise
|
||||
elif 16 <= self.bit < 24: # in temperature byte
|
||||
self.temperature = (self.temperature << 1) + val
|
||||
elif 0 <= self.bit < 8: # in humidity byte
|
||||
self.humidity = (self.humidity << 1) + val
|
||||
else: # skip header bits
|
||||
pass
|
||||
self.bit += 1
|
||||
|
||||
def _edge_FALL(self, tick, diff):
|
||||
"""
|
||||
Handle Fall signal.
|
||||
"""
|
||||
self.high_tick = tick
|
||||
if diff <= 250000:
|
||||
return
|
||||
self.bit = -2
|
||||
self.checksum = 0
|
||||
self.temperature = 0
|
||||
self.humidity = 0
|
||||
|
||||
def _edge_EITHER(self, tick, diff):
|
||||
"""
|
||||
Handle Either signal.
|
||||
"""
|
||||
self.pi.set_watchdog(self.gpio, 0)
|
||||
|
||||
def read(self):
|
||||
"""
|
||||
Start reading over DHT11 sensor.
|
||||
"""
|
||||
self.pi.write(self.gpio, pigpio.LOW)
|
||||
time.sleep(0.017) # 17 ms
|
||||
self.pi.set_mode(self.gpio, pigpio.INPUT)
|
||||
self.pi.set_watchdog(self.gpio, 200)
|
||||
time.sleep(0.2)
|
||||
|
||||
def close(self):
|
||||
"""
|
||||
Stop reading sensor, remove callbacks.
|
||||
"""
|
||||
self.pi.set_watchdog(self.gpio, 0)
|
||||
if self.either_edge_cb:
|
||||
self.either_edge_cb.cancel()
|
||||
self.either_edge_cb = None
|
||||
|
||||
def __iter__(self):
|
||||
"""
|
||||
Support the iterator protocol.
|
||||
"""
|
||||
return self
|
||||
|
||||
def next(self):
|
||||
"""
|
||||
Call the read method and return temperature and humidity informations.
|
||||
"""
|
||||
self.read()
|
||||
response = {
|
||||
'humidity': self.humidity,
|
||||
'temperature': self.temperature
|
||||
}
|
||||
return response
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
pi = pigpio.pi()
|
||||
sensor = DHT11(pi, 4)
|
||||
for d in sensor:
|
||||
print("temperature: {}".format(d['temperature']))
|
||||
print("humidity: {}".format(d['humidity']))
|
||||
time.sleep(1)
|
||||
sensor.close()
|
||||
|
283
pigpio-master/EXAMPLES/Python/DHT22_AM2302_SENSOR/DHT22.py
Normal file
283
pigpio-master/EXAMPLES/Python/DHT22_AM2302_SENSOR/DHT22.py
Normal file
@@ -0,0 +1,283 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# 2014-07-11 DHT22.py
|
||||
|
||||
import time
|
||||
import atexit
|
||||
|
||||
import pigpio
|
||||
|
||||
class sensor:
|
||||
"""
|
||||
A class to read relative humidity and temperature from the
|
||||
DHT22 sensor. The sensor is also known as the AM2302.
|
||||
|
||||
The sensor can be powered from the Pi 3V3 or the Pi 5V rail.
|
||||
|
||||
Powering from the 3V3 rail is simpler and safer. You may need
|
||||
to power from 5V if the sensor is connected via a long cable.
|
||||
|
||||
For 3V3 operation connect pin 1 to 3V3 and pin 4 to ground.
|
||||
|
||||
Connect pin 2 to a gpio.
|
||||
|
||||
For 5V operation connect pin 1 to 5V and pin 4 to ground.
|
||||
|
||||
The following pin 2 connection works for me. Use at YOUR OWN RISK.
|
||||
|
||||
5V--5K_resistor--+--10K_resistor--Ground
|
||||
|
|
||||
DHT22 pin 2 -----+
|
||||
|
|
||||
gpio ------------+
|
||||
"""
|
||||
|
||||
def __init__(self, pi, gpio, LED=None, power=None):
|
||||
"""
|
||||
Instantiate with the Pi and gpio to which the DHT22 output
|
||||
pin is connected.
|
||||
|
||||
Optionally a LED may be specified. This will be blinked for
|
||||
each successful reading.
|
||||
|
||||
Optionally a gpio used to power the sensor may be specified.
|
||||
This gpio will be set high to power the sensor. If the sensor
|
||||
locks it will be power cycled to restart the readings.
|
||||
|
||||
Taking readings more often than about once every two seconds will
|
||||
eventually cause the DHT22 to hang. A 3 second interval seems OK.
|
||||
"""
|
||||
|
||||
self.pi = pi
|
||||
self.gpio = gpio
|
||||
self.LED = LED
|
||||
self.power = power
|
||||
|
||||
if power is not None:
|
||||
pi.write(power, 1) # Switch sensor on.
|
||||
time.sleep(2)
|
||||
|
||||
self.powered = True
|
||||
|
||||
self.cb = None
|
||||
|
||||
atexit.register(self.cancel)
|
||||
|
||||
self.bad_CS = 0 # Bad checksum count.
|
||||
self.bad_SM = 0 # Short message count.
|
||||
self.bad_MM = 0 # Missing message count.
|
||||
self.bad_SR = 0 # Sensor reset count.
|
||||
|
||||
# Power cycle if timeout > MAX_TIMEOUTS.
|
||||
self.no_response = 0
|
||||
self.MAX_NO_RESPONSE = 2
|
||||
|
||||
self.rhum = -999
|
||||
self.temp = -999
|
||||
|
||||
self.tov = None
|
||||
|
||||
self.high_tick = 0
|
||||
self.bit = 40
|
||||
|
||||
pi.set_pull_up_down(gpio, pigpio.PUD_OFF)
|
||||
|
||||
pi.set_watchdog(gpio, 0) # Kill any watchdogs.
|
||||
|
||||
self.cb = pi.callback(gpio, pigpio.EITHER_EDGE, self._cb)
|
||||
|
||||
def _cb(self, gpio, level, tick):
|
||||
"""
|
||||
Accumulate the 40 data bits. Format into 5 bytes, humidity high,
|
||||
humidity low, temperature high, temperature low, checksum.
|
||||
"""
|
||||
diff = pigpio.tickDiff(self.high_tick, tick)
|
||||
|
||||
if level == 0:
|
||||
|
||||
# Edge length determines if bit is 1 or 0.
|
||||
|
||||
if diff >= 50:
|
||||
val = 1
|
||||
if diff >= 200: # Bad bit?
|
||||
self.CS = 256 # Force bad checksum.
|
||||
else:
|
||||
val = 0
|
||||
|
||||
if self.bit >= 40: # Message complete.
|
||||
self.bit = 40
|
||||
|
||||
elif self.bit >= 32: # In checksum byte.
|
||||
self.CS = (self.CS << 1) + val
|
||||
|
||||
if self.bit == 39:
|
||||
|
||||
# 40th bit received.
|
||||
|
||||
self.pi.set_watchdog(self.gpio, 0)
|
||||
|
||||
self.no_response = 0
|
||||
|
||||
total = self.hH + self.hL + self.tH + self.tL
|
||||
|
||||
if (total & 255) == self.CS: # Is checksum ok?
|
||||
|
||||
self.rhum = ((self.hH << 8) + self.hL) * 0.1
|
||||
|
||||
if self.tH & 128: # Negative temperature.
|
||||
mult = -0.1
|
||||
self.tH = self.tH & 127
|
||||
else:
|
||||
mult = 0.1
|
||||
|
||||
self.temp = ((self.tH << 8) + self.tL) * mult
|
||||
|
||||
self.tov = time.time()
|
||||
|
||||
if self.LED is not None:
|
||||
self.pi.write(self.LED, 0)
|
||||
|
||||
else:
|
||||
|
||||
self.bad_CS += 1
|
||||
|
||||
elif self.bit >= 24: # in temp low byte
|
||||
self.tL = (self.tL << 1) + val
|
||||
|
||||
elif self.bit >= 16: # in temp high byte
|
||||
self.tH = (self.tH << 1) + val
|
||||
|
||||
elif self.bit >= 8: # in humidity low byte
|
||||
self.hL = (self.hL << 1) + val
|
||||
|
||||
elif self.bit >= 0: # in humidity high byte
|
||||
self.hH = (self.hH << 1) + val
|
||||
|
||||
else: # header bits
|
||||
pass
|
||||
|
||||
self.bit += 1
|
||||
|
||||
elif level == 1:
|
||||
self.high_tick = tick
|
||||
if diff > 250000:
|
||||
self.bit = -2
|
||||
self.hH = 0
|
||||
self.hL = 0
|
||||
self.tH = 0
|
||||
self.tL = 0
|
||||
self.CS = 0
|
||||
|
||||
else: # level == pigpio.TIMEOUT:
|
||||
self.pi.set_watchdog(self.gpio, 0)
|
||||
if self.bit < 8: # Too few data bits received.
|
||||
self.bad_MM += 1 # Bump missing message count.
|
||||
self.no_response += 1
|
||||
if self.no_response > self.MAX_NO_RESPONSE:
|
||||
self.no_response = 0
|
||||
self.bad_SR += 1 # Bump sensor reset count.
|
||||
if self.power is not None:
|
||||
self.powered = False
|
||||
self.pi.write(self.power, 0)
|
||||
time.sleep(2)
|
||||
self.pi.write(self.power, 1)
|
||||
time.sleep(2)
|
||||
self.powered = True
|
||||
elif self.bit < 39: # Short message receieved.
|
||||
self.bad_SM += 1 # Bump short message count.
|
||||
self.no_response = 0
|
||||
|
||||
else: # Full message received.
|
||||
self.no_response = 0
|
||||
|
||||
def temperature(self):
|
||||
"""Return current temperature."""
|
||||
return self.temp
|
||||
|
||||
def humidity(self):
|
||||
"""Return current relative humidity."""
|
||||
return self.rhum
|
||||
|
||||
def staleness(self):
|
||||
"""Return time since measurement made."""
|
||||
if self.tov is not None:
|
||||
return time.time() - self.tov
|
||||
else:
|
||||
return -999
|
||||
|
||||
def bad_checksum(self):
|
||||
"""Return count of messages received with bad checksums."""
|
||||
return self.bad_CS
|
||||
|
||||
def short_message(self):
|
||||
"""Return count of short messages."""
|
||||
return self.bad_SM
|
||||
|
||||
def missing_message(self):
|
||||
"""Return count of missing messages."""
|
||||
return self.bad_MM
|
||||
|
||||
def sensor_resets(self):
|
||||
"""Return count of power cycles because of sensor hangs."""
|
||||
return self.bad_SR
|
||||
|
||||
def trigger(self):
|
||||
"""Trigger a new relative humidity and temperature reading."""
|
||||
if self.powered:
|
||||
if self.LED is not None:
|
||||
self.pi.write(self.LED, 1)
|
||||
|
||||
self.pi.write(self.gpio, pigpio.LOW)
|
||||
time.sleep(0.017) # 17 ms
|
||||
self.pi.set_mode(self.gpio, pigpio.INPUT)
|
||||
self.pi.set_watchdog(self.gpio, 200)
|
||||
|
||||
def cancel(self):
|
||||
"""Cancel the DHT22 sensor."""
|
||||
|
||||
self.pi.set_watchdog(self.gpio, 0)
|
||||
|
||||
if self.cb is not None:
|
||||
self.cb.cancel()
|
||||
self.cb = None
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
import time
|
||||
|
||||
import pigpio
|
||||
|
||||
import DHT22
|
||||
|
||||
# Intervals of about 2 seconds or less will eventually hang the DHT22.
|
||||
INTERVAL = 3
|
||||
|
||||
pi = pigpio.pi()
|
||||
|
||||
s = DHT22.sensor(pi, 22, LED=16, power=8)
|
||||
|
||||
r = 0
|
||||
|
||||
next_reading = time.time()
|
||||
|
||||
while True:
|
||||
|
||||
r += 1
|
||||
|
||||
s.trigger()
|
||||
|
||||
time.sleep(0.2)
|
||||
|
||||
print("{} {} {} {:3.2f} {} {} {} {}".format(
|
||||
r, s.humidity(), s.temperature(), s.staleness(),
|
||||
s.bad_checksum(), s.short_message(), s.missing_message(),
|
||||
s.sensor_resets()))
|
||||
|
||||
next_reading += INTERVAL
|
||||
|
||||
time.sleep(next_reading-time.time()) # Overall INTERVAL second polling.
|
||||
|
||||
s.cancel()
|
||||
|
||||
pi.stop()
|
||||
|
2
pigpio-master/EXAMPLES/Python/DHT22_AM2302_SENSOR/README
Normal file
2
pigpio-master/EXAMPLES/Python/DHT22_AM2302_SENSOR/README
Normal file
@@ -0,0 +1,2 @@
|
||||
Class to read the relative humidity and temperature from a DHT22/AM2302 sensor.
|
||||
|
2
pigpio-master/EXAMPLES/Python/GPIO_STATUS/README
Normal file
2
pigpio-master/EXAMPLES/Python/GPIO_STATUS/README
Normal file
@@ -0,0 +1,2 @@
|
||||
Script to display the status of gpios 0-31.
|
||||
|
65
pigpio-master/EXAMPLES/Python/GPIO_STATUS/gpio_status.py
Normal file
65
pigpio-master/EXAMPLES/Python/GPIO_STATUS/gpio_status.py
Normal file
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import time
|
||||
import curses
|
||||
import atexit
|
||||
import sys
|
||||
|
||||
import pigpio
|
||||
|
||||
GPIOS=32
|
||||
|
||||
MODES=["INPUT", "OUTPUT", "ALT5", "ALT4", "ALT0", "ALT1", "ALT2", "ALT3"]
|
||||
|
||||
def cleanup():
|
||||
curses.nocbreak()
|
||||
curses.echo()
|
||||
curses.endwin()
|
||||
pi.stop()
|
||||
|
||||
pi = pigpio.pi()
|
||||
if not pi.connected:
|
||||
sys.exit(1)
|
||||
|
||||
stdscr = curses.initscr()
|
||||
curses.noecho()
|
||||
curses.cbreak()
|
||||
|
||||
atexit.register(cleanup)
|
||||
|
||||
cb = []
|
||||
|
||||
for g in range(GPIOS):
|
||||
cb.append(pi.callback(g, pigpio.EITHER_EDGE))
|
||||
|
||||
# disable gpio 28 as the PCM clock is swamping the system
|
||||
|
||||
cb[28].cancel()
|
||||
|
||||
stdscr.nodelay(1)
|
||||
|
||||
stdscr.addstr(0, 23, "Status of gpios 0-31", curses.A_REVERSE)
|
||||
|
||||
while True:
|
||||
|
||||
for g in range(GPIOS):
|
||||
tally = cb[g].tally()
|
||||
mode = pi.get_mode(g)
|
||||
|
||||
col = (g // 11) * 25
|
||||
row = (g % 11) + 2
|
||||
|
||||
stdscr.addstr(row, col, "{:2}".format(g), curses.A_BOLD)
|
||||
|
||||
stdscr.addstr(
|
||||
"={} {:>6}: {:<10}".format(pi.read(g), MODES[mode], tally))
|
||||
|
||||
stdscr.refresh()
|
||||
|
||||
time.sleep(0.1)
|
||||
|
||||
c = stdscr.getch()
|
||||
|
||||
if c != curses.ERR:
|
||||
break
|
||||
|
2
pigpio-master/EXAMPLES/Python/HALL_EFFECT_SENSOR/README
Normal file
2
pigpio-master/EXAMPLES/Python/HALL_EFFECT_SENSOR/README
Normal file
@@ -0,0 +1,2 @@
|
||||
Program to show status changes for a Hall effect sensor.
|
||||
|
32
pigpio-master/EXAMPLES/Python/HALL_EFFECT_SENSOR/hall.py
Normal file
32
pigpio-master/EXAMPLES/Python/HALL_EFFECT_SENSOR/hall.py
Normal file
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import time
|
||||
|
||||
import pigpio
|
||||
|
||||
#
|
||||
# OH3144E or equivalent Hall effect sensor
|
||||
#
|
||||
# Pin 1 - 5V
|
||||
# Pin 2 - Ground
|
||||
# Pin 3 - gpio (here P1-8, gpio 14, TXD is used)
|
||||
#
|
||||
# The internal gpio pull-up is enabled so that the sensor
|
||||
# normally reads high. It reads low when a magnet is close.
|
||||
#
|
||||
|
||||
HALL=14
|
||||
|
||||
pi = pigpio.pi() # connect to local Pi
|
||||
|
||||
pi.set_mode(HALL, pigpio.INPUT)
|
||||
pi.set_pull_up_down(HALL, pigpio.PUD_UP)
|
||||
|
||||
start = time.time()
|
||||
|
||||
while (time.time() - start) < 60:
|
||||
print("Hall = {}".format(pi.read(HALL)))
|
||||
time.sleep(0.2)
|
||||
|
||||
pi.stop()
|
||||
|
163
pigpio-master/EXAMPLES/Python/I2C_SNIFFER/I2C_sniffer.py
Normal file
163
pigpio-master/EXAMPLES/Python/I2C_SNIFFER/I2C_sniffer.py
Normal file
@@ -0,0 +1,163 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import time
|
||||
|
||||
import pigpio
|
||||
|
||||
class sniffer:
|
||||
"""
|
||||
A class to passively monitor activity on an I2C bus. This should
|
||||
work for an I2C bus running at 100kbps or less. You are unlikely
|
||||
to get any usable results for a bus running any faster.
|
||||
"""
|
||||
|
||||
def __init__(self, pi, SCL, SDA, set_as_inputs=True):
|
||||
"""
|
||||
Instantiate with the Pi and the gpios for the I2C clock
|
||||
and data lines.
|
||||
|
||||
If you are monitoring one of the Raspberry Pi buses you
|
||||
must set set_as_inputs to False so that they remain in
|
||||
I2C mode.
|
||||
|
||||
The pigpio daemon should have been started with a higher
|
||||
than default sample rate.
|
||||
|
||||
For an I2C bus rate of 100Kbps sudo pigpiod -s 2 should work.
|
||||
|
||||
A message is printed for each I2C transaction formatted with
|
||||
"[" for the START
|
||||
"XX" two hex characters for each data byte
|
||||
"+" if the data is ACKd, "-" if the data is NACKd
|
||||
"]" for the STOP
|
||||
|
||||
E.g. Reading the X, Y, Z values from an ADXL345 gives:
|
||||
|
||||
[A6+32+]
|
||||
[A7+01+FF+F2+FF+06+00-]
|
||||
"""
|
||||
|
||||
self.pi = pi
|
||||
self.gSCL = SCL
|
||||
self.gSDA = SDA
|
||||
|
||||
self.FALLING = 0
|
||||
self.RISING = 1
|
||||
self.STEADY = 2
|
||||
|
||||
self.in_data = False
|
||||
self.byte = 0
|
||||
self.bit = 0
|
||||
self.oldSCL = 1
|
||||
self.oldSDA = 1
|
||||
|
||||
self.transact = ""
|
||||
|
||||
if set_as_inputs:
|
||||
self.pi.set_mode(SCL, pigpio.INPUT)
|
||||
self.pi.set_mode(SDA, pigpio.INPUT)
|
||||
|
||||
self.cbA = self.pi.callback(SCL, pigpio.EITHER_EDGE, self._cb)
|
||||
self.cbB = self.pi.callback(SDA, pigpio.EITHER_EDGE, self._cb)
|
||||
|
||||
def _parse(self, SCL, SDA):
|
||||
"""
|
||||
Accumulate all the data between START and STOP conditions
|
||||
into a string and output when STOP is detected.
|
||||
"""
|
||||
|
||||
if SCL != self.oldSCL:
|
||||
self.oldSCL = SCL
|
||||
if SCL:
|
||||
xSCL = self.RISING
|
||||
else:
|
||||
xSCL = self.FALLING
|
||||
else:
|
||||
xSCL = self.STEADY
|
||||
|
||||
if SDA != self.oldSDA:
|
||||
self.oldSDA = SDA
|
||||
if SDA:
|
||||
xSDA = self.RISING
|
||||
else:
|
||||
xSDA = self.FALLING
|
||||
else:
|
||||
xSDA = self.STEADY
|
||||
|
||||
if xSCL == self.RISING:
|
||||
if self.in_data:
|
||||
if self.bit < 8:
|
||||
self.byte = (self.byte << 1) | SDA
|
||||
self.bit += 1
|
||||
else:
|
||||
self.transact += '{:02X}'.format(self.byte)
|
||||
if SDA:
|
||||
self.transact += '-'
|
||||
else:
|
||||
self.transact += '+'
|
||||
self.bit = 0
|
||||
self.byte = 0
|
||||
|
||||
elif xSCL == self.STEADY:
|
||||
|
||||
if xSDA == self.RISING:
|
||||
if SCL:
|
||||
self.in_data = False
|
||||
self.byte = 0
|
||||
self.bit = 0
|
||||
self.transact += ']' # STOP
|
||||
print (self.transact)
|
||||
self.transact = ""
|
||||
|
||||
if xSDA == self.FALLING:
|
||||
if SCL:
|
||||
self.in_data = True
|
||||
self.byte = 0
|
||||
self.bit = 0
|
||||
self.transact += '[' # START
|
||||
|
||||
def _cb(self, gpio, level, tick):
|
||||
"""
|
||||
Check which line has altered state (ignoring watchdogs) and
|
||||
call the parser with the new state.
|
||||
"""
|
||||
SCL = self.oldSCL
|
||||
SDA = self.oldSDA
|
||||
|
||||
if gpio == self.gSCL:
|
||||
if level == 0:
|
||||
SCL = 0
|
||||
elif level == 1:
|
||||
SCL = 1
|
||||
|
||||
if gpio == self.gSDA:
|
||||
if level == 0:
|
||||
SDA = 0
|
||||
elif level == 1:
|
||||
SDA = 1
|
||||
|
||||
self._parse(SCL, SDA)
|
||||
|
||||
def cancel(self):
|
||||
"""Cancel the I2C callbacks."""
|
||||
self.cbA.cancel()
|
||||
self.cbB.cancel()
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
import time
|
||||
|
||||
import pigpio
|
||||
|
||||
import I2C_sniffer
|
||||
|
||||
pi = pigpio.pi()
|
||||
|
||||
s = I2C_sniffer.sniffer(pi, 1, 0, False) # leave gpios 1/0 in I2C mode
|
||||
|
||||
time.sleep(60000)
|
||||
|
||||
s.cancel()
|
||||
|
||||
pi.stop()
|
||||
|
2
pigpio-master/EXAMPLES/Python/I2C_SNIFFER/README
Normal file
2
pigpio-master/EXAMPLES/Python/I2C_SNIFFER/README
Normal file
@@ -0,0 +1,2 @@
|
||||
A program to passively sniff I2C transactions (100kHz bus maximum) and display the results.
|
||||
|
2
pigpio-master/EXAMPLES/Python/IR_RECEIVER/README
Normal file
2
pigpio-master/EXAMPLES/Python/IR_RECEIVER/README
Normal file
@@ -0,0 +1,2 @@
|
||||
Class to hash a code from an IR receiver (reading an IR remote control).
|
||||
|
165
pigpio-master/EXAMPLES/Python/IR_RECEIVER/ir_hasher.py
Normal file
165
pigpio-master/EXAMPLES/Python/IR_RECEIVER/ir_hasher.py
Normal file
@@ -0,0 +1,165 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import pigpio
|
||||
|
||||
class hasher:
|
||||
|
||||
"""
|
||||
This class forms a hash over the IR pulses generated by an
|
||||
IR remote.
|
||||
|
||||
The remote key press is not converted into a code in the manner of
|
||||
the lirc module. No attempt is made to decode the type of protocol
|
||||
used by the remote. The hash is likely to be unique for different
|
||||
keys and different remotes but this is not guaranteed.
|
||||
|
||||
This hashing process works for some remotes/protocols but not for
|
||||
others. The only way to find out if it works for one or more of
|
||||
your remotes is to try it and see.
|
||||
|
||||
EXAMPLE CODE
|
||||
|
||||
#!/usr/bin/env python
|
||||
|
||||
import time
|
||||
import pigpio
|
||||
import ir_hasher
|
||||
|
||||
def callback(hash):
|
||||
print("hash={}".format(hash));
|
||||
|
||||
pi = pigpio.pi()
|
||||
|
||||
ir = ir_hasher.hasher(pi, 7, callback, 5)
|
||||
|
||||
print("ctrl c to exit");
|
||||
|
||||
time.sleep(300)
|
||||
|
||||
pi.stop()
|
||||
"""
|
||||
|
||||
def __init__(self, pi, gpio, callback, timeout=5):
|
||||
|
||||
"""
|
||||
Initialises an IR remote hasher on a pi's gpio. A gap of timeout
|
||||
milliseconds indicates the end of the remote key press.
|
||||
"""
|
||||
|
||||
self.pi = pi
|
||||
self.gpio = gpio
|
||||
self.code_timeout = timeout
|
||||
self.callback = callback
|
||||
|
||||
self.in_code = False
|
||||
|
||||
pi.set_mode(gpio, pigpio.INPUT)
|
||||
|
||||
self.cb = pi.callback(gpio, pigpio.EITHER_EDGE, self._cb)
|
||||
|
||||
def _hash(self, old_val, new_val):
|
||||
|
||||
if new_val < (old_val * 0.60):
|
||||
val = 13
|
||||
elif old_val < (new_val * 0.60):
|
||||
val = 23
|
||||
else:
|
||||
val = 2
|
||||
|
||||
self.hash_val = self.hash_val ^ val
|
||||
self.hash_val *= 16777619 # FNV_PRIME_32
|
||||
self.hash_val = self.hash_val & ((1<<32)-1)
|
||||
|
||||
def _cb(self, gpio, level, tick):
|
||||
|
||||
if level != pigpio.TIMEOUT:
|
||||
|
||||
if self.in_code == False:
|
||||
|
||||
self.in_code = True
|
||||
|
||||
self.pi.set_watchdog(self.gpio, self.code_timeout)
|
||||
|
||||
self.hash_val = 2166136261 # FNV_BASIS_32
|
||||
|
||||
self.edges = 1
|
||||
|
||||
self.t1 = None
|
||||
self.t2 = None
|
||||
self.t3 = None
|
||||
self.t4 = tick
|
||||
|
||||
else:
|
||||
|
||||
self.edges += 1
|
||||
|
||||
self.t1 = self.t2
|
||||
self.t2 = self.t3
|
||||
self.t3 = self.t4
|
||||
self.t4 = tick
|
||||
|
||||
if self.t1 is not None:
|
||||
|
||||
d1 = pigpio.tickDiff(self.t1,self.t2)
|
||||
d2 = pigpio.tickDiff(self.t3,self.t4)
|
||||
|
||||
self._hash(d1, d2)
|
||||
|
||||
else:
|
||||
|
||||
if self.in_code:
|
||||
|
||||
self.in_code = False
|
||||
|
||||
self.pi.set_watchdog(self.gpio, 0)
|
||||
|
||||
if self.edges > 12:
|
||||
|
||||
self.callback(self.hash_val)
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
import time
|
||||
import pigpio
|
||||
import ir_hasher
|
||||
|
||||
hashes = {
|
||||
142650387: '2', 244341844: 'menu', 262513468: 'vol-',
|
||||
272048826: '5', 345069212: '6', 363685443: 'prev.ch',
|
||||
434191356: '1', 492745084: 'OK', 549497027: 'mute',
|
||||
603729091: 'text', 646476378: 'chan-', 832916949: 'home',
|
||||
923778138: 'power', 938165610: 'power', 953243510: 'forward',
|
||||
1009731980:'1', 1018231875:'TV', 1142888517:'c-up',
|
||||
1151589683:'chan+', 1344018636:'OK', 1348032067:'chan+',
|
||||
1367109971:'prev.ch', 1370712102:'c-left', 1438405361:'rewind',
|
||||
1452589043:'pause', 1518578730:'chan-', 1554432645:'8',
|
||||
1583569525:'0', 1629745313:'rewind', 1666513749:'record',
|
||||
1677653754:'c-down', 1825951717:'c-right', 1852412236:'6',
|
||||
1894279468:'9', 1904895749:'vol+', 1941947509:'ff',
|
||||
2076573637:'0', 2104823531:'back', 2141641957:'home',
|
||||
2160787557:'record', 2398525299:'7', 2468117013:'8',
|
||||
2476712746:'play', 2574308838:'forward', 2577952149:'4',
|
||||
2706654902:'stop', 2829002741:'c-up', 2956097083:'back',
|
||||
3112717386:'5', 3263244773:'ff', 3286088195:'pause',
|
||||
3363767978:'c-down', 3468076364:'vol-', 3491068358:'stop',
|
||||
3593710134:'c-left', 3708232515:'3', 3734134565:'back',
|
||||
3766109107:'TV', 3798010010:'play', 3869937700:'menu',
|
||||
3872715523:'7', 3885097091:'2', 3895301587:'text',
|
||||
3931058739:'mute', 3983900853:'c-right', 4032250885:'4',
|
||||
4041913909:'vol+', 4207017660:'9', 4227138677:'back',
|
||||
4294027955:'3'}
|
||||
|
||||
def callback(hash):
|
||||
if hash in hashes:
|
||||
print("key={} hash={}".format(hashes[hash], hash));
|
||||
|
||||
pi = pigpio.pi()
|
||||
|
||||
ir = ir_hasher.hasher(pi, 7, callback, 5)
|
||||
|
||||
print("ctrl c to exit");
|
||||
|
||||
time.sleep(300)
|
||||
|
||||
pi.stop()
|
||||
|
2
pigpio-master/EXAMPLES/Python/MORSE_CODE/README
Normal file
2
pigpio-master/EXAMPLES/Python/MORSE_CODE/README
Normal file
@@ -0,0 +1,2 @@
|
||||
Script to transmit the morse code corresponding to a text string.
|
||||
|
72
pigpio-master/EXAMPLES/Python/MORSE_CODE/morse_code.py
Normal file
72
pigpio-master/EXAMPLES/Python/MORSE_CODE/morse_code.py
Normal file
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import pigpio
|
||||
|
||||
morse={
|
||||
'a':'.-' , 'b':'-...' , 'c':'-.-.' , 'd':'-..' , 'e':'.' ,
|
||||
'f':'..-.' , 'g':'--.' , 'h':'....' , 'i':'..' , 'j':'.---' ,
|
||||
'k':'-.-' , 'l':'.-..' , 'm':'--' , 'n':'-.' , 'o':'---' ,
|
||||
'p':'.--.' , 'q':'--.-' , 'r':'.-.' , 's':'...' , 't':'-' ,
|
||||
'u':'..-' , 'v':'...-' , 'w':'.--' , 'x':'-..-' , 'y':'-.--' ,
|
||||
'z':'--..' , '1':'.----', '2':'..---', '3':'...--', '4':'....-',
|
||||
'5':'.....', '6':'-....', '7':'--...', '8':'---..', '9':'----.',
|
||||
'0':'-----'}
|
||||
|
||||
GPIO=22
|
||||
|
||||
MICROS=100000
|
||||
|
||||
NONE=0
|
||||
|
||||
DASH=3
|
||||
DOT=1
|
||||
|
||||
GAP=1
|
||||
LETTER_GAP=3-GAP
|
||||
WORD_GAP=7-LETTER_GAP
|
||||
|
||||
def transmit_string(pi, gpio, str):
|
||||
|
||||
pi.wave_clear() # start a new waveform
|
||||
|
||||
wf=[]
|
||||
|
||||
for C in str:
|
||||
c=C.lower()
|
||||
print(c)
|
||||
if c in morse:
|
||||
k = morse[c]
|
||||
for x in k:
|
||||
|
||||
if x == '.':
|
||||
wf.append(pigpio.pulse(1<<gpio, NONE, DOT * MICROS))
|
||||
else:
|
||||
wf.append(pigpio.pulse(1<<gpio, NONE, DASH * MICROS))
|
||||
|
||||
wf.append(pigpio.pulse(NONE, 1<<gpio, GAP * MICROS))
|
||||
|
||||
wf.append(pigpio.pulse(NONE, 1<<gpio, LETTER_GAP * MICROS))
|
||||
|
||||
elif c == ' ':
|
||||
wf.append(pigpio.pulse(NONE, 1<<gpio, WORD_GAP * MICROS))
|
||||
|
||||
pi.wave_add_generic(wf)
|
||||
|
||||
pi.wave_tx_start()
|
||||
|
||||
pi = pigpio.pi()
|
||||
|
||||
pi.set_mode(GPIO, pigpio.OUTPUT)
|
||||
|
||||
transmit_string(pi, GPIO, "Now is the winter of our discontent")
|
||||
|
||||
while pi.wave_tx_busy():
|
||||
pass
|
||||
|
||||
transmit_string(pi, GPIO, "made glorious summer by this sun of York")
|
||||
|
||||
while pi.wave_tx_busy():
|
||||
pass
|
||||
|
||||
pi.stop()
|
||||
|
64
pigpio-master/EXAMPLES/Python/PCF8591_YL-40/PCF8591.py
Normal file
64
pigpio-master/EXAMPLES/Python/PCF8591_YL-40/PCF8591.py
Normal file
@@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# 2014-08-26 PCF8591.py
|
||||
|
||||
import time
|
||||
import curses
|
||||
|
||||
import pigpio
|
||||
|
||||
# sudo pigpiod
|
||||
# ./PCF8591.py
|
||||
|
||||
# Connect Pi 3V3 - VCC, Ground - Ground, SDA - SDA, SCL - SCL.
|
||||
|
||||
YL_40=0x48
|
||||
|
||||
pi = pigpio.pi() # Connect to local Pi.
|
||||
|
||||
handle = pi.i2c_open(1, YL_40, 0)
|
||||
|
||||
stdscr = curses.initscr()
|
||||
|
||||
curses.noecho()
|
||||
curses.cbreak()
|
||||
|
||||
aout = 0
|
||||
|
||||
stdscr.addstr(10, 0, "Brightness")
|
||||
stdscr.addstr(12, 0, "Temperature")
|
||||
stdscr.addstr(14, 0, "AOUT->AIN2")
|
||||
stdscr.addstr(16, 0, "Resistor")
|
||||
|
||||
stdscr.nodelay(1)
|
||||
|
||||
try:
|
||||
while True:
|
||||
|
||||
for a in range(0,4):
|
||||
aout = aout + 1
|
||||
pi.i2c_write_byte_data(handle, 0x40 | ((a+1) & 0x03), aout&0xFF)
|
||||
v = pi.i2c_read_byte(handle)
|
||||
hashes = v / 4
|
||||
spaces = 64 - hashes
|
||||
stdscr.addstr(10+a*2, 12, str(v) + ' ')
|
||||
stdscr.addstr(10+a*2, 16, '#' * hashes + ' ' * spaces )
|
||||
|
||||
stdscr.refresh()
|
||||
time.sleep(0.04)
|
||||
|
||||
c = stdscr.getch()
|
||||
|
||||
if c != curses.ERR:
|
||||
break
|
||||
|
||||
except:
|
||||
pass
|
||||
|
||||
curses.nocbreak()
|
||||
curses.echo()
|
||||
curses.endwin()
|
||||
|
||||
pi.i2c_close(handle)
|
||||
pi.stop()
|
||||
|
2
pigpio-master/EXAMPLES/Python/PCF8591_YL-40/README
Normal file
2
pigpio-master/EXAMPLES/Python/PCF8591_YL-40/README
Normal file
@@ -0,0 +1,2 @@
|
||||
Script to display readings from the (I2C) PCF8591.
|
||||
|
2
pigpio-master/EXAMPLES/Python/PIGPIO_BENCHMARK/README
Normal file
2
pigpio-master/EXAMPLES/Python/PIGPIO_BENCHMARK/README
Normal file
@@ -0,0 +1,2 @@
|
||||
Script to benchmark the pigpio Python module's performance.
|
||||
|
91
pigpio-master/EXAMPLES/Python/PIGPIO_BENCHMARK/bench_1.py
Normal file
91
pigpio-master/EXAMPLES/Python/PIGPIO_BENCHMARK/bench_1.py
Normal file
@@ -0,0 +1,91 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#
|
||||
# WARNING!
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
# #
|
||||
# Unless you know what you are doing don't run this script with anything #
|
||||
# connected to the gpios. You will CAUSE damage. #
|
||||
# #
|
||||
##############################################################################
|
||||
|
||||
#
|
||||
# WARNING!
|
||||
#
|
||||
|
||||
import time
|
||||
|
||||
import pigpio
|
||||
|
||||
delay = 30
|
||||
|
||||
class gpioTest:
|
||||
|
||||
def __init__(self, pi, gpio, edge, freq, duty):
|
||||
self.pi = pi
|
||||
self.gpio = gpio
|
||||
self.edge = edge
|
||||
self.freq = freq
|
||||
self.duty = duty
|
||||
self.calls = 0
|
||||
|
||||
def cb(self, g, t, l):
|
||||
self.calls = self.calls + 1
|
||||
# print g,t,l
|
||||
|
||||
def num(self):
|
||||
return self.calls
|
||||
|
||||
def start(self):
|
||||
self.pi.set_PWM_frequency(self.gpio, self.freq)
|
||||
self.pi.set_PWM_range(self.gpio, 25)
|
||||
self.pi.set_PWM_dutycycle(self.gpio, self.duty)
|
||||
self.n = self.pi.callback(self.gpio, self.edge, self.cb)
|
||||
|
||||
def stop(self):
|
||||
self.pi.set_PWM_dutycycle(self.gpio, 0)
|
||||
self.n.cancel()
|
||||
|
||||
pi = pigpio.pi()
|
||||
|
||||
t1 = gpioTest(pi, 4, pigpio.EITHER_EDGE, 4000, 1)
|
||||
t2 = gpioTest(pi, 7, pigpio.RISING_EDGE, 8000, 2)
|
||||
t3 = gpioTest(pi, 8, pigpio.FALLING_EDGE, 8000, 3)
|
||||
t4 = gpioTest(pi, 9, pigpio.EITHER_EDGE, 4000, 4)
|
||||
t5 = gpioTest(pi,10, pigpio.RISING_EDGE, 8000, 5)
|
||||
t6 = gpioTest(pi,11, pigpio.FALLING_EDGE, 8000, 6)
|
||||
t7 = gpioTest(pi,14, pigpio.EITHER_EDGE, 4000, 7)
|
||||
t8 = gpioTest(pi,15, pigpio.RISING_EDGE, 8000, 8)
|
||||
t9 = gpioTest(pi,17, pigpio.FALLING_EDGE, 8000, 9)
|
||||
t10 = gpioTest(pi,18, pigpio.EITHER_EDGE, 4000, 10)
|
||||
t11 = gpioTest(pi,22, pigpio.RISING_EDGE, 8000, 11)
|
||||
t12 = gpioTest(pi,23, pigpio.FALLING_EDGE, 8000, 12)
|
||||
t13 = gpioTest(pi,24, pigpio.EITHER_EDGE, 4000, 13)
|
||||
t14 = gpioTest(pi,25, pigpio.RISING_EDGE, 8000, 14)
|
||||
|
||||
# R1: 0 1 4 7 8 9 10 11 14 15 17 18 21 22 23 24 25
|
||||
# R2: 2 3 4 7 8 9 10 11 14 15 17 18 22 23 24 25 27 28 29 30 31
|
||||
|
||||
tests = [t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14]
|
||||
|
||||
for i in tests: i.start()
|
||||
|
||||
time.sleep(delay)
|
||||
|
||||
for i in tests: i.stop()
|
||||
|
||||
pi.stop()
|
||||
|
||||
tot = 0
|
||||
msg = ""
|
||||
|
||||
for i in tests:
|
||||
tot += i.num()
|
||||
msg += str(i.num()) + " "
|
||||
|
||||
print(msg)
|
||||
|
||||
print("eps={} ({}/{})".format(tot/delay, tot, delay))
|
||||
|
2
pigpio-master/EXAMPLES/Python/ROTARY_ENCODER/README
Normal file
2
pigpio-master/EXAMPLES/Python/ROTARY_ENCODER/README
Normal file
@@ -0,0 +1,2 @@
|
||||
Class to decode a mechanical rotary encoder.
|
||||
|
135
pigpio-master/EXAMPLES/Python/ROTARY_ENCODER/rotary_encoder.py
Normal file
135
pigpio-master/EXAMPLES/Python/ROTARY_ENCODER/rotary_encoder.py
Normal file
@@ -0,0 +1,135 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import pigpio
|
||||
|
||||
class decoder:
|
||||
|
||||
"""Class to decode mechanical rotary encoder pulses."""
|
||||
|
||||
def __init__(self, pi, gpioA, gpioB, callback):
|
||||
|
||||
"""
|
||||
Instantiate the class with the pi and gpios connected to
|
||||
rotary encoder contacts A and B. The common contact
|
||||
should be connected to ground. The callback is
|
||||
called when the rotary encoder is turned. It takes
|
||||
one parameter which is +1 for clockwise and -1 for
|
||||
counterclockwise.
|
||||
|
||||
EXAMPLE
|
||||
|
||||
import time
|
||||
import pigpio
|
||||
|
||||
import rotary_encoder
|
||||
|
||||
pos = 0
|
||||
|
||||
def callback(way):
|
||||
|
||||
global pos
|
||||
|
||||
pos += way
|
||||
|
||||
print("pos={}".format(pos))
|
||||
|
||||
pi = pigpio.pi()
|
||||
|
||||
decoder = rotary_encoder.decoder(pi, 7, 8, callback)
|
||||
|
||||
time.sleep(300)
|
||||
|
||||
decoder.cancel()
|
||||
|
||||
pi.stop()
|
||||
|
||||
"""
|
||||
|
||||
self.pi = pi
|
||||
self.gpioA = gpioA
|
||||
self.gpioB = gpioB
|
||||
self.callback = callback
|
||||
|
||||
self.levA = 0
|
||||
self.levB = 0
|
||||
|
||||
self.lastGpio = None
|
||||
|
||||
self.pi.set_mode(gpioA, pigpio.INPUT)
|
||||
self.pi.set_mode(gpioB, pigpio.INPUT)
|
||||
|
||||
self.pi.set_pull_up_down(gpioA, pigpio.PUD_UP)
|
||||
self.pi.set_pull_up_down(gpioB, pigpio.PUD_UP)
|
||||
|
||||
self.cbA = self.pi.callback(gpioA, pigpio.EITHER_EDGE, self._pulse)
|
||||
self.cbB = self.pi.callback(gpioB, pigpio.EITHER_EDGE, self._pulse)
|
||||
|
||||
def _pulse(self, gpio, level, tick):
|
||||
|
||||
"""
|
||||
Decode the rotary encoder pulse.
|
||||
|
||||
+---------+ +---------+ 0
|
||||
| | | |
|
||||
A | | | |
|
||||
| | | |
|
||||
+---------+ +---------+ +----- 1
|
||||
|
||||
+---------+ +---------+ 0
|
||||
| | | |
|
||||
B | | | |
|
||||
| | | |
|
||||
----+ +---------+ +---------+ 1
|
||||
"""
|
||||
|
||||
if gpio == self.gpioA:
|
||||
self.levA = level
|
||||
else:
|
||||
self.levB = level;
|
||||
|
||||
if gpio != self.lastGpio: # debounce
|
||||
self.lastGpio = gpio
|
||||
|
||||
if gpio == self.gpioA and level == 1:
|
||||
if self.levB == 1:
|
||||
self.callback(1)
|
||||
elif gpio == self.gpioB and level == 1:
|
||||
if self.levA == 1:
|
||||
self.callback(-1)
|
||||
|
||||
def cancel(self):
|
||||
|
||||
"""
|
||||
Cancel the rotary encoder decoder.
|
||||
"""
|
||||
|
||||
self.cbA.cancel()
|
||||
self.cbB.cancel()
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
import time
|
||||
import pigpio
|
||||
|
||||
import rotary_encoder
|
||||
|
||||
pos = 0
|
||||
|
||||
def callback(way):
|
||||
|
||||
global pos
|
||||
|
||||
pos += way
|
||||
|
||||
print("pos={}".format(pos))
|
||||
|
||||
pi = pigpio.pi()
|
||||
|
||||
decoder = rotary_encoder.decoder(pi, 7, 8, callback)
|
||||
|
||||
time.sleep(300)
|
||||
|
||||
decoder.cancel()
|
||||
|
||||
pi.stop()
|
||||
|
28
pigpio-master/EXAMPLES/Python/SENT_PROTOCOL/README.md
Normal file
28
pigpio-master/EXAMPLES/Python/SENT_PROTOCOL/README.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# Python Class for Reading Single Edge Nibble Transmission (SENT) using the Raspberry Pi
|
||||
|
||||
A full description of this Python script is described at [www.surfncircuits.com](https://surfncircuits.com) in the blog entry: [Implementing a Single Edge Nibble Transmission (SENT) protocol in Python for the Raspberry Pi Zero](https://surfncircuits.com/?p=3725)
|
||||
|
||||
|
||||
This python library will read a Raspberry Pi GPIO pin connected. Start the pigpiod daemon with one microsecond sampling to read SENT transmissions with three microsecond tick times.
|
||||
|
||||
## To start the daemon on Raspberry Pi
|
||||
- sudo pigpiod -s 1
|
||||
|
||||
## SENT packet frame summary
|
||||
|
||||
- Sync Pulse: 56 ticks
|
||||
- 4 bit Status and Message Pulse: 17-32 ticks
|
||||
- 4 bit (9:12) Data1 Field: 17-32 ticks
|
||||
- 4 bit (5:8) Data1 Field: 17-32 ticks
|
||||
- 4 bit (1:4) Data1 Field: 17-32 ticks
|
||||
- 4 bit (9-12) Data2 Field: 17-32 ticks
|
||||
- 4 bit (5-8) Data2 Field: 17-32 ticks
|
||||
- 4 bit (1-4) Data2 Field: 17-32 ticks
|
||||
- 4 bit CRC: 17-32 ticks
|
||||
|
||||
|
||||
## requirements
|
||||
[pigpiod](http://abyz.me.uk/rpi/pigpio/) library required
|
||||
|
||||
## To run the script for a signal attached to GPIO BCD 18 (pin 12)
|
||||
- python3 sent_READ.py
|
322
pigpio-master/EXAMPLES/Python/SENT_PROTOCOL/read_SENT.py
Normal file
322
pigpio-master/EXAMPLES/Python/SENT_PROTOCOL/read_SENT.py
Normal file
@@ -0,0 +1,322 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# read_PWM.py
|
||||
# Public Domain by mark smith, www.surfncircuits.com
|
||||
# blog:https://surfncircuits.com/2020/11/27/implementing-a-single-edge-nibble-transmission-sent-protocol-in-python-for-the-raspberry-pi-zero/
|
||||
|
||||
import time
|
||||
import pigpio # http://abyz.co.uk/rpi/pigpio/python.html
|
||||
import threading
|
||||
|
||||
class SENTReader:
|
||||
"""
|
||||
A class to read short Format SENT frames
|
||||
(see the LX3302A datasheet for a SENT reference from Microchip)
|
||||
(also using sent transmission mode where )
|
||||
from wikiPedia: The SAE J2716 SENT (Single Edge Nibble Transmission) protocol
|
||||
is a point-to-point scheme for transmitting signal values
|
||||
from a sensor to a controller. It is intended to allow for
|
||||
transmission of high resolution data with a low system cost.
|
||||
|
||||
Short sensor format:
|
||||
The first is the SYNC pulse (56 ticks)
|
||||
first Nibble : Status (4 bits)
|
||||
2nd NIbble : DAta1 (4 bits)
|
||||
3nd Nibble : Data2 (4 bits)
|
||||
4th Nibble : Data3 (4 bits)
|
||||
5th Nibble : Data1 (4 bits)
|
||||
6th Nibble : Data2 (4 bits)
|
||||
7th Nibble : Data3 (4 bits)
|
||||
8th Nibble : CRC (4 bits)
|
||||
"""
|
||||
def __init__(self, pi, gpio, Mode = 0):
|
||||
"""
|
||||
Instantiate with the Pi and gpio of the SENT signal
|
||||
to monitor.
|
||||
SENT mode = A0: Microchip LX3302A where the two 12 bit data values are identical. there are other modes
|
||||
|
||||
"""
|
||||
self.pi = pi
|
||||
self.gpio = gpio
|
||||
self.SENTMode = Mode
|
||||
|
||||
# the time that pulse goes high
|
||||
self._high_tick = 0
|
||||
# the period of the low tick
|
||||
self._low_tick = 0
|
||||
# the period of the pulse (total data)
|
||||
self._period = 0
|
||||
# the time the item was low during the period
|
||||
self._low = 0
|
||||
# the time the output was high during the period
|
||||
self._high = 0
|
||||
# setting initial value to 100
|
||||
self.syncTick = 100
|
||||
|
||||
|
||||
#keep track of the periods
|
||||
self.syncWidth = 0
|
||||
self.status = 0
|
||||
self.data1 = 0
|
||||
self.data2 = 0
|
||||
self.data3 = 0
|
||||
self.data4 = 0
|
||||
self.data5 = 0
|
||||
self.data6 = 0
|
||||
self.crc = 0
|
||||
#initize the sent frame . Need to use hex for data
|
||||
#self.frame = [0,0,0,'0x0','0x0','0x0','0x0','0x0','0x0',0]
|
||||
self.frame = [0,0,0,0,0,0,0,0,0,0]
|
||||
self.syncFound = False
|
||||
self.frameComplete = False
|
||||
self.nibble = 0
|
||||
self.numberFrames = 0
|
||||
self.SampleStopped = False
|
||||
|
||||
self.pi.set_mode(gpio, pigpio.INPUT)
|
||||
|
||||
#self._cb = pi.callback(gpio, pigpio.EITHER_EDGE, self._cbf)
|
||||
#sleep enougth to start reading SENT
|
||||
#time.sleep(0.05)
|
||||
|
||||
#start thread to sample the SENT property
|
||||
# this is needed for piGPIO sample of 1us and sensing the 3us
|
||||
self.OutputSampleThread = threading.Thread(target = self.SampleCallBack)
|
||||
self.OutputSampleThread.daemon = True
|
||||
self.OutputSampleThread.start()
|
||||
|
||||
#give time for thread to start capturing data
|
||||
time.sleep(.05)
|
||||
|
||||
|
||||
def SampleCallBack(self):
|
||||
|
||||
# this will run in a loop and sample the SENT path
|
||||
# this sampling is required when 1us sample rate for SENT 3us tick time
|
||||
while True:
|
||||
|
||||
self.SampleStopped = False
|
||||
self._cb = self.pi.callback(self.gpio, pigpio.EITHER_EDGE, self._cbf)
|
||||
# wait until sample stopped
|
||||
while self.SampleStopped == False:
|
||||
#do nothing
|
||||
time.sleep(.001)
|
||||
|
||||
# gives the callback time to cancel so we can start again.
|
||||
time.sleep(0.20)
|
||||
|
||||
def _cbf(self, gpio, level, tick):
|
||||
# depending on the system state set the tick times.
|
||||
# first look for sync pulse. this is found when duty ratio >90
|
||||
#print(pgio)
|
||||
#print("inside _cpf")
|
||||
#print(tick)
|
||||
if self.syncFound == False:
|
||||
if level == 1:
|
||||
self._high_tick = tick
|
||||
self._low = pigpio.tickDiff(self._low_tick,tick)
|
||||
elif level == 0:
|
||||
# this may be a syncpulse if the duty is 51/56
|
||||
self._period = pigpio.tickDiff(self._low_tick,tick)
|
||||
# not reset the self._low_tick
|
||||
self._low_tick = tick
|
||||
self._high = pigpio.tickDiff(self._high_tick,tick)
|
||||
# sync pulse is detected by finding duty ratio. 51/56
|
||||
# but also filter if period is > 90us*56 = 5040
|
||||
if (100*self._high/self._period) > 87 and (self._period<5100):
|
||||
self.syncFound = True
|
||||
self.syncWidth = self._high
|
||||
self.syncPeriod = self._period
|
||||
#self.syncTick = round(self.syncPeriod/56.0,2)
|
||||
self.syncTick = self.syncPeriod
|
||||
# reset the nibble to zero
|
||||
self.nibble = 0
|
||||
self.SampleStopped = False
|
||||
else:
|
||||
# now look for the nibble information for each nibble (8 Nibbles)
|
||||
if level == 1:
|
||||
self._high_tick = tick
|
||||
self._low = pigpio.tickDiff(self._low_tick,tick)
|
||||
elif level == 0:
|
||||
# This will be a data nibble
|
||||
self._period = pigpio.tickDiff(self._low_tick,tick)
|
||||
# not reset the self._low_tick
|
||||
self._low_tick = tick
|
||||
self._high = pigpio.tickDiff(self._high_tick,tick)
|
||||
self.nibble = self.nibble + 1
|
||||
if self.nibble == 1:
|
||||
self.status = self._period
|
||||
elif self.nibble == 2:
|
||||
#self.data1 = hex(int(round(self._period / self.syncTick)-12))
|
||||
self.data1 = self._period
|
||||
elif self.nibble == 3:
|
||||
self.data2 = self._period
|
||||
elif self.nibble == 4:
|
||||
self.data3 = self._period
|
||||
elif self.nibble == 5:
|
||||
self.data4 = self._period
|
||||
elif self.nibble == 6:
|
||||
self.data5 = self._period
|
||||
elif self.nibble == 7:
|
||||
self.data6 = self._period
|
||||
elif self.nibble == 8:
|
||||
self.crc = self._period
|
||||
# now send all to the SENT Frame
|
||||
self.frame = [self.syncPeriod,self.syncTick,self.status,self.data1,self.data2,self.data3,self.data4,self.data5,self.data6,self.crc]
|
||||
self.syncFound = False
|
||||
self.nibble = 0
|
||||
self.numberFrames += 1
|
||||
if self.numberFrames > 2:
|
||||
self.cancel()
|
||||
self.SampleStopped = True
|
||||
self.numberFrames = 0
|
||||
|
||||
def ConvertData(self,tickdata,tickTime):
|
||||
if tickdata == 0:
|
||||
t = '0x0'
|
||||
else:
|
||||
t = hex(int(round(tickdata / tickTime)-12))
|
||||
if t[0] =='-':
|
||||
t='0x0'
|
||||
return t
|
||||
|
||||
def SENTData(self):
|
||||
# check that data1 = Data2 if they are not equal return fault = True
|
||||
# will check the CRC code for faults. if fault, return = true
|
||||
# returns status, data1, data2, crc, fault
|
||||
#self._cb = self.pi.callback(self.gpio, pigpio.EITHER_EDGE, self._cbf)
|
||||
#time.sleep(0.1)
|
||||
fault = False
|
||||
SentFrame = self.frame[:]
|
||||
SENTTick = round(SentFrame[1]/56.0,2)
|
||||
|
||||
# the greatest SYNC sync is 90us. So trip a fault if this occurs
|
||||
if SENTTick > 90:
|
||||
fault = True
|
||||
|
||||
#print(SentFrame)
|
||||
# convert SentFrame to HEX Format including the status and Crc bits
|
||||
for x in range (2,10):
|
||||
SentFrame[x] = self.ConvertData(SentFrame[x],SENTTick)
|
||||
SENTCrc = SentFrame[9]
|
||||
SENTStatus = SentFrame[2]
|
||||
SENTPeriod = SentFrame[0]
|
||||
#print(SentFrame)
|
||||
# combine the datafield nibbles
|
||||
datanibble = '0x'
|
||||
datanibble2 = '0x'
|
||||
for x in range (3,6):
|
||||
datanibble = datanibble + str((SentFrame[x]))[2:]
|
||||
for x in range (6,9):
|
||||
datanibble2 = datanibble2 + str((SentFrame[x]))[2:]
|
||||
# if using SENT mode 0, then data nibbles should be equal
|
||||
#if self.SENTMode == 0 :
|
||||
# if datanibble != datanibble2:
|
||||
# fault = True
|
||||
# if datanibble or datanibble2 == 0 then fault = true
|
||||
if (int(datanibble,16) == 0) or (int(datanibble2,16) ==0):
|
||||
fault = True
|
||||
# if datanibble or datanibble2 > FFF (4096) then fault = True
|
||||
if ( (int(datanibble,16) > 0xFFF) or (int(datanibble2,16) > 0xFFF)):
|
||||
fault = True
|
||||
#print(datanibble)
|
||||
# CRC checking
|
||||
# converting the datanibble values to a binary bit string.
|
||||
# remove the first two characters. Not needed for crcCheck
|
||||
InputBitString = bin(int((datanibble + datanibble2[2:]),16))[2:]
|
||||
# converting Crcvalue to bin but remove the first two characters 0b
|
||||
# format is set to remove the leading 0b, 4 charactors long
|
||||
crcBitValue = format(int(str(SENTCrc),16),'04b')
|
||||
#checking the crcValue
|
||||
# polybitstring is 1*X^4+1*X^3+1*x^2+0*X+1 = '11101'
|
||||
if self.crcCheck(InputBitString,'11101',crcBitValue) == False:
|
||||
fault = True
|
||||
|
||||
# converter to decimnal
|
||||
returnData = int(datanibble,16)
|
||||
returnData2 = int(datanibble2,16)
|
||||
#returns both Data values and if there is a FAULT
|
||||
return (SENTStatus, returnData, returnData2,SENTTick, SENTCrc, fault, SENTPeriod)
|
||||
|
||||
def tick(self):
|
||||
status, data1, data2, ticktime, crc, errors, syncPulse = self.SENTData()
|
||||
return ticktime
|
||||
|
||||
def crcNibble(self):
|
||||
status, data1, data2, ticktime, crc, errors, syncPulse = self.SENTData()
|
||||
return crc
|
||||
|
||||
def dataField1(self):
|
||||
status, data1, data2, ticktime, crc, errors, syncPulse = self.SENTData()
|
||||
return data1
|
||||
|
||||
def dataField2(self):
|
||||
status, data1, data2, ticktime, crc, errors, syncPulse = self.SENTData()
|
||||
return data2
|
||||
|
||||
def statusNibble(self):
|
||||
status, data1, data2, ticktime, crc, errors, syncPulse = self.SENTData()
|
||||
return status
|
||||
|
||||
def syncPulse(self):
|
||||
status, data1, data2, ticktime, crc, errors, syncPulse = self.SENTData()
|
||||
return syncPulse
|
||||
|
||||
def errorFrame(self):
|
||||
status, data1, data2, ticktime, crc, errors, syncPulse = self.SENTData()
|
||||
return errors
|
||||
|
||||
def cancel(self):
|
||||
self._cb.cancel()
|
||||
|
||||
def stop(self):
|
||||
self.OutputSampleThread.stop()
|
||||
|
||||
def crcCheck(self, InputBitString, PolyBitString, crcValue ):
|
||||
# the input string will be a binary string all 6 nibbles of the SENT data
|
||||
# the seed value ( = '0101) is appended to the input string. Do not use zeros for SENT protocal
|
||||
# this uses the SENT CRC recommended implementation.
|
||||
checkOK = False
|
||||
|
||||
LenPolyBitString = len(PolyBitString)
|
||||
PolyBitString = PolyBitString.lstrip('0')
|
||||
LenInput = len(InputBitString)
|
||||
InputPaddedArray = list(InputBitString + '0101')
|
||||
while '1' in InputPaddedArray[:LenInput]:
|
||||
cur_shift = InputPaddedArray.index('1')
|
||||
for i in range(len(PolyBitString)):
|
||||
InputPaddedArray[cur_shift + i] = str(int(PolyBitString[i] != InputPaddedArray[cur_shift + i]))
|
||||
|
||||
if (InputPaddedArray[LenInput:] == list(crcValue)):
|
||||
checkOK = True
|
||||
|
||||
return checkOK
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
import time
|
||||
import pigpio
|
||||
import read_SENT
|
||||
|
||||
SENT_GPIO = 18
|
||||
RUN_TIME = 6000000000.0
|
||||
SAMPLE_TIME = 0.1
|
||||
|
||||
pi = pigpio.pi()
|
||||
|
||||
p = read_SENT.SENTReader(pi, SENT_GPIO)
|
||||
|
||||
start = time.time()
|
||||
|
||||
while (time.time() - start) < RUN_TIME:
|
||||
|
||||
time.sleep(SAMPLE_TIME)
|
||||
|
||||
status, data1, data2, ticktime, crc, errors, syncPulse = p.SENTData()
|
||||
print("Sent Status= %s - 12-bit DATA 1= %4.0f - DATA 2= %4.0f - tickTime(uS)= %4.2f - CRC= %s - Errors= %s - PERIOD = %s" % (status,data1,data2,ticktime,crc,errors,syncPulse))
|
||||
print("Sent Stat2s= %s - 12-bit DATA 1= %4.0f - DATA 2= %4.0f - tickTime(uS)= %4.2f - CRC= %s - Errors= %s - PERIOD = %s" % (p.statusNibble(),p.dataField1(),p.dataField2(),p.tick(),p.crcNibble(),p.errorFrame(),p.syncPulse()))
|
||||
|
||||
# stop the thread in SENTReader
|
||||
p.stop()
|
||||
# clear the pi object instance
|
||||
pi.stop()
|
2
pigpio-master/EXAMPLES/Python/SONAR_RANGER/README
Normal file
2
pigpio-master/EXAMPLES/Python/SONAR_RANGER/README
Normal file
@@ -0,0 +1,2 @@
|
||||
Class to read sonar rangers with separate trigger and echo pins.
|
||||
|
114
pigpio-master/EXAMPLES/Python/SONAR_RANGER/sonar_trigger_echo.py
Normal file
114
pigpio-master/EXAMPLES/Python/SONAR_RANGER/sonar_trigger_echo.py
Normal file
@@ -0,0 +1,114 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import time
|
||||
|
||||
import pigpio
|
||||
|
||||
class ranger:
|
||||
"""
|
||||
This class encapsulates a type of acoustic ranger. In particular
|
||||
the type of ranger with separate trigger and echo pins.
|
||||
|
||||
A pulse on the trigger initiates the sonar ping and shortly
|
||||
afterwards a sonar pulse is transmitted and the echo pin
|
||||
goes high. The echo pins stays high until a sonar echo is
|
||||
received (or the response times-out). The time between
|
||||
the high and low edges indicates the sonar round trip time.
|
||||
"""
|
||||
|
||||
def __init__(self, pi, trigger, echo):
|
||||
"""
|
||||
The class is instantiated with the Pi to use and the
|
||||
gpios connected to the trigger and echo pins.
|
||||
"""
|
||||
self.pi = pi
|
||||
self._trig = trigger
|
||||
self._echo = echo
|
||||
|
||||
self._ping = False
|
||||
self._high = None
|
||||
self._time = None
|
||||
|
||||
self._triggered = False
|
||||
|
||||
self._trig_mode = pi.get_mode(self._trig)
|
||||
self._echo_mode = pi.get_mode(self._echo)
|
||||
|
||||
pi.set_mode(self._trig, pigpio.OUTPUT)
|
||||
pi.set_mode(self._echo, pigpio.INPUT)
|
||||
|
||||
self._cb = pi.callback(self._trig, pigpio.EITHER_EDGE, self._cbf)
|
||||
self._cb = pi.callback(self._echo, pigpio.EITHER_EDGE, self._cbf)
|
||||
|
||||
self._inited = True
|
||||
|
||||
def _cbf(self, gpio, level, tick):
|
||||
if gpio == self._trig:
|
||||
if level == 0: # trigger sent
|
||||
self._triggered = True
|
||||
self._high = None
|
||||
else:
|
||||
if self._triggered:
|
||||
if level == 1:
|
||||
self._high = tick
|
||||
else:
|
||||
if self._high is not None:
|
||||
self._time = tick - self._high
|
||||
self._high = None
|
||||
self._ping = True
|
||||
|
||||
def read(self):
|
||||
"""
|
||||
Triggers a reading. The returned reading is the number
|
||||
of microseconds for the sonar round-trip.
|
||||
|
||||
round trip cms = round trip time / 1000000.0 * 34030
|
||||
"""
|
||||
if self._inited:
|
||||
self._ping = False
|
||||
self.pi.gpio_trigger(self._trig)
|
||||
start = time.time()
|
||||
while not self._ping:
|
||||
if (time.time()-start) > 5.0:
|
||||
return 20000
|
||||
time.sleep(0.001)
|
||||
return self._time
|
||||
else:
|
||||
return None
|
||||
|
||||
def cancel(self):
|
||||
"""
|
||||
Cancels the ranger and returns the gpios to their
|
||||
original mode.
|
||||
"""
|
||||
if self._inited:
|
||||
self._inited = False
|
||||
self._cb.cancel()
|
||||
self.pi.set_mode(self._trig, self._trig_mode)
|
||||
self.pi.set_mode(self._echo, self._echo_mode)
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
import time
|
||||
|
||||
import pigpio
|
||||
|
||||
import sonar_trigger_echo
|
||||
|
||||
pi = pigpio.pi()
|
||||
|
||||
sonar = sonar_trigger_echo.ranger(pi, 23, 18)
|
||||
|
||||
end = time.time() + 600.0
|
||||
|
||||
r = 1
|
||||
while time.time() < end:
|
||||
|
||||
print("{} {}".format(r, sonar.read()))
|
||||
r += 1
|
||||
time.sleep(0.03)
|
||||
|
||||
sonar.cancel()
|
||||
|
||||
pi.stop()
|
||||
|
2
pigpio-master/EXAMPLES/Python/VIRTUAL_WIRE/README
Normal file
2
pigpio-master/EXAMPLES/Python/VIRTUAL_WIRE/README
Normal file
@@ -0,0 +1,2 @@
|
||||
Class to send and receive radio messages compatible with the Virtual Wire library for Arduinos.
|
||||
|
372
pigpio-master/EXAMPLES/Python/VIRTUAL_WIRE/vw.py
Normal file
372
pigpio-master/EXAMPLES/Python/VIRTUAL_WIRE/vw.py
Normal file
@@ -0,0 +1,372 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
This module provides a 313MHz/434MHz radio interface compatible
|
||||
with the Virtual Wire library used on Arduinos.
|
||||
|
||||
It has been tested between a Pi, TI Launchpad, and Arduino Pro Mini.
|
||||
"""
|
||||
# 2014-08-14
|
||||
# vw.py
|
||||
|
||||
import time
|
||||
|
||||
import pigpio
|
||||
|
||||
MAX_MESSAGE_BYTES=77
|
||||
|
||||
MIN_BPS=50
|
||||
MAX_BPS=10000
|
||||
|
||||
_HEADER=[0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x38, 0x2c]
|
||||
|
||||
_CTL=3
|
||||
|
||||
_SYMBOL=[
|
||||
0x0d, 0x0e, 0x13, 0x15, 0x16, 0x19, 0x1a, 0x1c,
|
||||
0x23, 0x25, 0x26, 0x29, 0x2a, 0x2c, 0x32, 0x34]
|
||||
|
||||
|
||||
def _sym2nibble(symbol):
|
||||
for nibble in range(16):
|
||||
if symbol == _SYMBOL[nibble]:
|
||||
return nibble
|
||||
return 0
|
||||
|
||||
def _crc_ccitt_update(crc, data):
|
||||
|
||||
data = data ^ (crc & 0xFF);
|
||||
|
||||
data = (data ^ (data << 4)) & 0xFF;
|
||||
|
||||
return (
|
||||
(((data << 8) & 0xFFFF) | (crc >> 8)) ^
|
||||
((data >> 4) & 0x00FF) ^ ((data << 3) & 0xFFFF)
|
||||
)
|
||||
|
||||
class tx():
|
||||
|
||||
def __init__(self, pi, txgpio, bps=2000):
|
||||
"""
|
||||
Instantiate a transmitter with the Pi, the transmit gpio,
|
||||
and the bits per second (bps). The bps defaults to 2000.
|
||||
The bps is constrained to be within MIN_BPS to MAX_BPS.
|
||||
"""
|
||||
self.pi = pi
|
||||
|
||||
self.txbit = (1<<txgpio)
|
||||
|
||||
if bps < MIN_BPS:
|
||||
bps = MIN_BPS
|
||||
elif bps > MAX_BPS:
|
||||
bps = MAX_BPS
|
||||
|
||||
self.mics = int(1000000 / bps)
|
||||
|
||||
self.wave_id = None
|
||||
|
||||
pi.wave_add_new()
|
||||
|
||||
pi.set_mode(txgpio, pigpio.OUTPUT)
|
||||
|
||||
|
||||
def _nibble(self, nibble):
|
||||
|
||||
for i in range(6):
|
||||
if nibble & (1<<i):
|
||||
self.wf.append(pigpio.pulse(self.txbit, 0, self.mics))
|
||||
else:
|
||||
self.wf.append(pigpio.pulse(0, self.txbit, self.mics))
|
||||
|
||||
def _byte(self, crc, byte):
|
||||
self._nibble(_SYMBOL[byte>>4])
|
||||
self._nibble(_SYMBOL[byte&0x0F])
|
||||
return _crc_ccitt_update(crc, byte)
|
||||
|
||||
def put(self, data):
|
||||
"""
|
||||
Transmit a message. If the message is more than
|
||||
MAX_MESSAGE_BYTES in size it is discarded. If a message
|
||||
is currently being transmitted it is aborted and replaced
|
||||
with the new message. True is returned if message
|
||||
transmission has successfully started. False indicates
|
||||
an error.
|
||||
"""
|
||||
if len(data) > MAX_MESSAGE_BYTES:
|
||||
return False
|
||||
|
||||
self.wf = []
|
||||
|
||||
self.cancel()
|
||||
|
||||
for i in _HEADER:
|
||||
self._nibble(i)
|
||||
|
||||
crc = self._byte(0xFFFF, len(data)+_CTL)
|
||||
|
||||
for i in data:
|
||||
|
||||
if type(i) == type(""):
|
||||
v = ord(i)
|
||||
else:
|
||||
v = i
|
||||
|
||||
crc = self._byte(crc, v)
|
||||
|
||||
crc = ~crc
|
||||
|
||||
self._byte(0, crc&0xFF)
|
||||
self._byte(0, crc>>8)
|
||||
|
||||
self.pi.wave_add_generic(self.wf)
|
||||
|
||||
self.wave_id = self.pi.wave_create()
|
||||
|
||||
if self.wave_id >= 0:
|
||||
self.pi.wave_send_once(self.wave_id)
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def ready(self):
|
||||
"""
|
||||
Returns True if a new message may be transmitted.
|
||||
"""
|
||||
return not self.pi.wave_tx_busy()
|
||||
|
||||
def cancel(self):
|
||||
"""
|
||||
Cancels the wireless transmitter, aborting any message
|
||||
in progress.
|
||||
"""
|
||||
if self.wave_id is not None:
|
||||
self.pi.wave_tx_stop()
|
||||
self.pi.wave_delete(self.wave_id)
|
||||
self.pi.wave_add_new()
|
||||
|
||||
self.wave_id = None
|
||||
|
||||
class rx():
|
||||
|
||||
def __init__(self, pi, rxgpio, bps=2000):
|
||||
"""
|
||||
Instantiate a receiver with the Pi, the receive gpio, and
|
||||
the bits per second (bps). The bps defaults to 2000.
|
||||
The bps is constrained to be within MIN_BPS to MAX_BPS.
|
||||
"""
|
||||
self.pi = pi
|
||||
self.rxgpio = rxgpio
|
||||
|
||||
self.messages = []
|
||||
self.bad_CRC = 0
|
||||
|
||||
if bps < MIN_BPS:
|
||||
bps = MIN_BPS
|
||||
elif bps > MAX_BPS:
|
||||
bps = MAX_BPS
|
||||
|
||||
slack = 0.20
|
||||
self.mics = int(1000000 / bps)
|
||||
slack_mics = int(slack * self.mics)
|
||||
self.min_mics = self.mics - slack_mics # Shortest legal edge.
|
||||
self.max_mics = (self.mics + slack_mics) * 4 # Longest legal edge.
|
||||
|
||||
self.timeout = 8 * self.mics / 1000 # 8 bits time in ms.
|
||||
if self.timeout < 8:
|
||||
self.timeout = 8
|
||||
|
||||
self.last_tick = None
|
||||
self.good = 0
|
||||
self.bits = 0
|
||||
self.token = 0
|
||||
self.in_message = False
|
||||
self.message = [0]*(MAX_MESSAGE_BYTES+_CTL)
|
||||
self.message_len = 0
|
||||
self.byte = 0
|
||||
|
||||
pi.set_mode(rxgpio, pigpio.INPUT)
|
||||
|
||||
self.cb = pi.callback(rxgpio, pigpio.EITHER_EDGE, self._cb)
|
||||
|
||||
def _calc_crc(self):
|
||||
|
||||
crc = 0xFFFF
|
||||
for i in range(self.message_length):
|
||||
crc = _crc_ccitt_update(crc, self.message[i])
|
||||
return crc
|
||||
|
||||
def _insert(self, bits, level):
|
||||
|
||||
for i in range(bits):
|
||||
|
||||
self.token >>= 1
|
||||
|
||||
if level == 0:
|
||||
self.token |= 0x800
|
||||
|
||||
if self.in_message:
|
||||
|
||||
self.bits += 1
|
||||
|
||||
if self.bits >= 12: # Complete token.
|
||||
|
||||
byte = (
|
||||
_sym2nibble(self.token & 0x3f) << 4 |
|
||||
_sym2nibble(self.token >> 6))
|
||||
|
||||
if self.byte == 0:
|
||||
self.message_length = byte
|
||||
|
||||
if byte > (MAX_MESSAGE_BYTES+_CTL):
|
||||
self.in_message = False # Abort message.
|
||||
return
|
||||
|
||||
self.message[self.byte] = byte
|
||||
|
||||
self.byte += 1
|
||||
self.bits = 0
|
||||
|
||||
if self.byte >= self.message_length:
|
||||
self.in_message = False
|
||||
self.pi.set_watchdog(self.rxgpio, 0)
|
||||
|
||||
crc = self._calc_crc()
|
||||
|
||||
if crc == 0xF0B8: # Valid CRC.
|
||||
self.messages.append(
|
||||
self.message[1:self.message_length-2])
|
||||
else:
|
||||
self.bad_CRC += 1
|
||||
|
||||
else:
|
||||
if self.token == 0xB38: # Start message token.
|
||||
self.in_message = True
|
||||
self.pi.set_watchdog(self.rxgpio, self.timeout)
|
||||
self.bits = 0
|
||||
self.byte = 0
|
||||
|
||||
def _cb(self, gpio, level, tick):
|
||||
|
||||
if self.last_tick is not None:
|
||||
|
||||
if level == pigpio.TIMEOUT:
|
||||
|
||||
self.pi.set_watchdog(self.rxgpio, 0) # Switch watchdog off.
|
||||
|
||||
if self.in_message:
|
||||
self._insert(4, not self.last_level)
|
||||
|
||||
self.good = 0
|
||||
self.in_message = False
|
||||
|
||||
else:
|
||||
|
||||
edge = pigpio.tickDiff(self.last_tick, tick)
|
||||
|
||||
if edge < self.min_mics:
|
||||
|
||||
self.good = 0
|
||||
self.in_message = False
|
||||
|
||||
elif edge > self.max_mics:
|
||||
|
||||
if self.in_message:
|
||||
self._insert(4, level)
|
||||
|
||||
self.good = 0
|
||||
self.in_message = False
|
||||
|
||||
else:
|
||||
|
||||
self.good += 1
|
||||
|
||||
if self.good > 8:
|
||||
|
||||
bitlen = (100 * edge) / self.mics
|
||||
|
||||
if bitlen < 140:
|
||||
bits = 1
|
||||
elif bitlen < 240:
|
||||
bits = 2
|
||||
elif bitlen < 340:
|
||||
bits = 3
|
||||
else:
|
||||
bits = 4
|
||||
|
||||
self._insert(bits, level)
|
||||
|
||||
self.last_tick = tick
|
||||
self.last_level = level
|
||||
|
||||
def get(self):
|
||||
"""
|
||||
Returns the next unread message, or None if none is avaiable.
|
||||
"""
|
||||
if len(self.messages):
|
||||
return self.messages.pop(0)
|
||||
else:
|
||||
return None
|
||||
|
||||
def ready(self):
|
||||
"""
|
||||
Returns True if there is a message available to be read.
|
||||
"""
|
||||
return len(self.messages)
|
||||
|
||||
def cancel(self):
|
||||
"""
|
||||
Cancels the wireless receiver.
|
||||
"""
|
||||
if self.cb is not None:
|
||||
self.cb.cancel()
|
||||
self.pi.set_watchdog(self.rxgpio, 0)
|
||||
self.cb = None
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
import time
|
||||
|
||||
import pigpio
|
||||
|
||||
import vw
|
||||
|
||||
RX=11
|
||||
TX=25
|
||||
|
||||
BPS=2000
|
||||
|
||||
pi = pigpio.pi() # Connect to local Pi.
|
||||
|
||||
rx = vw.rx(pi, RX, BPS) # Specify Pi, rx gpio, and baud.
|
||||
tx = vw.tx(pi, TX, BPS) # Specify Pi, tx gpio, and baud.
|
||||
|
||||
msg = 0
|
||||
|
||||
start = time.time()
|
||||
|
||||
while (time.time()-start) < 300:
|
||||
|
||||
msg += 1
|
||||
|
||||
while not tx.ready():
|
||||
time.sleep(0.1)
|
||||
|
||||
time.sleep(0.2)
|
||||
|
||||
tx.put([48, 49, 65, ((msg>>6)&0x3F)+32, (msg&0x3F)+32])
|
||||
|
||||
while not tx.ready():
|
||||
time.sleep(0.1)
|
||||
|
||||
time.sleep(0.2)
|
||||
|
||||
tx.put("Hello World #{}!".format(msg))
|
||||
|
||||
while rx.ready():
|
||||
print("".join(chr (c) for c in rx.get()))
|
||||
|
||||
rx.cancel()
|
||||
tx.cancel()
|
||||
|
||||
pi.stop()
|
||||
|
2
pigpio-master/EXAMPLES/Python/WIEGAND_CODE/README
Normal file
2
pigpio-master/EXAMPLES/Python/WIEGAND_CODE/README
Normal file
@@ -0,0 +1,2 @@
|
||||
Class to decode a Wiegand code.
|
||||
|
135
pigpio-master/EXAMPLES/Python/WIEGAND_CODE/wiegand.py
Normal file
135
pigpio-master/EXAMPLES/Python/WIEGAND_CODE/wiegand.py
Normal file
@@ -0,0 +1,135 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import pigpio
|
||||
|
||||
class decoder:
|
||||
|
||||
"""
|
||||
A class to read Wiegand codes of an arbitrary length.
|
||||
|
||||
The code length and value are returned.
|
||||
|
||||
EXAMPLE
|
||||
|
||||
#!/usr/bin/env python
|
||||
|
||||
import time
|
||||
|
||||
import pigpio
|
||||
|
||||
import wiegand
|
||||
|
||||
def callback(bits, code):
|
||||
print("bits={} code={}".format(bits, code))
|
||||
|
||||
pi = pigpio.pi()
|
||||
|
||||
w = wiegand.decoder(pi, 14, 15, callback)
|
||||
|
||||
time.sleep(300)
|
||||
|
||||
w.cancel()
|
||||
|
||||
pi.stop()
|
||||
"""
|
||||
|
||||
def __init__(self, pi, gpio_0, gpio_1, callback, bit_timeout=5):
|
||||
|
||||
"""
|
||||
Instantiate with the pi, gpio for 0 (green wire), the gpio for 1
|
||||
(white wire), the callback function, and the bit timeout in
|
||||
milliseconds which indicates the end of a code.
|
||||
|
||||
The callback is passed the code length in bits and the value.
|
||||
"""
|
||||
|
||||
self.pi = pi
|
||||
self.gpio_0 = gpio_0
|
||||
self.gpio_1 = gpio_1
|
||||
|
||||
self.callback = callback
|
||||
|
||||
self.bit_timeout = bit_timeout
|
||||
|
||||
self.in_code = False
|
||||
|
||||
self.pi.set_mode(gpio_0, pigpio.INPUT)
|
||||
self.pi.set_mode(gpio_1, pigpio.INPUT)
|
||||
|
||||
self.pi.set_pull_up_down(gpio_0, pigpio.PUD_UP)
|
||||
self.pi.set_pull_up_down(gpio_1, pigpio.PUD_UP)
|
||||
|
||||
self.cb_0 = self.pi.callback(gpio_0, pigpio.FALLING_EDGE, self._cb)
|
||||
self.cb_1 = self.pi.callback(gpio_1, pigpio.FALLING_EDGE, self._cb)
|
||||
|
||||
def _cb(self, gpio, level, tick):
|
||||
|
||||
"""
|
||||
Accumulate bits until both gpios 0 and 1 timeout.
|
||||
"""
|
||||
|
||||
if level < pigpio.TIMEOUT:
|
||||
|
||||
if self.in_code == False:
|
||||
self.bits = 1
|
||||
self.num = 0
|
||||
|
||||
self.in_code = True
|
||||
self.code_timeout = 0
|
||||
self.pi.set_watchdog(self.gpio_0, self.bit_timeout)
|
||||
self.pi.set_watchdog(self.gpio_1, self.bit_timeout)
|
||||
else:
|
||||
self.bits += 1
|
||||
self.num = self.num << 1
|
||||
|
||||
if gpio == self.gpio_0:
|
||||
self.code_timeout = self.code_timeout & 2 # clear gpio 0 timeout
|
||||
else:
|
||||
self.code_timeout = self.code_timeout & 1 # clear gpio 1 timeout
|
||||
self.num = self.num | 1
|
||||
|
||||
else:
|
||||
|
||||
if self.in_code:
|
||||
|
||||
if gpio == self.gpio_0:
|
||||
self.code_timeout = self.code_timeout | 1 # timeout gpio 0
|
||||
else:
|
||||
self.code_timeout = self.code_timeout | 2 # timeout gpio 1
|
||||
|
||||
if self.code_timeout == 3: # both gpios timed out
|
||||
self.pi.set_watchdog(self.gpio_0, 0)
|
||||
self.pi.set_watchdog(self.gpio_1, 0)
|
||||
self.in_code = False
|
||||
self.callback(self.bits, self.num)
|
||||
|
||||
def cancel(self):
|
||||
|
||||
"""
|
||||
Cancel the Wiegand decoder.
|
||||
"""
|
||||
|
||||
self.cb_0.cancel()
|
||||
self.cb_1.cancel()
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
import time
|
||||
|
||||
import pigpio
|
||||
|
||||
import wiegand
|
||||
|
||||
def callback(bits, value):
|
||||
print("bits={} value={}".format(bits, value))
|
||||
|
||||
pi = pigpio.pi()
|
||||
|
||||
w = wiegand.decoder(pi, 14, 15, callback)
|
||||
|
||||
time.sleep(300)
|
||||
|
||||
w.cancel()
|
||||
|
||||
pi.stop()
|
||||
|
7
pigpio-master/EXAMPLES/Shell/GPIOTEST/README
Normal file
7
pigpio-master/EXAMPLES/Shell/GPIOTEST/README
Normal file
@@ -0,0 +1,7 @@
|
||||
This bash script tests the user gpios.
|
||||
|
||||
Everything should be disconnected from the gpios.
|
||||
|
||||
The pigpio daemon must be running (sudo pigpiod).
|
||||
|
||||
Video at http://youtu.be/sCJFLKWaxHo
|
126
pigpio-master/EXAMPLES/Shell/GPIOTEST/gpiotest
Normal file
126
pigpio-master/EXAMPLES/Shell/GPIOTEST/gpiotest
Normal file
@@ -0,0 +1,126 @@
|
||||
#!/bin/bash
|
||||
|
||||
skipped=""
|
||||
tested=""
|
||||
failed=""
|
||||
|
||||
usage()
|
||||
{
|
||||
cat <<EOF
|
||||
This program checks the Pi's (user) gpios.
|
||||
|
||||
The program reads and writes all the gpios. Make sure NOTHING
|
||||
is connected to the gpios during this test.
|
||||
|
||||
The program uses the pigpio daemon which must be running.
|
||||
|
||||
To start the daemon use the command sudo pigpiod.
|
||||
|
||||
Press the ENTER key to continue or ctrl-C to abort...
|
||||
EOF
|
||||
|
||||
read a
|
||||
}
|
||||
|
||||
restore_mode()
|
||||
{
|
||||
# $1 gpio
|
||||
# $2 mode
|
||||
|
||||
case "$2" in
|
||||
0) m="r" ;;
|
||||
1) m="w" ;;
|
||||
2) m="5" ;;
|
||||
3) m="4" ;;
|
||||
4) m="0" ;;
|
||||
5) m="1" ;;
|
||||
6) m="2" ;;
|
||||
7) m="3" ;;
|
||||
*)
|
||||
echo "invalid mode $2 for gpio $1"
|
||||
exit 1
|
||||
esac
|
||||
|
||||
$(pigs m $1 $m)
|
||||
}
|
||||
|
||||
check_gpio()
|
||||
{
|
||||
# $1 gpio
|
||||
# $2 i2c
|
||||
|
||||
m=$(pigs mg $1) # save mode
|
||||
L=$(pigs r $1) # save level
|
||||
|
||||
s=$(pigs m $1 w)
|
||||
|
||||
if [[ $s = "" ]]
|
||||
then
|
||||
f=0
|
||||
tested+="$1 "
|
||||
|
||||
# write mode tests
|
||||
$(pigs w $1 0)
|
||||
r=$(pigs r $1)
|
||||
if [[ $r -ne 0 ]]; then f=1; echo "Write 0 to gpio $1 failed."; fi
|
||||
|
||||
$(pigs w $1 1)
|
||||
r=$(pigs r $1)
|
||||
if [[ $r -ne 1 ]]; then f=1; echo "Write 1 to gpio $1 failed."; fi
|
||||
|
||||
# read mode tests using pull-ups and pull-downs
|
||||
$(pigs m $1 r)
|
||||
|
||||
if [[ $2 -eq 0 ]]
|
||||
then
|
||||
$(pigs pud $1 d)
|
||||
r=$(pigs r $1)
|
||||
if [[ $r -ne 0 ]]; then f=1; echo "Pull down on gpio $1 failed."; fi
|
||||
fi
|
||||
|
||||
$(pigs pud $1 u)
|
||||
r=$(pigs r $1)
|
||||
if [[ $r -ne 1 ]]; then f=1; echo "Pull up on gpio $1 failed."; fi
|
||||
|
||||
$(pigs pud $1 o) # switch pull-ups/downs off
|
||||
$(pigs w $1 $L) # restore original level
|
||||
restore_mode $1 $m # restore original mode
|
||||
|
||||
if [[ $f -ne 0 ]]; then failed+="$1 "; fi
|
||||
else
|
||||
skipped+="$1 "
|
||||
fi
|
||||
} 2>/dev/null
|
||||
|
||||
usage
|
||||
|
||||
v=$(pigs hwver)
|
||||
|
||||
if [[ $v < 0 ]]
|
||||
then
|
||||
echo "The pigpio daemon wasn't found. Did you sudo pigpiod?"
|
||||
exit
|
||||
fi
|
||||
|
||||
echo "Testing..."
|
||||
|
||||
for ((i=0; i<4; i++)) do check_gpio $i 1; done
|
||||
for ((i=4; i<16; i++)) do check_gpio $i 0; done
|
||||
|
||||
if [[ $v -ge 16 ]];
|
||||
then
|
||||
check_gpio 16 0
|
||||
else
|
||||
skipped+="16 "
|
||||
fi
|
||||
|
||||
for ((i=17; i<28; i++)) do check_gpio $i 0; done
|
||||
for ((i=28; i<30; i++)) do check_gpio $i 1; done
|
||||
for ((i=30; i<32; i++)) do check_gpio $i 0; done
|
||||
|
||||
if [[ $failed = "" ]]; then failed="None"; fi
|
||||
|
||||
echo "Skipped non-user gpios: $skipped"
|
||||
echo "Tested user gpios: $tested"
|
||||
echo "Failed user gpios: $failed"
|
||||
|
Reference in New Issue
Block a user