Помощь в коде контроллер для управления электронного терморегулирующего вентиля
- Войдите на сайт для отправки комментариев
Втр, 07/11/2017 - 02:35
Прошу помощи не работает скетч появляется ошибка: exit status 1 'printTemperature' was not declared in this scope
#include <LiquidCrystal.h>
#include <AccelStepper.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 12 // Data wire is plugged into port 12 on the Arduino
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress Suction;
#define STEPS 480 // change this to the number of steps on your motor
AccelStepper stepper(AccelStepper::HALF4WIRE, 0, 1, 2, 3);
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
int sensorPin = A0; // select the input pin for the key
int sensorValue = 1023; // variable to store the value coming from the sensor
float PressureValue ; // среднеарифм показания датчика давления ,флоат.
long intPressureValue ; // Показания датчика давления ,бин, 10 разр,макс 2,147,483,647.
float UPressureValue ; // Показания датчика давления ,Вольт
int minst = 66; // минимальное число шагов открытия ЭРВ.
int nulst = 100; // среднестатистическое положение ЭРВ, относительно которого производится ввод поправки в плюс/минус. Если брать аналогию с ТРВ, то нужно вообще делать minst=nulst
int start_pos = 0; //при простое компрессора это значение вычитается из nulst для закрытия эрв.
int st = minst; //установка ЭРВ в минимально открытое состояние.
int pre_st = minst; // предыдущее положение.
int m = 0; // Защёлка входа-выхода в ручной режим.
int p = 0; //Опред простоя компрессора
int p1 = 0; //Опред запуска компрессора
int p2 = 0; //Опред запуска компрессора
unsigned long k1 = 0; // счётчик времени интегратора 1
unsigned long k2 = 0; // счётчик времени интегратора 2
unsigned long t_over = 550000; // время ,mс, по истечении которого интегр сост приравнивается к сумме интегр и пропорциональной составляющих при ошибке более 2 гр. Задано на минуту больше времени разогрева ТН. При изменении t_discr менять не нужно.
unsigned int s = 10000; // количество усреднений с датч давл. 10000 это около 1.2 секунд. Это время не должно превышать t_discr (ms) и не должно быть равным нулю
int start = 0; // обнул Kci и Kp после входа в главный цикл программы
float err = 0.0 ; // Константы и переменные для вычисления ошибки и необходимого положения ЭРВ (st)
float need_SH = 4.0; // Заданное значение перегрева
float tempA1; // Температура кипения (давление) для использования в основном цикле
float tempB1; // Температура всаса для использования в основном цикле
float pre_tempA1;
float pre_tempB1; // Предыдущая температура
float Kp = 0.2; // Коэф пропорц.Kp*err*err*err Тогда ошибка при 480 шагах будет 7.6гр.
int Kp_on = 0; // Включение-выключение проп сост. Изначально проп сост выключена и включается при определении включения компрессора.
float Ki; // Коэф интегр для подстановки в формулу st=.... Расчитывается в теле программы как Ki=t_discr/Ti. Ki не должен быть равен нулю.
int Ki_on = 1; // Вкл-выкл интегральной сост. В программе не меняется, задаётся только здесь для вкл-выкл.
int Ti = 70; // Постоянная времени интегрирования в секундах, нормированная. Не зависит от частоты расчёта ошибки. Для исключения интегральной сотавляющей, Ti сделать максимально большим. 32 767. Или выключить коэффициентом Ki_on. Ti не должно быть равным нулю
int Kci = 0; // Выключатель разрешения процесса накопления интегр состаляющей. Изначально запрещено до определения вкл компрессора.
float C = 0.0; // Служебная переменная интегрирования (накопительная)
int Td = 0; // Постоянная времени дифференцирования в секундах, нормированная. Не зависит от частоты расчёта ошибки. Для исключения дифф составляющей сделать Td=0.
float Kd; // Коэф дифф для подстановки в формулу st=.... Расчитывается в теле программы как Kd=Td/t_discr.
int Kd_on = 0; // Вкл-выкл дифф сост. Включается- выключается в теле программы по условиям определения вкл или выкл компрессора.
float pre_err = 0.0; // Предыдущая ошибка в общем цикле вычисления шагов
float SH = 0.0;
unsigned long t_discr = 3000; // Время дискретизации PID st=......... Обязательно должна быть того же типа что и millis . не должно быть равным нулю
unsigned long previousMillis = 0; // Служебная переменная коррекция интегрирующей цепью
unsigned long previousMillis3 = 0; // Служебная переменная3 для гашения подсветки через заданное время после последнего нажатия любой кнопки.
int led = 1; // переменная для гашения подсветки
int ledoff = 1; // плавн гашение
void setup() {
Ki = (float)t_discr / ((float)Ti * 1000.0); // Коэф интегр для подстановки в формулу st=....
Kd = (float)Td * 1000.0 / (float)t_discr; //Коэф дифф для подстановки в формулу st=....
pinMode(10, OUTPUT); // для гашения дисплея
analogWrite(10, 40); // При старте подсветка дисплея включена
sensors.begin();
if (!sensors.getAddress(Suction, 0)) lcd.print("no find 0");
sensors.setResolution(Suction, 12);
stepper.setAcceleration(100);
stepper.setMaxSpeed(70);
lcd.begin(16, 2);
lcd.print("Set EEV to");
lcd.setCursor(0, 1);
lcd.print("start position");
delay(1000);
stepper.runToNewPosition(-STEPS - 40);
stepper.setCurrentPosition(0);
delay(2000);
stepper.runToNewPosition(minst);
delay(2000);
lcd.clear();
}
void manual() // Функция ручного управления ЭРВ
{
analogWrite(10, 40); // В ручном режиме подсветка включена и не выключается.
lcd.clear();
lcd.print("Manual mode");
delay (1000);
while (m == 1)
sensors.requestTemperatures();
printTemperature(Suction);
lcd.setCursor(9, 0);
lcd.print("Meev");
lcd.print(st);
{
sensorValue = analogRead(sensorPin); // read the value from the sensor: LEFT
while (sensorValue < 550 && sensorValue > 355)
{
if (st > 0)
{
st = st - 1;
lcd.clear();
lcd.setCursor(9, 0);
lcd.print("Meev");
lcd.print(st);
stepper.runToNewPosition(st);
delay(200);
}
sensorValue = analogRead(sensorPin); // read the value from the sensor:
}
while (sensorValue < 30)
{
if (st < STEPS)
{
st = st + 1;
lcd.clear();
lcd.setCursor(9, 0);
lcd.print("Meev");
lcd.print(st);
stepper.runToNewPosition(st);
delay(200);
}
sensorValue = analogRead(sensorPin); // read the value from the sensor: 1023 none; 639 (720)SET; 408 (481) LEFT; 0 RIGHT; 98 (131)UP; 254 (307) DOWN
}
if (sensorValue < 780 && sensorValue > 600) // Выход из ручного режима
{
m = 0;
lcd.clear();
lcd.print("Auto mode");
led = 1; // Для гашения подсветки экрана через x минут после входа в автоматический режим.
delay (1000);
}
while (sensorValue < 350 && sensorValue > 200) // По нажатию кнопки Down уменьшаем перегрев (need_SH) с дискретностью 0,1 градус.
{
need_SH = need_SH - 0.1;
if (need_SH <= 0.5) {
need_SH = 0.5;
}
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("set SH=");
lcd.print(need_SH);
delay(400);
sensorValue = analogRead(sensorPin);
}
while (sensorValue < 180 && sensorValue > 50) // По нажатию кнопки UP увеличиваем перегрев (need_SH) с дискретностью 0,1 градус.
{
need_SH = need_SH + 0.1;
if (need_SH >= 10.0) {
need_SH = 10.0;
}
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("set SH=");
lcd.print(need_SH);
delay(300);
sensorValue = analogRead(sensorPin);
}
delay(200);
stepper.disableOutputs();
}
}
void printTemperature(DeviceAddress t)
{
intPressureValue = 0; // Усредняем значение считанного давления. 112 мкс на одно чтение. 1.12 c на 10000 циклов
for (long i = 0; i < s; ++i) {
intPressureValue = intPressureValue + analogRead(A2);
}
PressureValue = (float)intPressureValue / (float)s; // среднее знач давл, float 1023.0
UPressureValue = PressureValue * 0.004875044 ; // 5/*1023, но поскольку реальный на этом контроллере Uref=4,98717 --->(4,98717/1023). ( до этого выставлял 0.00489632 )
float tempA = 0.00 - 0.23783374 * pow(UPressureValue, 6) + 5.49765589 * pow(UPressureValue, 5) - 52.43191395 * pow(UPressureValue, 4) + 264.81602585 * pow(UPressureValue, 3) - 752.10945958 * pow(UPressureValue, 2) + 1166.07930268 * UPressureValue - 803.62383077 ; // Температура кипения Полином 6 степени сделанный в экселе по таблице температура кипения-напряжение.
float tempB = sensors.getTempC(Suction); // считываем температуру всасывания
if (tempB > -127.00) // защита от сбоя датчика.
{
tempB1 = tempB;
}
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Ev:");
lcd.print(tempA); // Температура кипения
tempA1 = tempA;
lcd.setCursor(0, 1);
lcd.print("Sc:");
lcd.print(tempB); // Suction temperature
lcd.setCursor(9, 1);
lcd.print("SH=");
SH = tempB1 - tempA1;
lcd.print(SH);
lcd.setCursor(10, 0);
lcd.print("eev");
lcd.print(st);
delay(200);
}
void loop() {
unsigned long currentMillis = millis();
sensors.requestTemperatures(); // Запрос датчиков, расчёт SH и новой ошибки
printTemperature(Suction);
sensorValue = analogRead(sensorPin); // read the value from the sensor: 1023 none; 639 (720)SET; 408 (481) LEFT; 0 RIGHT; 98 (131)UP; 254 (307) DOWN
if (sensorValue < 780 && sensorValue > 600) // По нажатию кнопки SET вход в меню ручного управления.
{
m = 1;
manual();
}
if (sensorValue < 900) // При нажатии любой кнопки зажигаем подсветку.
{
analogWrite(10, 40);
led = 1;
}
if (led == 1)
{
previousMillis3 = currentMillis;
led = 0;
ledoff = 1;
}
if ((currentMillis - previousMillis3) >= 60000 && ledoff == 1) // Гасим подсветку дисплея по истечении x минут после последнего нажатия любой клавиши.
{
analogWrite(10, 40);
delay(100);
analogWrite(10, 20);
delay(100);
analogWrite(10, 10);
delay(100);
analogWrite(10, 5);
delay(100);
digitalWrite(10, LOW);
ledoff = 0;
}
if ((currentMillis - previousMillis) >= t_discr) // ПОСТОЯННАЯ ВРЕМЕНИ ДЛЯ ПРОПОРЦИОНАЛЬНОЙ, ИНТЕГРАЛЬНОЙ И ДИФФЕРЕНЦИАЛЬНОЙ СОСТАВЛЯЮЩИХ , мС.Проблема была в разном типе переменных и в операции в функции абс()
{
err = SH - need_SH;
if (err > 50) {
err = 50;
}
if (err < -50) {
err = -50;
}
previousMillis = currentMillis;
// ********************************************************************************************Определение начальных условий******************************************
if (start == 0) // Обнуление проп и интегр сост при включении
{
start = 1;
C = 0.0;
Kp_on = 0;
Kci = 0;
Kd_on = 0;
start_pos = nulst - minst;
}
float deltaB1 = pre_tempB1 - tempB1;
float temp_derr = err - pre_err;
if (abs(deltaB1) < 0.1 && abs(err) > 3 && abs(temp_derr) < 0.1) {
p = p + 1;
}
else {
p = 0;
} // При ошибке более 2 гр и отсутствии реакции датчика температуры на всасе, ошибки и дельты ошибки на протяжении времени p*3 cек подряд, определяем простой компрессора, сбрасываем интегральную состовляющую "С", пропорц и дифф в ноль.
if (p >= 130)
{
C = 0.0;
Kci = 0;
Kp_on = 0;
Kd_on = 0;
start_pos = nulst - minst;
p = 0;
}
if (tempA1 - pre_tempA1 < -0.1) // Вкл пропорц и накопительную и дифф сост при вкл комрессора.
{
p1 = p1 + 1;
}
else {
p1 = 0;
}
if (p1 > 3)
{
Kp_on = 1;
Kci = 1;
Kd_on = 1;
start_pos = 0;
p1 = 0;
}
if (tempA1 - pre_tempA1 < -4.0) // Вкл пропорц и накопительную и дифф сост при вкл комрессора.
{
p2 = p2 + 1;
}
else {
p2 = 0;
}
if (p2 > 1)
{
Kp_on = 1;
Kci = 1;
Kd_on = 1;
start_pos = 0;
p2 = 0;
}
if (SH > 20 && tempA1 < -20) // Вкл пропорц и накопительную и дифф сост при вкл комрессора.
{
Kp_on = 1;
Kci = 1;
Kd_on = 1;
start_pos = 0;
}
// ********************************************************************************************Конец определения начальных условий********************************
// ******************** Обработка интегальной составляющей
if (abs(err) >= abs(pre_err) || err > 2.0 || err < -1.5) // изменяем интегратор "С" только при ошибке более 2 или менее -1 градуса или при условии что ошибка увеличивается или остаётся прежней. и только если определено включение компресора (Kci=1)
{
if (err <= 10.0 && err >= -4.0) {
C = C + (float)Kci * err; // При ошибке не более 4 градусов интеграл с вычисляется без ограничений
}
if (err < -4.0) {
C = C - Kci * 4.0; // при ошибке менее -4 градусов, считаем err=-4.
}
if (err > 10.0) { // при ошибке более +10 градусов, считаем err=10.
C = C + Kci * 10.0;
}
if (SH < 0.8) { // при опасно низком перегреве - ещё раз
C = C + Kci * err;
}
}
if (Ki_on * Ki * C > 40)
{
if (abs(err) >= abs(pre_err) || err > 2.0 || err < -1.4) // Повторяем расчёт С при предыдущем положении более 100 шагов.
{
if (err <= 10.0 && err >= -4.0) {
C = C + (float)Kci * err;
}
if (err < -4.0) {
C = C - Kci * 4.0;
}
if (err > 10.0) {
C = C + Kci * 10.0;
}
if (SH < 0.9) {
C = C + Kci * err;
}
}
}
if (Ki_on * Ki * C > 80)
{
if (abs(err) >= abs(pre_err) || err > 2.0 || err < -1.3) // Повторяем расчёт С при предыдущем положении более 160 шагов.
{
if (err <= 10.0 && err >= -4.0) {
C = C + (float)Kci * err;
}
if (err < -4.0) {
C = C - Kci * 4.0;
}
if (err > 10.0) {
C = C + Kci * 10.0;
}
if (SH < 1.0) {
C = C + Kci * err;
}
}
}
if (Ki_on * Ki * C > 160)
{
if (abs(err) >= abs(pre_err) || err > 2.0 || err < -1.2) // Повторяем расчёт С при предыдущем положении более 256 шагов.
{
if (err <= 10.0 && err >= -4.0) {
C = C + (float)Kci * err;
}
if (err < -4.0) {
C = C - Kci * 4.0;
}
if (err > 10.0) {
C = C + Kci * 10.0;
}
if (SH < 1.1) {
C = C + Kci * err;
}
}
}
if (Ki_on * Ki * C > 320)
{
if (abs(err) >= abs(pre_err) || err > 2.0 || err < -1.1) // Повторяем расчёт С при предыдущем положении более 409 шагов.
{
if (err <= 10.0 && err >= -4.0) {
C = C + (float)Kci * err;
}
if (err < -4.0) {
C = C - Kci * 4.0;
}
if (err > 10.0) {
C = C + Kci * 10.0;
}
if (SH < 1.2) {
C = C + Kci * err;
}
}
}
if (err < -1.4) {
k1 = k1 + 1;
}
else {
k1 = 0;
}
if (k1 > t_over / t_discr) { // При ошибке менее -2 градусов в течение 10 минут (600000 мсек) подряд,
C = C + (Kp_on * Ki_on * Kp * err * err * err) / Ki; // "C" устанавливается такой, чтобы новый интеграл был равен предыдущим интегралу и пропорц сост. Необходимое количество шагов обеспечивается за счёт интегрирующей составляющей.
k1 = 0;
}
if (err > 2.0) {
k2 = k2 + 1;
}
else {
k2 = 0;
}
if ((k2 > t_over / t_discr)) { // При ошибке более +2 градусов в течение 10 минут (600000 мсек) подряд,
C = C + (Kp_on * Ki_on * Kp * err * err * err) / Ki; // "С" устанавливается такой, чтобы новый интеграл был равен предыдущим интегралу и пропорц сост. Необходимое количество шагов обеспечивается за счёт интегрирующей составляющей.
k2 = 0;
}
if (Ki * C >= (STEPS - nulst)) {
C = (STEPS - nulst) / Ki;
} // Ограничение выражения nulst+Ki*C пределами (0 шагов- STEPS шагов) относительно средней точки nulst
if (Ki * C <= (minst - nulst)) {
C = (minst - nulst) / Ki;
} // Ограничение произведения nulst+Ki*C пределами (0 шагов- STEPS шагов) относительно средней точки nulst
// ******************* Конец обработки интегральной составляющей.*********************************
if (err >= 0)
{
st = (float)nulst - (float)start_pos + (float)Kp_on * Kp * err * err * err + (float)Ki_on * Ki * C + (float)Kd_on * Kd * (err - pre_err);
}
else
{
st = (float)nulst - (float)start_pos + (float)Kp_on * Kp * err * err * err * 2.0 + (float)Ki_on * Ki * C + (float)Kd_on * Kd * (err - pre_err);
}
// Максимальная температура кипения не более 19.5 градусов. Это максимум для Резистора 390 Ом и датчика 4-20 ма, сигнал на А2=5В.
if (st > pre_st + 50) { // Огранчиваем максимальное перемещение эрв за 1 шаг t_discr
st = pre_st + 50;
}
if (st < pre_st - 50) {
st = pre_st - 50;
}
if (st >= STEPS) { // Ограничиваем диапазон шагов
st = STEPS;
}
if (st <= minst) {
st = minst;
}
stepper.runToNewPosition(st);
delay (400);
stepper.disableOutputs();
if (sensorValue < 350 && sensorValue > 200) // По нажатию кнопки Down на 2 секунды выводятся сервисные параметры.
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("nSH=");
lcd.print(need_SH);
lcd.setCursor(7, 0);
lcd.print(" err=");
lcd.print(err);
lcd.setCursor(0, 1);
lcd.print(nulst);
lcd.setCursor(3, 1);
if (Kp_on * Kp * err * err * err >= 0)
{
lcd.print("+");
lcd.setCursor(4, 1);
lcd.print(Kp_on * Kp * err * err * err);
}
else
{
lcd.print(2.0 * Kp_on * Kp * err * err * err);
}
lcd.setCursor(7, 1);
if (Ki_on * Ki * C >= 0)
{
lcd.print("+");
lcd.setCursor(8, 1);
}
lcd.print(Ki_on * Ki * C);
lcd.setCursor(12, 1);
if (Kd_on * Kd * (err - pre_err) >= 0)
{
lcd.print("+");
lcd.setCursor(13, 1);
}
lcd.print(Kd_on * Kd * (err - pre_err));
delay (2000);
}
pre_err = err;
pre_tempA1 = tempA1;
pre_tempB1 = tempB1;
pre_st = st;
}
}
Перенесите функцию printTemperature выше того места, где она вызывается.
и научись вставлять чужой авнокод правильно.
http://arduino.ru/forum/obshchii/vstavka-programmnogo-koda-v-temukomment...
Конкретно этот кусок кода, если есть возможность укажите как правильно надо перенести void manual() // Функция ручного управления ЭРВ { analogWrite(10, 40); // В ручном режиме подсветка включена и не выключается. lcd.clear(); lcd.print("Manual mode"); delay (1000); while (m == 1) sensors.requestTemperatures(); printTemperature(Suction); lcd.setCursor(9, 0); lcd.print("Meev"); lcd.print(st);Конкретно тут всё рассказано с примерами: http://cppstudio.com/post/5291/ -> "В языках C и C++, функции должны быть объявлены до момента их вызова"
Конкретно этот кусок кода, если есть возможность укажите как правильно надо перенести
Конкретно этот кусок кода трогать не надо - прочитайте еще раз ВНИМАТЕЛЬНО сообщение №1