Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Driver and example for PAT9125EL motion sensor #136

Merged
merged 2 commits into from
Jan 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions examples/nucleo_f429zi/pat9125el/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Copyright (c) 2018 Christopher Durand
*
* This file is part of the modm project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// ----------------------------------------------------------------------------

#include <modm/board.hpp>

#include <modm/processing/timer.hpp>
#include <modm/processing/protothread.hpp>
#include <modm/driver/motion/pat9125el.hpp>

using I2c = I2cMaster1;
using Scl = GpioB8;
using Sda = GpioB9;

// int pin is optional, set to void for polling mode
using Int = GpioInputA5;

class Thread : public modm::pt::Protothread
{
public:
Thread() : sensor{0x75}
{
}

bool
update()
{
PT_BEGIN();

MODM_LOG_INFO << "Ping device" << modm::endl;
// ping the device until it responds
while(true)
{
if (PT_CALL(sensor.ping())) {
break;
}
// otherwise, try again in 100ms
this->timeout.restart(100);
PT_WAIT_UNTIL(this->timeout.isExpired());
}
MODM_LOG_INFO << "Ping successful" << modm::endl;

// set x and y resolution
PT_CALL(sensor.configure(0x14, 0x14));

while (true)
{
PT_CALL(sensor.readData());
if(sensor.hasMoved()) {
position += sensor.getData();

Board::Leds::write(0b111);
MODM_LOG_INFO << "Position: " << position.x << ", " << position.y << modm::endl;
sensor.resetMoved();
} else {
Board::Leds::write(0b000);
}
}

PT_END();
}

private:
modm::ShortTimeout timeout;
modm::pat9125el::Motion2D position;
modm::Pat9125el<modm::Pat9125elI2cTransport<I2c>, Int> sensor;
};

Thread thread;

// ----------------------------------------------------------------------------
int
main()
{
Board::initialize();
Board::Leds::setOutput();

MODM_LOG_INFO << "\n\nPAT9125EL I2C example\n\n";

I2c::connect<Sda::Sda, Scl::Scl>();
I2c::initialize<Board::systemClock, 400'000, modm::Tolerance::TwentyPercent>();

while (1) {
thread.update();
}

return 0;
}
13 changes: 13 additions & 0 deletions examples/nucleo_f429zi/pat9125el/project.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<library>
<extends>modm:board:nucleo-f429zi</extends>
<options>
<option name="modm:build:build.path">../../../build/nucleo_f429zi/pat9125el</option>
</options>
<modules>
<module>modm:driver:pat9125el</module>
<module>modm:io</module>
<module>modm:platform:i2c:1</module>
<module>modm:processing:protothread</module>
<module>modm:build:scons</module>
</modules>
</library>
152 changes: 152 additions & 0 deletions src/modm/driver/motion/pat9125el.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/*
* Copyright (c) 2018, Christopher Durand
*
* This file is part of the modm project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// ----------------------------------------------------------------------------

#ifndef MODM_PAT9125EL_HPP
#define MODM_PAT9125EL_HPP

#include <array>
#include <type_traits>
#include <modm/driver/motion/pat9125el_transport.hpp>
#include <modm/math/geometry/vector2.hpp>

namespace modm
{

/// @ingroup modm_driver_pat9125el
struct pat9125el
{
enum class Register : uint8_t
{
ProductId1 = 0x00,
ProductId2 = 0x01,
MotionStatus = 0x02,
DeltaXLow = 0x03,
DeltaYLow = 0x04,
OperationMode = 0x05,
Configuration = 0x06,
WriteProtect = 0x09,
Sleep1 = 0x0A,
Sleep2 = 0x0B,
ResolutionX = 0x0D,
ResolutionY = 0x0E,
DeltaXYHigh = 0x12,
ShutterTime = 0x14,
AvgBrightness = 0x17,
Orientation = 0x19
};

enum class MotionStatus : uint8_t
{
DataAvailable = (1 << 7)
};
MODM_FLAGS8(MotionStatus);

enum class WriteProtect : uint8_t
{
Enabled = 0,
Disabled = 0x5A
};
MODM_FLAGS8(WriteProtect);

static constexpr uint8_t ProductId1 = 0x31;

using Motion2D = modm::Vector<int16_t, 2>;
};

/**
* Driver for PAT9125EL motion sensor. Currently only the I2C version
* is supported.
*
* @tparam Transport Either I2C or SPi transport layer
* @see Pat9125elI2cTransport
*
* @tparam IntPin Optional interrupt pin. If pin is not connected, set to void.
*
* @todo implement SPI transport layer
* @todo add sensor sleep modes
*
* @author Christopher Durand
* @ingroup modm_driver_pat9125el
*/
template<typename Transport, typename IntPin = void>
class Pat9125el : public pat9125el, public Transport
{
public:
static constexpr bool UseInterruptPin = !std::is_void_v<IntPin>;

/**
* @tparam TransportArgs Arguments forwarded to transport layer
* @see Pat9125elI2cTransport
*/
template<typename... TransportArgs>
Pat9125el(TransportArgs&&... args);

/**
* Configure sensor resolution
*
* @param xResolution x resolution in unit of 5 counts per inch
* @param yResolution y resolution in unit of 5 counts per inch
*/
modm::ResumableResult<bool>
configure(uint8_t xResolution = 0x14, uint8_t yResolution = 0x14);

/**
* Check if the device is available
*/
modm::ResumableResult<bool>
ping();

/**
* Returns the last measured movement data read from the device
*/
Motion2D
getData() const;

/**
* Read movement measurement from the device
*/
modm::ResumableResult<bool>
readData();

/**
* Check if non-zero movement data has been read form the device
*/
bool
hasMoved() const;

void
resetMoved();

private:
modm::ResumableResult<bool>
writeRegister(Register reg, uint8_t data);

modm::ResumableResult<bool>
readRegister(Register reg, uint8_t& data);

modm::ResumableResult<bool>
readRegister(Register reg, uint8_t* data, size_t size);

void
updateData();

Motion2D data = {};
bool moved = false;
uint8_t status = 0;
bool success = true;
std::array<uint8_t, 3> readBuffer = {};
};

}

#include "pat9125el_impl.hpp"

#endif // MODM_PAT9125EL_HPP
33 changes: 33 additions & 0 deletions src/modm/driver/motion/pat9125el.lb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (c) 2018, Christopher Durand
#
# This file is part of the modm project.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# -----------------------------------------------------------------------------


def init(module):
module.parent = "driver"
module.name = "pat9125el"
module.description = "Driver for PAT9125EL motion sensor"

def prepare(module, options):
module.depends(
":architecture:delay",
":architecture:spi",
":architecture:i2c.device",
":math:geometry",
":debug")
return True

def build(env):
env.outbasepath = "modm/src/modm/driver/motion"
env.copy("pat9125el.hpp")
env.copy("pat9125el_impl.hpp")
env.copy("pat9125el_transport.hpp")
env.copy("pat9125el_transport_impl.hpp")
Loading