Прошу помощи с Blink через PID
- Войдите на сайт для отправки комментариев
Заранее еще раз напомню, что начинающий "ардуинщик". Поэтому прошу строго не судить. Что-то почитать никогда не против по данной теме.
Итак, ситуация такая. Злободневный PID-регулятор температуры ТЭНов (на данном этапе лампочка)
DHТ11, SSR, Лампа накаливания.
В зависимоти от показания температуры расчитываются показания PID регулятора, в зависимости от показания PID, происходи вкл/выкл SSR по типу Blink.
Первая задача - регулировать промежуток между Blink и время самого горения светодиода.
Нарисовал скетч
int ledPin = 3;
int ledState = LOW;
unsigned long previousMillis = 0;
long OnTime = 50;
long OffTime = 1000;
void setup()
{
pinMode(ledPin, OUTPUT);
}
void loop()
{
unsigned long currentMillis = millis();
if((ledState == HIGH) && (currentMillis - previousMillis >= OnTime))
{
ledState = LOW;
previousMillis = currentMillis;
digitalWrite(ledPin, ledState);
}
else if ((ledState == LOW) && (currentMillis - previousMillis >= OffTime))
{
ledState = HIGH;
previousMillis = currentMillis;
digitalWrite(ledPin, ledState);
}
}
здесь путем изменения
long OnTime = 50; и long OffTime = 1000;
получается все это регулировать.
Сама суть проблемы -
Когда вставляю этот скетч в скетч самого регулятора, параметры Blink работают по другому. Сам PID работает корректо, по крайней мере для моих задач. Но не регулируется, точнее неккоректно регуляируется длительность мерцания, а промежуток между Блинками не получается опустить менее чем 500 мс.
Первая мысль, которая приходит в голову, это то, что на это происходит в силу времени расчета PID.
В общем все, что мог просмотрел и прочитал, как местное так и буржуйское, но с проблеммой не спарвился. Возможно я вообще не правильно использую millis. Хочется не только доработать аппарат, но понять суть всей работы.
Сам код PID - регулятора.
#include <PID_v1.h>
#include <Wire.h>
#include <DHT.h>
#define DHTPIN 5
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
double Setpoint, Input, Output;
PID myPID(&Input, &Output, &Setpoint ,8, 0, 1, DIRECT);
int ledPin = 3;
int ledState = LOW;
unsigned long previousMillis = 0;
void setup()
{
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
Setpoint = 40;
myPID.SetMode(AUTOMATIC);
myPID.SetOutputLimits(0, 255);
}
void loop()
{
int t = dht.readTemperature(); // Send the command to get temperatures
Input = t;
myPID.Compute();
int val = Output;
val = map(val, 0, 255, 0, 100);
if ( val > 30) {PIDon();}
if ( val <= 30 && val >= 21) {PIDx();}
if ( val <= 20 && val >= 10 ) {PIDx1();}
if ( val <= 9) {PIDx2();}
if ( val < 3) {PIDoff();}
Serial.print("OUTPUT ");
Serial.print(val);
Serial.print(" %");
Serial.print("Temperature: ");
Serial.print(t);
Serial.println(" *C");
}
void PIDx()
{
long OnTime = 1;
long OffTime = 50;
unsigned long currentMillis = millis();
if((ledState == HIGH) && (currentMillis - previousMillis >= OnTime))
{
ledState = LOW; // Turn it off
previousMillis = currentMillis; // Remember the time
digitalWrite(ledPin, ledState); // Update the actual LED
}
else if ((ledState == LOW) && (currentMillis - previousMillis >= OffTime))
{
ledState = HIGH; // turn it on
previousMillis = currentMillis; // Remember the time
digitalWrite(ledPin, ledState); // Update the actual LED
}
}
void PIDx1()
{
long OnTime = 50;
long OffTime = 250;
unsigned long currentMillis = millis();
if((ledState == HIGH) && (currentMillis - previousMillis >= OnTime))
{
ledState = LOW; // Turn it off
previousMillis = currentMillis; // Remember the time
digitalWrite(ledPin, ledState); // Update the actual LED
}
else if ((ledState == LOW) && (currentMillis - previousMillis >= OffTime))
{
ledState = HIGH; // turn it on
previousMillis = currentMillis; // Remember the time
digitalWrite(ledPin, ledState); // Update the actual LED
}
}
void PIDx2()
{
long OnTime = 50;
long OffTime = 500;
unsigned long currentMillis = millis();
if((ledState == HIGH) && (currentMillis - previousMillis >= OnTime))
{
ledState = LOW; // Turn it off
previousMillis = currentMillis; // Remember the time
digitalWrite(ledPin, ledState); // Update the actual LED
}
else if ((ledState == LOW) && (currentMillis - previousMillis >= OffTime))
{
ledState = HIGH; // turn it on
previousMillis = currentMillis; // Remember the time
digitalWrite(ledPin, ledState); // Update the actual LED
}
}
void PIDon()
{
digitalWrite(ledPin, HIGH);
}
void PIDoff()
{
digitalWrite(ledPin, LOW);
}
За ранее благодарен и прошу прощения за почерк.
класс титановый велосипед для delay без delay().
класс титановый велосипед для delay без delay().
Извините, я не нашел где в этом классе можно задать время горения LED? Мне необходимо, чтобы светодиод "сверкал", т.е. говоря аппаратным языком - горел 50 млс, а негорел 1000 млс.
класс титановый велосипед для delay без delay().
И кстати, попробовал поставить этот класс в свой скетч, таже история, ставлю 100, а все равно быстрее 500 не моргает.
И кстати, попробовал поставить этот класс в свой скетч, таже история, ставлю 100, а все равно быстрее 500 не моргает.
поробуй этот "класс" воткнуть в свой скетч
тоже быстрее 500 не моргает? :D
Извините, я не нашел где в этом классе можно задать время горения LED? Мне необходимо, чтобы светодиод "сверкал", т.е. говоря аппаратным языком - горел 50 млс, а негорел 1000 млс.
казалось бы, вкуда здесь nD_01.read(100); #28 воткнуть 100, что бы тикало каждые 100 миллисекунд?
что нужно сделать, что бы тикало то 50, то 1000 - угадай с первого раза?
#include "class_noDELAY.h" noDELAY led; void setup () { pinMode(13, OUTPUT); // LED_01 digitalWrite(13, 1); led.start(); } void loop() { unsigned int t; if (digitalRead(13) == 1) {t = 1000;} else {t = 50;} led.read(t); if (led.tick == 1) {digitalWrite(13, !digitalRead(13));} }#include "Arduino.h" #include "uTimerList.h" extern TTimerList TimerList; void BlinkOff(void) { digitalWrite(13, LOW); } void BlinkOn(void) { digitalWrite(13, HIGH); } void setup() { pinMode(13, OUTPUT); TimerList.Add(BlinkOff, 50); TimerList.Add(BlinkOn, 1000); } void loop() { /* add main program code here */ }всё.
Извините, я не нашел где в этом классе можно задать время горения LED? Мне необходимо, чтобы светодиод "сверкал", т.е. говоря аппаратным языком - горел 50 млс, а негорел 1000 млс.
казалось бы, вкуда здесь nD_01.read(100); #28 воткнуть 100, что бы тикало каждые 100 миллисекунд?
что нужно сделать, что бы тикало то 50, то 1000 - угадай с первого раза?
#include "class_noDELAY.h" noDELAY led; void setup () { pinMode(13, OUTPUT); // LED_01 digitalWrite(13, 1); led.start(); } void loop() { unsigned int t; if (digitalRead(13) == 1) {t = 1000;} else {t = 50;} led.read(t); if (led.tick == 1) {digitalWrite(13, !digitalRead(13));} }Ругается
#include "Arduino.h" #include "uTimerList.h" extern TTimerList TimerList; void BlinkOff(void) { digitalWrite(13, LOW); } void BlinkOn(void) { digitalWrite(13, HIGH); } void setup() { pinMode(13, OUTPUT); TimerList.Add(BlinkOff, 50); TimerList.Add(BlinkOn, 1000); } void loop() { /* add main program code here */ }всё.
Спасибо большое.
Я так понимаю это таймер, еще не изучал работу по таймеру.
Но всё заработало как положено, только возникает большая проблемма - виснет монитор порта через несколько секунд((((
Ругается
#7 #5
странно. переделал вот так
void BlinkOn(void) { static int16_t count = 0; digitalWrite(13, HIGH); Serial.print("Tick "); Serial.println(count++); } void setup() { Serial.begin(115200); pinMode(13, OUTPUT); TimerList.Add(BlinkOff, 50); TimerList.Add(BlinkOn, 1000); }не зависает сериал. не хочет, наерн. :)
странно. переделал вот так
void BlinkOn(void) { static int16_t count = 0; digitalWrite(13, HIGH); Serial.print("Tick "); Serial.println(count++); } void setup() { Serial.begin(115200); pinMode(13, OUTPUT); TimerList.Add(BlinkOff, 50); TimerList.Add(BlinkOn, 1000); }не зависает сериал. не хочет, наерн. :)
Отдельным скетчем не зависает, когда в скетч пида вставляю зависает.
#7 #5
Таже самая история, отдельным скетчем работает все как положено, в скетче пида минимум 500, даже когда задано 100.(((
Таже самая история, отдельным скетчем работает все как положено, в скетче пида минимум 500, даже когда задано 100.(((
я же тебя просил проверить digitalWrite(13, !digitalRead(13));
мошт, надо нам пидаскетч показать?
мошт, надо нам пидаскетч показать?
в самом начале нарисован
мошт, надо нам пидаскетч показать?
Если уже с таймером, то
Вариант 1
#include <PID_v1.h> #include "Arduino.h" #include "uTimerList.h" #include <Wire.h> #include <DHT.h> #define DHTPIN 5 #define DHTTYPE DHT11 DHT dht(DHTPIN, DHTTYPE); double Setpoint, Input, Output; extern TTimerList TimerList; PID myPID(&Input, &Output, &Setpoint ,8, 0, 1, DIRECT); int ledPin = 3; int ledState = LOW; void BlinkOff(void) { digitalWrite(ledPin, LOW); } void BlinkOn(void) { digitalWrite(ledPin, HIGH); } void setup() { Serial.begin(9600); pinMode(ledPin, OUTPUT); Setpoint = 36; myPID.SetMode(AUTOMATIC); myPID.SetOutputLimits(0, 255); } void loop() { int t = dht.readTemperature(); // Send the command to get temperatures Input = t; myPID.Compute(); int val = Output; val = map(val, 0, 255, 0, 100); if ( val > 30) {PIDon();} if ( val <= 30 && val >= 21) {PIDx();} if ( val <= 20 && val >= 10 ) {PIDx1();} if ( val <= 9) {PIDx2();} if ( val < 3) {PIDoff();} Serial.print("OUTPUT "); Serial.print(val); Serial.print(" %"); Serial.print("Temperature: "); Serial.print(t); Serial.println(" *C"); } void PIDx() { TimerList.Add(BlinkOff, 50); TimerList.Add(BlinkOn, 100); } void PIDx1() { TimerList.Add(BlinkOff, 50); TimerList.Add(BlinkOn, 500); } void PIDx2() { TimerList.Add(BlinkOff, 50); TimerList.Add(BlinkOn, 1000); } void PIDon() { digitalWrite(ledPin, HIGH); } void PIDoff() { digitalWrite(ledPin, LOW); }Вариан 2
#include <PID_v1.h> #include "uTimerList.h" #include <Wire.h> #include <DHT.h> #define DHTPIN 5 #define DHTTYPE DHT11 DHT dht(DHTPIN, DHTTYPE); extern TTimerList TimerList; double Setpoint, Input, Output; PID myPID(&Input, &Output, &Setpoint ,8, 0, 1, DIRECT); int ledPin = 3; void BlinkOff(void) { digitalWrite(ledPin, LOW); } void BlinkOn(void) { digitalWrite(ledPin, HIGH); } void setup() { Serial.begin(9600); pinMode(ledPin, OUTPUT); Setpoint = 36; myPID.SetMode(AUTOMATIC); myPID.SetOutputLimits(0, 255); } void loop() { int t = dht.readTemperature(); // Send the command to get temperatures Input = t; myPID.Compute(); int val = Output; val = map(val, 0, 255, 0, 100); if ( val > 30) { digitalWrite(ledPin, HIGH);} if ( val <= 30 && val >= 21) { TimerList.Add(BlinkOff, 50); TimerList.Add(BlinkOn, 100); } if ( val <= 20 && val >= 10 ) { TimerList.Add(BlinkOff, 100); TimerList.Add(BlinkOn, 300); } if ( val <= 6) { TimerList.Add(BlinkOff, 50); TimerList.Add(BlinkOn, 500); } if ( val < 3) {digitalWrite (ledPin, LOW);} Serial.print("OUTPUT "); Serial.print(val); Serial.print(" %"); Serial.print("Temperature: "); Serial.print(t); Serial.println(" *C"); }Во втором варианте строчка
if ( val < 3) {digitalWrite (ledPin, LOW);}вообще не срабатывает.
А всё, въехал. Прочитал 1 пост внимательно. Мой TTimerList Вам не подойдет.
Хотя, могу его чуть переделать.
#include <PID_v1.h> #include "Arduino.h" #include "uTimerList.h" #include <Wire.h> #include <DHT.h> #define DHTPIN 5 #define DHTTYPE DHT11 DHT dht(DHTPIN, DHTTYPE); double Setpoint, Input, Output; extern TTimerList TimerList; PID myPID(&Input, &Output, &Setpoint, 8, 0, 1, DIRECT); int ledPin = 3; int ledState = LOW; void BlinkOff(void) { digitalWrite(ledPin, LOW); } void BlinkOn(void) { digitalWrite(ledPin, HIGH); } THandle Offhnd; THandle Onhnd; void setup() { Serial.begin(9600); pinMode(ledPin, OUTPUT); Setpoint = 36; myPID.SetMode(AUTOMATIC); myPID.SetOutputLimits(0, 255); Offhnd = TimerList.Add(BlinkOff, 50); //добавили 2 таймера Onhnd = TimerList.Add(BlinkOn, 1000); TimerList.TimerStop(Offhnd); // и остановили пока TimerList.TimerStop(Onhnd); } void loop() { int t = dht.readTemperature(); // Send the command to get temperatures Input = t; myPID.Compute(); int val = Output; val = map(val, 0, 255, 0, 100); if (val > 30) { PIDon(); } if (val <= 30 && val >= 21) { PIDx(); } if (val <= 20 && val >= 10) { PIDx1(); } if (val <= 9) { PIDx2(); } if (val < 3) { PIDoff(); } Serial.print("OUTPUT "); Serial.print(val); Serial.print(" %"); Serial.print("Temperature: "); Serial.print(t); Serial.println(" *C"); } void PIDx() { TimerList.TimerNewInterval(Offhnd, 50); TimerList.TimerNewInterval(Onhnd, 100); } void PIDx1() { TimerList.TimerNewInterval(Offhnd, 50); TimerList.TimerNewInterval(Onhnd, 500); } void PIDx2() { TimerList.TimerNewInterval(Offhnd, 50); TimerList.TimerNewInterval(Onhnd, 1000); } void PIDon() { TimerList.TimerStop(Offhnd); TimerList.TimerStop(Onhnd); // оба таймера остановлены, светодиод просто горит digitalWrite(ledPin, HIGH); } void PIDoff() { TimerList.TimerStop(Offhnd); TimerList.TimerStop(Onhnd); // оба таймера остановлены, светодиод просто потушен digitalWrite(ledPin, LOW); }скачайте новый uTimerList и пропробовайте так.
скачайте новый uTimerList и пропробовайте так.
Там же на GitHube? Скачал. В общем ситуация такая, все работает, не виснет но когда val опускается ниже 21, ledPin выключается совсем, т.е. уже на PIDx1() срабатывает LOW, в скетче причины не нашел. Ну а так начало отличное.
ОК, приеду с дачи, буду разбираца
ОК, приеду с дачи, буду разбираца
Хорошо, будем подождать))
А меня пока работой завалили. :(
А меня пока работой завалили. :(
Ясненько :( , ну ладно, как будет времячко по свободнее, тогда поглядите что там, да как...Если все заработает я закину вам немножко спасибо ))
попробуй в loop вотак написать, чо будет?
попробуй в loop вотак написать, чо будет?
Тоже самое, там кстати надо < а не >, val обратно температуре.
Дошло до уставки с такими условиями
if (val > 30) { PIDon(); } if (val <= 30 ) { PIDx(); } else if (val <= 20 ) { PIDx1(); } else if (val <= 9) { PIDx2(); } if (val < 3) { PIDoff(); }Но частота блинка не менялась.
А если поменять значения в PIDx1 например на 500 , то вообще не моргает (LOW)
А кинь мне весь скетч на почту, я ночером поразбира
А кинь мне весь скетч на почту, я ночером поразбира
кинуто)
а я понял в чем дело. loop выполняется быстро и таймеры каждый раз при выполнении условия перезапускаюца. Во первых исправь if-ы вот так
скопируй как есть, не исправляй ничего.
опрос датчиков, надо изменить, если с последнего измерения ничего не изменилось, не надо дальше и идти.
примерно так
у меня моргает как заводная. :)
Смекаешь?
правильней бы было вообще опрос датчика из loop убрать а в нем проверять только изменения.
Домашка: сделай опрос датчика тоже по таймеру, раз допустим в 3 - 5 секунд.
только переменную, где хранишь val обьяви как volatile int
правильней бы было вообще опрос датчика из loop убрать а в нем проверять только изменения.
Домашка: сделай опрос датчика тоже по таймеру, раз допустим в 3 - 5 секунд.
только переменную, где хранишь val обьяви как volatile int
Хорошо, будем попробывать). Мне кстати в ближайшие пару дней далласы придут, я поменяю DHT на даллас)
правильней бы было вообще опрос датчика из loop убрать а в нем проверять только изменения.
Домашка: сделай опрос датчика тоже по таймеру, раз допустим в 3 - 5 секунд.
только переменную, где хранишь val обьяви как volatile int
Что-то не получается, даже DHT не заводится, пицот вариантов испробывал и две библиотеки, не то что время опроса датчика не изменяется, сам датчик с таймером запустить не могу.
На сегодня силы исчерпаны. Может завтра еще попробую.
А PID заработал, спасибо огромное, как обещал с з.п. закину немного спасибо)
не пытайся в функции таймера читать DHT, она работает в контексте прерывания, DHT врет безбожно, потому что micros() не работает.
Как я сделал: В функции таймера которая вызывается раз в 5 секунд взвожу флаг, что надо прочитать DHT, a в loop, если этот флаг взведен, вызываю уже функцию чтения DHT, которая флаг этот сбрасывает, то есть следующее чтение будет опять через 5 сек.