Skip to content

Commit

Permalink
async analog read
Browse files Browse the repository at this point in the history
  • Loading branch information
t0mpr1c3 committed Sep 29, 2023
1 parent fd6c7ad commit 443ac12
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 84 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 1 addition & 0 deletions lib/AnalogReadAsync
Submodule AnalogReadAsync added at b97e43
193 changes: 109 additions & 84 deletions src/ayab/encoders.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
*/

#include <Arduino.h>
#include <analogReadAsync.h>

#include "encoders.h"

Expand Down Expand Up @@ -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<uint8_t>(m_machineType)])) {
m_position = m_position + 1;
}

if ((hallValue < FILTER_L_MIN[static_cast<uint8_t>(m_machineType)]) ||
(hallValue > FILTER_L_MAX[static_cast<uint8_t>(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<uint8_t>(m_machineType)];

if (hallValue >= FILTER_L_MIN[static_cast<uint8_t>(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<uint8_t>(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<uint8_t>(m_machineType)]);

if (hallValueSmall || (hallValue > FILTER_R_MAX[static_cast<uint8_t>(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<uint8_t>(m_machineType)];
}
}

/*!
* \brief Read Hall sensor on left and right.
* \param pSensor Which sensor to read (left or right).
Expand Down Expand Up @@ -132,7 +238,7 @@ Machine_t Encoders::getMachineType() {
return m_machineType;
}

// Private Methods
// Private methods

/*!
* \brief Interrupt service subroutine.
Expand All @@ -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<uint8_t>(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.
Expand All @@ -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<uint8_t>(m_machineType)]) ||
(hallValue > FILTER_L_MAX[static_cast<uint8_t>(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<uint8_t>(m_machineType)];

if (hallValue >= FILTER_L_MIN[static_cast<uint8_t>(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);
}

/*!
Expand All @@ -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<uint8_t>(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<uint8_t>(m_machineType)]);

if (hallValueSmall || (hallValue > FILTER_R_MAX[static_cast<uint8_t>(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<uint8_t>(m_machineType)];
}
analogReadAsync(EOL_PIN_R, GlobalEncoders::hallRightCallback);
}
6 changes: 6 additions & 0 deletions src/ayab/encoders.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand All @@ -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;
Expand Down
8 changes: 8 additions & 0 deletions src/ayab/global_encoders.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
1 change: 1 addition & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 443ac12

Please sign in to comment.