Один вариант кода работает, второй - не работает. Где я ошибся?

funakoshi
Offline
Зарегистрирован: 13.03.2015

Всем привет.

Имею вот такой очень короткий кода, который отрабатывает исправно:

//********************************************************************
volatile unsigned long micros_sp = 0;
volatile byte sz = 0; //счетчик обнуления
volatile unsigned int sp = 0; //скорость
volatile boolean st = false; //триггер
long previousMillis = 0;
long interval = 1000; //1000 - 1 секунда
//********************************************************************
void setup() {
  pinMode(2, INPUT_PULLUP);
  Serial.begin(115200); //инициализация ком порта
  attachInterrupt(0, speedometr, FALLING); //прерывание спидометра по фронту импульса
}
//********************************************************************
void loop() {
  Serial.println (sp);
  if (sz != 0) {
    sz--;
  } else {
    sp = 0;
  };
  delay(500);
}
//********************************************************************
void speedometr() { //измеряем частоту на входе спидометра по прерыванию
  if (!st) {
    micros_sp = micros();
  }
  else {
    sp = 1.6 * (1000000 / (micros() - micros_sp)); 
  }
  st = !st;
  sz = 30;
}

А вот тот же самый код, но с попыткой избавиться от delay:

//********************************************************************
volatile unsigned long micros_sp = 0;
volatile byte sz = 0; //счетчик обнуления
volatile unsigned int sp = 0; //скорость
volatile boolean st = false; //триггер
long previousMillis = 0;        
long interval = 1000; //1000 - 1 секунда
//********************************************************************
void setup() {
  pinMode(2, INPUT_PULLUP);
  Serial.begin(115200); //инициализация ком порта
  attachInterrupt(0, speedometr, FALLING); //прерывание спидометра по фронту импульса
}
//********************************************************************
void loop() {
  //Serial.println (sp);
  if (sz != 0) {
    sz--;
  } else {
    sp = 0;
  };
  //delay(500);
  unsigned long currentMillis = millis();
  //проверяем не прошел ли нужный интервал, если прошел то
  if (currentMillis - previousMillis > interval) {
    // сохраняем время последнего переключения
    previousMillis = currentMillis;
    Serial.println(sp);
  }
}
//********************************************************************
void speedometr() { //измеряем частоту на входе спидометра по прерыванию
  if (!st) {
    micros_sp = micros();
  }
  else {
    sp = 1.6 * (1000000 / (micros() - micros_sp)); 
  }
  st = !st;
  sz = 30;
}

Первый код отрабатывает правильно (выводит в консоль скорость авто), второй - выводит нули. Где я накосячил?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Вы уменьшаете sz ДО проверки "прошел ли нужный интервал", - при каждом вызове loop.

Пока там интервал пройдёт, sz давно уже успеет обнулиться.

funakoshi
Offline
Зарегистрирован: 13.03.2015

Все, спасибо - дошло. Вот так должно работать.

//********************************************************************
volatile unsigned long micros_sp = 0;
volatile byte sz = 0; //счетчик обнуления
volatile unsigned int sp = 0; //скорость
volatile boolean st = false; //триггер
long previousMillis = 0;        // храним время последнего переключения светодиода
long interval = 1000; //1000 - 1 секунда
//********************************************************************
void setup() {
  pinMode(2, INPUT_PULLUP);
  Serial.begin(115200); //инициализация ком порта
  attachInterrupt(0, speedometr, FALLING); //прерывание спидометра по фронту импульса
}
//********************************************************************
void loop() {
  unsigned long currentMillis = millis();
  //проверяем не прошел ли нужный интервал, если прошел то
  if (currentMillis - previousMillis > interval) {
    // сохраняем время последнего переключения
    previousMillis = currentMillis;
    Serial.println(sp);
    if (sz != 0) {
      sz--;
    } else {
      sp = 0;
    };
  }
}
//********************************************************************
void speedometr() { //измеряем частоту на входе спидометра по прерыванию
  if (!st) {
    micros_sp = micros();
  }
  else {
    sp = 1.6 * (1000000 / (micros() - micros_sp));
  }
  st = !st;
  sz = 30;
}

Пошел до машины - проверю.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Не за что.