Add files via upload
This commit is contained in:
parent
cb16abdff6
commit
16647bc5ff
184
Motors.ino
Normal file
184
Motors.ino
Normal file
@ -0,0 +1,184 @@
|
||||
/* Copyright (C) 2013-2015 Kristian Lauszus, TKJ Electronics. All rights reserved.
|
||||
This software may be distributed and modified under the terms of the GNU
|
||||
General Public License version 2 (GPL2) as published by the Free Software
|
||||
Foundation and appearing in the file GPL2.TXT included in the packaging of
|
||||
this file. Please note that GPL2 Section 2[b] requires that all works based
|
||||
on this software must also be made publicly available under the terms of
|
||||
the GPL2 ("Copyleft").
|
||||
Contact information
|
||||
-------------------
|
||||
Kristian Lauszus, TKJ Electronics
|
||||
Web : http://www.tkjelectronics.dk
|
||||
e-mail : kristianl@tkjelectronics.dk
|
||||
*/
|
||||
|
||||
void updatePID(float restAngle, float offset, float turning, float dt) {
|
||||
/* Brake */
|
||||
if (steerStop) {
|
||||
int32_t wheelPosition = getWheelsPosition();
|
||||
int32_t positionError = wheelPosition - targetPosition;
|
||||
if (cfg.backToSpot) {
|
||||
if (abs(positionError) > zoneA) // Inside zone A
|
||||
restAngle -= (float)positionError / positionScaleA;
|
||||
else if (abs(positionError) > zoneB) // Inside zone B
|
||||
restAngle -= (float)positionError / positionScaleB;
|
||||
else if (abs(positionError) > zoneC) // Inside zone C
|
||||
restAngle -= (float)positionError / positionScaleC;
|
||||
else // Inside zone D
|
||||
restAngle -= (float)positionError / positionScaleD;
|
||||
} else {
|
||||
if (abs(positionError) < zoneC)
|
||||
restAngle -= (float)positionError / positionScaleD;
|
||||
else
|
||||
targetPosition = wheelPosition;
|
||||
}
|
||||
restAngle -= (float)wheelVelocity / velocityScaleStop;
|
||||
|
||||
restAngle = constrain(restAngle, cfg.targetAngle - 10, cfg.targetAngle + 10); // Limit rest Angle
|
||||
}
|
||||
/* Drive forward and backward */
|
||||
else {
|
||||
if ((offset > 0 && wheelVelocity < 0) || (offset < 0 && wheelVelocity > 0) || offset == 0) // Scale down offset at high speed - wheel velocity is negative when driving forward and positive when driving backward
|
||||
offset += (float)wheelVelocity / velocityScaleMove; // We will always compensate if the offset is 0, but steerStop is not set
|
||||
restAngle -= offset;
|
||||
}
|
||||
|
||||
restAngle = constrain(restAngle, lastRestAngle - 1, lastRestAngle + 1); // Don't change restAngle with more than 1 degree in each loop
|
||||
lastRestAngle = restAngle;
|
||||
|
||||
/* Update PID values */
|
||||
float error = restAngle - pitch;
|
||||
float pTerm = cfg.P * error;
|
||||
iTerm += cfg.I * 100.0f * error * dt; // Multiplication with Ki is done before integration limit, to make it independent from integration limit value
|
||||
iTerm = constrain(iTerm, -100.0f, 100.0f); // Limit the integrated error - prevents windup
|
||||
float dTerm = (cfg.D / 100.0f) * (error - lastError) / dt;
|
||||
lastError = error;
|
||||
float PIDValue = pTerm + iTerm + dTerm;
|
||||
|
||||
/* Steer robot sideways */
|
||||
if (turning < 0) { // Left
|
||||
turning += abs((float)wheelVelocity / velocityScaleTurning); // Scale down at high speed
|
||||
if (turning > 0)
|
||||
turning = 0;
|
||||
}
|
||||
else if (turning > 0) { // Right
|
||||
turning -= abs((float)wheelVelocity / velocityScaleTurning); // Scale down at high speed
|
||||
if (turning < 0)
|
||||
turning = 0;
|
||||
}
|
||||
|
||||
float PIDLeft = PIDValue + turning;
|
||||
float PIDRight = PIDValue - turning;
|
||||
|
||||
PIDLeft *= cfg.leftMotorScaler; // Compensate for difference in some of the motors
|
||||
PIDRight *= cfg.rightMotorScaler;
|
||||
|
||||
/* Set PWM Values */
|
||||
if (PIDLeft >= 0)
|
||||
moveMotor(left, forward, PIDLeft);
|
||||
else
|
||||
moveMotor(left, backward, -PIDLeft);
|
||||
if (PIDRight >= 0)
|
||||
moveMotor(right, forward, PIDRight);
|
||||
else
|
||||
moveMotor(right, backward, -PIDRight);
|
||||
}
|
||||
|
||||
void moveMotor(Command motor, Command direction, float speedRaw) { // Speed is a value in percentage 0-100%
|
||||
if (speedRaw > 100.0f)
|
||||
speedRaw = 100.0f;
|
||||
setPWM(motor, speedRaw * (float)PWMVALUE / 100.0f); // Scale from 0-100 to 0-PWMVALUE
|
||||
if (motor == left) {
|
||||
if (direction == forward) {
|
||||
leftA::Clear();
|
||||
leftB::Set();
|
||||
}
|
||||
else {
|
||||
leftA::Set();
|
||||
leftB::Clear();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (direction == forward) {
|
||||
rightA::Set();
|
||||
rightB::Clear();
|
||||
}
|
||||
else {
|
||||
rightA::Clear();
|
||||
rightB::Set();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void stopMotor(Command motor) {
|
||||
setPWM(motor, PWMVALUE); // Set high
|
||||
if (motor == left) {
|
||||
leftA::Set();
|
||||
leftB::Set();
|
||||
}
|
||||
else {
|
||||
rightA::Set();
|
||||
rightB::Set();
|
||||
}
|
||||
}
|
||||
|
||||
void setPWM(Command motor, uint16_t dutyCycle) { // dutyCycle is a value between 0-ICR1
|
||||
if (motor == left)
|
||||
OCR1A = dutyCycle;
|
||||
else
|
||||
OCR1B = dutyCycle;
|
||||
}
|
||||
|
||||
void stopAndReset() {
|
||||
stopMotor(left);
|
||||
stopMotor(right);
|
||||
lastError = 0;
|
||||
iTerm = 0;
|
||||
targetPosition = getWheelsPosition();
|
||||
lastRestAngle = cfg.targetAngle;
|
||||
}
|
||||
|
||||
/* Interrupt routine and encoder read functions */
|
||||
// It uses gray code to detect if any pulses are missed. See: https://www.circuitsathome.com/mcu/reading-rotary-encoder-on-arduino and http://en.wikipedia.org/wiki/Rotary_encoder#Incremental_rotary_encoder.
|
||||
|
||||
#if defined(PIN_CHANGE_INTERRUPT_VECTOR_LEFT) && defined(PIN_CHANGE_INTERRUPT_VECTOR_RIGHT)
|
||||
static const int8_t enc_states[16] = { 0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0 }; // Encoder lookup table if it interrupts on every edge
|
||||
|
||||
ISR(PIN_CHANGE_INTERRUPT_VECTOR_LEFT) {
|
||||
leftEncoder();
|
||||
#if BALANDUINO_REVISION >= 13
|
||||
}
|
||||
ISR(PIN_CHANGE_INTERRUPT_VECTOR_RIGHT) {
|
||||
#endif
|
||||
rightEncoder();
|
||||
}
|
||||
#elif BALANDUINO_REVISION < 13
|
||||
#warning "Only interrupting on every second edge!"
|
||||
static const int8_t enc_states[16] = { 0, 0, 0, -1, 0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0, 0 }; // Encoder lookup table if it only interrupts on every second edge - this only works on revision 1.2 and older
|
||||
#endif
|
||||
|
||||
void leftEncoder() {
|
||||
static uint8_t old_AB = 0;
|
||||
old_AB <<= 2; // Remember previous state
|
||||
old_AB |= (leftEncoder2::IsSet() >> (leftEncoder2::Number - 1)) | (leftEncoder1::IsSet() >> leftEncoder1::Number);
|
||||
leftCounter -= enc_states[ old_AB & 0x0F ];
|
||||
}
|
||||
|
||||
void rightEncoder() {
|
||||
static uint8_t old_AB = 0;
|
||||
old_AB <<= 2; // Remember previous state
|
||||
old_AB |= (rightEncoder2::IsSet() >> (rightEncoder2::Number - 1)) | (rightEncoder1::IsSet() >> rightEncoder1::Number);
|
||||
rightCounter += enc_states[ old_AB & 0x0F ];
|
||||
}
|
||||
|
||||
int32_t readLeftEncoder() { // The encoders decrease when motors are traveling forward and increase when traveling backward
|
||||
return leftCounter;
|
||||
}
|
||||
|
||||
int32_t readRightEncoder() {
|
||||
return rightCounter;
|
||||
}
|
||||
|
||||
int32_t getWheelsPosition() {
|
||||
return leftCounter + rightCounter;
|
||||
}
|
Loading…
Reference in New Issue
Block a user