Детекция смены знака переменной

Если переменная Вам нужна, зачем Вы уничтожаете ее содержимое во второй строке скетча?

Это - другая переменная, которая хранит старое значение х. Передавать ее в функцию не нужно, функция должна сама запоминать старое значение переменной x в переменной x_old.

“Не выходит пока каменный цветок…”
Затыка в функции MUVE, она в конце скетча. Не могу запустить ее полноценно.
Переменная Х меняется адекватно в соответствии с положением резистора. Но прочему то не происходит подачи 0 в порты реле, даже при принудительной команде в основном цикле. Х и Х_old меняются синхронно и все время одинаковые, соответственно не происходит никакой детекции смены их знака (не выводятся 888), хотя сами они бывают и положительными и отрицательтными. Пробовал оба варианта детекции.
Вот то, что удалось написать. ЧАсы и угол поворота выводятся в порт нормально.


#define position_sensor_pin 0  // средняя ножка резистора ОС по положению на пин 0
#define relay1 8  // пин 8 реле 1
#define relay2 7  // пин 7 реле 2
int val, L;  //переменная для хранения значения фактического угла, угол из таблицы
byte T;  // время расчетное
int X, X_old; // текущее и предыдущее значение рассогласования


#include <microDS3231.h>
MicroDS3231 rtc;

void setup() {


      Serial.begin(9600);   // Устанавливаем скорость передачи данных 
   delay(200);                               // Ждем 200 мкс
  Serial.println("DS3231RTC Read Test");    // Выводим данные на последовательный порт
  Serial.println("-------------------");    // Выводим данные на последовательный порт

  
  // проверка наличия модуля на линии i2c
  if (!rtc.begin()) {
    Serial.println("DS3231 not found");
    for(;;);
pinMode(relay2, OUTPUT);
pinMode(relay1, OUTPUT);

  }

  // получаем все данные в структуру
  DateTime now = rtc.getTime();

   //меняем любой параметр
  //now.year += -10;
  //now.second =0;
  //now.minute =54;
  //now.hour =22;
  //now.day =6;
  //now.date =26;
  //now.month =5;

   //отправляем в rtc
  //rtc.setTime(now);
}


void loop() {

if (X_old != X) {X_old = X;}; //сравниваем текущее и предыдущее значение, сохраняем текущее значение для следующего раза в случае изменения

  printTime();
  delay(100);
 digitalWrite(relay2, LOW); // включение реле2 для проверки, все равно не включается
}

void MUVE ();

void printTime() {
  // получаем все данные в структуру и используем их
  // этот способ быстрее и "легче" вызова отдельных get-функций
  DateTime now = rtc.getTime();

  Serial.print(now.hour);
  Serial.print(":");
  Serial.print(now.minute);
  Serial.print(":");
  Serial.print(now.second);
  Serial.print(" ");
  Serial.print(now.day);
  Serial.print(" ");
  Serial.print(now.date);
  Serial.print("/");
  Serial.print(now.month);
  Serial.print("/");
  Serial.println(now.year);


  val = analogRead(position_sensor_pin);  // чтение резистора ОС
  val = map(val, 0, 1023, 15, 345);       //конвертировать выходной диапазон в градусах угола поворота потенциометра
  constrain(val, 0, 360); //ограничение диапазона
  Serial.println(val);
  delay(300);


X_old = 33;// НАЧАЛЬНОЕ значение для примера
L=100; // значение для ПРОВЕРКИ функции поворота
MUVE (); // запуск функции поворота
}


 
////////////////////////////
  void MUVE () {   //функция поворота
int X = val-L; // разница между фактическим углом и требуемым на данный момент
if (X>0){ digitalWrite(relay1, LOW);}  else {digitalWrite(relay2, LOW);} //включаем двигатель

//if (X_old != X) {X_old = X;}; //сравниваем текущее и предыдущее значение, сохраняем текущее значение для следующего раза в случае изменения
 delay(1000);
Serial.println(X);
Serial.println(X_old);
Serial.println(L);
//if((X * X_old) < 0){
if (((X < 0) && (X_old > 0)) || ((X > 0) && (X_old < 0))) {  //контроль смены знака х (продолжить выполнение после смены знака Х)
Serial.println(888);}; // для контроля проверки смены знака
digitalWrite (relay1, HIGH); //откл. реле
digitalWrite (relay2, HIGH); //откл. реле
 delay(1000);
}

Буду признателен за дельный совет.
Кстати, где этот обратный апостроф? На букве ё? Он такой маленький, что и не разглядеть.

Программирование - это не твоё, брось.

3 лайка

Вам надо почитать о правилах объявления и определения функций.
А так же об области видимости переменных.(Это я про Х, если что)

нет, судя по коду это не так. X_old у вас всегда должна быть 33, потому что вы ее сбрасываете перед каждым входом в свою фунцию muve.
В целом по коду видно полное непонимание логики своей же программы.
Могу дать вам плохой совет, но вам он может и поможет - избавтесь от всех фунций, вы все одно используете их неправильно. Соберите весь код в loop().

Нет, не поможет. Поможет открыть учебник и учиться по порядку и делать приведенные там упражнения.

3 лайка

Всем спасибо!
Программирование, конечно же, когда то брошу.
…но только после того, как добью этот проект:)

Отдельное спасибо!
Это по делу.
На такие советы и расчитывал.

помогло?

1 лайк

Да, спасибо!
Совет очень своевременный. Значительно продвинулся.
Сейчас разбираюсь, почему не включаются реле внутри функции.
Вот обновленный код :

//трекер на 1 ось по времени

#define position_sensor_pin 0  // средняя ножка резистора ОС по положению на пин 0
#define relay1 8  // пин 8 реле 1
#define relay2 7  // пин 7 реле 2
int val, L;  //переменная для хранения значения фактического угла, угол из таблицы
byte T;  // время расчетное
int delta, delta_old; // текущее и предыдущее значение рассогласования


#include <microDS3231.h>
MicroDS3231 rtc;

void setup() {


      Serial.begin(9600);   // Устанавливаем скорость передачи данных 
   delay(200);                               // Ждем 200 мкс
  Serial.println("DS3231RTC Read Test");    // Выводим данные на последовательный порт
  Serial.println("-------------------");    // Выводим данные на последовательный порт

  
  // проверка наличия модуля на линии i2c
  if (!rtc.begin()) {
    Serial.println("DS3231 not found");
    for(;;);
pinMode(relay2, OUTPUT);
pinMode(relay1, OUTPUT);

  }

  // получаем все данные в структуру
  DateTime now = rtc.getTime();

   //меняем любой параметр
  //now.year += -10;
  //now.second =0;
  //now.minute =54;
  //now.hour =22;
  //now.day =6;
  //now.date =26;
  //now.month =5;

   //отправляем в rtc
  //rtc.setTime(now);

   void MUVE ();
}


void loop() {

  printTime();
  delay(100);
 digitalWrite(relay2, LOW); // включение реле2 для проверки, все равно не включается


void MUVE ();}

void printTime() {
  // получаем все данные в структуру и используем их
  // этот способ быстрее и "легче" вызова отдельных get-функций
  DateTime now = rtc.getTime();

  Serial.print(now.hour);
  Serial.print(":");
  Serial.print(now.minute);
  Serial.print(":");
  Serial.print(now.second);
  Serial.print(" ");
  Serial.print(now.day);
  Serial.print(" ");
  Serial.print(now.date);
  Serial.print("/");
  Serial.print(now.month);
  Serial.print("/");
  Serial.println(now.year);



L=100; // значение для ПРОВЕРКИ функции поворота
MUVE (); // запуск функции поворота

}


 
////////////////////////////
  void MUVE () {   //функция поворота
  //int  delta_old, delta;

val = analogRead(position_sensor_pin);  // чтение резистора ОС
  val = map(val, 0, 1023, 15, 345);       //конвертировать выходной диапазон в градусах угола поворота потенциометра
  constrain(val, 0, 360); //ограничение диапазона
delta = val-L; // разница между фактическим углом и требуемым на данный момент
if (delta>0){digitalWrite(relay1, LOW);}  else {digitalWrite(relay2, LOW);} //включаем двигатель


 Serial.println(val);
Serial.println(delta);
Serial.println(delta_old);
Serial.println(L);
Serial.println("ssssssssssssssssssssssssssssssss");//для удобства чтения
 delay(1000);
if (((delta < 0) && (delta_old > 0)) || ((delta > 0) && (delta_old < 0))) {  //контроль смены знака х (продолжить выполнение после смены знака Х)
Serial.println(888); //контроль этой ветки


digitalWrite (relay1, HIGH); //откл. реле
digitalWrite (relay2, HIGH);
return;
} else
{Serial.println(444); //контроль этой ветки
if (delta_old != delta) {delta_old = delta;}; 
Serial.println(delta_old);
//if (delta_old != delta) {delta_old = delta;}; 
MUVE ();}

}

Адекватности в работе функции поворота значительно добавилось. По крайней мере все переменные выводятся на печать адекватно. Но реле почему то не работают. Без них трудно проверить логику работы, не хватает воображения. Другой программой запускаются, как и положено. Чувствую, что-то нужно еще определить внутри функции.
Буду признателен за намек всем, снизошедшим до объяснения азбучных истин дедушке из Богом забытой, депрессивной, воюющей страны.
А то, что все получится, не сомневаюсь нисколько.

Off topic
Недавно делал систему отопления в своем доме. Все спроектировал и почти все сделал сам (супеорсварщика только на пару дней нанимал) Ранее никогда с этим не сталкивался. На профильных форумах , естественно, вопросы разные задавал. Ситуация примерно как здесь, только вместо программистов теплотехники собираются. 80% снисходительно посмеивались над моими хотелками и упражнялись в сарказме, но и несколько дельных советов получил. В итоге уже второй год зимую и радуюсь. Получился практически шедевр по логике работы, надежности, простоте. Шабашники никогда бы мне ничего подобного не сваяли. Поэтому и за управление трекером взялся без сомнений.

он даже не компилируется.
Научитесь пользоваться функцией автоформата в Ардуино ИДЕ - комбинация клавишь Ctrl-T - она будет выстраивать ваши скобки с соответвующим отступом, может тогда вы заметите, что некоторые операторы вы вставили не туда.

Сильно!

Круто

и даже так???

1 лайк

Многие знания - многие печали. Ваше отопление кажется вам шедевром скорее всего именно потому, что вы нифига не понимаете в теплотехнике.
Вы наверно и этот код будете считать “шедевром”, когда запустите и будете им хвастать на каком-нить форуме огородников…

Очень познавательно.
Классика самоутверждения.

Конечно познавательно.
Еще скажите, что вы впервые слышите, что функции внутри функций определять нельзя?
Кстати, на какое отношение вы рассчитываете, когда выкладываете некомпилируемый код и начинаете врать, что он у вас “работает”, хотя еще и не идеально? :slight_smile:
Наверно ваше отопление “работает” так же, вы просто не замечаете этого…

Да уж, вообще не заметно…как будто про функции и не читали.
Хотя стоит лишь в гугле набрать - информации полно.
Теперь видно ещё, что не знаете, как правильно делать вызов функции. Если цель лишь-бы как-нибудь дописать - делайте, как b707
подсказал , всё в loop(), может проще будет

Я сам с удивлением сейчас почитал про “вложенные” функции,
спасибо ТС, сам бы и не додумался до такого))

Ркит, как всегда, был прав…

Я действительно впервые слышу об этом. Мне нужно было с этого места вернуться в начало функции, ничего другого не придумал. Проверил - работает. Код компилируется, на печать все параметры выводит адекватно, равно как и реагирует на смену угла. На очереди - реле, не включаются сволочи.
Принт-скрин работы прилагаю. Скетч (ну или то, что пока имею) не менял, только автоформат применил (совет дельный - спасибо).


Небольшое отступление.
Это как сыграть “Кузнечика” одним пальцем. И выпускник консерватории и первокласник выдадут примерно одно и то же в первом приближении. Просто для последнего это будет потолком. Так вот, мне нужен “Кузнечик” одним пальцем. К гаммам и сольфеджио не готов. Задача разовая и мне видится посильной. Пока что использую готовые фрагменты примеров, проверяю их на функционирование и попутно учусь. Зачастую не понимаю, как работает фрагмент. А что, все присутствующие родились сразу с пониманием всего?

Ну если всё так просто, как ты говоришь, то чего же ты сюда пришел с проблемами? Не стыдно быть человеком, который не справился с задачей, с которой первоклассник должен справиться?