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

Add driver for AB (incremental) encoder output #153

Merged
merged 2 commits into from
Jun 15, 2020
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
16 changes: 9 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,56 +190,58 @@ can easily configure them for you specific needs.
<td align="center">DS1631</td>
<td align="center">DS18B20</td>
<td align="center">EA-DOG</td>
<td align="center">ENCODER-OUTPUT</td>
<td align="center">FT245</td>
<td align="center">FT6X06</td>
</tr><tr>
<td align="center">FT6X06</td>
<td align="center">HCLAx</td>
<td align="center">HD44780</td>
<td align="center">HMC58x</td>
<td align="center">HMC6343</td>
<td align="center">HX711</td>
<td align="center">I2C-EEPROM</td>
</tr><tr>
<td align="center">I2C-EEPROM</td>
<td align="center">ITG3200</td>
<td align="center">L3GD20</td>
<td align="center">LAWICEL</td>
<td align="center">LIS302DL</td>
<td align="center">LIS3DSH</td>
<td align="center">LM75</td>
</tr><tr>
<td align="center">LM75</td>
<td align="center">LP503X</td>
<td align="center">LSM303A</td>
<td align="center">LTC2984</td>
<td align="center">MAX6966</td>
<td align="center">MAX7219</td>
<td align="center">MCP23X17</td>
</tr><tr>
<td align="center">MCP23X17</td>
<td align="center">MCP2515</td>
<td align="center">NOKIA5110</td>
<td align="center">NRF24</td>
<td align="center">TFT-DISPLAY</td>
<td align="center">PAT9125EL</td>
<td align="center">PCA8574</td>
</tr><tr>
<td align="center">PCA8574</td>
<td align="center">PCA9535</td>
<td align="center">PCA9548A</td>
<td align="center">PCA9685</td>
<td align="center">SIEMENS-S65</td>
<td align="center">SIEMENS-S75</td>
<td align="center">SK6812</td>
</tr><tr>
<td align="center">SK6812</td>
<td align="center">SK9822</td>
<td align="center">SSD1306</td>
<td align="center">SX1276</td>
<td align="center">TCS3414</td>
<td align="center">TCS3472</td>
<td align="center">TLC594X</td>
</tr><tr>
<td align="center">TLC594X</td>
<td align="center">TMP102</td>
<td align="center">TMP175</td>
<td align="center">VL53L0</td>
<td align="center">VL6180</td>
<td align="center">WS2812</td>
</tr><tr>
</tr>
</table>
<!--/drivertable-->
Expand Down
39 changes: 39 additions & 0 deletions examples/stm32f4_discovery/encoder_output/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright (c) 2020, Raphael Lehmann
*
* 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/driver/encoder/encoder_output.hpp>

using namespace Board;

// ----------------------------------------------------------------------------
int
main()
{

initialize();

LedBlue::set();
LedGreen::set();

// period=100000 // 100000us => 10Hz (visible)
using TestEncoder = modm::EncoderOutput<LedBlue, LedGreen, int32_t, modm::PrecisePeriodicTimer, 100'000>;
TestEncoder testEncoder{0};

testEncoder.setPosition(1 << 31);
while (1)
{
testEncoder.update();
LedRed::toggle();
}

return 0;
}
10 changes: 10 additions & 0 deletions examples/stm32f4_discovery/encoder_output/project.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<library>
<extends>modm:disco-f407vg</extends>
<options>
<option name="modm:build:build.path">../../../build/stm32f4_discovery/encoder_output</option>
</options>
<modules>
<module>modm:driver:encoder.output</module>
<module>modm:build:scons</module>
</modules>
</library>
86 changes: 86 additions & 0 deletions src/modm/driver/encoder/encoder_output.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// coding: utf-8
/*
* Copyright (c) 2019, Raphael Lehmann
*
* 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_ENCODER_OUTPUT_HPP
#define MODM_ENCODER_OUTPUT_HPP

#include <modm/processing/timer/periodic_timer.hpp>

namespace modm
{

/**
* @ingroup modm_driver_encoder_output
* @author Raphael Lehmann
*
* @brief This driver generates a AB (incremental) encoder signal to
* emulate a hardware encoder with a microcontroller.
*
* @tparam PinA First modm::platform::Gpio pin to output the encoder signal.
* @tparam PinB Second modm::platform::Gpio pin to output the encoder signal.
* @tparam PositionType Data type (integer) of the position value, default `int32_t`.
* @tparam PeriodicTimer Defaults to `modm::PeriodicTimer`, must be replaced for
* encoder frequencies above 1kHz by a class that offers
* time steps less than 1ms, e.g. `modm::PrecisePeriodicTimer`.
* @tparam period Timebase for the output signal. This limits the maximal
* frequency of the encoder signal. Defaults to `1`.
*/
template <
class PinA,
class PinB,
typename PositionType = int32_t,
class PeriodicTimer = modm::PeriodicTimer,
uint32_t period = 1
>
class EncoderOutput {
public:
/**
* @brief Initializes the Encoder.
*
* Sets pins (PinA and PinB) as output pins.
*
* @param initialValue for the encoder. Useful with unsigned PositionType
* data types. Defaults to 0.
*/
EncoderOutput(PositionType initialValue);

/**
* @brief Update method. Generates the encoder signal.
*
* Call this function in your main loop.
*/
void update();

/**
* @brief Set the position for the encoder.
* @param position The position setpoint for the encoder.
*/
void setPosition(PositionType position) { setpoint = position; };

private:
PositionType setpoint;
PositionType actualValue;
PeriodicTimer timer;
enum class State : uint8_t {
State0,
State1,
State2,
State3,
};
State state;
};

}

#include "encoder_output_impl.hpp"

#endif
33 changes: 33 additions & 0 deletions src/modm/driver/encoder/encoder_output.lb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (c) 2019, Raphael Lehmann
#
# 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 = "encoder.output"
module.description = """\
# Encoder Output
This driver generates a AB (incremental) encoder signal to
emulate a hardware encoder with a microcontroller.
"""

def prepare(module, options):
module.depends(
":architecture:gpio",
":processing:timer")
return True

def build(env):
env.outbasepath = "modm/src/modm/driver/encoder"
env.copy("encoder_output.hpp")
env.copy("encoder_output_impl.hpp")
92 changes: 92 additions & 0 deletions src/modm/driver/encoder/encoder_output_impl.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// coding: utf-8
/*
* Copyright (c) 2019, Raphael Lehmann
*
* 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_ENCODER_OUTPUT_HPP
# error "Don't include this file directly, use 'encoder_output.hpp' instead!"
#endif
#include "encoder_output.hpp"

template <
class PinA,
class PinB,
typename PositionType,
class PeriodicTimer,
uint32_t period
>
modm::EncoderOutput<PinA, PinB, PositionType, PeriodicTimer, period>::EncoderOutput(PositionType initialValue) :
setpoint(initialValue), actualValue(initialValue), timer(period), state(State::State0)
{
PinA::setOutput();
PinB::setOutput();
PinA::set();
PinB::set();
setpoint = initialValue;
actualValue = initialValue;
}

template <
class PinA,
class PinB,
typename PositionType,
class PeriodicTimer,
uint32_t period
>
void
modm::EncoderOutput<PinA, PinB, PositionType, PeriodicTimer, period>::update()
{
if(timer.execute()){
if(setpoint > actualValue) {
// generate forward tick
switch(state) {
case State::State0:
PinA::reset();
state = State::State1;
break;
case State::State1:
PinB::reset();
state = State::State2;
break;
case State::State2:
PinA::set();
state = State::State3;
break;
case State::State3:
PinB::set();
state = State::State0;
break;
}
actualValue++;
}
else if(setpoint < actualValue) {
// generate backward tick
switch(state) {
case State::State0:
PinB::reset();
state = State::State3;
break;
case State::State1:
PinA::reset();
state = State::State0;
break;
case State::State2:
PinB::set();
state = State::State1;
break;
case State::State3:
PinA::set();
state = State::State2;
break;
}
actualValue--;
}
}
}