From d22b8a53faef5e838a4ebccbca564de89b4d303a Mon Sep 17 00:00:00 2001 From: t0mpr1c3 Date: Fri, 29 Sep 2023 16:56:49 -0400 Subject: [PATCH] async analog read --- .gitmodules | 3 + lib/AnalogReadAsync | 1 + src/ayab/encoders.cpp | 193 +++++++++++++++++++--------------- src/ayab/encoders.h | 6 ++ src/ayab/global_encoders.cpp | 8 ++ test/CMakeLists.txt | 1 + test/mocks/asynchAnalogRead.h | 27 +++++ 7 files changed, 155 insertions(+), 84 deletions(-) create mode 160000 lib/AnalogReadAsync create mode 100644 test/mocks/asynchAnalogRead.h diff --git a/.gitmodules b/.gitmodules index 2eaf3e3ca..4157c19fb 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,3 +10,6 @@ active = true path = lib/avr-libc url = https://github.com/avrdudes/avr-libc.git +[submodule "lib/AnalogReadAsync"] + path = lib/AnalogReadAsync + url = https://github.com/boothinator/AnalogReadAsync diff --git a/lib/AnalogReadAsync b/lib/AnalogReadAsync new file mode 160000 index 000000000..b97e43bb3 --- /dev/null +++ b/lib/AnalogReadAsync @@ -0,0 +1 @@ +Subproject commit b97e43bb34bf8f5c8312e8fc5728314a9384192b diff --git a/src/ayab/encoders.cpp b/src/ayab/encoders.cpp index 2d6fde150..33c9052d5 100644 --- a/src/ayab/encoders.cpp +++ b/src/ayab/encoders.cpp @@ -24,6 +24,7 @@ */ #include +#include #include "encoders.h" @@ -75,6 +76,111 @@ void Encoders::isr() { m_oldState = currentState; } +/*! + * \brief Callback from interrupt service subroutine. + * + * Hall value is used to detect whether carriage is in front of Left Hall sensor + */ +void Encoders::hallLeftCallback(uint16_t hallValue, void *data) { + (void) data; // unused + + // Update direction + m_direction = digitalRead(ENC_PIN_B) ? Direction_t::Right : Direction_t::Left; + + // Update carriage position + if ((Direction_t::Right == m_direction) && (m_position < END_RIGHT[static_cast(m_machineType)])) { + m_position = m_position + 1; + } + + if ((hallValue < FILTER_L_MIN[static_cast(m_machineType)]) || + (hallValue > FILTER_L_MAX[static_cast(m_machineType)])) { + // In front of Left Hall Sensor + m_hallActive = Direction_t::Left; + + Carriage detected_carriage = Carriage_t::NoCarriage; + uint8_t start_position = END_LEFT_PLUS_OFFSET[static_cast(m_machineType)]; + + if (hallValue >= FILTER_L_MIN[static_cast(m_machineType)]) { + detected_carriage = Carriage_t::Knit; + } else { + detected_carriage = Carriage_t::Lace; + } + + if (m_machineType == Machine_t::Kh270) { + // KH270 uses Knit carriage only + m_carriage = Carriage_t::Knit; + + // Belt shift is ignored for KH270 + + // The first magnet on the carriage looks like Lace, the second looks like Knit + if (detected_carriage == Carriage_t::Knit) { + m_position = start_position + MAGNET_DISTANCE_270; + } else { + m_position = start_position; + } + } else if ((m_carriage != Carriage_t::NoCarriage) && (m_carriage != detected_carriage) && (m_position > start_position)) { + // Garter carriage detected + m_carriage = Carriage_t::Garter; + + // Belt shift and start position were set when the first magnet passed + // the sensor and we assumed we were working with a standard carriage. + return; + } else { + // Knit or Lace carriage detected, machine is not KH270 + m_carriage = detected_carriage; + + // Belt shift signal only decided in front of Hall sensor + m_beltShift = digitalRead(ENC_PIN_C) ? BeltShift::Regular : BeltShift::Shifted; + + // Carriage is known to be in front of the Hall sensor so overwrite position + m_position = start_position; + } + } +} + +/*! + * \brief Callback from interrupt service subroutine. + * + * Hall value is used to detect whether carriage is in front of Right Hall sensor + */ +void Encoders::hallRightCallback(uint16_t hallValue, void *data) { + (void) data; // unused + + // Update direction + m_direction = digitalRead(ENC_PIN_B) ? Direction_t::Left : Direction_t::Right; + + // Update carriage position + if ((Direction_t::Left == m_direction) && (m_position > END_LEFT[static_cast(m_machineType)])) { + m_position = m_position - 1; + } + + // Avoid 'comparison of unsigned expression < 0 is always false' + // by being explicit about that behaviour being expected. + bool hallValueSmall = false; + hallValueSmall = (hallValue < FILTER_R_MIN[static_cast(m_machineType)]); + + if (hallValueSmall || (hallValue > FILTER_R_MAX[static_cast(m_machineType)])) { + // In front of Right Hall Sensor + m_hallActive = Direction_t::Right; + + // The Garter carriage has a second set of magnets that are going to + // pass the sensor and will reset state incorrectly if allowed to + // continue. + if (hallValueSmall && (m_carriage != Carriage_t::Garter)) { + m_carriage = Carriage_t::Knit; + } + + // Belt shift is ignored for KH270 + if (m_machineType != Machine_t::Kh270) { + // Belt shift signal only decided in front of Hall sensor + m_beltShift = digitalRead(ENC_PIN_C) ? BeltShift::Shifted : BeltShift::Regular; + } + + // Known position of the carriage -> overwrite position + m_position = END_RIGHT_MINUS_OFFSET[static_cast(m_machineType)]; + } +} + /*! * \brief Read Hall sensor on left and right. * \param pSensor Which sensor to read (left or right). @@ -132,7 +238,7 @@ Machine_t Encoders::getMachineType() { return m_machineType; } -// Private Methods +// Private methods /*! * \brief Interrupt service subroutine. @@ -142,14 +248,6 @@ Machine_t Encoders::getMachineType() { * Bounds on `m_machineType` not checked. */ void Encoders::encA_rising() { - // Update direction - m_direction = digitalRead(ENC_PIN_B) ? Direction_t::Right : Direction_t::Left; - - // Update carriage position - if ((Direction_t::Right == m_direction) && (m_position < END_RIGHT[static_cast(m_machineType)])) { - m_position = m_position + 1; - } - // The garter carriage has a second set of magnets that are going to // pass the sensor and will reset state incorrectly if allowed to // continue. @@ -163,46 +261,7 @@ void Encoders::encA_rising() { } // Hall value is used to detect whether carriage is in front of Left Hall sensor - uint16_t hallValue = analogRead(EOL_PIN_L); - - if ((hallValue < FILTER_L_MIN[static_cast(m_machineType)]) || - (hallValue > FILTER_L_MAX[static_cast(m_machineType)])) { - // In front of Left Hall Sensor - m_hallActive = Direction_t::Left; - - Carriage detected_carriage = Carriage_t::NoCarriage; - uint8_t start_position = END_LEFT_PLUS_OFFSET[static_cast(m_machineType)]; - - if (hallValue >= FILTER_L_MIN[static_cast(m_machineType)]) { - detected_carriage = Carriage_t::Knit; - } else { - detected_carriage = Carriage_t::Lace; - } - - if (m_machineType == Machine_t::Kh270) { - m_carriage = Carriage_t::Knit; - - // The first magnet on the carriage looks like Lace, the second looks like Knit - if (detected_carriage == Carriage_t::Knit) { - start_position = start_position + MAGNET_DISTANCE_270; - } - } else if ((m_carriage != Carriage_t::NoCarriage) && (m_carriage != detected_carriage) && (m_position > start_position)) { - m_carriage = Carriage_t::Garter; - - // Belt shift and start position were set when the first magnet passed - // the sensor and we assumed we were working with a standard carriage. - return; - } else { - m_carriage = detected_carriage; - - // Belt shift signal only decided in front of Hall sensor - // Belt shift is ignored for KH270 - m_beltShift = digitalRead(ENC_PIN_C) ? BeltShift::Regular : BeltShift::Shifted; - } - - // Known position of the carriage -> overwrite position - m_position = start_position; - } + analogReadAsync(EOL_PIN_L, GlobalEncoders::hallLeftCallback); } /*! @@ -213,40 +272,6 @@ void Encoders::encA_rising() { * Bounds on `m_machineType` not checked. */ void Encoders::encA_falling() { - // Update direction - m_direction = digitalRead(ENC_PIN_B) ? Direction_t::Left : Direction_t::Right; - - // Update carriage position - if ((Direction_t::Left == m_direction) && (m_position > END_LEFT[static_cast(m_machineType)])) { - m_position = m_position - 1; - } - // Hall value is used to detect whether carriage is in front of Right Hall sensor - uint16_t hallValue = analogRead(EOL_PIN_R); - - // Avoid 'comparison of unsigned expression < 0 is always false' - // by being explicit about that behaviour being expected. - bool hallValueSmall = false; - hallValueSmall = (hallValue < FILTER_R_MIN[static_cast(m_machineType)]); - - if (hallValueSmall || (hallValue > FILTER_R_MAX[static_cast(m_machineType)])) { - // In front of Right Hall Sensor - m_hallActive = Direction_t::Right; - - // The Garter carriage has a second set of magnets that are going to - // pass the sensor and will reset state incorrectly if allowed to - // continue. - if (hallValueSmall && (m_carriage != Carriage_t::Garter)) { - m_carriage = Carriage_t::Knit; - } - - // Belt shift is ignored for KH270 - if (m_machineType != Machine_t::Kh270) { - // Belt shift signal only decided in front of Hall sensor - m_beltShift = digitalRead(ENC_PIN_C) ? BeltShift::Shifted : BeltShift::Regular; - } - - // Known position of the carriage -> overwrite position - m_position = END_RIGHT_MINUS_OFFSET[static_cast(m_machineType)]; - } + analogReadAsync(EOL_PIN_R, GlobalEncoders::hallRightCallback); } diff --git a/src/ayab/encoders.h b/src/ayab/encoders.h index 031d5b987..edf53768a 100644 --- a/src/ayab/encoders.h +++ b/src/ayab/encoders.h @@ -123,6 +123,8 @@ class EncodersInterface { virtual void init(Machine_t machineType) = 0; virtual void setUpInterrupt() = 0; virtual void isr() = 0; + virtual void hallLeftCallback(uint16_t hallValue, void *data) = 0; + virtual void hallRightCallback(uint16_t hallValue, void *data) = 0; virtual uint16_t getHallValue(Direction_t pSensor) = 0; virtual Machine_t getMachineType() = 0; virtual BeltShift_t getBeltShift() = 0; @@ -151,6 +153,8 @@ class GlobalEncoders final { //#ifndef AYAB_TESTS static void isr(); //#endif + static void hallLeftCallback(uint16_t hallValue, void *data); + static void hallRightCallback(uint16_t hallValue, void *data); static uint16_t getHallValue(Direction_t pSensor); static Machine_t getMachineType(); static BeltShift_t getBeltShift(); @@ -167,6 +171,8 @@ class Encoders : public EncodersInterface { void init(Machine_t machineType) final; void setUpInterrupt() final; void isr() final; + void hallLeftCallback(uint16_t hallValue, void *data) final; + void hallRightCallback(uint16_t hallValue, void *data) final; uint16_t getHallValue(Direction_t pSensor) final; Machine_t getMachineType() final; BeltShift_t getBeltShift() final; diff --git a/src/ayab/global_encoders.cpp b/src/ayab/global_encoders.cpp index 79116dae8..189295629 100644 --- a/src/ayab/global_encoders.cpp +++ b/src/ayab/global_encoders.cpp @@ -40,6 +40,14 @@ void GlobalEncoders::isr() { } #endif // AYAB_TESTS +void GlobalEncoders::hallLeftCallback(uint16_t hallValue, void *data) { + m_instance->hallLeftCallback(hallValue, data); +} + +void GlobalEncoders::hallRightCallback(uint16_t hallValue, void *data) { + m_instance->hallRightCallback(hallValue, data); +} + uint16_t GlobalEncoders::getHallValue(Direction_t pSensor) { return m_instance->getHallValue(pSensor); } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 25793aaed..2a187edba 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -33,6 +33,7 @@ set(COMMON_INCLUDES ) set(EXTERNAL_LIB_INCLUDES ${LIBRARY_DIRECTORY}/Adafruit_MCP23008 + ${LIBRARY_DIRECTORY}/AnalogReadAsync #${LIBRARY_DIRECTORY}/avr-libc/include ) set(COMMON_SOURCES diff --git a/test/mocks/asynchAnalogRead.h b/test/mocks/asynchAnalogRead.h new file mode 100644 index 000000000..a2242bbd3 --- /dev/null +++ b/test/mocks/asynchAnalogRead.h @@ -0,0 +1,27 @@ +/*!` + * \file asynchAnalogRead.h + * + * This file is part of AYAB. + * + * AYAB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * AYAB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with AYAB. If not, see . + * + * Original Work Copyright 2013 Christian Obersteiner, Andreas Müller + * Modified Work Copyright 2020-3 Sturla Lange, Tom Price + * http://ayab-knitting.com + */ + +#ifndef ASYNCHANALOGREAD_MOCK_H_ +#define ASYNCHANALOGREAD_MOCK_H_ + +#endif // ASYNCHANALOGREAD_MOCK_H_