Почему переменные разного типа???

junior_developer
Offline
Зарегистрирован: 27.11.2017

Посмотрел образец кода http://arduino.ru/tutorials/BlinkWithoutDelay

Вот он:
 

/* Blink without Delay
 2005
 by David A. Mellis
 modified 8 Feb 2010
 by Paul Stoffregen
 */

const int ledPin =  13;      // номер выхода, подключенного к светодиоду
// Variables will change:
int ledState = LOW;             // этой переменной устанавливаем состояние светодиода 
long previousMillis = 0;        // храним время последнего переключения светодиода

long interval = 1000;           // интервал между включение/выключением светодиода (1 секунда)

void setup() {
  // задаем режим выхода для порта, подключенного к светодиоду
  pinMode(ledPin, OUTPUT);      
}

void loop()
{
  // здесь будет код, который будет работать постоянно
  // и который не должен останавливаться на время между переключениями свето
  unsigned long currentMillis = millis();
 
  //проверяем не прошел ли нужный интервал, если прошел то
  if(currentMillis - previousMillis > interval) {
    // сохраняем время последнего переключения
    previousMillis = currentMillis;  

    // если светодиод не горит, то зажигаем, и наоборот
    if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;

    // устанавливаем состояния выхода, чтобы включить или выключить светодиод
    digitalWrite(ledPin, ledState);
  }
}

Мне непонятно, почему previousMillis типа long, а currentMillis unsigned long? Это ведь не одно и то же? Верно? А там есть строка:
 

previousMillis = currentMillis;

Будет ли это работать правильно?

5N62V
Offline
Зарегистрирован: 25.02.2016

Будет, но только в пределах long. 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

unior_develope, будет ли это работать правильно, зависит от того, как Вы будете это использовать.

В очень многих случаях присваивание величинам одного типа значений переменных другого работает правильно. 

Но не всегда.

Главное - понимать, что происходит при таком присваивании.

bwn
Offline
Зарегистрирован: 25.08.2014

junior_developer пишет:

Мне непонятно, почему previousMillis типа long, а currentMillis unsigned long? Это ведь не одно и то же? Верно? А там есть строка:

previousMillis = currentMillis;

Будет ли это работать правильно?

Мне вот непонятно, зачем вообще currentMillis в данном случае. millis()-previousMillis>interval, делает тоже самое и экономит четыре байта оперативки. Это из разряда использования int для назначении пинов.

Logik
Offline
Зарегистрирован: 05.08.2014

Не. тогда нужно два вызова millis(). А они иногда разные результаты будут давать что на интервале скажется, для мигания светодиода раз в сек конечно пофиг, но в общем случае плохо. Если уж про экономию - заменить лонги на не лонги.

По теме. Сочитать в выражениях знаковое и беззнаковое - плохой стиль и потенциальный источник неприятных ошибок. Компилятор варнинг обычно выдает.

bwn
Offline
Зарегистрирован: 25.08.2014

Logik пишет:

Не. тогда нужно два вызова millis(). А они иногда разные результаты будут давать что на интервале скажется, для мигания светодиода раз в сек конечно пофиг, но в общем случае плохо. Если уж про экономию - заменить лонги на не лонги.

Я ведь написал, для "конкретного". Да и для подавляющего большинства домашних поделок. Обычное домашнее применение - интервал опроса датчиков или вывода чего то, а считает-выведет через 10 секунд или 10,001сек разницы уже никакой. Если нужны действительно точные тайминги с миллисом вроде никто и не заморачивается. Вчера померил на своей программе луп, а там везде 0 миллисов. А он и динамически символ формирует, и строку из прогмемов на семисегментники, и ДС-ку опрашивает, и часы, и ИР слушает, и температуру держит. Честно говоря, даже не представляю ситуацию, где эта погрешность может сказаться (в бытовом применении). ИМХО.

Logik
Offline
Зарегистрирован: 05.08.2014

Там дело не в длине лопа, даже очень быстрый лоп иногда будет попадать в ситуацию когда при первом его вызове, в проверке, он вернет N, а в следующем, в присвоении уже, N+1. Так по 1мс терятся будет.

Если писать аккуратно, то и на милисе тайминги точные как кварц позволит выйдут. По опыту уход до 2-3сек/час. А аккуратность вобщем - писать previousMillis += 1000 , да прерывания не запрещать надолго.

//чера померил на своей программе луп, а там везде 0 миллисов.

То неверно мерили. Среднее не катит. Посмотреть глазками сотню отсчетов тоже. Стройте гистаграмму, намного интересней все будет.  Массив в котором в ячейке 0 кол-во лупов выполненых за 0мс, в 1 - за 1мс и т.д. сколько памяти не жалко, в последней ячейке (например 100) - кол-во лупов выполненых за 100 и более мс. В каждом лупе как длительность померили делаем +1 в соответствующую ячейку. Дайте коду поработать, например 100000 циклов, затем смотрите результат и думайте.

ПС. таки нашел кусок своего кода для этого. Там еще и максимально длинный лоп ищет и еще коечего делает.

#define SIZE_HISTOGRAMM_LOOP 16
word HistogrammaLoopTime[SIZE_HISTOGRAMM_LOOP]; //последний элемент - максимальная длительность

/* Формируем новое системное время для текущего цикла, 
   собираем статистику загрузки, 
   определяем короткий цикл для запуска */
boolean GetNewTime(word* Timer)
{
  word T=millis();
  word i=T-*Timer;
  {
   if(i>SIZE_HISTOGRAMM_LOOP-2) i=SIZE_HISTOGRAMM_LOOP-2; 
   HistogrammaLoopTime[i]++;
   if(i>HistogrammaLoopTime[SIZE_HISTOGRAMM_LOOP-1])
      HistogrammaLoopTime[SIZE_HISTOGRAMM_LOOP-1]=i;
   if(!HistogrammaLoopTime[i])
   {
     memset(HistogrammaLoopTime, 0, SIZE_HISTOGRAMM_LOOP*2);
   }
  }
  *Timer=T;
  return i==0;
}

 

bwn
Offline
Зарегистрирован: 25.08.2014

Ну ладно, ладно, обманул.((( Гистограмм не строил, сегодня на микросе погонял. Массовые штучные замеры, все двузначные микросы, в глазах рябят, примерно с интервалом опроса DS-ки 2,7 и 5,6мС единичные проскакивают. Похоже запрос и считывание. 
Если не поленюсь потом, попробую посчитать, сейчас она меня уже достала со своим меню на табло из двух семисегментников, завершать пора.))))