Skip to content

Commit e551d7a

Browse files
authored
Sync from master
2 parents 6f19946 + 503e839 commit e551d7a

File tree

7 files changed

+127
-120
lines changed

7 files changed

+127
-120
lines changed

Adafruit_BBIO/Encoder.py

Lines changed: 65 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -3,53 +3,62 @@
33
from subprocess import check_output, STDOUT, CalledProcessError
44
import os
55
import logging
6-
7-
8-
class QEP :
9-
10-
def __init__(self, channel=1, debug=False):
11-
self.channel = channel
12-
self.debug = debug
13-
14-
def errMsg(self):
15-
print("Error accessing 0x%02X: Check your QEP channel" % self.address)
16-
return -1
17-
18-
# example method from Adafruit_I2C
19-
# TODO: delete this
20-
# def write8(self, reg, value):
21-
# "Writes an 8-bit value to the specified register/address"
22-
# try:
23-
# self.bus.write_byte_data(self.address, reg, value)
24-
# if self.debug:
25-
# print("Rotary: Wrote 0x%02X to register 0x%02X" % (value, reg))
26-
# except IOError as err:
27-
# return self.errMsg()
28-
#
29-
#
30-
#if __name__ == '__main__':
31-
# try:
32-
# qep = Adafruit_BBIO.Encoder.QEP()
33-
# print("Default QEP channel is accessible")
34-
# except:
35-
# print("Error accessing default Rotary bus")
36-
6+
import itertools
7+
8+
eQEP0 = 0
9+
eQEP1 = 1
10+
eQEP2 = 2
11+
eQEP2b = 3
12+
13+
_OCP_PATH = "/sys/devices/platform/ocp"
14+
_eQEP_DEFS = [
15+
{'channel': 'eQEP0', 'pin_A': 'P9_92', 'pin_B': 'P9_27',
16+
'sys_path': os.path.join(_OCP_PATH, '48300000.epwmss/48300180.eqep')},
17+
{'channel': 'eQEP1', 'pin_A': 'P8_35', 'pin_B': 'P8_33',
18+
'sys_path': os.path.join(_OCP_PATH, '48302000.epwmss/48302180.eqep')},
19+
{'channel': 'eQEP2', 'pin_A': 'P8_12', 'pin_B': 'P8_11',
20+
'sys_path': os.path.join(_OCP_PATH, '48304000.epwmss/48304180.eqep')},
21+
{'channel': 'eQEP2b', 'pin_A': 'P8_41', 'pin_B': 'P8_42',
22+
'sys_path': os.path.join(_OCP_PATH, '48304000.epwmss/48304180.eqep')}
23+
]
24+
25+
26+
class eQEP(object):
27+
'''Enhanced Quadrature Encoder Pulse (eQEP) module class. Abstraction
28+
for either of the three available channels (eQEP0, eQEP1, eQEP2) on
29+
the Beaglebone'''
30+
31+
@classmethod
32+
def fromdict(cls, d):
33+
'''Creates a class instance from a dictionary'''
34+
35+
allowed = ('channel', 'pin_A', 'pin_B', 'sys_path')
36+
df = {k: v for k, v in d.iteritems() if k in allowed}
37+
return cls(**df)
38+
39+
def __init__(self, channel, pin_A, pin_B, sys_path):
40+
'''Initialize the eQEP module
41+
42+
Attributes:
43+
channel (str): eQEP channel name. E.g. "eQEP0", "eQEP1", etc.
44+
Note that "eQEP2" and "eQEP2b" are channel aliases for the
45+
same module, but on different (mutually-exclusive) sets of
46+
pins
47+
pin_A (str): physical input pin for the A signal of the
48+
rotary encoder
49+
pin_B (str): physical input pin for the B signal of the
50+
rotary encoder
51+
sys_path (str): sys filesystem path to access the attributes
52+
of this eQEP module
53+
54+
'''
55+
self.channel = channel
56+
self.pin_A = pin_A
57+
self.pin_B = pin_B
58+
self.sys_path = sys_path
3759

3860

3961
class RotaryEncoder(object):
40-
# TODO: check that kernel 4.1+
41-
# TODO: use config-pin to set qep mode
42-
OCP_PATH = "/sys/devices/platform/ocp"
43-
_eqep_dirs = [
44-
'%s/48300000.epwmss/48300180.eqep' % OCP_PATH,
45-
'%s/48302000.epwmss/48302180.eqep' % OCP_PATH,
46-
'%s/48304000.epwmss/48304180.eqep' % OCP_PATH
47-
]
48-
49-
EQEP0 = 0
50-
EQEP1 = 1
51-
EQEP2 = 2
52-
EQEP2b = 3
5362

5463
def _run_cmd(self, cmd):
5564
'''Runs a command. If not successful (i.e. error code different than zero),
@@ -93,64 +102,19 @@ def __init__(self, eqep_num):
93102
self._logger = logging.getLogger(__name__)
94103
self._logger.addHandler(logging.NullHandler())
95104

96-
# Configure eqep0
97-
self._logger.info("Configuring eqep0, pins: P9.27, P9.92")
98-
99-
pin = "P9_27"
100-
self.config_pin(pin)
101-
102-
pin = "P9_92"
103-
self.config_pin(pin)
104-
105-
path = "/sys/devices/platform/ocp/48300000.epwmss/48300180.eqep/position"
106-
self.cat_file(path)
107-
108-
# Configure eqep1
109-
self._logger.info("Configuring eqep1, pins: P8.33, P8.35")
110-
111-
pin = "P8.33"
112-
self.config_pin(pin)
113-
114-
pin = "P8.35"
115-
self.config_pin(pin)
116-
117-
path = "/sys/devices/platform/ocp/48302000.epwmss/48302180.eqep/position"
118-
self.cat_file(path);
119-
120-
# Configure eqep2
121-
self._logger.info("Configuring eqep2, pins: P8.11, P8.12")
122-
123-
pin = "P8.11"
124-
self.config_pin(pin)
125-
126-
pin = "P8.12"
127-
self.config_pin(pin)
128-
129-
path = "/sys/devices/platform/ocp/48304000.epwmss/48304180.eqep/position"
130-
self.cat_file(path);
131-
132-
# Configure eqep2b
133-
self._logger.info("Configuring eqep2, pins: P8.41, P8.42")
134-
135-
pin = "P8.41"
136-
self.config_pin(pin)
137-
138-
pin = "P8.42"
139-
self.config_pin(pin)
140-
141-
path = "/sys/devices/platform/ocp/48304000.epwmss/48304180.eqep/position"
142-
self.cat_file(path);
143-
144-
self._logger.debug("RotaryEncoder(): eqep_num: {0}".format(eqep_num))
145-
self._logger.debug("RotaryEncoder(): self._eqep_dirs[0]: {0}".format(self._eqep_dirs[0]))
146-
self._logger.debug("RotaryEncoder(): self._eqep_dirs[1]: {0}".format(self._eqep_dirs[1]))
147-
self._logger.debug("RotaryEncoder(): self._eqep_dirs[2]: {0}".format(self._eqep_dirs[2]))
148-
self._logger.debug("RotaryEncoder(): self._eqep_dirs[eqep_num: {0}]: {1}".format(eqep_num, self._eqep_dirs[eqep_num]))
105+
# Configure eqep module
106+
self._eqep = eQEP.fromdict(_eQEP_DEFS[eqep_num])
107+
self._logger.info(
108+
"Configuring: {}, pin A: {}, pin B: {}, sys path: {}".format(
109+
self._eqep.channel, self._eqep.pin_A, self._eqep.pin_B,
110+
self._eqep.sys_path))
149111

150-
assert 0 <= eqep_num <= 3 , "eqep_num must be between 0 and 3"
112+
self.config_pin(self._eqep.pin_A)
113+
self.config_pin(self._eqep.pin_B)
151114

152-
self.base_dir = self._eqep_dirs[eqep_num]
153-
self._logger.debug("RotaryEncoder(): self.base_dir: {0}".format(self.base_dir))
115+
self.base_dir = self._eqep.sys_path
116+
self._logger.debug(
117+
"RotaryEncoder(): self.base_dir: {0}".format(self.base_dir))
154118

155119
self.enable()
156120

@@ -220,6 +184,7 @@ def getPosition(self):
220184
In relative mode, this attribute represents the position of the
221185
encoder at the last unit timer overflow.
222186
'''
187+
self._logger.debug("Channel: {}".format(self._eqep.channel))
223188
position_file = "%s/position" % self.base_dir
224189
self._logger.debug("getPosition(): position_file: {0}".format(position_file))
225190
position_handle = open(position_file, 'r')

CHANGELOG.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,32 @@
1+
1.0.8
2+
----
3+
**Fixes:**
4+
* Issue #196: cache board type to avoid poor performance
5+
* Issue #192: fix PocketBeagle PWM pin typo
6+
* Issue #191: turn off RotaryEncoder's debug output by default
7+
* Issue #188: GPIO is extremely slow (20ms to toggle)
8+
* Issue #186: problems with UART
9+
10+
**shortlog:**
11+
* David Planella (12):
12+
* Copy Encoder module comments to README.md
13+
* Formatted Encoder README in markdown
14+
* Fixed Encoder README formatting
15+
* Removed QEP instructions from Encoder module
16+
* Fixes to Encoder README
17+
* Updated Encoder README
18+
* Encoder README: added info on dedicated overlays
19+
* Encoder README: updated info on pre-requisites
20+
* Encoder README update
21+
* Encoder README update
22+
* Add logging support, turn off unconditional debug output
23+
* Encoder: remove unused logging code
24+
25+
* Drew Fustini (3):
26+
* Merge pull request #195 from dplanella/master
27+
* Fix PocketBeagle PWM pin typo (#192)
28+
* cache board type to avoid poor performance (#196)
29+
130
1.0.7
231
----
332
**Fixes:**

distribute_setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def quote(arg):
5050
return os.spawnl(os.P_WAIT, sys.executable, *args) == 0
5151

5252
DEFAULT_VERSION = "0.6.45"
53-
DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/"
53+
DEFAULT_URL = "https://pypi.python.org/packages/source/d/distribute/"
5454
SETUPTOOLS_FAKED_VERSION = "0.6c11"
5555

5656
SETUPTOOLS_PKG_INFO = """\

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
}
4141

4242
setup(name = 'Adafruit_BBIO',
43-
version = '1.0.7',
43+
version = '1.0.8',
4444
author = 'Justin Cooper',
4545
author_email = '[email protected]',
4646
description = 'A module to control BeagleBone IO channels',

source/c_pwm.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,9 @@ BBIO_err pwm_setup(const char *key, __attribute__ ((unused)) float duty, __attri
553553
close(period_fd);
554554
close(duty_fd);
555555
close(polarity_fd);
556+
#ifdef BBBVERSION41
557+
close(enable_fd);
558+
#endif
556559
syslog(LOG_ERR, "Adafruit_BBIO: pwm_setup: %s couldn't malloc pwm_exp: %i-%s",
557560
key, errno, strerror(errno));
558561
return BBIO_MEM; // out of memory
@@ -717,6 +720,9 @@ BBIO_err pwm_disable(const char *key)
717720
#endif
718721

719722
//close the fd
723+
#ifdef BBBVERSION41
724+
close(pwm->enable_fd);
725+
#endif
720726
close(pwm->period_fd);
721727
close(pwm->duty_fd);
722728
close(pwm->polarity_fd);

source/common.c

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ pwm_t pwm_table[] = {
301301
{ "ehrpwm0", 0, 0, 1, "ehrpwm.0:0", "EHRPWM0A", "48300000", "48300200", "P1_8"},
302302
{ "ehrpwm0", 0, 0, 1, "ehrpwm.0:0", "EHRPWM0A", "48300000", "48300200", "P1_36"},
303303
{ "ehrpwm0", 1, 1, 1, "ehrpwm.0:1", "EHRPWM0B", "48300000", "48300200", "P1_10"},
304-
{ "ehrpwm0", 1, 1, 1, "ehrpwm.0:1", "EHRPWM0B", "48300000", "48300200", "P1_13"},
304+
{ "ehrpwm0", 1, 1, 1, "ehrpwm.0:1", "EHRPWM0B", "48300000", "48300200", "P1_33"},
305305
{ "ehrpwm1", 3, 0, 6, "ehrpwm.1:0", "EHRPWM1A", "48302000", "48302200", "P2_1"},
306306
{ "ehrpwm2", 6, 1, 3, "ehrpwm.2:1", "EHRPWM2B", "48304000", "48304200", "P2_3"},
307307
{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }
@@ -601,23 +601,30 @@ int pocketbeagle(void) {
601601
*/
602602
int beaglebone_blue(void) {
603603
const char *cmd = "/bin/grep -c 'TI AM335x BeagleBone Blue' /proc/device-tree/model";
604-
char blue;
604+
// cache the value to avoid poor performance
605+
// in functions that are called frequently like
606+
// gpio_set_value() in source/event_gpio.c
607+
static int initialized = 0;
608+
static int retval = 0;
605609
FILE *file = NULL;
606610

607-
file = popen(cmd, "r");
608-
if (file == NULL) {
609-
fprintf(stderr, "error: beaglebone_blue() failed to run cmd=%s\n", cmd);
610-
syslog(LOG_ERR, "Adafruit_BBIO: error: beaglebone_blue() failed to run cmd=%s\n", cmd);
611-
return -1;
611+
//fprintf(stderr, "beaglebone_blue(): initialized=[%d] retval=[%d]\n", initialized, retval);
612+
if(!initialized) {
613+
initialized = 1;
614+
//fprintf(stderr, "beaglebone_blue(): not initialized\n");
615+
file = popen(cmd, "r");
616+
if (file == NULL) {
617+
fprintf(stderr, "Adafruit_BBIO: error in beaglebone_blue(): failed to run cmd=%s\n", cmd);
618+
syslog(LOG_ERR, "Adafruit_BBIO: error in beaglebone_blue(): failed to run cmd=%s\n", cmd);
619+
return -1;
620+
}
621+
if( fgetc(file) == '1' ) {
622+
retval = 1;
623+
}
624+
pclose(file);
612625
}
613-
blue = fgetc(file);
614-
pclose(file);
615626

616-
if(blue == '1') {
617-
return 1;
618-
} else {
619-
return 0;
620-
}
627+
return retval;
621628
}
622629

623630

test/test_led.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ def set_brightness(self, state, led, name):
1414
prefix = "/sys/class/leds/beaglebone:green:{0}/brightness"
1515
path = prefix.format(led.lower())
1616
value = self.read_led_file(path)
17-
if value < 0:
17+
if value == "":
1818
path = prefix.format(name)
1919
value = self.read_led_file(path)
2020
if state == 1:
@@ -25,16 +25,16 @@ def set_brightness(self, state, led, name):
2525
def read_led_file(self, path):
2626
try:
2727
return open(path).read()
28-
except IOError, e:
28+
except (IOError, e):
2929
if e.errno == errno.ENOENT:
30-
return -1
30+
return ""
3131

3232
def set_all_leds(self, state):
3333
test_leds = { "USR0": "heartbeat", \
3434
"USR1": "mmc0", \
3535
"USR2": "cpu0", \
3636
"USR3": "mmc1" }
37-
for led, name in test_leds.iteritems():
37+
for led, name in test_leds.items():
3838
self.set_brightness(state, led, name)
3939
GPIO.cleanup()
4040

0 commit comments

Comments
 (0)