Пока пишу, кто-то успеет постебаться))) Наздоровье)
Попытка 2
Ломаю принтер. У него на подачу и движение каретки стоят коллекторные двигатели и энкодеры. Решил освоить для себя классы и объекты. Есть у меня переменная-флаг moveDone внутри класса, которая должна меняться в прерывании. Столкнулся с проблемой: она то ли не меняется, то ли возвращает неправильное значение, когда ее же использует другой объект.
class Motor {
public:
Motor (byte pinEnable, byte pinA, byte pinB);
void move(boolean moveDirection, byte moveSpeed, int distance);
void stop();
void hardStop();
volatile boolean moveDone = true;
int upperLimit;
int lowerLimit;
int pos;
private:
byte _pinEnable;
byte _pinA;
byte _pinB;
};
boolean A,B;
Motor head(10,11,12);
Motor feed(10,14,15);
int prevHeadPosition;
volatile boolean temp;
void setup() {
Serial.begin(9600);
attachInterrupt(0, headMove, CHANGE);
attachInterrupt(1, feedMove, CHANGE);
pinMode (4, INPUT);
pinMode (5, INPUT);
pinMode (13, OUTPUT);
}
void loop() {
feed.pos = 0;
feed.move (0,255, -200);
while (!feed.moveDone){
digitalWrite (13,HIGH);
}
waitms(100);
feed.pos = 0;
feed.move (1,255, 31000);
while (!feed.moveDone){
digitalWrite (13,LOW);
}
while (1){
Serial.println(feed.pos);
waitms (100);
}
}
void waitms(int ms){
unsigned long myTimer;
myTimer = millis()+ms;
while (millis() < myTimer){}
}
Motor::Motor (byte pinEnable, byte pinA, byte pinB) // конструктор класса
{
_pinEnable = pinEnable;
_pinA = pinA;
_pinB = pinB;
pinMode (pinA, OUTPUT);
pinMode (pinB, OUTPUT);
}
void Motor::move(boolean moveDirection, byte moveSpeed, int distance){ // метод класса который вращает мотор до нужного значения
moveDone = false;
analogWrite (_pinEnable, moveSpeed);
if (moveDirection) {
upperLimit = distance;
lowerLimit = pos - 500;
digitalWrite (_pinA, HIGH);
digitalWrite (_pinB, LOW);
} else {
lowerLimit = distance;
upperLimit = pos + 500;
digitalWrite (_pinA, LOW);
digitalWrite (_pinB, HIGH);
}
}
void Motor::stop() {// остановка мотора
moveDone = true;
digitalWrite (_pinEnable, LOW);
digitalWrite (_pinA, LOW);
digitalWrite (_pinB, LOW);
}
void Motor::hardStop() {// остановка мотора с торможением
moveDone = true;
digitalWrite (_pinEnable, HIGH);
digitalWrite (_pinA, LOW);
digitalWrite (_pinB, LOW);
}
void headMove(){
A=digitalRead(2);
B=digitalRead(7);
if (B==A) {
head.pos--;
// if (head.pos < head.lowerLimit) head.stop();
}
else {
head.pos++;
// if (head.pos > head.upperLimit) head.stop();
}
}
void feedMove(){
A=digitalRead(3);
B=digitalRead(5);
if (B==A) {
feed.pos--;
if (feed.pos < feed.lowerLimit) feed.stop();
}
else {
feed.pos++;
if (feed.pos > feed.upperLimit) feed.stop();
}
}
Все работает как должно, но если в headMove раскомментировать строки с if все перестает работать. Навечно остаюсь в цикле while и жду изменения feed.moveDone при том, что двигатель останавливается. Не могу понять как вообще программа попадает в прерывание moveHead, но даже если попадает и даже если выполняется условие, то head.stop должно менять moveDone в объекте head.
Забыл еще один вопрос. В строках 43 и 49 дергаю 13 ногой, потому что пустой цикл как будто вообще игнорируется и программа выполняется дальше. Почему не едут лыжи?)
Конечно и в сериал выводил и лампочками мигал, чтобы понять. 2 дня уже сижу с этой ерундой. Уже почти решил все простыми функциями отдельными для feed и для head сделать. Но тут так красиво. Не хотелось бы сдаваться.
Когда у меня возникает проблема, я нормально отношусь к тому, что она требует пару недель для своего решения. Но за пару недель, обычно, решаются. Так что, не сдавайтесь, у Вас ещё много времени.
Переписал все на отдельных функциях для каждого мотора (исключил объекты). Проблема не ушла. Потихоньку ковырял функции и я разобрался! Случилась эврика!!! У энкодера, видимо, какое-то пограничное состояние может быть. И когда мотор стоит все-равно генерятся прерывания и позиция то +1, то -1, либо еще выбег (инерция от предыдущего движения). В итоге оно срабатывало в момент, когда строка 75 (moveDone = false) уже выполнилась но до задания пределов (строка 78, 79) еще не дошло. А в прерывании срабатывало условие и метод stop, а в нем moveDone опять становился true. Поэтому и цикл while не выполнялся (я думал какой то глюк).
В итоге перенес строку 75 после 87, а в прерывании в условии добавил, что метод stop срабатывает только если мы думаем, что движемся (moveDone = false). Теперь все работает и с объектами. Они были не при чем. И цикл наладился. На него тоже грешил.
Здравствуйте.
Ломаю стары
Пока пишу, кто-то успеет постебаться))) Наздоровье)
Попытка 2
Ломаю принтер. У него на подачу и движение каретки стоят коллекторные двигатели и энкодеры. Решил освоить для себя классы и объекты. Есть у меня переменная-флаг moveDone внутри класса, которая должна меняться в прерывании. Столкнулся с проблемой: она то ли не меняется, то ли возвращает неправильное значение, когда ее же использует другой объект.
Все работает как должно, но если в headMove раскомментировать строки с if все перестает работать. Навечно остаюсь в цикле while и жду изменения feed.moveDone при том, что двигатель останавливается. Не могу понять как вообще программа попадает в прерывание moveHead, но даже если попадает и даже если выполняется условие, то head.stop должно менять moveDone в объекте head.
Забыл еще один вопрос. В строках 43 и 49 дергаю 13 ногой, потому что пустой цикл как будто вообще игнорируется и программа выполняется дальше. Почему не едут лыжи?)
а как вообще отлаживать программки на ардуинке? можно запустить дебуггер и пошагово выполнять и видеть состояние регистров переменных?
Без приложения усилий - нет
Без приложения усилий - нет
ЕвгенийП рекомендовал выводить в сериал
Конечно и в сериал выводил и лампочками мигал, чтобы понять. 2 дня уже сижу с этой ерундой. Уже почти решил все простыми функциями отдельными для feed и для head сделать. Но тут так красиво. Не хотелось бы сдаваться.
Почему не едут лыжи?)
Отвечать? Или "ну его на"?
2 дня уже сижу ... Не хотелось бы сдаваться.
Когда у меня возникает проблема, я нормально отношусь к тому, что она требует пару недель для своего решения. Но за пару недель, обычно, решаются. Так что, не сдавайтесь, у Вас ещё много времени.
Видимо помог коллективный дух.
Переписал все на отдельных функциях для каждого мотора (исключил объекты). Проблема не ушла. Потихоньку ковырял функции и я разобрался! Случилась эврика!!! У энкодера, видимо, какое-то пограничное состояние может быть. И когда мотор стоит все-равно генерятся прерывания и позиция то +1, то -1, либо еще выбег (инерция от предыдущего движения). В итоге оно срабатывало в момент, когда строка 75 (moveDone = false) уже выполнилась но до задания пределов (строка 78, 79) еще не дошло. А в прерывании срабатывало условие и метод stop, а в нем moveDone опять становился true. Поэтому и цикл while не выполнялся (я думал какой то глюк).
В итоге перенес строку 75 после 87, а в прерывании в условии добавил, что метод stop срабатывает только если мы думаем, что движемся (moveDone = false). Теперь все работает и с объектами. Они были не при чем. И цикл наладился. На него тоже грешил.
И как же хорошо, что чудес все-таки не бывает.
ЕвгенийП как талисман )))