blob: 489ffc3a196e5253bf23b9369d99c13de170465a [file] [log] [blame]
# Copyright 2019 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""A factory test for reading accelerometers
Description
-----------
This is a test to check if values read back from accelerometers are within a
certain range. If we put it on a flat table we can get (x, y, z) = (0, 0, 9.8)
at an ideal case. For upside down we'll have (x, y, z) = (0, 0, -9.8).
Since accelerometer is very sensitive, the digital output will be different
for each query. For example, (0.325, -0.278, 9.55).
In addition, temperature or the assembly quality may impact the accuracy
of the accelerometer during manufacturing (ex, position is tilt). To mitigate
this kind of errors, we'll sample several records of raw data and compute
its average value under an ideal environment.
Test Procedure
--------------
1. The test will auto start unless argument `autostart` is false, otherwise, it
will wait for operators to press `SPACE`.
2. Check if values are within the threashold, pass / fail automatically.
Dependency
----------
- Device API (``cros.factory.device.accelerometer``)
Examples
--------
If the device is expected to be place horizontally on desk, this test can be
added as simple as::
{
"pytest_name": "accelerometers"
}
You can also change the limits of each axis to loose the criteria::
{
"pytest_name": "accelerometers"
"args": {
"limits": {
"x": [-1.0, 1.0],
"y": [-1.0, 1.0],
"z": [8.0, 11.0]
}
}
}
"""
from six import iteritems
from six import viewkeys
from six.moves import xrange
import factory_common # pylint: disable=unused-import
from cros.factory.device import accelerometer
from cros.factory.device import device_utils
from cros.factory.test.i18n import _
from cros.factory.test import test_case
from cros.factory.test import test_ui
from cros.factory.utils.arg_utils import Arg
from cros.factory.testlog import testlog
DEFAULT_LIMITS = {
'x': [-0.5, 0.5],
'y': [-0.5, 0.5],
'z': [8.8, 10.8],
}
class AccelerometersTest(test_case.TestCase):
ARGS = [
Arg('autostart', bool,
'If this is false, this test will not start until operators press '
'space', default=True),
Arg('limits', dict,
'A dictionary of expected range for x, y, z values. For example, '
'{"x": [-0.5, 0.5], "y": [-0.5, 0.5], "z": [8.8, 10.8]}',
default=None),
Arg('sample_rate_hz', int,
'The sample rate in Hz to get raw data from '
'accelerometers.', default=20),
Arg('capture_count', int,
'How many times to capture the raw data to '
'calculate the average value.', default=100),
Arg('setup_time_secs', int,
'How many seconds to wait before starting '
'to calibration.', default=2),
Arg('location', str,
'The location for the accelerometer', default='base'),
]
def setUp(self):
self.ui.ToggleTemplateClass('font-large', True)
if self.args.limits is None:
self.args.limits = DEFAULT_LIMITS
assert viewkeys(self.args.limits) == {'x', 'y', 'z'}, (
'Limits should be a dictionary with keys "x", "y" and "z"')
for unused_axis, [limit_min, limit_max] in iteritems(self.args.limits):
assert limit_min <= limit_max
self.dut = device_utils.CreateDUTInterface()
self.accelerometer_controller = (
self.dut.accelerometer.GetController(self.args.location))
def runTest(self):
if not self.args.autostart:
self.ui.SetState(_('Press SPACE to continue'))
self.ui.WaitKeysOnce(test_ui.SPACE_KEY)
# Waits for a few seconds to let machine become stable.
for i in xrange(self.args.setup_time_secs):
self.ui.SetState(
_('Test will be started within {secs} seconds. '
'Please do not move the device.',
secs=self.args.setup_time_secs - i))
self.Sleep(1)
self.ui.SetState(_('Test is in progress, please do not move the device.'))
try:
raw_data = self.accelerometer_controller.GetData(self.args.capture_count)
except accelerometer.AccelerometerException:
self.FailTask('Read raw data failed.')
passed = True
for axis, [limit_min, limit_max] in iteritems(self.args.limits):
key = 'in_accel_' + axis # in_accel_(x|y|z)
passed &= testlog.CheckNumericParam(
name=key, value=raw_data[key], min=limit_min, max=limit_max)
if not passed:
self.FailTask('Sensor value out of limit %r' % raw_data)