Помогите отладить код

Megawollt
Offline
Зарегистрирован: 06.12.2015

Устройство такое. Есть штанга, управляющая частотным преобразователем с двумя концевиками. Имеет два положения, внизу и вверху.

На штанге вращающаяся стрелка с мотором постоянного двигателя. Управляется ШИМом

Устройство имеет 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;
}


} //Конец цикла

 

Megawollt
Offline
Зарегистрирован: 06.12.2015

Основная проблема с прерываниями. Переменные за проход магнита увеличиваются не на единицу, а на несколько, хотя на макете все работало правильно

Megawollt
Offline
Зарегистрирован: 06.12.2015

На данный момент код такой:

/*Контроллер управления ракетой*/

#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