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] Adding AS5047 driver and example #1138

Merged
merged 1 commit into from
Mar 8, 2024
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
29 changes: 15 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -720,100 +720,101 @@ your specific needs.
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ads816x">ADS816x</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ams5915">AMS5915</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-apa102">APA102</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-as5047">AS5047</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-at24mac402">AT24MAC402</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-block-device-spi-flash">SPI Flash</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-block-device-spi-flash">SPI Flash</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-bme280">BME280</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-bmi088">BMI088</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-bmp085">BMP085</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-bno055">BNO055</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-cat24aa">CAT24AA</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-cycle_counter">CYCLE-COUNTER</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-cycle_counter">CYCLE-COUNTER</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-drv832x_spi">DRV832X</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ds1302">DS1302</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ds1631">DS1631</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ds18b20">DS18B20</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ea_dog">EA-DOG</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-encoder_input">Encoder Input</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-encoder_input">Encoder Input</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-encoder_input-bitbang">Encoder Input BitBang</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-encoder_output-bitbang">Encoder Output BitBang</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ft245">FT245</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ft6x06">FT6x06</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-gpio_sampler">Gpio Sampler</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-hclax">HCLAx</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-hclax">HCLAx</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-hd44780">HD44780</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-hmc58x">HMC58x</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-hmc6343">HMC6343</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-hx711">HX711</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-i2c-eeprom">I2C-EEPROM</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ili9341">ILI9341</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ili9341">ILI9341</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-is31fl3733">IS31FL3733</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-itg3200">ITG3200</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ixm42xxx">IXM42XXX</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-l3gd20">L3GD20</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-lan8720a">LAN8720A</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-lawicel">LAWICEL</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-lawicel">LAWICEL</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-lis302dl">LIS302DL</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-lis3dsh">LIS3DSH</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-lis3mdl">LIS3MDL</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-lm75">LM75</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-lp503x">LP503x</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-lsm303a">LSM303A</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-lsm303a">LSM303A</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-lsm6ds33">LSM6DS33</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-lsm6dso">LSM6DSO</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ltc2984">LTC2984</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-max31855">MAX31855</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-max31865">MAX31865</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-max6966">MAX6966</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-max6966">MAX6966</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-max7219">MAX7219</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-mcp23x17">MCP23x17</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-mcp2515">MCP2515</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-mcp3008">MCP3008</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-mcp7941x">MCP7941x</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-mcp990x">MCP990X</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-mcp990x">MCP990X</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-mmc5603">MMC5603</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ms5611">MS5611</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ms5837">MS5837</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-nokia5110">NOKIA5110</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-nrf24">NRF24</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-parallel_tft_display">TFT-DISPLAY</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-parallel_tft_display">TFT-DISPLAY</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-pat9125el">PAT9125EL</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-pca8574">PCA8574</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-pca9535">PCA9535</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-pca9548a">PCA9548A</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-pca9685">PCA9685</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-qmc5883l">QMC5883L</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-qmc5883l">QMC5883L</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-sh1106">SH1106</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-siemens_s65">SIEMENS-S65</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-siemens_s75">SIEMENS-S75</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-sk6812">SK6812</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-sk9822">SK9822</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ssd1306">SSD1306</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ssd1306">SSD1306</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-st7586s">ST7586S</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-st7789">ST7789</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-stts22h">STTS22H</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-stusb4500">STUSB4500</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-sx1276">SX1276</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-sx128x">SX128X</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-sx128x">SX128X</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tcs3414">TCS3414</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tcs3472">TCS3472</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tlc594x">TLC594x</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tmp102">TMP102</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tmp12x">TMP12x</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tmp175">TMP175</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tmp175">TMP175</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-touch2046">TOUCH2046</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-vl53l0">VL53L0</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-vl6180">VL6180</a></td>
Expand Down
79 changes: 79 additions & 0 deletions examples/nucleo_g474re/as5047/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// coding: utf-8
/*
* Copyright (c) 2024, Henrik Hose
*
* 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/as5047.hpp>
#include <modm/processing.hpp>

using SpiMaster = SpiMaster1;

using Cs = modm::platform::GpioB10;
using Mosi = modm::platform::GpioB5;
using Miso = modm::platform::GpioB4;
using Sck = modm::platform::GpioB3;

using namespace Board;
using namespace modm::literals;

class EncoderThread : public modm::pt::Protothread
{
public:
EncoderThread() : encoder(data) {}

bool
run()
{
PT_BEGIN();

while (true)
{
PT_CALL(encoder.readout());

MODM_LOG_INFO << "\nNew readout:" << modm::endl;
MODM_LOG_INFO << " angle degree: " << data.getAngleDeg() << " degrees" << modm::endl;
MODM_LOG_INFO << " angle rad: " << data.getAngleRad() << " radians" << modm::endl;
MODM_LOG_INFO << " angle raw: " << data.getAngleRaw() << modm::endl;

timeout.restart(std::chrono::milliseconds(500));
PT_WAIT_UNTIL(timeout.isExpired());
}

PT_END();
}

private:
modm::as5047::Data data;
modm::As5047<SpiMaster, Cs> encoder;

modm::ShortTimeout timeout;
} encoderThread;

int
main()
{
Board::initialize();

Cs::setOutput(modm::Gpio::High);

SpiMaster::connect<Miso::Miso, Mosi::Mosi, Sck::Sck>();
SpiMaster::initialize<Board::SystemClock, 1.3_MHz>();

MODM_LOG_INFO << "==========AS5047 Test==========" << modm::endl;
MODM_LOG_DEBUG << "Debug logging here" << modm::endl;
MODM_LOG_INFO << "Info logging here" << modm::endl;
MODM_LOG_WARNING << "Warning logging here" << modm::endl;
MODM_LOG_ERROR << "Error logging here" << modm::endl;
MODM_LOG_INFO << "===============================" << modm::endl;

while (true) { encoderThread.run(); }

return 0;
}
14 changes: 14 additions & 0 deletions examples/nucleo_g474re/as5047/project.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<library>
<extends>modm:nucleo-g474re</extends>
<options>
<option name="modm:build:build.path">../../../build/nucleo_g474re/as5047</option>
</options>
<modules>
<module>modm:driver:as5047</module>
<module>modm:platform:gpio</module>
<module>modm:platform:spi:1</module>
<module>modm:processing:protothread</module>
<module>modm:processing:timer</module>
<module>modm:build:scons</module>
</modules>
</library>
157 changes: 157 additions & 0 deletions src/modm/driver/encoder/as5047.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
// coding: utf-8
// ----------------------------------------------------------------------------
/*
* Copyright (c) 2024, Henrik Hose
*
* 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_AS5047_HPP
#define MODM_AS5047_HPP

#include <array>
#include <modm/architecture/interface/register.hpp>
#include <modm/architecture/interface/spi_device.hpp>
#include <modm/processing/resumable.hpp>
#include <modm/processing/timer.hpp>
#include <numbers>

namespace modm
{

/// @cond
namespace detail
{
constexpr uint16_t
as5047_setMsbToEvenParity(const uint16_t num)
{
uint16_t par = 0x7fff & num;
par ^= par >> 8;
par ^= par >> 4;
par ^= par >> 2;
par ^= par >> 1;
return ((par & 1) << 15) | (0x7fff & num);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the modm namespace which is quite generic. Would be good to move to struct as5047 or put into the relevant :math module.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure, how to move it into the struct?

If I declare `setMsbToEvenParity` as `static constexpr` in the `as5047` struct, I get an error saying `error: 'static constexpr uint16_t modm::as5047::setMsbToEvenParity(uint16_t)' used before its definition`
struct as5047
{
	enum class Errorfl : uint16_t
	{
		Parerr = Bit2,
		Invcomm = Bit1,
		Frerr = Bit0,
	};
	MODM_FLAGS16(Errorfl)

	enum class Prog : uint16_t
	{
		Progver = Bit6,
		Progotp = Bit3,
		Otpref = Bit2,
		Progen = Bit0,
	};
	MODM_FLAGS16(Prog)

	enum class Diaagc : uint16_t
	{
		Magl = Bit11,
		Magh = Bit10,
		Cof = Bit9,
		Lf = Bit8,
	};
	MODM_FLAGS16(Diaagc)

	static constexpr uint16_t
	setMsbToEvenParity(const uint16_t num)
	{
		uint16_t par = 0x7fff & num;
		par ^= par >> 8;
		par ^= par >> 4;
		par ^= par >> 2;
		par ^= par >> 1;
		return ((par & 1) << 15) | (0x7fff & num);
	}

	enum class Register : uint16_t
	{
		ReadNop = setMsbToEvenParity(((1 << 14) | 0x0000)),
		ReadErrfl = setMsbToEvenParity(((1 << 14) | 0x0001)),
		ReadProg = setMsbToEvenParity(((1 << 14) | 0x0003)),
		ReadDiaagc = setMsbToEvenParity(((1 << 14) | 0x3FFC)),
		ReadMag = setMsbToEvenParity(((1 << 14) | 0x3FFD)),
		ReadAngleunc = setMsbToEvenParity(((1 << 14) | 0x3FFE)),
		ReadAnglecom = setMsbToEvenParity(((1 << 14) | 0x3FFF)),

	};

	struct modm_packed Data
	{
		/// @return
		constexpr float
		getAngleRad() const
		{
			const uint16_t angle = data & 0x3fff;
			return static_cast<float>(angle) / 16383.f * 2.f * std::numbers::pi_v<float>;
		}

		/// @return
		constexpr float
		getAngleDeg() const
		{
			const uint16_t angle = data & 0x3fff;
			return static_cast<float>(angle) / 16383.f * 360.f;
		}

		/// @return
		constexpr uint16_t
		getAngleRaw() const
		{
			const uint16_t angle = data & 0x3fff;
			return angle;
		}

		uint16_t data;
	};
};  // struct as5047

I think this might be related to this:

The Standard should make clear that a constexpr member function cannot be used in a constant expression until its class is complete.

Do you have any suggestions?
Should I put everything into an as5047 namespace?

I don't think moving the function as is to the math: is appropriate, since the function specifically calculates and sets bit 15 of a uint16_t, if moved to math:, a more generic version might be more appropriate. Also, other modm modules like etlcpp have their own functions to calculate parity bits...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ugh, C++ amiright!1!!

You can put it into a modm::details namespace then and use /// @cond and /// @endcond to block doxypress from indexing it (Examples). Prolly prefix the function with as5047_ to avoid collisions if you wanna be super careful.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ugh, C++ amiright!1!!

🐈 No we are super careful 🐱

} // namespace detail
/// @endcond

/// @ingroup modm_driver_as5047
struct as5047
{
enum class Errorfl : uint16_t
{
Parerr = Bit2,
Invcomm = Bit1,
Frerr = Bit0,
};
MODM_FLAGS16(Errorfl)

enum class Prog : uint16_t
{
Progver = Bit6,
Progotp = Bit3,
Otpref = Bit2,
Progen = Bit0,
};
MODM_FLAGS16(Prog)

enum class Diaagc : uint16_t
{
Magl = Bit11,
Magh = Bit10,
Cof = Bit9,
Lf = Bit8,
};
MODM_FLAGS16(Diaagc)

enum class Register : uint16_t
{
ReadNop = detail::as5047_setMsbToEvenParity(((1 << 14) | 0x0000)),
ReadErrfl = detail::as5047_setMsbToEvenParity(((1 << 14) | 0x0001)),
ReadProg = detail::as5047_setMsbToEvenParity(((1 << 14) | 0x0003)),
ReadDiaagc = detail::as5047_setMsbToEvenParity(((1 << 14) | 0x3FFC)),
ReadMag = detail::as5047_setMsbToEvenParity(((1 << 14) | 0x3FFD)),
ReadAngleunc = detail::as5047_setMsbToEvenParity(((1 << 14) | 0x3FFE)),
ReadAnglecom = detail::as5047_setMsbToEvenParity(((1 << 14) | 0x3FFF)),

};

struct modm_packed Data
{
/// @return
constexpr float
getAngleRad() const
{
const uint16_t angle = data & 0x3fff;
return static_cast<float>(angle) / 16383.f * 2.f * std::numbers::pi_v<float>;
}

/// @return
constexpr float
getAngleDeg() const
{
const uint16_t angle = data & 0x3fff;
return static_cast<float>(angle) / 16383.f * 360.f;
}

/// @return
constexpr uint16_t
getAngleRaw() const
{
const uint16_t angle = data & 0x3fff;
return angle;
}

uint16_t data;
};
}; // struct as5047

/**
* @tparam SpiMaster
* @tparam Cs
*
* @author Henrik Hose
* @ingroup modm_driver_as5047
*/
template<typename SpiMaster, typename Cs>
class As5047 : public as5047, public modm::SpiDevice<SpiMaster>, protected modm::NestedResumable<5>
{
public:
using Data = as5047::Data;

/**
* @param data pointer to buffer of the internal data of type Data
*/
As5047(Data &data);

/// Call this function once before using the device
modm::ResumableResult<void>
initialize();

/// Read the raw data from the sensor
modm::ResumableResult<void>
readout();

/// Get the data object for this sensor
inline Data &
getData()
{
return data;
}

private:
Data &data;
uint8_t inBuffer[2];
uint8_t outBuffer[2];
};

} // namespace modm

#include "as5047_impl.hpp"

#endif // MODM_AS5047_HPP
Loading