Конфликт двух процессов - помогите разобраться
- Войдите на сайт для отправки комментариев
Добрый день, корифеи
Опять я со своим увлажнителем - теперь засел за подключение электродвигателя вентилятора к нему. Когда работает только код управления двигателем, то все прекрасно работает и регулируется (сейчас подключена лампа накаливания в качестве нагрузки) - лампочка светит ровно, яркость меняется, мерцания не видно. По осцилограмме тоже все в порядке - ширина полуволны регулируется, переход через ноль определяется корректно.
Но вот когда начинаем опрашивать датчик влажности - имеем моргание лампочки с частотой опроса датчика (по осциллограмме пропуски периодов идут). Если закомментировать опрос датчика и просто присваивать значение переменной - тоже глюков нет. Остальной код, влияния на этот глюк не оказывает, поэтому я его убрал. Глюк происходит именно в момент опроса датчика (и видимо ожидания ответа от него).
Вопрос - как побороть этот эффект? И показания от датчика нужно получать, и напряжение на мотор должно подаваться без пропусков.
#define DEBUG 0 // включение отладки const byte SensorLevel = 0; //присваиваем имена выводам const byte LedMedSpeed = 3; const byte LedDio = 4; const byte LedClk = 5; const byte MotorOsc = 6; const byte LedAutoSpeed = 7; const byte LedLowSpeed = 8; const byte FanMotor = 9; const byte Buzzer = 10; const byte LedHighSpeed = 11; const byte PumpWater = 12; const byte LedPower = 13; const byte LedOsc = 14; const byte SensorDht = 15; const byte ButtonPower = 16; const byte ButtonSpeed = 17; const byte ButtonOsc = 18; const byte ButtonHum = 19; #include "stDHT.h" //подключаем библиотеку датчика влажности DHT sens(DHT22); //указать датчик DHT11, DHT21, DHT22 unsigned long DHTpreviousMillis = 0; // время, когда датчик влажности опрашивался в последний раз const int DHTinterval = 2000; // интервал опроса датчика влажности - 2 секунды const int FanInterval = 20000; // интервал между расчетами разницы между расчетной и усредненной влажностью для изменения скорости мотора - 20 сек byte HumTarget = 50; // Влажность, которую нужно поддерживать byte HumCurrent; // Влажность, которую измерили датчиком const int HumNumReadings = 10; // Количество измерений для усреднения показаний DHT int HumReadings[HumNumReadings]; // данные, считанные с входного аналогового контакта volatile int FanLowSpeedDelay = 80; //Время задержки для низкой скорости мотора volatile unsigned long ZeroCrossTime; // время в микросекундах срабатывания датчика нуля unsigned long ZeroCrossTims; // переменная показаний времени void setup() { //устанавливаем PIN A1-A5 в режим входа и включаем подтяжку for (byte pin = 15; pin <= 19; ++pin) { pinMode(pin, INPUT); digitalWrite(pin, HIGH); } pinMode(SensorLevel, INPUT); digitalWrite(SensorLevel, HIGH); // устанавливаем PIN D3-D13 в режим выхода for (byte pin = 3; pin <= 14; ++pin) { pinMode(pin, OUTPUT); digitalWrite(pin, LOW); attachInterrupt(0, zero_crosss_int, RISING); // Choose the zero cross interrupt # from the table above } if (DEBUG == 1) { Serial.begin(9600); } byte HumCurrent = sens.readHumidity(SensorDht); // измеряем однократно влажность, чтобы HumCurrent не была пустой if (isnan(HumCurrent)) { // проверяем, были ли ошибки при считывании: if (DEBUG == 1) { Serial.println("Не удается считать показания"); } return; // если были - начинаем заново, } for (int HumThisReading = 0; HumThisReading < HumNumReadings; HumThisReading++) HumReadings[HumThisReading] = 0; if (DEBUG == 1) { Serial.print("Starting, target humidity set to: "); Serial.print(HumTarget); Serial.println("%."); Serial.print("Current humidity: "); Serial.print(HumCurrent); Serial.println("%."); } } void zero_crosss_int() // function to be fired at the zero crossing to dim the light { ZeroCrossTime = micros(); //запоминаем время перехода напряжения через ноль } void loop() { // управление мотором int dimtime = (75 * FanLowSpeedDelay); // For 60Hz =>65 ZeroCrossTims = micros(); // считываем время, прошедшее с момента запуска программы if (ZeroCrossTims >= (ZeroCrossTime + dimtime)) { //если время больше или равно времени срабатывания нуля + время задержки digitalWrite(FanMotor, HIGH); // открываем симистор if (ZeroCrossTims >= (ZeroCrossTime + dimtime + 10)) { } digitalWrite(FanMotor, LOW); // выключаем сигнал на симистор. } // конец управления мотором unsigned long CurrentMillis = millis(); // запоминаем текущее время для разных таймеров // Опрос датчика влажности if (CurrentMillis - DHTpreviousMillis > DHTinterval) { // проверяем не прошел ли заданный интервал между измерениями, и если прошел, то DHTpreviousMillis = CurrentMillis; // сохраняем время последнего измерения // byte HumCurrent = 56; //когда просто присваиваем значение переменной - пропусков нет byte HumCurrent = sens.readHumidity(SensorDht); // измеряем однократно влажность, чтобы HumCurrent не была пустой if (isnan(HumCurrent)) { // проверяем, были ли ошибки при считывании return; // если были, начинаем заново } } // Конец опроса датчика влажности }
мошт, дело в библиотеке для DHT?
Там библиотека вроде прерывания запрещает на время опроса. А чем это на двигатель повлияет?
Там библиотека вроде прерывания запрещает на время опроса. А чем это на двигатель повлияет?
А зачем в Вашем коде zero_crosss_int()?
Там библиотека вроде прерывания запрещает на время опроса. А чем это на двигатель повлияет?
А зачем в Вашем коде zero_crosss_int()?
В моем нет, у меня вообще кода нет.))))
В этом коде для диммера уже заложена не стабильность фазы. Пока нет ничего другого в цикле ещё как то работает. Любые дополнения в loop будут приводить к морганию. Ничего сделать нельзя. Надо диммер на прерывании таймера делать.
Управлять импульсом на симистор программно - это значит всегда рисковать выдать его не вовремя. В коде, тем более при использовании сторонних библиотек, всегда могут возникнуть задержки, которые предвидеть и учесть очень трудно.
Я бы предложил выдавать импульс аппаратным таймером, установив период счёта приблизительно равным полупериоду сетевого напряжения, и длину импульса - те же 10мкс, или сколько там требуется для надёжного срабатывания.
А вот положение импульса относительно момента пересечения нуля - это уже действительно можно подстраивать программмно, причём достаточно плавно, изменяя в небольших пределах значение, загружаемое в счётчик таймера.
Получится конечно посложней, чем сейчас, но зато красиво, и пригодно для использования в других проектах.
Ну а если лень с этим всем возиться - можно просто поставить на управление мотором отдельный контроллер.
Как это посмотреть и корректно поправить? Прошу прощения если вопрос чайниковский - я и есть чайник :)
Двигатель работает рывками, что не есть гуд.
А зачем в Вашем коде zero_crosss_int()?
Поймать момент перехода напряжения через ноль, чтобы открыть симистор и отсчитать ширину имульса. Не?
На самом деле только опрос датчика влажности вызывает указанный эффект, если датчик не опрашивать, то остальной код не вызывает проблем (ту там собственно кода то кот наплакал - опрос кнопок и вывод показаний влажности на дисплей. А где почитать про "надо диммер на прерывании таймера" можно?
Согласен, по видимому на этом момент я и напоролся.
Ткните пожалуйста носом где про это почитать можно?
Да, тоже вариант. Во всяком случае, лучше чем просто в цикле.
Но если библиотека DHT, или ещё кто-то, действительно надолго запрещает прерывания, такой способ не сильно поможет.
Ткните пожалуйста носом где про это почитать можно?
Да сам только что придумал. :)
Но вообще-то, подозреваю что не я первый, поэтому можно попробовать погуглить.
А читать, конечно же, даташит на контроллер - программирование таймеров.
Думаю, если чётко понимать, что требуется - вполне можно осилить. Осциллограф есть - это уже хорошо, с ним намного проще.
Как это посмотреть и корректно поправить? Прошу прощения если вопрос чайниковский - я и есть чайник :)
Двигатель работает рывками, что не есть гуд.
Посмотрите в сторону Ciber-lib, там на таймере, но этот эффект тоже присутствует. У меня на лампе (нагреватель) немного видно, думал на движке, за счет инерции, будет незаметно.
P/S следующий вариант - самописный опрос датчика, это мне не по зубам.((((
Проитайте тему http://arduino.ru/forum/programmirovanie/attiny85-i-preryvanie . Там всё разжёвано. А тема не совместимости программного диммера и DHT22 ещё в 16 году обсуждалась на форуме. Поиск рулит.
Управление импульсом нужно организовать при помощи флагов, а не так как в программе.
Что то не работает... :(