Помогите отладить код
- Войдите на сайт для отправки комментариев
Устройство такое. Есть штанга, управляющая частотным преобразователем с двумя концевиками. Имеет два положения, внизу и вверху.
На штанге вращающаяся стрелка с мотором постоянного двигателя. Управляется ШИМом
Устройство имеет 2 программы:
1) Штанга стоит на верхнем концевике, светится диод программы 1
При однократном нажатии кнопки штанга опускается до нижнего концевика, диод программы 1 моргает. По приходу на концевик реле подъема выключается, диод 1 программы гаснет, загорается диод программы 2
2)Штанга стоит на нижнем концевике, светится диод программы 2
При нажатии кнопки начинает вращаться стрелка с плавным разгоном и торможением. Стрелка делает 8.5 оборотов, после чего останавливается и срабатывает подъем штанги наверх до срабатывания верхнего концевика.
Во время работы программы 2, светодиод программы 2 мигает.
По приходу на верхний концевик система возвращается к программе 1.
Счет происходит путем проходов магнитов на диске через 2 датчика Холла. Всего 8 магнитов по кругу для счета положения и 1 магнит во втором ряду для счета оборотов.
Так же есть отдельная кнопка для ручного вращения стрелки в нижнем положении штанги. Имеет плавный старт по удержанию и плавный стоп по отпусканию.
Скетч выглядит вот так, но на данный момент имеет несколько ошибок, например ложное срабатывание кнопки пуска или самостоятельное включение реле подъема
#include <Arduino.h>
#define REL_UP 19 //Пин реле "Вверх"
#define REL_DN 0 //Пин реле "Вниз"
#define MOTOR 10 //Пин ШИМа мотора
#define DIRECT 9 //Пин включения реверса
#define MAN 4 //Пин кнопки ручного вращения
#define LED_PR1 5 //Пин светодиода программы "1"
#define LED_PR2 7 //Пин светодиода программы "2"
#define LIM_UP 15 //Пин верхнего концевика
#define LIM_DN 13 //Пин нижнего концевика
#define SW 8 //Пин кнопки
#define PCB_LED 1 //Пин диода на плате
#define C_SENS 2 //Пин датчика 1 (прерывание 1 )
#define H_SENS 3 //Пин датчика 2 (прерывание 2 )
#define INTERVAL1 500 //Интервал мигания диода на плате (мС)
#define INTERVAL2 250 //Интервал мигания диода программы (мС)
class noDELAY {
public:
unsigned long previous;
unsigned long interval;
boolean s;
boolean tick;
noDELAY() {
previous = millis();
s = 0;
tick = 0;
}
void stop() {s = 0; }
void start() {s = 1; }
void read(unsigned long _interval) {
interval = _interval;
unsigned long current = millis(); tick = 0;
if (s == 0) {previous = current; }
if (current - previous > interval) {previous = current; tick = 1;}
}
};
bool prog = 0; //Номер программы 0-первая 1-вторая
volatile byte counter = 1; //Счетчик импульсов
byte spd; //Скорость
volatile byte loops = 0; //Количество оборотов
int startTime; //Время разгона
int stopTime; //Время торможения
byte val; //Значение ШИМа скорости
bool state = 0; //Состояние кнопки для программы 2
bool stt = 0; //Состоянте кнопки для ручного управления
noDELAY timer1;
noDELAY timer2;
noDELAY timer3; //Таймеры
noDELAY timer4;
void setup() {
pinMode(REL_UP, OUTPUT); //Режимы и стартовые уровни
pinMode(REL_DN, OUTPUT);
pinMode(MOTOR,OUTPUT);
pinMode(DIRECT,OUTPUT);
pinMode(LED_PR1,OUTPUT);
pinMode(LED_PR2,OUTPUT);
pinMode(PCB_LED,OUTPUT);
pinMode(SW, INPUT_PULLUP);
pinMode(C_SENS, INPUT_PULLUP);
pinMode(H_SENS, INPUT_PULLUP);
pinMode(MAN, INPUT_PULLUP);
pinMode(LIM_UP, INPUT);
pinMode(LIM_DN, INPUT);
digitalWrite(REL_UP, LOW);
digitalWrite(REL_DN, LOW);
digitalWrite(MOTOR , LOW);
digitalWrite(LED_PR1, LOW);
digitalWrite(LED_PR2, LOW);
digitalWrite(LIM_UP, LOW);
digitalWrite(LIM_DN, LOW);
digitalWrite(C_SENS, HIGH);
digitalWrite(H_SENS, HIGH);
digitalWrite(SW, HIGH);
digitalWrite(MAN, HIGH);
digitalWrite(PCB_LED, LOW);
digitalWrite(DIRECT, LOW); //Направление вращения
//attachInterrupt(0,increase, FALLING);
//attachInterrupt(1,loopcounter, FALLING);
timer1.start();
timer2.start();
timer3.start();
timer4.start();
startTime = map(analogRead(A4), 0, 1023, 0, 40); //Опрос регуляторов скорости и старт/стопа
stopTime = map(analogRead(A3), 0, 1023, 0, 50);
spd = map(analogRead(A2), 0, 1023, 0, 254);
}
void increase(){
counter+=1;
}
void loopcounter(){
loops+=1;
}
void loop() { //Старт цикла
if(loops > 10) {loops = 0;}
if(digitalRead(C_SENS) == LOW && digitalRead(H_SENS) == LOW || counter > 6) {counter = 0;} //Сброс счетчиков
timer1.read(INTERVAL1); //Генератор морганий диода на плате
timer2.read(INTERVAL2); //Генератор морганий диодов программы
timer3.read(startTime); //Таймер разгона
timer4.read(stopTime); //Таймер торможения
if (timer1.tick) {digitalWrite(PCB_LED, !digitalRead(PCB_LED));} //Генератор морганий диода на плате
if (val < spd && timer3.tick && digitalRead(MAN)== LOW && digitalRead(LIM_DN)== HIGH){ //Ручное вращение
stt=1;
val++;
analogWrite(MOTOR, val);
}
else if(stt==1 && val > 0 && timer4.tick && digitalRead(MAN)== HIGH){
val--;
analogWrite(MOTOR, val);
}
if(prog == 0 && !digitalRead(REL_DN) == HIGH) { //Включение диода программы 1 в режиме ожидания
digitalWrite(LED_PR1, HIGH);
digitalWrite(LED_PR2, LOW);
}
else if((prog == 0 && digitalRead(REL_DN) == HIGH)){ //Включение диода программы 1 в режиме работы
if (timer2.tick) {
digitalWrite(LED_PR1, !digitalRead(LED_PR1));
}
}
if(digitalRead(SW)== LOW && prog == 0) { //Запуск реле программы 1
digitalWrite(REL_DN, HIGH);
digitalWrite(REL_UP, LOW);
}
if(digitalRead(LIM_DN)== HIGH){ //Остановка программы 1 по концевику
digitalWrite(REL_DN, LOW);
prog = 1;
}
if(prog == 1 && val <= 5) { //Включение диода программы 2 в режиме ожидания
digitalWrite(LED_PR1, LOW);
digitalWrite(LED_PR2, HIGH);
}
else if( (prog == 1 && val > 5) || digitalRead(REL_UP) == HIGH ) { //Включение диода программы 2 в режиме работы
if (timer2.tick) {digitalWrite(LED_PR2, !digitalRead(LED_PR2));}
}
if (digitalRead(SW)== LOW && prog==1 && digitalRead(LIM_DN)== HIGH) { //Состояние кнопки для программы 2
state=1;
}
if (val < spd && timer3.tick && state==1){ //Запуск программы 2, плавный старт мотора
stt=0;
val++;
}
else if (loops >=8 && counter >= 4 && prog==1 && val > 0 && timer4.tick){
val--;
analogWrite(MOTOR, val);
}
if(loops >=8 && counter >=5 && prog==1){
digitalWrite(MOTOR, 0);
}
if(loops >=8 && counter >=4 && prog==1){
digitalWrite(REL_UP, HIGH);
}
if(digitalRead(LIM_UP)==HIGH){ //Выключение всего по приходу на верхний концевик
digitalWrite(REL_UP, LOW);
analogWrite(MOTOR, 0);
prog = 0; //Переход к программе 1
counter = 0;
loops = 0;
state=0;
val = 0;
}
} //Конец цикла
Основная проблема с прерываниями. Переменные за проход магнита увеличиваются не на единицу, а на несколько, хотя на макете все работало правильно
На данный момент код такой:
/*Контроллер управления ракетой*/ #include <Arduino.h> #define REL_UP 19 //Пин реле "Вверх" #define REL_DN 0 //Пин реле "Вниз" #define MOTOR 10 //Пин ШИМа мотора #define DIRECT 9 //Пин включения реверса #define MAN 4 //Пин кнопки ручного вращения #define LED_PR1 5 //Пин светодиода программы "1" #define LED_PR2 7 //Пин светодиода программы "2" #define LIM_UP 15 //Пин верхнего концевика #define LIM_DN 13 //Пин нижнего концевика #define SW 8 //Пин кнопки #define PCB_LED 1 //Пин диода на плате #define C_SENS 2 //Пин датчика 1 (прерывание 1 ) #define H_SENS 3 //Пин датчика 2 (прерывание 2 ) class noDELAY { public: unsigned long previous; unsigned long interval; boolean s; boolean tick; noDELAY() { previous = millis(); s = 0; tick = 0; } void stop() {s = 0; } void start() {s = 1; } void read(unsigned long _interval) { interval = _interval; unsigned long current = millis(); tick = 0; if (s == 0) {previous = current; } if (current - previous > interval) {previous = current; tick = 1;} } }; class BUTTON { public: //============================================================================================ // константы настроек класса. static const byte bounce_ = 100; static const byte doubleclick_ = 250; static const unsigned long timer_ = 5000; static const unsigned int retention_ = 2000; //============================================================================================ unsigned long start; boolean p; boolean s; boolean b; byte c; boolean t; boolean r; //============================================================ boolean click_down; boolean click_up; boolean doubleclick; boolean timer; boolean retention; //============================================================ byte _pb; //============================================================ BUTTON(byte pb) { _pb = pb; pinMode(_pb, INPUT); digitalWrite(_pb, 1); //=================== start = millis(); p = digitalRead(_pb); s = p; b = 0; c = 0; t = 0; r = 0; //============== click_down = 0; click_up = 0; doubleclick = 0; timer = 0; retention = 0; //============== } void read() { //============================================================================== boolean np = digitalRead(_pb); unsigned long stop = millis(); //============================================================================== click_down = 0; click_up = 0; doubleclick = 0; timer = 0; retention = 0; //============================================================================== if (np != p) {p = np; click(); start = stop; b = 1; t = 1; r = 1;} //============================================================================== if (b != 0 ) {if (stop - start > bounce_ ) {b = 0; click(); }} if (c != 0 ) {if (stop - start > doubleclick_) {c = 0; }} if (t != 0 && s == 1) {if (stop - start > timer_ ) {t = 0; timer = 1;}} if (r != 0 && s == 0) {if (stop - start > retention_ ) {r = 0; retention = 1;}} //============================================================================== } void click() { if (b == 0 && s != p) {s = p; if (s == 0) {click_down = 1; ++c; if (c == 2) {c = 0; doubleclick = 1;}} if (s == 1) {click_up = 1; } } } }; bool prog = 0; //Номер программы 0-первая 1-вторая byte counter = 0; //Счетчик импульсов const byte spd = 200; //Скорость byte loops = 0; //Количество оборотов const int startTime = 2; //Время разгона const int stopTime = 7; //Время торможения byte val; //Значение ШИМа скорости bool state = 0; //Состояние кнопки для программы 2 bool stt = 0; //Состоянте кнопки для ручного управления const byte turns = 8; //Количество оборотов byte pp = 0; //Вспомогательная переменная const byte stopspd = 55; const int interval1 = 500; const int interval2 = 250; noDELAY timer1; noDELAY timer2; noDELAY timer3; //Таймеры noDELAY timer4; BUTTON increase(C_SENS); BUTTON loopcntr(H_SENS); void setup() { pinMode(REL_UP, OUTPUT); //Режимы и стартовые уровни pinMode(REL_DN, OUTPUT); pinMode(MOTOR,OUTPUT); pinMode(DIRECT,OUTPUT); pinMode(LED_PR1,OUTPUT); pinMode(LED_PR2,OUTPUT); pinMode(PCB_LED,OUTPUT); pinMode(SW, INPUT_PULLUP); pinMode(C_SENS, INPUT_PULLUP); pinMode(H_SENS, INPUT_PULLUP); pinMode(MAN, INPUT_PULLUP); pinMode(LIM_UP, INPUT); pinMode(LIM_DN, INPUT); digitalWrite(REL_UP, LOW); digitalWrite(REL_DN, LOW); digitalWrite(MOTOR , LOW); digitalWrite(LED_PR1, LOW); digitalWrite(LED_PR2, LOW); digitalWrite(LIM_UP, LOW); digitalWrite(LIM_DN, LOW); digitalWrite(C_SENS, HIGH); digitalWrite(H_SENS, HIGH); digitalWrite(SW, HIGH); digitalWrite(MAN, HIGH); digitalWrite(PCB_LED, LOW); digitalWrite(DIRECT, LOW); //Направление вращения timer1.start(); timer2.start(); timer3.start(); timer4.start(); } void loop() { //Старт цикла loopcntr.read(); if(loopcntr.click_down && digitalRead(MAN)== HIGH){ loops+=1; } increase.read(); if(increase.click_down && digitalRead(MAN)== HIGH && loops >= turns){ counter+=1; } if(loops > 12) {loops = 0;} if(digitalRead(C_SENS) == LOW && digitalRead(H_SENS) == LOW || counter > 7) {counter = 0;} //Сброс счетчиков timer1.read(interval1); //Генератор морганий диода на плате timer2.read(interval2); //Генератор морганий диодов программы timer3.read(startTime); //Таймер разгона timer4.read(stopTime); //Таймер торможения if (timer1.tick) {digitalWrite(PCB_LED, !digitalRead(PCB_LED));} //Генератор морганий диода на плате if (digitalRead(MAN) == LOW && state==0) { //Ручное вращение analogWrite(MOTOR, 40); counter = 0; loops = 0; } else if(digitalRead(MAN) == HIGH && state==0) { counter = 0; loops = 0; analogWrite(MOTOR, 0); } if(prog == 0 && !digitalRead(REL_DN) == HIGH) { //Включение диода программы 1 в режиме ожидания digitalWrite(LED_PR1, HIGH); digitalWrite(LED_PR2, LOW); } else if((prog == 0 && digitalRead(REL_DN) == HIGH)){ //Включение диода программы 1 в режиме работы if (timer2.tick) { digitalWrite(LED_PR1, !digitalRead(LED_PR1)); } } if(digitalRead(SW) == LOW && prog == 0) { //Запуск реле программы 1 digitalWrite(REL_DN, HIGH); digitalWrite(REL_UP, LOW); } if(digitalRead(LIM_DN)== HIGH){ //Остановка программы 1 по концевику digitalWrite(REL_DN, LOW); prog = 1; } if(prog == 1 && val <= 5) { //Включение диода программы 2 в режиме ожидания digitalWrite(LED_PR1, LOW); digitalWrite(LED_PR2, HIGH); } else if((prog == 1 && val > 5) || digitalRead(REL_UP) == HIGH) { //Включение диода программы 2 в режиме работы if (timer2.tick) {digitalWrite(LED_PR2, !digitalRead(LED_PR2));} } if (digitalRead(SW) == LOW && prog==1 && digitalRead(LIM_DN)== HIGH && digitalRead(MAN) == HIGH) { //Состояние кнопки для программы 2 stt=0; state=1; } if (val < spd && timer3.tick && state==1 && pp==0){ //Запуск программы 2, плавный старт мотора val++; analogWrite(MOTOR, val); } else if (loops >=turns && prog==1 && val > 0){ if(timer4.tick && val > stopspd){ val--; analogWrite(MOTOR, val); } analogWrite(MOTOR, val); if(loops >=turns && counter >=4){ digitalWrite(REL_UP, HIGH); analogWrite(MOTOR, 0); state = 0; pp = 1; } } if(digitalRead(LIM_UP)==HIGH){ //Выключение всего по приходу на верхний концевик digitalWrite(REL_UP, LOW); analogWrite(MOTOR, 0); pp = 0; prog = 0; //Переход к программе 1 counter = 0; loops = 0; state=0; val = 0; } } //Конец циклаСтрелка должна делать 8 оборотов, после чего плавно сбрасывать скорость с 200 до 30 и плавно доводить еще полоборота.
На деле же после 8ми оборотов ничего не происходит, а через полоборота она сбрасывает скорость резко в 0(что собственно и должно быть)
Все это должно происходить со строки 248