Показать сообщение отдельно
Старый 14.09.2016, 13:45   #19
BNSF9399
Местный
 
Аватар для BNSF9399
 
Регистрация: 06.03.2014
Адрес: Москва
Сообщений: 1,741
Сказал(а) 'не согласен(а)'!: 5
Сказали 'не согласен'! 9 раз(а) в 7 сообщениях
Сказал(а) спасибо: 553
Поблагодарили 2,794 раз(а) в 755 сообщениях
Все 'Спасибо' этого пользователя. :
0 за это сообщение
0 Всего
Репутация: репутация неоспорима (2791)
По умолчанию

Шальные руки голове покоя не дают.
в процессе экспериментов выяснилось, что функция dtostrf превосходно округляет сама.
также выяснилось, что при расчете скорости в м/с V = S / T при большом значении T, зачастую получаем на выходе 0.
проблему решил умножением S на 1000, с последующим умножением на 0.001 результата масштабной скорости
Arduino код:
  V 1000.0 T;
  
sV units[selected_unit][1].toFloat() * scale[selected_scale][1].toInt() * 0.001
Ну и универсальности хочется... Добавил кнопку выбора количества знаков после запятой при выводе результата.
Ниже два скетча. Первый без кнопки, количество знаков задается в переменной
Arduino код:
int decimals 1
переставил датчики на 2-й и 3-й выходы
схема
Нажмите на изображение для увеличения
Название: SSMv310.jpg
Просмотров: 446
Размер:	132.7 Кб
ID:	130605

скетч v2.10 - без кнопки
Arduino код:
/*
 scale speed meter v2.10 2016.09.14 13:14 GMT
 */
#include <LiquidCrystal.h> // Добавляем библиотеку LCD 
#include <EEPROM.h> // Добавляем библиотеку работы с энергонезависимой памятью 
// Добавляем библиотеку антидребезга кнопок 
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * 
  Main code by Thomas O Fredericks (tof@t-o-f.info) 
  Previous contributions by Eric Lowry, Jim Schimpf and Tom Harkaway 
  [url]https://github.com/thomasfredericks/Bounce2/archive/master.zip[/url] 
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
#include <Bounce2.h> 

// переменные, которые можно менять
int S 70//дистанция (расстояние между датчиками) в миллиметрах
int resultDelay 5000// время показа результата измерений в миллисекундах
int animationDelay 50// время задержки анимации в миллисекундах
unsigned long timeoutDelay 160000// время ожидания срабатывания второго датчика в миллисекундах

// флаги
unsigned long flagLeft 0// время срабатывания левого датчика
unsigned long flagRight 0// время срабатывания правого датчика
unsigned long flagShow 0//время окончания отображения результатов
unsigned long flagAnimation 0//время отображения следующего символа при анимации

// переменные для расчетов
unsigned long timeStart;//время срабатывания первого датчика
unsigned long timeStop;//время срабатывания второго датчика
long T//интервал в милисекундах
float V//скорость в м/с
float sV//масштабная скорость
int selected_scale EEPROM.read(0); // ключ массива выбранного масштаба
int selected_unit EEPROM.read(1); // ключ массива выбранных единиц измерения
int decimals 1// точности отображения результата

// массивы, которые можно дополнять или изменять
const String scale[][2] = {{" HO""87"}, {" TT""120"}, {"  N""160"}}; // массив масштабов (отображение на экране, множитель)
const String units[][2] = {{"KPH""3.6"}, {"MPH""2.23694"}}; // массив единиц измерения (отображение на экране, коэффициент перевода из метров в секунду)

LiquidCrystal lcd(456789); // (RS, E, DB4, DB5, DB6, DB7) инициализируем дисплей
int ir_left 2// вход лекого датчика
int ir_right 3// вход правого датчика
int scalePin 10// вход кноки выбора масштаба
int unitsPin 11// вход кнопки выбора единиц измерения скорости
int decimalsPin 12// вход кнопки выбора точночти отображения результатов

Bounce scaleBouncer Bounce(); // объект-обработчик антидребезга кнопки выбра масштаба
Bounce unitsBouncer Bounce(); // объект-обработчик антидребезга кнопки выбора единиц измерения

// переменные для анимации
int r;
char c;

void setup() {
  
lcd.begin(162);
  
pinMode(ir_leftINPUT);
  
pinMode(ir_rightINPUT);
  
pinMode(scalePinINPUT);
  
pinMode(unitsPinINPUT);
  
// параметры обработчика антидребезга
  
scaleBouncer.attach(scalePin);
  
scaleBouncer.interval(5);
  
unitsBouncer.attach(unitsPin);
  
unitsBouncer.interval(5);
}

// расчет скорости
void calculateSpeed(int selected_unitint selected_scaleint decimals){
  
= (timeStop timeStart);
  
1000.0 T;
  
sV units[selected_unit][1].toFloat() * scale[selected_scale][1].toInt() * 0.001;
  
char buffer[12];
  
String tmpStr dtostrf(sV12decimalsbuffer);
  
lcd.setCursor(00);
  
lcd.print(tmpStr);
  
flagShow millis() + resultDelay;
  
timeStart 0;
  
timeStop 0;
}

//рисуем бегущую строку
void animation() {
  
lcd.setCursor(r1);
  
lcd.print(c);
  if(
flagRight 0) {
    
r++;
    if(
11){
      
1;
      if(
== '>') {
        
' ';
      }
      else {
        
'>';
      }
    }
  }
  else if(
flagLeft 0) {
    
r--;
    if(
1){
      
11;
      if(
== '<') {
        
' ';
      }
      else {
        
'<';
      }
    }
  }
  
flagAnimation millis() + animationDelay;
}

void loop() {
  if(
selected_scale sizeof(scale)/sizeof(scale[0])-1) {
    
// если считанное значение больше, чем количество элементов в массиве масштабов - обнуляем значение
    
selected_scale 0;
    
EEPROM.write(00);
  }
  if(
selected_unit sizeof(units)/sizeof(units[0])-1) {
    
// если считанное значение больше, чем количество элементов в массиве единиц измерения скоростей - обнуляем значение
    
selected_unit 0;
    
EEPROM.write(10);
  }
  
// если флаг отображения результатов меньше текущего времени выполняем код, в противном случае продолжаем отображать результаты измерений
  
if(flagShow millis()) {
    
flagShow 0;
    
// если сработал один датчик, но за время timeoutDelay не сработал второй - выводим TIME OUT
    
if(timeStart && timeStart timeoutDelay millis()) {
      
lcd.clear();
      
lcd.setCursor(00);
      
lcd.print("    TIME OUT    ");
      
flagShow millis() + resultDelay;
      
timeStart 0;
      
timeStop 0;
      
flagLeft 0;
      
flagRight 0;
      
flagAnimation 0;
    }
    
// если одновременно сработали оба датчика, но не выставлены флаги начала измерения - выводим ошибку
    
else if(digitalRead(ir_right) == LOW && digitalRead(ir_left) == LOW && flagLeft == && flagRight == 0) {
      
lcd.clear();
      
lcd.setCursor(00);
      
lcd.print("     ERROR      ");
      
flagShow millis() + 1000;
    }
    
// если нет сигнала от обоих датчиков и не выставлены флаги обоих датчиков - система готова к измерениям
    
else if(digitalRead(ir_right) == HIGH && digitalRead(ir_left) == HIGH && flagLeft == && flagRight == 0) {
      
// если была нажата кнопка масштаба
      
if(scaleBouncer.update()){
        if(
scaleBouncer.read() == HIGH) {
          
selected_scale++;
          if(
selected_scale sizeof(scale)/sizeof(scale[0])-1){
            
selected_scale 0;
          }
        }
       }
      
// если была нажата кнопка единиц измерения
      
if (unitsBouncer.update()){
        if(
unitsBouncer.read() == HIGH) {
          
selected_unit++;
          if(
selected_unit sizeof(units)/sizeof(units[0])-1){
            
selected_unit 0;
          }
        }
      }
      
// если была нажата кнопка единиц измерения
      
if (unitsBouncer.update()){
        if(
unitsBouncer.read() == HIGH) {
          
selected_unit++;
          if(
selected_unit sizeof(units)/sizeof(units[0])-1){
            
selected_unit 0;
          }
        }
      }
      
char buffer[12];
      
String tmpStr dtostrf(0.00012decimalsbuffer);
      
lcd.setCursor(00);
      
lcd.print(tmpStr);
      
lcd.setCursor(130);
      
lcd.print(units[selected_unit][0]);
      
lcd.setCursor(131);
      
lcd.print(scale[selected_scale][0]);
      
lcd.setCursor(11);
      
lcd.print("READY      ");
    }
    
// если измерения не началось и сработал один из датчиков при этом нет флага второго датчика - начинаем замер
    
else if(timeStart == && ((digitalRead(ir_right) == LOW && flagLeft == 0) || (digitalRead(ir_left) == LOW && flagRight == 0))) {
      
timeStart millis();
      if(
digitalRead(ir_right) == LOW){
        
flagRight millis();
        
'>';
        
1;
      }
      else {
        
flagLeft millis();
        
'<';
        
11;
      }
      
lcd.setCursor(11);
      
lcd.print("           ");
      
animation();
    }
    
// если сработал один из датчиков и выставлен флаг второго - заканчиваем измерения и производим расчет скорости
    
else if((digitalRead(ir_right) == LOW && flagLeft 0) || (digitalRead(ir_left) == LOW && flagRight 0)) {
      
timeStop millis();
      
flagLeft 0;
      
flagRight 0;
      
flagAnimation 0;
      
EEPROM.update(0selected_scale);
      
EEPROM.update(1selected_unit);
      
lcd.setCursor(11);
      
lcd.print("RESULT     ");
      
calculateSpeed(selected_unitselected_scaledecimals);
    }
    
// если настало время рисовать новый символ при анимации
    
else if(flagAnimation millis()){
      
animation();
    }
  }

во втором варианте, (v3.10) выбор кнопкой от одного до трех знаков


Arduino код:
/*
 scale speed meter v3.10 2016.09.14 13:14 GMT
 */
#include <LiquidCrystal.h> // Добавляем библиотеку LCD 
#include <EEPROM.h> // Добавляем библиотеку работы с энергонезависимой памятью 
// Добавляем библиотеку антидребезга кнопок 
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * 
  Main code by Thomas O Fredericks (tof@t-o-f.info) 
  Previous contributions by Eric Lowry, Jim Schimpf and Tom Harkaway 
  [url]https://github.com/thomasfredericks/Bounce2/archive/master.zip[/url] 
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
#include <Bounce2.h> 

// переменные, которые можно менять
int S 70//дистанция (расстояние между датчиками) в миллиметрах
int resultDelay 5000// время показа результата измерений в миллисекундах
int animationDelay 50// время задержки анимации в миллисекундах
unsigned long timeoutDelay 160000// время ожидания срабатывания второго датчика в миллисекундах

// флаги
unsigned long flagLeft 0// время срабатывания левого датчика
unsigned long flagRight 0// время срабатывания правого датчика
unsigned long flagShow 0//время окончания отображения результатов
unsigned long flagAnimation 0//время отображения следующего символа при анимации

// переменные для расчетов
unsigned long timeStart;//время срабатывания первого датчика
unsigned long timeStop;//время срабатывания второго датчика
long T//интервал в милисекундах
float V//скорость в м/с
float sV//масштабная скорость
int selected_scale EEPROM.read(0); // ключ массива выбранного масштаба
int selected_unit EEPROM.read(1); // ключ массива выбранных единиц измерения
int selected_decimals EEPROM.read(2); // ключ массива точности отображения результата

// массивы, которые можно дополнять или изменять
const String scale[][2] = {{" HO""87"}, {" TT""120"}, {"  N""160"}}; // массив масштабов (отображение на экране, множитель)
const String units[][2] = {{"KPH""3.6"}, {"MPH""2.23694"}}; // массив единиц измерения (отображение на экране, коэффициент перевода из метров в секунду)
int decimals[] = {123}; // массив точности отображения результата.

LiquidCrystal lcd(456789); // (RS, E, DB4, DB5, DB6, DB7) инициализируем дисплей
int ir_left 2// вход лекого датчика
int ir_right 3// вход правого датчика
int scalePin 10// вход кноки выбора масштаба
int unitsPin 11// вход кнопки выбора единиц измерения скорости
int decimalsPin 12// вход кнопки выбора точночти отображения результатов

Bounce scaleBouncer Bounce(); // объект-обработчик антидребезга кнопки выбра масштаба
Bounce unitsBouncer Bounce(); // объект-обработчик антидребезга кнопки выбора единиц измерения
Bounce decimalsBouncer Bounce(); // объект-обработчик антидребезга кнопки выбора точночти отображения результата

// переменные для анимации
int r;
char c;

void setup() {
  
lcd.begin(162);
  
pinMode(ir_leftINPUT);
  
pinMode(ir_rightINPUT);
  
pinMode(scalePinINPUT);
  
pinMode(unitsPinINPUT);
  
// параметры обработчика антидребезга
  
scaleBouncer.attach(scalePin);
  
scaleBouncer.interval(5);
  
unitsBouncer.attach(unitsPin);
  
unitsBouncer.interval(5);
  
decimalsBouncer.attach(decimalsPin);
  
decimalsBouncer.interval(5);
}

// расчет скорости
void calculateSpeed(int selected_unitint selected_scaleint selected_decimals){
  
= (timeStop timeStart);
  
1000.0 T;
  
sV units[selected_unit][1].toFloat() * scale[selected_scale][1].toInt() * 0.001;
  
char buffer[12];
  
String tmpStr dtostrf(sV12decimals[selected_decimals], buffer);
  
lcd.setCursor(00);
  
lcd.print(tmpStr);
  
flagShow millis() + resultDelay;
  
timeStart 0;
  
timeStop 0;
}

//рисуем бегущую строку
void animation() {
  
lcd.setCursor(r1);
  
lcd.print(c);
  if(
flagRight 0) {
    
r++;
    if(
11){
      
1;
      if(
== '>') {
        
' ';
      }
      else {
        
'>';
      }
    }
  }
  else if(
flagLeft 0) {
    
r--;
    if(
1){
      
11;
      if(
== '<') {
        
' ';
      }
      else {
        
'<';
      }
    }
  }
  
flagAnimation millis() + animationDelay;
}

void loop() {
  if(
selected_scale sizeof(scale)/sizeof(scale[0])-1) {
    
// если считанное значение больше, чем количество элементов в массиве масштабов - обнуляем значение
    
selected_scale 0;
    
EEPROM.write(00);
  }
  if(
selected_unit sizeof(units)/sizeof(units[0])-1) {
    
// если считанное значение больше, чем количество элементов в массиве единиц измерения скоростей - обнуляем значение
    
selected_unit 0;
    
EEPROM.write(10);
  }
  if(
selected_decimals sizeof(decimals)/sizeof(int)-1) {
    
// если считанное значение больше, чем количество элементов в массиве точночти отображения результата - обнуляем значение
    
selected_decimals 0;
    
EEPROM.write(20);
  }
  
// если флаг отображения результатов меньше текущего времени выполняем код, в противном случае продолжаем отображать результаты измерений
  
if(flagShow millis()) {
    
flagShow 0;
    
// если сработал один датчик, но за время timeoutDelay не сработал второй - выводим TIME OUT
    
if(timeStart && timeStart timeoutDelay millis()) {
      
lcd.clear();
      
lcd.setCursor(00);
      
lcd.print("    TIME OUT    ");
      
flagShow millis() + resultDelay;
      
timeStart 0;
      
timeStop 0;
      
flagLeft 0;
      
flagRight 0;
      
flagAnimation 0;
    }
    
// если одновременно сработали оба датчика, но не выставлены флаги начала измерения - выводим ошибку
    
else if(digitalRead(ir_right) == LOW && digitalRead(ir_left) == LOW && flagLeft == && flagRight == 0) {
      
lcd.clear();
      
lcd.setCursor(00);
      
lcd.print("     ERROR      ");
      
flagShow millis() + 1000;
    }
    
// если нет сигнала от обоих датчиков и не выставлены флаги обоих датчиков - система готова к измерениям
    
else if(digitalRead(ir_right) == HIGH && digitalRead(ir_left) == HIGH && flagLeft == && flagRight == 0) {
      
// если была нажата кнопка масштаба
      
if(scaleBouncer.update()){
        if(
scaleBouncer.read() == HIGH) {
          
selected_scale++;
          if(
selected_scale sizeof(scale)/sizeof(scale[0])-1){
            
selected_scale 0;
          }
        }
       }
      
// если была нажата кнопка единиц измерения
      
if (unitsBouncer.update()){
        if(
unitsBouncer.read() == HIGH) {
          
selected_unit++;
          if(
selected_unit sizeof(units)/sizeof(units[0])-1){
            
selected_unit 0;
          }
        }
      }
      
// если была нажата кнопка единиц измерения
      
if (unitsBouncer.update()){
        if(
unitsBouncer.read() == HIGH) {
          
selected_unit++;
          if(
selected_unit sizeof(units)/sizeof(units[0])-1){
            
selected_unit 0;
          }
        }
      }
      
// если была нажата кнопка выбора точночти отображения результата
      
if (decimalsBouncer.update()){
        if(
decimalsBouncer.read() == HIGH) {
          
selected_decimals++;
          if(
selected_decimals sizeof(decimals)/sizeof(int)-1){
            
selected_decimals 0;
          }
        }
      }
      
char buffer[12];
      
String tmpStr dtostrf(0.00012decimals[selected_decimals], buffer);
      
lcd.setCursor(00);
      
lcd.print(tmpStr);
      
lcd.setCursor(130);
      
lcd.print(units[selected_unit][0]);
      
lcd.setCursor(131);
      
lcd.print(scale[selected_scale][0]);
      
lcd.setCursor(11);
      
lcd.print("READY      ");
    }
    
// если измерения не началось и сработал один из датчиков при этом нет флага второго датчика - начинаем замер
    
else if(timeStart == && ((digitalRead(ir_right) == LOW && flagLeft == 0) || (digitalRead(ir_left) == LOW && flagRight == 0))) {
      
timeStart millis();
      if(
digitalRead(ir_right) == LOW){
        
flagRight millis();
        
'>';
        
1;
      }
      else {
        
flagLeft millis();
        
'<';
        
11;
      }
      
lcd.setCursor(11);
      
lcd.print("           ");
      
animation();
    }
    
// если сработал один из датчиков и выставлен флаг второго - заканчиваем измерения и производим расчет скорости
    
else if((digitalRead(ir_right) == LOW && flagLeft 0) || (digitalRead(ir_left) == LOW && flagRight 0)) {
      
timeStop millis();
      
flagLeft 0;
      
flagRight 0;
      
flagAnimation 0;
      
EEPROM.update(0selected_scale);
      
EEPROM.update(1selected_unit);
      
EEPROM.update(2selected_decimals);
      
lcd.setCursor(11);
      
lcd.print("RESULT     ");
      
calculateSpeed(selected_unitselected_scaleselected_decimals);
    }
    
// если настало время рисовать новый символ при анимации
    
else if(flagAnimation millis()){
      
animation();
    }
  }

BNSF9399 вне форума  
Вверх
3 пользователя(ей) сказали cпасибо: