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

Fix carriage detection on the right #205

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
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
123 changes: 71 additions & 52 deletions src/ayab/encoders.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ void Encoders::init(Machine_t machineType) {
m_hallActive = Direction_t::NoDirection;
m_beltShift = BeltShift::Unknown;
m_carriage = Carriage_t::NoCarriage;
m_previousDetectedCarriageLeft = detectCarriageLeft();
m_previousDetectedCarriageLeft = Carriage_t::NoCarriage;
m_previousDetectedCarriageRight = Carriage_t::NoCarriage;
m_oldState = false;
m_passedLeft = false;
m_passedRight = false;
Expand Down Expand Up @@ -134,6 +135,25 @@ Carriage_t Encoders::detectCarriageLeft() {
return Carriage_t::NoCarriage;
}

Carriage_t Encoders::detectCarriageRight() {
uint16_t hallValue = analogRead(EOL_PIN_R);
if (m_machineType == MachineType::Kh910) {
// Due to an error in wiring on the shield, the KH910/KH950 right sensor
// only triggers for the K carriage, and with a low voltage so we can't
// use the same logic as for other machines.
if (hallValue < FILTER_R_MIN[static_cast<uint8_t>(m_machineType)]) {
return Carriage_t::Knit;
}
} else {
if (hallValue > FILTER_R_MAX[static_cast<uint8_t>(m_machineType)]) {
return Carriage_t::Knit;
} else if (hallValue < FILTER_R_MIN[static_cast<uint8_t>(m_machineType)]){
return Carriage_t::Lace;
}
}
return Carriage_t::NoCarriage;
}

/*!
* \brief Interrupt service subroutine.
*
Expand Down Expand Up @@ -166,50 +186,31 @@ void Encoders::encA_rising() {
detected_carriage != previous_detected_carriage) {
m_hallActive = Direction_t::Left;

// Only set the belt shift the first time a magnet passes the turn mark.
// Headed to the right.
if (!m_passedLeft && Direction_t::Right == m_direction) {
// Belt shift signal only decided in front of hall sensor
m_beltShift = digitalRead(ENC_PIN_C) != 0 ? BeltShift::Shifted : BeltShift::Regular;
m_passedLeft = true;

if (Carriage_t::Garter == m_carriage) {
// This has to be the first magnet and the belt shift needs to be swapped
// But only for the G-carriage
if (m_position < 30) {
if (BeltShift::Regular == m_beltShift) {
m_beltShift = BeltShift::Shifted;
} else {
m_beltShift = BeltShift::Regular;
}
}
}
}

// 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 (Carriage_t::Garter == m_carriage) {
return;
}

// If the carriage is already set, ignore the rest.
if ((Carriage_t::Knit == m_carriage) && (Machine_t::Kh270 == m_machineType)) {
// For KH-270, if the carriage is already set, ignore the rest.
if (Machine_t::Kh270 == m_machineType && Carriage_t::Knit == m_carriage) {
return;
}

uint8_t start_position = END_LEFT_PLUS_OFFSET[static_cast<uint8_t>(m_machineType)];
// Only set the belt shift the first time a magnet passes the turn mark.
// Headed to the right.
if (!m_passedLeft && Direction_t::Right == m_direction) {
// Belt shift signal only decided in front of hall sensor
m_beltShift = digitalRead(ENC_PIN_C) != 0 ? BeltShift::Shifted : BeltShift::Regular;
m_passedLeft = true;
}

if (m_machineType == Machine_t::Kh270) {
m_carriage = Carriage_t::Knit;
uint8_t start_position = END_LEFT_PLUS_OFFSET[static_cast<uint8_t>(m_machineType)];

// 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;
} else if (m_carriage != detected_carriage && m_position > start_position) {
if (m_carriage == Carriage_t::Lace &&
detected_carriage == Carriage_t::Knit &&
m_position > start_position) {
m_carriage = Carriage_t::Garter;

// We swap the belt shift for the g-carriage because the point of work for
Expand Down Expand Up @@ -257,40 +258,58 @@ void Encoders::encA_falling() {
}
}

// In front of Right Hall Sensor?
uint16_t hallValue = analogRead(EOL_PIN_R);
// Scan for carriage in front of right Hall sensor
Carriage_t detected_carriage = detectCarriageRight();
Carriage_t previous_detected_carriage = m_previousDetectedCarriageRight;
m_previousDetectedCarriageRight = detected_carriage;

// Avoid 'comparison of unsigned expression < 0 is always false'
// by being explicit about that behaviour being expected.
bool hallValueSmall = false;
// New carriage detected and headed to the left?
if (Direction_t::Left == m_direction &&
detected_carriage != Carriage_t::NoCarriage &&
detected_carriage != previous_detected_carriage) {
m_hallActive = Direction_t::Right;

hallValueSmall = (hallValue < FILTER_R_MIN[static_cast<uint8_t>(m_machineType)]);
// 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 (Carriage_t::Garter == m_carriage) {
return;
}

if (hallValueSmall || hallValue > FILTER_R_MAX[static_cast<uint8_t>(m_machineType)]) {
m_hallActive = Direction_t::Right;
// For KH-270, if the carriage is already set, ignore the rest.
if (Machine_t::Kh270 == m_machineType && Carriage_t::Knit == m_carriage) {
return;
}

// Only set the belt shift when the first magnet passes the turn mark.
// Only set the belt shift the first time a magnet passes the turn mark.
// Headed to the left.
if (!m_passedRight && Direction_t::Left == m_direction) {
// Belt shift signal only decided in front of hall sensor
m_beltShift = digitalRead(ENC_PIN_C) != 0 ? BeltShift::Regular : BeltShift::Shifted;
m_passedRight = true;

// Shift doens't need to be swapped for the g-carriage in this direction.
// Shift doesn't need to be swapped for the g-carriage in this direction.
}

// The garter carriage has extra magnets that are going to
// pass the sensor and will reset state incorrectly if allowed to
// continue.
if (m_carriage == Carriage_t::Garter) {
return;
}
uint8_t start_position = END_RIGHT_MINUS_OFFSET[static_cast<uint8_t>(m_machineType)];

if (m_carriage == Carriage_t::Lace &&
detected_carriage == Carriage_t::Knit &&
m_position < start_position) {
m_carriage = Carriage_t::Garter;

if (hallValueSmall) {
m_carriage = Carriage_t::Knit;
// Belt shift and start position were set when the first magnet passed
// the sensor and we assumed we were working with a standard carriage.

// Because we detected the leftmost magnet on the G-carriage first,
// for consistency with the left side where we detect the rightmost magnet
// first, we need to adjust the carriage position.
start_position = m_position + GARTER_L_MAGNET_SPACING;
} else {
m_carriage = detected_carriage;
}

// Known position of the carriage -> overwrite position
m_position = END_RIGHT_MINUS_OFFSET[static_cast<uint8_t>(m_machineType)];
m_position = start_position;
}
}
22 changes: 13 additions & 9 deletions src/ayab/encoders.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,13 @@ constexpr uint8_t END_OF_LINE_OFFSET_L[NUM_MACHINES] = {12U, 12U, 6U};
constexpr uint8_t END_OF_LINE_OFFSET_R[NUM_MACHINES] = {12U, 12U, 6U};

constexpr uint8_t END_LEFT[NUM_MACHINES] = {0U, 0U, 0U};
constexpr uint8_t END_RIGHT[NUM_MACHINES] = {255U, 255U, 140U};
constexpr uint8_t END_OFFSET[NUM_MACHINES] = {28U, 28U, 5U};
constexpr uint8_t END_RIGHT[NUM_MACHINES] = {255U, 255U, 150U};
constexpr uint8_t END_OFFSET[NUM_MACHINES] = {28U, 28U, 17U};

// The following two arrays are created by combining, respectively,
// the arrays END_LEFT and END_RIGHT with END_OFFSET
constexpr uint8_t END_LEFT_PLUS_OFFSET[NUM_MACHINES] = {28U, 28U, 5U};
constexpr uint8_t END_RIGHT_MINUS_OFFSET[NUM_MACHINES] = {227U, 227U, 135U};
constexpr uint8_t END_LEFT_PLUS_OFFSET[NUM_MACHINES] = {28U, 28U, 17U};
constexpr uint8_t END_RIGHT_MINUS_OFFSET[NUM_MACHINES] = {227U, 227U, 133U};

constexpr uint8_t ALL_MAGNETS_CLEARED_LEFT[NUM_MACHINES] = {56U, 56U, 10U};
constexpr uint8_t ALL_MAGNETS_CLEARED_RIGHT[NUM_MACHINES] = {199U, 199U, 130U};
Expand All @@ -81,19 +81,23 @@ constexpr uint8_t ALL_MAGNETS_CLEARED_RIGHT[NUM_MACHINES] = {199U, 199U, 130U};
// If we didn't have it, we'd decide which carriage we had when the first magnet passed the sensor.
// For the garter carriage we need to see both magnets.
constexpr uint8_t GARTER_SLOP = 2U;
// Spacing between a garter carriage's outer (L-carriage-like) magnets.
// For consistency between a garter carriage starting on the left or the right,
// we need to adjust the position by this distance when starting from the right.
constexpr uint8_t GARTER_L_MAGNET_SPACING = 24U;

constexpr uint8_t START_OFFSET[NUM_MACHINES][NUM_DIRECTIONS][NUM_CARRIAGES] = {
// KH910
{
// K, L, G
{42U, 32U, 32U}, // Left
{16U, 32U, 50U} // Right
{16U, 24U, 48U} // Right
},
// KH930
{
// K, L, G
{42U, 32U, 32U}, // Left
{16U, 32U, 50U} // Right
{16U, 24U, 48U} // Right
},
// KH270
{
Expand All @@ -108,13 +112,11 @@ constexpr uint8_t START_OFFSET[NUM_MACHINES][NUM_DIRECTIONS][NUM_CARRIAGES] = {
// KH910 KH930 KH270
constexpr uint16_t FILTER_L_MIN[NUM_MACHINES] = { 200U, 200U, 200U};
constexpr uint16_t FILTER_L_MAX[NUM_MACHINES] = { 600U, 600U, 600U};
constexpr uint16_t FILTER_R_MIN[NUM_MACHINES] = { 200U, 0U, 0U};
constexpr uint16_t FILTER_R_MIN[NUM_MACHINES] = { 200U, 200U, 200U};
constexpr uint16_t FILTER_R_MAX[NUM_MACHINES] = {1023U, 600U, 600U};

constexpr uint16_t SOLENOIDS_BITMASK = 0xFFFFU;

constexpr uint8_t MAGNET_DISTANCE_270 = 12U;

/*!
* \brief Encoder interface.
*
Expand Down Expand Up @@ -181,6 +183,7 @@ class Encoders : public EncodersInterface {
volatile BeltShift_t m_beltShift;
volatile Carriage_t m_carriage;
volatile Carriage_t m_previousDetectedCarriageLeft;
volatile Carriage_t m_previousDetectedCarriageRight;
volatile Direction_t m_direction;
volatile Direction_t m_hallActive;
volatile uint8_t m_position;
Expand All @@ -189,6 +192,7 @@ class Encoders : public EncodersInterface {
volatile bool m_passedRight;

Carriage_t detectCarriageLeft();
Carriage_t detectCarriageRight();
void encA_rising();
void encA_falling();
};
Expand Down
28 changes: 23 additions & 5 deletions src/ayab/knitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ void Knitter::init() {
m_workedOnLine = false;
m_lastHall = Direction_t::NoDirection;
m_position = 0U;
m_carriage = Carriage_t::NoCarriage;
m_hallActive = Direction_t::NoDirection;
m_pixelToSet = 0;
#ifdef DBG_NOMACHINE
Expand Down Expand Up @@ -216,10 +217,12 @@ bool Knitter::isReady() {
(m_position > (END_LEFT_PLUS_OFFSET[static_cast<uint8_t>(m_machineType)] + GARTER_SLOP));
bool passedRight = (Direction_t::Left == m_direction) && (Direction_t::Right == m_lastHall) &&
(m_position < (END_RIGHT_MINUS_OFFSET[static_cast<uint8_t>(m_machineType)] - GARTER_SLOP));
// Machine is initialized when left Hall sensor is passed in Right direction
// New feature (August 2020): the machine is also initialized
// when the right Hall sensor is passed in Left direction.
if (passedLeft || passedRight) {
// Machine is initialized when the left Hall sensor is passed in Right
// direction, or the right Hall sensor is passed in Left direction. Or, as
// soon as we have detected a Garter carriage, because in that case we may
// need to start setting solenoids before the carriage center has crossed the
// turn mark.
if (passedLeft || passedRight || m_carriage == Carriage_t::Garter) {

#endif // DBG_NOMACHINE
GlobalSolenoids::setSolenoids(SOLENOIDS_BITMASK);
Expand Down Expand Up @@ -432,7 +435,22 @@ bool Knitter::calculatePixelAndSolenoid() {
return false;
}

m_pixelToSet = m_position - startOffset;
// Unsigned 8-bit arithmetic computes modulo 256 — this is not
// appropriate when you have 12 solenoids, it causes pixel -1 to
// have more than 1 solenoid of difference from pixel 0.
// So instead we use a 16-bit int to compute the pixel, then
// convert it back to an unsigned 8-bit integer using a multiple
// of the number of solenoids as the modulus.
// We only handle the underflow case, because the machine with 12
// solenoids (KH270) has only 112 needles and can therefore never
// have positions that cause an 8-bit overflow.
int pixelToSet = (int)m_position - startOffset;

if (pixelToSet < 0) {
pixelToSet += Machine_t::Kh270 == m_machineType ? 252 : 256;
}
jonathanperret marked this conversation as resolved.
Show resolved Hide resolved

m_pixelToSet = pixelToSet;

if (!beltShift) {
m_solenoidToSet = (m_pixelToSet + bulkyOffset) % SOLENOIDS_NUM[static_cast<uint8_t>(m_machineType)];
Expand Down
Loading
Loading