untested motor controller
This commit is contained in:
parent
b24ebba1f6
commit
754275d7b2
|
|
@ -1,5 +1,7 @@
|
||||||
package dev.asdf00.visionfive.hc
|
package dev.asdf00.visionfive.hc
|
||||||
|
|
||||||
|
import kotlin.math.abs
|
||||||
|
|
||||||
class Controller(private val senseBot: GpioPin, private val senseTop: GpioPin, private val motor: PinGroup) {
|
class Controller(private val senseBot: GpioPin, private val senseTop: GpioPin, private val motor: PinGroup) {
|
||||||
constructor(senseBot: GpioPin, senseTop: GpioPin, m0: GpioPin, m1: GpioPin, m2: GpioPin, m3: GpioPin) : this(
|
constructor(senseBot: GpioPin, senseTop: GpioPin, m0: GpioPin, m1: GpioPin, m2: GpioPin, m3: GpioPin) : this(
|
||||||
senseBot,
|
senseBot,
|
||||||
|
|
@ -8,7 +10,7 @@ class Controller(private val senseBot: GpioPin, private val senseTop: GpioPin, p
|
||||||
)
|
)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
motor.intState = initialStep
|
motor.intState = INITIAL_STEP
|
||||||
}
|
}
|
||||||
|
|
||||||
private var internalState = -1
|
private var internalState = -1
|
||||||
|
|
@ -18,11 +20,71 @@ class Controller(private val senseBot: GpioPin, private val senseTop: GpioPin, p
|
||||||
get() = if (internalState < 0) Double.NaN else internalState.toDouble() / maxStep.toDouble()
|
get() = if (internalState < 0) Double.NaN else internalState.toDouble() / maxStep.toDouble()
|
||||||
set(target) {
|
set(target) {
|
||||||
if (internalState < 0)
|
if (internalState < 0)
|
||||||
throw IllegalStateException("call Controller#runInitSequence before using it")
|
throw IllegalStateException("call Controller#runCalibrationSequence before using it")
|
||||||
TODO()
|
if (target < 0 || target > 1)
|
||||||
|
throw IllegalArgumentException("state must always be between 0 and 1")
|
||||||
|
if (target isCloseTo 0) {
|
||||||
|
// full close
|
||||||
|
runToBot()
|
||||||
|
internalState = 0
|
||||||
|
} else if (target isCloseTo 1) {
|
||||||
|
// full open
|
||||||
|
runToTop()
|
||||||
|
internalState = maxStep
|
||||||
|
} else {
|
||||||
|
// normal case
|
||||||
|
val dif = (maxStep.toDouble() * target).toInt() - internalState
|
||||||
|
if (dif > 0) {
|
||||||
|
val realDif = stepAnti(dif)
|
||||||
|
if (realDif != dif) {
|
||||||
|
// maybe log correction
|
||||||
|
// recalibrate if deviation was too much
|
||||||
|
if (abs(internalState.toDouble() / maxStep.toDouble() - target) > RECALIB_DATA) {
|
||||||
|
// turn to middle
|
||||||
|
val mDif = stepClock(maxStep / 2)
|
||||||
|
if (mDif != maxStep / 2) {
|
||||||
|
// something has gone VERY wrong here
|
||||||
|
internalState = -1
|
||||||
|
throw IllegalStateException("unrecoverable state")
|
||||||
|
}
|
||||||
|
runCalibrationSequence()
|
||||||
|
// and try again after calibration
|
||||||
|
@Suppress("RecursivePropertyAccessor")
|
||||||
|
this.state = target
|
||||||
|
return
|
||||||
|
}
|
||||||
|
internalState = maxStep
|
||||||
|
} else {
|
||||||
|
internalState += realDif
|
||||||
|
}
|
||||||
|
} else if (dif < 0) {
|
||||||
|
val realDif = stepClock(dif)
|
||||||
|
if (realDif != dif) {
|
||||||
|
// maybe log correction
|
||||||
|
// recalibrate if deviation was too much
|
||||||
|
if (abs(internalState.toDouble() / maxStep.toDouble() - target) > RECALIB_DATA) {
|
||||||
|
// turn to middle
|
||||||
|
val mDif = stepAnti(maxStep / 2)
|
||||||
|
if (mDif != maxStep / 2) {
|
||||||
|
// something has gone VERY wrong here
|
||||||
|
internalState = -1
|
||||||
|
throw IllegalStateException("unrecoverable state")
|
||||||
|
}
|
||||||
|
runCalibrationSequence()
|
||||||
|
// and try again after calibration
|
||||||
|
@Suppress("RecursivePropertyAccessor")
|
||||||
|
this.state = target
|
||||||
|
return
|
||||||
|
}
|
||||||
|
internalState = 0
|
||||||
|
} else {
|
||||||
|
internalState -= realDif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun runInitSequence() {
|
fun runCalibrationSequence() {
|
||||||
val prevState = runToBot()
|
val prevState = runToBot()
|
||||||
val range = runToTop()
|
val range = runToTop()
|
||||||
stepClock(range - prevState)
|
stepClock(range - prevState)
|
||||||
|
|
@ -77,18 +139,18 @@ class Controller(private val senseBot: GpioPin, private val senseTop: GpioPin, p
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun doStep(step: LongArray) {
|
private fun doStep(step: LongArray) {
|
||||||
assert(motor.intState == initialStep, { "step must ALWAYS start on initial step state" })
|
assert(motor.intState == INITIAL_STEP) { "step must ALWAYS start on initial step state" }
|
||||||
for (l in step) {
|
for (l in step) {
|
||||||
motor.intState = l
|
motor.intState = l
|
||||||
Thread.sleep(stepDelay)
|
Thread.sleep(STEP_DELAY)
|
||||||
}
|
}
|
||||||
assert(motor.intState == initialStep, { "step must ALWAYS end on initial step state" })
|
assert(motor.intState == INITIAL_STEP) { "step must ALWAYS end on initial step state" }
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val stepDelay = 10L
|
private const val STEP_DELAY = 10L
|
||||||
|
private const val INITIAL_STEP = 0b1001L
|
||||||
private val initialStep = 0b1001L
|
private const val RECALIB_DATA = 0.01
|
||||||
|
|
||||||
private val clockStep = longArrayOf(
|
private val clockStep = longArrayOf(
|
||||||
0b0001,
|
0b0001,
|
||||||
|
|
@ -112,4 +174,8 @@ class Controller(private val senseBot: GpioPin, private val senseTop: GpioPin, p
|
||||||
0b1001,
|
0b1001,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
infix fun Double.isCloseTo(other: Double) = this.isCloseTo(other, 0e-6)
|
||||||
|
infix fun Double.isCloseTo(other: Int) = this isCloseTo other.toDouble()
|
||||||
|
fun Double.isCloseTo(other: Double, epsilon: Double) = this >= other - epsilon && this <= other + epsilon
|
||||||
Loading…
Reference in New Issue
Block a user