Skip to content

Commit

Permalink
✨ (libs): Add TouchSensorKit
Browse files Browse the repository at this point in the history
  • Loading branch information
MMyster committed Jun 28, 2022
1 parent e37fa96 commit 2ac100d
Show file tree
Hide file tree
Showing 5 changed files with 372 additions and 0 deletions.
31 changes: 31 additions & 0 deletions libs/TouchSensorKit/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Leka - LekaOS
# Copyright 2022 APF France handicap
# SPDX-License-Identifier: Apache-2.0

add_library(TouchSensorKit STATIC)

target_include_directories(TouchSensorKit
PUBLIC
include
)

target_sources(TouchSensorKit
PRIVATE
source/TouchSensorKit.cpp
)

target_link_libraries(TouchSensorKit
mbed-os
IOKit
CoreI2C
CoreIOExpander
CoreDACTouch
)

if (${CMAKE_PROJECT_NAME} STREQUAL "LekaOSUnitTests")

leka_unit_tests_sources(
tests/TouchSensorKit_test.cpp
)

endif()
74 changes: 74 additions & 0 deletions libs/TouchSensorKit/include/TouchSensorKit.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Leka - LekaOS
// Copyright 2022 APF France handicap
// SPDX-License-Identifier: Apache-2.0

#pragma once

#include "CoreDACTouch.h"
#include "CoreI2C.h"
#include "CoreIOExpander.h"
#include "DigitalOut.h"
#include "IOKit/DigitalIn.h"
#include "IOKit/DigitalOut.h"
#include "LogKit.h"
#include "internal/TouchSensorSystem.h"

namespace leka {

class TouchSensorKit
{
public:
explicit TouchSensorKit() = default;
void setup();

void updateState();
void printState();

void resetByPowerMode();

void adjust_sensivity(uint16_t value);
void calibration();

private:
void setPullMode(PinMode mode);

void setPowerMode(int power_mode);

void initDACTouch();

void calibrateTwoSensors(bool &sensor_left, bool &sensor_right, uint8_t channel);
void calibrateEars();
void calibrateBeltLBRF();
void calibrateBeltRBLF();

CoreI2C corei2c {PinName::SENSOR_PROXIMITY_MUX_I2C_SDA, PinName::SENSOR_PROXIMITY_MUX_I2C_SCL};
mbed::DigitalOut io_expander_reset {PinName::SENSOR_PROXIMITY_MUX_RESET, 0};
CoreIOExpanderMCP23017 io_expander {corei2c, io_expander_reset};
CoreDACTouchMCP4728 dac_touch_left {corei2c, 0xC0};
CoreDACTouchMCP4728 dac_touch_right {corei2c, 0xC2};

leka::io::expanded::DigitalIn<> _ear_left_input {io_expander, touch::pin::ear_left_input};
leka::io::expanded::DigitalIn<> _ear_right_input {io_expander, touch::pin::ear_right_input};
leka::io::expanded::DigitalIn<> _belt_left_back_input {io_expander, touch::pin::belt_left_back_input};
leka::io::expanded::DigitalIn<> _belt_left_front_input {io_expander, touch::pin::belt_left_front_input};
leka::io::expanded::DigitalIn<> _belt_right_back_input {io_expander, touch::pin::belt_right_back_input};
leka::io::expanded::DigitalIn<> _belt_right_front_input {io_expander, touch::pin::belt_right_front_input};

leka::io::expanded::DigitalOut<> _ear_left_pm {io_expander, touch::pin::ear_left_power_mode};
leka::io::expanded::DigitalOut<> _ear_right_pm {io_expander, touch::pin::ear_right_power_mode};
leka::io::expanded::DigitalOut<> _belt_left_back_pm {io_expander, touch::pin::belt_left_back_power_mode};
leka::io::expanded::DigitalOut<> _belt_left_front_pm {io_expander, touch::pin::belt_left_front_power_mode};
leka::io::expanded::DigitalOut<> _belt_right_back_pm {io_expander, touch::pin::belt_right_back_power_mode};
leka::io::expanded::DigitalOut<> _belt_right_front_pm {io_expander, touch::pin::belt_right_front_power_mode};

bool _ear_left_touched {false};
bool _ear_right_touched {false};
bool _belt_left_back_touched {false};
bool _belt_left_front_touched {false};
bool _belt_right_back_touched {false};
bool _belt_right_front_touched {false};

uint16_t default_max_value_calib {0x0FFF};
uint16_t default_min_value_calib {0x0000};
};
} // namespace leka
33 changes: 33 additions & 0 deletions libs/TouchSensorKit/include/external/TouchSensorSystem.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Leka - LekaOS
// Copyright 2022 APF France handicap
// SPDX-License-Identifier: Apache-2.0

#pragma once

#include "CoreIOExpander.h"

namespace leka::touch {

namespace pin {
inline constexpr auto ear_left_input = uint16_t {leka::mcp23017::pin::PB5};
inline constexpr auto ear_right_input = uint16_t {leka::mcp23017::pin::PB4};
inline constexpr auto belt_left_back_input = uint16_t {leka::mcp23017::pin::PB3};
inline constexpr auto belt_left_front_input = uint16_t {leka::mcp23017::pin::PB2};
inline constexpr auto belt_right_back_input = uint16_t {leka::mcp23017::pin::PB1};
inline constexpr auto belt_right_front_input = uint16_t {leka::mcp23017::pin::PB0};

inline constexpr auto ear_left_power_mode = uint16_t {leka::mcp23017::pin::PA5};
inline constexpr auto ear_right_power_mode = uint16_t {leka::mcp23017::pin::PA4};
inline constexpr auto belt_left_back_power_mode = uint16_t {leka::mcp23017::pin::PA3};
inline constexpr auto belt_left_front_power_mode = uint16_t {leka::mcp23017::pin::PA2};
inline constexpr auto belt_right_back_power_mode = uint16_t {leka::mcp23017::pin::PA1};
inline constexpr auto belt_right_front_power_mode = uint16_t {leka::mcp23017::pin::PA0};
} // namespace pin

namespace power_mode {
inline constexpr auto low = uint16_t {0x00};
inline constexpr auto normal = uint16_t {0x01};

} // namespace power_mode

} // namespace leka::touch
185 changes: 185 additions & 0 deletions libs/TouchSensorKit/source/TouchSensorKit.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
// Leka - LekaOS
// Copyright 2022 APF France handicap
// SPDX-License-Identifier: Apache-2.0

#include "TouchSensorKit.h"

#include "rtos/ThisThread.h"

using namespace leka;
using namespace std::chrono_literals;

void TouchSensorKit::setup()
{
setPullMode(PinMode::PullUp);
setPowerMode(touch::power_mode::normal);
initDACTouch();
}

void TouchSensorKit::updateState()
{
_ear_left_touched = (0 == _ear_left_input.read());
_ear_right_touched = (0 == _ear_right_input.read());
_belt_left_back_touched = (0 == _belt_left_back_input.read());
_belt_left_front_touched = (0 == _belt_left_front_input.read());
_belt_right_back_touched = (0 == _belt_right_back_input.read());
_belt_right_front_touched = (0 == _belt_right_front_input.read());
}

void TouchSensorKit::printState()
{
log_info("Ear left touched: %s", _ear_left_touched ? "true" : "false");
log_info("Ear right touched: %s", _ear_right_touched ? "true" : "false");
log_info("Belt left front touched: %s", _belt_left_front_touched ? "true" : "false");
log_info("Belt left back touched: %s", _belt_left_back_touched ? "true" : "false");
log_info("Belt right front touched: %s", _belt_right_front_touched ? "true" : "false");
log_info("Belt right back touched: %s", _belt_right_back_touched ? "true" : "false");
}

void TouchSensorKit::resetByPowerMode()
{
setPowerMode(touch::power_mode::low);
rtos::ThisThread::sleep_for(5ms);
setPowerMode(touch::power_mode::normal);
rtos::ThisThread::sleep_for(5ms);
}

void TouchSensorKit::setPullMode(PinMode mode)
{
_ear_left_input.mode(mode);
_ear_right_input.mode(mode);
_belt_left_back_input.mode(mode);
_belt_left_front_input.mode(mode);
_belt_right_back_input.mode(mode);
_belt_right_front_input.mode(mode);
}

void TouchSensorKit::setPowerMode(int power_mode)
{
_ear_left_pm.write(power_mode);
_ear_right_pm.write(power_mode);
_belt_left_back_pm.write(power_mode);
_belt_left_front_pm.write(power_mode);
_belt_right_back_pm.write(power_mode);
_belt_right_front_pm.write(power_mode);
}

void TouchSensorKit::initDACTouch()
{
dac_touch_left.writeVoltageReference(0x00);
dac_touch_left.writePowerMode(0x00);
dac_touch_left.writeGain(0x00);
dac_touch_right.writeVoltageReference(0x00);
dac_touch_right.writePowerMode(0x00);
dac_touch_right.writeGain(0x00);
}

void TouchSensorKit::adjust_sensivity(uint16_t value)
{
auto buffer = std::array<uint8_t, 2> {};

buffer.at(0) = static_cast<uint8_t>((0x0F00 & value) >> 8);
buffer.at(1) = static_cast<uint8_t>(0x00FF & value);

dac_touch_left.writeToSpecificInputRegister(0, buffer);
dac_touch_right.writeToSpecificInputRegister(0, buffer);

dac_touch_left.writeToSpecificInputRegister(1, buffer);
dac_touch_right.writeToSpecificInputRegister(1, buffer);

dac_touch_left.writeToSpecificInputRegister(2, buffer);
dac_touch_right.writeToSpecificInputRegister(2, buffer);
rtos::ThisThread::sleep_for(1ms);
}

void TouchSensorKit::calibrateTwoSensors(bool &sensor_left, bool &sensor_right, uint8_t channel)
{
auto buffer_left = std::array<uint8_t, 2> {};
auto buffer_right = std::array<uint8_t, 2> {};

dac_touch_left.writeToSpecificInputRegister(channel, buffer_left);
dac_touch_right.writeToSpecificInputRegister(channel, buffer_right);
rtos::ThisThread::sleep_for(1ms);

auto value_left_calib = uint16_t {default_max_value_calib};
auto value_right_calib = uint16_t {default_max_value_calib};
auto step = uint8_t {0x00FF};

updateState();

while (!((sensor_left || value_left_calib <= value_left_calib % step) &&
(sensor_right || value_right_calib <= value_right_calib % step))) {
if (!sensor_left) {
if (value_left_calib - step > default_max_value_calib) {
value_left_calib = default_max_value_calib;
} else {
value_left_calib -= step;
}
}
if (!sensor_right) {
if (value_right_calib - step > default_max_value_calib) {
value_right_calib = default_max_value_calib;
} else {
value_right_calib -= step;
}
}

buffer_left.at(0) = static_cast<uint8_t>((0x0F00 & value_left_calib) >> 8);
buffer_left.at(1) = static_cast<uint8_t>(0x00FF & value_left_calib);
dac_touch_left.writeToSpecificInputRegister(channel, buffer_left);
rtos::ThisThread::sleep_for(1ms);

buffer_right.at(0) = static_cast<uint8_t>((0x0F00 & value_right_calib) >> 8);
buffer_right.at(1) = static_cast<uint8_t>(0x00FF & value_right_calib);
dac_touch_right.writeToSpecificInputRegister(channel, buffer_right);
rtos::ThisThread::sleep_for(1ms);

updateState();
rtos::ThisThread::sleep_for(500ms);
}

dac_touch_left.writeToSpecificMemoryRegister(channel, buffer_left);
dac_touch_right.writeToSpecificMemoryRegister(channel, buffer_right);
rtos::ThisThread::sleep_for(1ms);
log_info("Value Left Calibration : %d", value_left_calib);
log_info("Value Right Calibration : %d", value_right_calib);
log_info("CALIBRATED!");
rtos::ThisThread::sleep_for(1ms);
}

void TouchSensorKit::calibrateEars()
{
log_info("Place hands on EAR LEFT and EAR RIGHT");
log_info("Calibration will start in 5 seconds");
rtos::ThisThread::sleep_for(5s);
calibrateTwoSensors(_ear_left_touched, _ear_right_touched, 2);
}

void TouchSensorKit::calibrateBeltLBRF()
{
log_info("Place hands on BELT LEFT BACK and BELT RIGHT FRONT");
log_info("Calibration will start in 5 seconds");
rtos::ThisThread::sleep_for(5s);
calibrateTwoSensors(_belt_left_back_touched, _belt_right_front_touched, 1);
}

void TouchSensorKit::calibrateBeltRBLF()
{
log_info("Place hands on BELT LEFT FRONT and BELT RIGHT BACK");
log_info("Calibration will start in 5 seconds");
rtos::ThisThread::sleep_for(5s);
calibrateTwoSensors(_belt_left_front_touched, _belt_right_back_touched, 0);
}

void TouchSensorKit::calibration()
{
log_info("Touch calibration");
log_info("For each of 6 touch sensors, value of sensibility will change");
log_info("Please keep your hands on 2 sensors until \"CALIBRATED !\" appears.\n");
rtos::ThisThread::sleep_for(5s);

calibrateEars();
calibrateBeltLBRF();
calibrateBeltRBLF();
rtos::ThisThread::sleep_for(1s);
}
49 changes: 49 additions & 0 deletions libs/TouchSensorKit/tests/TouchSensorKit_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Leka - LekaOS
// Copyright 2022 APF France handicap
// SPDX-License-Identifier: Apache-2.0

#include "TouchSensorKit.h"

#include "gtest/gtest.h"

using namespace leka;
// using ::testing::_;

class TouchSensorTest : public ::testing::Test
{
protected:
// void SetUp() override {}
// void TearDown() override {}

TouchSensorKit touch_sensor_kit = TouchSensorKit();
};

TEST_F(TouchSensorTest, initializationDefault)
{
ASSERT_NE(&touch_sensor_kit, nullptr);
}

TEST_F(TouchSensorTest, setup)
{
touch_sensor_kit.setup();
}

TEST_F(TouchSensorTest, updateState)
{
touch_sensor_kit.updateState();
}

TEST_F(TouchSensorTest, printState)
{
touch_sensor_kit.printState();
}

TEST_F(TouchSensorTest, resetByPowerMode)
{
touch_sensor_kit.resetByPowerMode();
}

TEST_F(TouchSensorTest, calibration)
{
touch_sensor_kit.caliration();
}

0 comments on commit 2ac100d

Please sign in to comment.