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

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

                        //контроль смены знака Х (продолжить выполнение после смены знака Х)

digitalWrite (rele1, 0); //откл. реле
digitalWrite (rele2, 0); //откл. реле
}

Зашел в тупик. Это фрагмент программы управление солнечным трекером. Функция. Раз в час трекер должен менять свое положение.
Эта функция определяет положение трекера, включает нужное реле и отключает его после достижения нужного положения. В этой функции необходимо отследить смену знака и после этого отключить оба реле. После начала движения значение будет уменьшаться, но наперед неизвестно, с какой стороны от нуля будет начало. Поэтому важно определить именно смену знака.
Буду признателен за помощь. Это моя первая программа, опыта практически нет. Программистом становиться не собираюсь, собираюсь на пенсию:)

И что с этим огрызком делать?

Где тут “раз в час”?

Почему ты передаешь в функцию значение и тут же его затираешь?

Где тут отслеживания движения или вообще хоть каких-то изменений?

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

if (((x < 0) && (x_old > 0)) || ((x > 0) && (x_old < 0)))
1 лайк

Если Вы “не собираетесь становиться программистом”, то Вы ошиблись либо форумом, либо разделом.
Этот форум - клуб по интересам. Если Вы не разделяете интересов форума, рассчитывать на снисходительное к себе отношение, Вы вряд ли сможете. Так что основной вариант - обратиться в раздел “Ищу исполнителя”, где Вам за адекватное вознаграждение выполнят все Ваши хотелки.

По поводу смены знака: чтобы знать, что знак изменился, нам нужно два значение одной и той же величины - старое и новое. Самый простой способ отследить смену знака, - проверить знак их произведения. Т.е.:
if((x * x_old) < 0)
Примечание: строго говоря, такой подход (равно как и подход из предыдущего сообщения) может пропустить переход в случае, если одно из значений будет в точности равно 0, например: -2, 0, 3.
Для отслеживания перехода в таком случае рекомендуется пропускать нулевое значение, не перенося его в x_old, т.е. if(x != 0) x_old = x;

я тоже сначала хотел посоветовать перемножить величины, но в зависимости типа и значений тут можно здорово пролететь, кмк
Не проверял, какой знак будет иметь произведение 1000 * (-1000), посчитанное в типе int16

Кстати, исключительно академический вопрос - что по выч. ресурсу будет дороже - 5 сравнений или умножение плюс сравнение?

byte variable;
 bool sign;
 bool sign_;
 
 
 sign= variable&0X80;
 if(sign!=sign_)
 {
//  смена знака!!!! 
 }
 sign_=sign;

А если не байт ? Надо через сдвиг …

1 лайк

Просто как повод для размышлений(изучений)

Типа такого sign = value >> (sizeof(value)*8-1) ?

Возможно я не прав, но переменные в ардуине все кратны восьми и знак у них в старшем разряде поэтому variale&0x80 для 8 разрядной; variale&0x8000 для 16 разрядной и т.д., хотя можно и variable&(1<<8) или
variable&(1<<16).

Ну, как бэ да, нужно биты скинуть, кроме первого, а то прилезут при сдвиге отрицательного вправо.

Можно и так замутить: !!(variable & (1 << sizeof(variable)*8))

#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
    sign = *((byte*)&t + sizeof(t) - 1) & 0x80;
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
    sign = *((byte*)&t) & 0x80;
#elif __BYTE_ORDER__ == __ORDER_PDP_ENDIAN__
    sign =  *((byte*)&t + 1) & 0x80;
#else
    #error "What kind of hardware is this?!"
#endif

или sign = (t < 0);

Круто

sixeof(t) ?

1 лайк

С учетом того, что компилятор сам это делает при сравнении с нулём, вспоминается байка о Ходже Насреддине, про порошок от крыс.

Компилятор сдвигает старший байт влево и знаковый бит уходит во флаг переноса…

И? Это занимает больше тактов? :wink:

одна хрень
монопенисуально

Вот и я читая ответы , первой мыслью подумал, а зачем числа мусолить целиком, если достаточно только старшие биты сравнить…
К тут вон оно как …