Skip to content

Commit

Permalink
read twice the first time and immediately after changing channels, on…
Browse files Browse the repository at this point in the history
…ce otherwise. removed the samples constructor parameter
  • Loading branch information
npryce committed Feb 22, 2013
1 parent 566da35 commit 230500d
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 50 deletions.
22 changes: 5 additions & 17 deletions quick2wire/parts/pcf8591.py
Expand Up @@ -59,15 +59,6 @@
because the PCF8591 chip can only detect voltage differences of half
that between its reference voltage and ground.
The PCF8591 uses the successive approximation conversion technique.
The initial sample returned from the chip will be inaccurate and
successive samples will return increasingly accurate measurements.
Thus there is a trade-off between speed and accuracy. The PCF8591
class lets you tune this trade off by setting the number of samples
that are made every time the `value` property is queried by specifying
the `samples` parameter when instantiating the PCF8591 and by
assigning to the `samples` property after construction.
The output channel must be opened before use, to turn on the chip's
D/A converter, and closed when no longer required, to turn it off
again and conserve power. It's easiest to do this with a context
Expand Down Expand Up @@ -104,7 +95,7 @@ class PCF8591(object):
See module documentation for details on how to use this class.
"""

def __init__(self, master, mode, address=BASE_ADDRESS, samples=3):
def __init__(self, master, mode, address=BASE_ADDRESS):
"""Initialises a PCF8591.
Parameters:
Expand All @@ -114,12 +105,9 @@ def __init__(self, master, mode, address=BASE_ADDRESS, samples=3):
THREE_DIFFERENTIAL or SINGLE_ENDED_AND_DIFFERENTIAL.
address -- the I2C address of the PCF8591 chip.
(optional, default = BASE_ADDRESS)
samples -- the number of samples made per query.
(optional, default = 3)
"""
self.master = master
self.address = address
self.samples = samples
self._control_flags = (mode << 4)
self._last_channel_read = None
self._output = _OutputChannel(self)
Expand Down Expand Up @@ -197,12 +185,12 @@ def read_differential(self, channel):

def read_raw(self, channel):
if channel != self._last_channel_read:
self.master.transaction(writing_bytes(self.address, self._control_flags|channel))
self.master.transaction(
writing_bytes(self.address, self._control_flags|channel),
reading(self.address, 1))
self._last_channel_read = channel

for i in range(self.samples):
results = self.master.transaction(reading(self.address, 1))

results = self.master.transaction(reading(self.address, 1))
return results[0][0]


Expand Down
75 changes: 42 additions & 33 deletions quick2wire/parts/test_pcf8591.py
Expand Up @@ -114,20 +114,24 @@ def test_cannot_be_created_with_an_invalid_mode():
PCF8591(i2c, 999)

def test_can_read_a_single_ended_pin():
adc = create_pcf8591(i2c, FOUR_SINGLE_ENDED, samples=1)

adc = create_pcf8591(i2c, FOUR_SINGLE_ENDED)
pin = adc.single_ended_input(2)

i2c.add_response(bytes([64]))
i2c.add_response(bytes([0x80]))
i2c.add_response(bytes([0x40]))

sample = pin.value

assert i2c.request_count == 2

m1, = i2c.request(0)
assert is_write(m1)
assert m1.len == 1
assert m1.buf[0][0] == 0b00000010
m1a,m1b = i2c.request(0)
assert is_write(m1a)
assert m1a.len == 1
assert m1a.buf[0][0] == 0b00000010

assert is_read(m1b)
assert m1b.len == 1

m2, = i2c.request(1)
assert is_read(m2)
Expand All @@ -137,21 +141,27 @@ def test_can_read_a_single_ended_pin():


def test_can_read_a_differential_pin():
adc = create_pcf8591(i2c, THREE_DIFFERENTIAL, samples=1)
adc = create_pcf8591(i2c, THREE_DIFFERENTIAL)

pin = adc.differential_input(1)


i2c.add_response(bytes([0x80]))

# -64 in 8-bit 2's complement representation
i2c.add_response(bytes([0xC0]))

sample = pin.value

assert i2c.request_count == 2

m1, = i2c.request(0)
assert is_write(m1)
assert m1.len == 1
assert m1.buf[0][0] == 0b00010001
m1a,m1b = i2c.request(0)
assert is_write(m1a)
assert m1a.len == 1
assert m1a.buf[0][0] == 0b00010001

assert is_read(m1b)
assert m1b.len == 1

m2, = i2c.request(1)
assert is_read(m2)
Expand Down Expand Up @@ -200,44 +210,43 @@ def test_sends_correct_mode_bits_for_single_ended_and_differential_mode():
assert i2c.request(0)[0].buf[0][0] == 0b00100001


def test_can_be_configured_to_perform_multiple_samples_and_reports_last_one():
adc = create_pcf8591(i2c, FOUR_SINGLE_ENDED, samples=3)
def test_does_not_switch_channel_and_only_reads_once_for_subsequent_reads_from_same_pin():
adc = create_pcf8591(i2c, FOUR_SINGLE_ENDED)

pin = adc.single_ended_input(1)
pin0 = adc.single_ended_input(0)

i2c.add_response(bytes([32]))
i2c.add_response(bytes([64]))
i2c.add_response(bytes([128]))
sample = pin0.value
assert i2c.request_count == 2

sample = pin.value
sample = pin0.value
assert i2c.request_count == 3

assert_is_approx(0.5, sample)
sample = pin0.value
assert i2c.request_count == 4


def test_does_not_write_control_byte_to_switch_channel_if_multiple_reads_from_same_pin():
adc = create_pcf8591(i2c, FOUR_SINGLE_ENDED, samples=1)
def test_switches_channel_and_reads_twice_when_reading_from_different_pin():
adc = create_pcf8591(i2c, FOUR_SINGLE_ENDED)

pin0 = adc.single_ended_input(0)
pin1 = adc.single_ended_input(1)

sample = pin0.value
assert i2c.request_count == 2
ctl1, = i2c.request(0)
assert is_write(ctl1)
assert ctl1.len == 1
assert ctl1.buf[0][0] == 0b00000000

sample = pin0.value
assert i2c.request_count == 3

sample = pin1.value
assert i2c.request_count == 5

ctl2, = i2c.request(3)
assert is_write(ctl2)
assert ctl2.len == 1
assert ctl2.buf[0][0] == 0b00000001

ma,mb = i2c.request(3)
assert is_write(ma)
assert ma.len == 1
assert ma.buf[0][0] == 0b00000001
assert is_read(mb)
assert mb.len == 1


def test_opening_and_closing_the_output_pin_turns_the_digital_to_analogue_converter_on_and_off():
adc = create_pcf8591(i2c, FOUR_SINGLE_ENDED)
Expand Down Expand Up @@ -267,7 +276,7 @@ def test_output_pin_opens_and_closes_itself_when_used_as_a_context_manager():


def test_setting_value_of_output_pin_sends_value_as_second_written_byte():
adc = create_pcf8591(i2c, FOUR_SINGLE_ENDED, samples=1)
adc = create_pcf8591(i2c, FOUR_SINGLE_ENDED)

with adc.output as pin:
pin.value = 0.5
Expand All @@ -289,7 +298,7 @@ def test_setting_value_of_output_pin_sends_value_as_second_written_byte():


def test_setting_value_of_output_pin_does_not_affect_currently_selected_input_pin():
adc = create_pcf8591(i2c, FOUR_SINGLE_ENDED, samples=1)
adc = create_pcf8591(i2c, FOUR_SINGLE_ENDED)

with adc.output as opin:
assert i2c.request_count == 1
Expand Down

0 comments on commit 230500d

Please sign in to comment.