loop прерывает прерывания
- Войдите на сайт для отправки комментариев
Чт, 04/01/2018 - 10:48
Проблемма в том, что цикл loop ставит на паузу прерывания. Вот основной код:
#include <TimerOne.h> #include <AccelStepper.h> #include <max6675.h> #include <SoftwareSerial.h> #include <Nextion.h> SoftwareSerial nextion(17, 16);// Nextion TX to pin 2 and RX to pin 3 of Arduino Nextion myNextion(nextion, 9600); MAX6675 thermocouple(30, 32, 31); AccelStepper Stepper1(1,25,24); AccelStepper Stepper2(1,22,23); int calibration_1 = 0; int calibration_2 = 0; const int buttonPin = 33; long interval = 1000; long previousMillis = 0; int dir = -1; void setup() { Serial.begin(9600); myNextion.init(); Timer1.initialize(50); Timer1.attachInterrupt(Timer1_action); pinMode(buttonPin, INPUT); Stepper1.setMaxSpeed (2000); Stepper1.setAcceleration(2000); Stepper2.setMaxSpeed(2000); Stepper2.setSpeed(1000); } void Timer1_action(){ if(digitalRead(buttonPin)==1){ calibration_1 = 1; } Stepper1.run(); Stepper2.runSpeed(); } void loop() { if(calibration_1 == 0){ Stepper1.move(100*dir); } if (calibration_1 == 1 && calibration_2 == 0){ calibration_2 = 1; dir=1; Stepper1.move(2000*dir); } unsigned long currentMillis = millis(); if(currentMillis - previousMillis > interval) { previousMillis = currentMillis; myNextion.setComponentText("t0", String(thermocouple.readCelsius())); } }
Этот способ работает стабильнее:
#include <AccelStepper.h> #include <max6675.h> #include <SoftwareSerial.h> #include <Nextion.h> SoftwareSerial nextion(17, 16);// Nextion TX to pin 2 and RX to pin 3 of Arduino Nextion myNextion(nextion, 9600); MAX6675 thermocouple(30, 32, 31); AccelStepper Stepper1(1,25,24); AccelStepper Stepper2(1,22,23); int calibration_1 = 0; int calibration_2 = 0; const int buttonPin = 33; long interval = 1000; long previousMillis = 0; int dir = -1; void setup() { noInterrupts (); // отключить все прерывания TCCR1A = 0; TCCR1B = 0; TCNT1 = 0; OCR1A = 125; // сравнить регистр 16 МГц / 256/500 Гц (2ms=125) TCCR1B |= (1 << WGM12); // Режим СТС TCCR1B |= (1 << CS12); // 256 делитель TIMSK1 |= (1 << OCIE1A ); // включить таймер сравнить прерываний interrupts(); // включить все прерывания Serial.begin(9600); myNextion.init(); pinMode(buttonPin, INPUT); Stepper1.setMaxSpeed (2000); Stepper1.setAcceleration(2000); Stepper2.setMaxSpeed(2000); Stepper2.setSpeed(1000); } ISR (TIMER1_COMPA_vect) // Функция прерывания таймера { if(digitalRead(buttonPin)==1){ calibration_1 = 1; } Stepper1.run(); Stepper2.runSpeed(); } void loop() { if(calibration_1 == 0){ Stepper1.move(100*dir); } if (calibration_1 == 1 && calibration_2 == 0){ calibration_2 = 1; dir=1; Stepper1.move(2000*dir); } unsigned long currentMillis = millis(); //проверяем не прошел ли нужный интервал, если прошел то if(currentMillis - previousMillis > interval) { // сохраняем время последнего переключения previousMillis = currentMillis; myNextion.setComponentText("t0", String(thermocouple.readCelsius())); } }
Т.е. каждый раз при выполнении loop, останавливаются двигатели на долю секунды.
Помимо этого, вращение первого двигателя тормозит второй. Т.е. пока вращается первый, скорость второго меняется сама. При использовании второго кода, этот эффект заметен в два раза меньше.
Выполнение какий либо функций в прерывании нежелательно, особенно если там имеются задержки, лучше перенесите запуск шаговиков в loop, a в прерывание две переменные, и изменяя эти переменные в прерывании, управляйте выполнением функций Stepper1.run и Stepper2.runSpeed
Не понял. Как переменные, вы о чем? И если перенести запуск шагавиков в loop, то они же вообще остановятся от маленькой скорости цикла. Или я вообще ничего не понял? Можно пример?
unsigned char Flag_Step1_Run = 0;
Вектор прерывания таймера
{
Flag_Step1_Run = 1;
}
loop()
{
if(Flag_Step1_Run)
{
Stepper1.run();
Flag_Step1_Run = 0;
}
}
Со вторым шаговиком также, простите за оформление, пишу с мобильника в спешке.
Мне надо разбираться, что вы написали, что бы понять. Но разве в данном случае цикл loop не будет медленнее и не от него будет зависить скорость исполнения прерывания? Ну допустим прерывание 50 мкс и оно срабатывает несколько раз за то время, пока один раз отрабатывает loop. Если флаг несколько раз за это время поставится на 1, то он не отработает нужное количество шагов.
Вам semaawp правильно вобщем написал, забыв уточнить что loop действительно нужен быстрый, заметно быстрей чем требуемые временные интервалы управления степером. Если это невозможно - то управлять таки из прерывания непосредственно сигналами на степер, без каких либо задержек в обработчике и вызова невесть чего выполняемого невесть сколько времени;) С используемой либой степера это судя по всему тоже невозможно. Отдельных матюков заслуживает софтсириал. Он висит в обработчике прерывания безобразно долго - от начала передачи или приема байта до завершения. А там и следующий байт подоспел. Вот чего степеры приостанавливаются во времявывода на нексион! Про софтсириал лучше вобще не знать, хотя если сильно чешется - попробуйте поигратся его скоростью чтоб лично испробовать ;)
Вобщем Ваш проект в тупике. Выход - выбросить либы (ну или полезть в них разобратся что и как и по ходу переписать в нечто стоящее) и забыв что есть ардуино писать как для нормального МК. Чудес не бывает, эффективный софт из кубиков не собирается.
Вам semaawp правильно вобщем написал, забыв уточнить что loop действительно нужен быстрый, заметно быстрей чем требуемые временные интервалы управления степером. Если это невозможно - то управлять таки из прерывания непосредственно сигналами на степер, без каких либо задержек в обработчике и вызова невесть чего выполняемого невесть сколько времени;) С используемой либой степера это судя по всему тоже невозможно. Отдельных матюков заслуживает софтсириал. Он висит в обработчике прерывания безобразно долго - от начала передачи или приема байта до завершения. А там и следующий байт подоспел. Вот чего степеры приостанавливаются во времявывода на нексион! Про софтсириал лучше вобще не знать, хотя если сильно чешется - попробуйте поигратся его скоростью чтоб лично испробовать ;)
Вобщем Ваш проект в тупике. Выход - выбросить либы (ну или полезть в них разобратся что и как и по ходу переписать в нечто стоящее) и забыв что есть ардуино писать как для нормального МК. Чудес не бывает, эффективный софт из кубиков не собирается.
Я вас понял. Вот что я действительно в душе не чаю, так это то, как изменить скорость порта nextion. А это, как я понял, должно исправить ситуацию хотя бы от части.
Я это наугад сделал, комбинируя старую и новую инструкцию. Был сильно удивлен, когда заработало...
Можно управлять двигателями и без либ, но эта либа поддерживает плавный разгон, и много нужных функций, это очень удобно. Сравнивал работу без либ, различий не нашел.
Спасибо за подсказки. Понимаю, что код то еще УГ, но доводить и разбивать на классы я его буду, когда получу рабочий станок. Время слишком давит. И я так и не понял, зачем делать флаг в одном таймере для того, что бы использовать его в другом таймере...
И вот я обнаружил проблему.
Экран не запоминает, на какой скорости остановился код. А скорость указывается в начале программы.
Получается, что с таким значением я могу загрузиться, и изменить на 57600, после чего, не перезагружая экран, обновить прошивку ардуинки и все заработает. Но как только я перезагружу экран, значение снова скинется до 9600, а ардуинка будет пытаться приконектится на 57600.
Можно ли динамически изменять строку Nextion myNextion(nextion, 9600);?
Прошу прощения, если туплю в очевидном месте, но мне не знаком c++, пишу код интуитивно опираясь на другой язык.
Ютубер с ником thestrangecityguide помог:
nextion.begin(9600);