Изменение программ по нажатию кнопки

vitar
Offline
Зарегистрирован: 22.11.2014

Всем добрый день. По стандарту: Я новичек, с Ардуино разбираюсь гдето пятый день. Вот в чем вопрос. 

Есть три отдельные программы. 2 из них отличаются только несколькими строками в цикле void loop. Третяя посложнее (она еще не готова, поэтому речь пойдет только о двух, но в итоге она тоже должна там быть). 

Задача: переключатся между этими программами по нажатию кнопки. Тоесть: раз нажал на кнопку - первая работает, второй раз нажал - вторая работает, третий - третяя, еще раз нажал - заново пошло. Плата - Arduino UNO.

Вот собственно сам код:

int knopkaPin = 8;
int pwmPin = 6;
boolean poslSost = LOW;
boolean znachKnopki = LOW;
int dvig = 0;
int knopkaInt = 0; //Pin 2

void setup()
{
  pinMode(knopkaPin, INPUT);
  pinMode(pwmPin,OUTPUT);
  attachInterrupt (knopkaInt, swap, RISING);
}

void swap()
{

}

boolean debounce(boolean posl)
{
  boolean znach = digitalRead(knopkaPin);
  if (posl!=znach)
  {
   delay(5);
    znach = digitalRead(knopkaPin);
   }
  return znach;
}

void loop()
{
  znachKnopki = debounce(poslSost);
    if (poslSost==LOW && znachKnopki == HIGH)
   	{
   	dvig = dvig + 255;
  	}
    	poslSost=znachKnopki;
  		if (dvig > 255) 
		dvig = 0;
  analogWrite(pwmPin,dvig);
}

 void loop1()
{
  znachKnopki = debounce(poslSost);
      if (poslSost==LOW && znachKnopki == HIGH)
  	{
   	dvig = dvig + 127;
  	}
   	poslSost=znachKnopki;
   		if (dvig > 127)
  		dvig = 0;
  analogWrite(pwmPin,dvig);
}  

Краткое описание. Есть кнопка, которая имитирует сигнал. Тоесть по нажатию (единичному, не держать) выполняется if, eще по одному нажатию - else. Есть движок, который подключен к 6 пину (с ШИМ). В итоге: нажал кнопку, движок выехал полностью, нажал - заехал полностью. Вторая программа, это тоже самое, но на половину. 

Так вот, как их соеденить в одну. Я думал можно сделать 3 void loop, под разными номерами, в цикле swap сделать их чередование по нажатию кнопки с помощью прерывания (для этого влипил на второй пин). Но вразумительного ответа так и не нашел. Вот чтото похожее http://arduino.cc/en/Tutorial/MultipleBlinks но там Arduino DUE.

В итоге застрял. Прошу помощи у знатоков. 

GothThug
GothThug аватар
Offline
Зарегистрирован: 07.09.2014

выложи отдельно 2 кода

vitar
Offline
Зарегистрирован: 22.11.2014
int knopkaPin = 8;
int pwmPin = 6;
boolean poslSost = LOW;
boolean znachKnopki = LOW;
int dvig = 0;

void setup()
{
  pinMode(knopkaPin, INPUT);
  pinMode(pwmPin,OUTPUT);
 }

boolean debounce(boolean posl)
{
  boolean znach = digitalRead(knopkaPin);
  if (posl!=znach)
  {
   delay(5);
    znach = digitalRead(knopkaPin);
   }
  return znach;
}

void loop()
{
  znachKnopki = debounce(poslSost);
    if (poslSost==LOW && znachKnopki == HIGH)
   	{
   	dvig = dvig + 255;
  	}
    	poslSost=znachKnopki;
  		if (dvig > 255) 
		dvig = 0;
  analogWrite(pwmPin,dvig);
}
int knopkaPin = 8;
int pwmPin = 6;
boolean poslSost = LOW;
boolean znachKnopki = LOW;
int dvig = 0;

void setup()
{
  pinMode(knopkaPin, INPUT);
  pinMode(pwmPin,OUTPUT);
 }

boolean debounce(boolean posl)
{
  boolean znach = digitalRead(knopkaPin);
  if (posl!=znach)
  {
   delay(5);
    znach = digitalRead(knopkaPin);
   }
  return znach;
}

void loop()
{
  znachKnopki = debounce(poslSost);
    if (poslSost==LOW && znachKnopki == HIGH)
   	{
   	dvig = dvig + 127;
  	}
    	poslSost=znachKnopki;
  		if (dvig > 127) 
		dvig = 0;
  analogWrite(pwmPin,dvig);
}

Как видно они отличаются только одной цифрой. Третюю программу пока не ложу, она не готова, там тоже свои вопросы, но пока что надо сделать хоть это.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

vitar, Ну так и меняйте одну цифру. Сделайте для неё переменную,  вставьте её в код, и от  дополнительной кнопки меняйте значение переменной.

vitar
Offline
Зарегистрирован: 22.11.2014

Но это если бы мне надо было только эти 2 программы чередовать. Я же писал, что будет третяя, и она сильно отличается от этих двух. Тоесть надо создать какуюто глобальную подпрограмму, которая будет чередовть 3 цикла по нажатию кнопки. Я думал сделать void loop1, void loop2 и void loop3, и их менять по очереди в void swap. Но я не знаю как можно вызвать их в другом цикле и можно ли вообще.  

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

vitar, вы мутите что-то странное, так можно, но так не делают.  Нужно так составить одну программу, что бы она интегрировала в себе все необходимые функции.

vitar
Offline
Зарегистрирован: 22.11.2014

Вот поэтому я и написал здесь, так как еще плохо разбираюсь в этих всех командах и не знаю тонкостей программирования на Arduino, а сроки горят. Я написал так, как сам представляю то что должно получится, но может кто-то знает более оптимальный вариант или сталкивался с подобным. В моем представлении есть одна большая программа (код), который состоит из трех основных подпрограмм и одной подпрограммы для переключения их по кругу с помощью кнопки. Представим, что все три подпрограммы разные и их надо всунуть в одну большую. Для этого я и придумал такие цикли, как (для меня) самый очевидный вариант. Естественно код получился топорный и большой, не оптимизированный. Может кто-то что-то подскажет. Буду благодарен. 

fayvlad
Offline
Зарегистрирован: 27.03.2014
напиши через кейс
void loop()
{
читай кнопку и делай счетчик
типа  счетчик =1 , если кнопка нажата счетчик++, если счетчик больше 3, счетчик =1
а потом
swich(счетчик) 
{
case 1 : {firstcode(); break}
case 2 : {secondcode(); break}
case 3 : {thirdcode(); break}
}
}
потом 3 своих функций
int firstcode ()
{
...
}
...
fayvlad
Offline
Зарегистрирован: 27.03.2014

и забудь о том примере void swap и void loop2 ... 

у тебя должно быть 2 основных цикла, которые загружает дуина при работе - это первый void setup и void loop

все остальные функции пиши своими именами и еще если она ничего не возвращает, то пиши int <имя_функции> ()

если нужно ретурн делать - void MyFunction () { code... }

vitar
Offline
Зарегистрирован: 22.11.2014

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

А кнопку лучше ставить обычную (вроде int button1 = какойто пин) или использовать прерывания (на второй пин)?

И что значит "ничего не возвращает"? Что-то вроде обратной связи?  Тоесть в этих двух кодах у меня ее нет, тобишь можно int, а в третей у меня будет Serial.println, которая расчитывает значения из данных, полученных по обратной связи, и там мне надо будет использовать void?

fayvlad
Offline
Зарегистрирован: 27.03.2014

посмотрел свой код  int  работает с return, хотя когда-то читал именно такое, что функция void возвращает. Может это в том случае если функция - обработчик типу void calc(x,y) когда параметр возвращает второй переменной.

Непойму о каких перерываниях вы говорите, поставте кнопку на какой-то пин, заземлите резистором ее и пропишите тот пин в программе.

кстати можно поставить кучу кнопок   через резистор на аналоговый пин и прописать типа такого

int getButton()
{
  int buttonValue = analogRead(0); // считываем значения с аналогового входа(A0) 
 
  if (buttonValue < 50) {
    return BUTTON_LEFT;  
  }
  else if (buttonValue < 150) {
    return BUTTON_DOWN;
  }
  else if (buttonValue < 300){
    return BUTTON_SELECT;
  }
  else if (buttonValue < 500){
    return BUTTON_RIGHT;
  }
  else if (buttonValue < 800){
    return BUTTON_UP;
  }
  return BUTTON_NONE;
}

все 3 своих функций пропишите через int MyFunction () {...} с главной программы оно будет вызыватся и выполнятся после выполнения перескакивать в void loop() и ждать кнопки. 

vitar
Offline
Зарегистрирован: 22.11.2014

Я просмотрел видео разные, нашел что-то похожее на то, что хотел, вот и решил отталкиватся от этого. 

Вот с 9 минуты и дальше вторая часть: http://www.youtube.com/watch?v=wjB2qZ3Zkh0&index=18&list=PLfDmj22jP9S759DT250VVzfZs_4VnJqLa

А так спасибо, как попробую - отпишусь. 

vitar
Offline
Зарегистрирован: 22.11.2014

Всем привет. Добрался до программы наконецто.

Переделал с использованием case. Впринципе логику понял. Но возникла проблема со счетчиком. Походу не считывает значения. В программе вроде все верно, все условия заданы. Пины менял, кнопки менял, case местами менял, все работает, но когда собираю все в кучу то не работает. Вот код. Я уверен что проблема со счетчиком, но в упор не вижу. Когда нажимаю на кнопку счетчика, программа все равно работает по первому варианту. Если удерживаю ее, то вообще не работает. 

const int knopkaPin = 8;
const int pwmPin = 6;
boolean poslSost = LOW;
boolean znachKnopki = LOW;
int dvig = 0;
const int swichButtonPin=12;
int counter = 1;

void setup()
{
  pinMode(knopkaPin, INPUT);
  pinMode(swichButtonPin, INPUT);
  pinMode(pwmPin,OUTPUT);
}

boolean debounce(boolean posl)
{
  boolean znach = digitalRead(knopkaPin);
  if (posl!=znach)
  {
    delay(5);
    znach = digitalRead(knopkaPin);
  }
  return znach;
}

void loop()
{  
    if (digitalRead(swichButtonPin) == HIGH)
      counter++;
    else if (counter > 2)
      counter = 1;

znachKnopki = debounce(poslSost);
   
switch (counter)
{
case 1: {firstcode(); break;}
case 2: {secondcode(); break;}
}
}
  
int firstcode()
{
    if (poslSost==LOW && znachKnopki == HIGH)
      dvig = dvig + 255;
      poslSost=znachKnopki;
    if (dvig > 255) 
      dvig = 0;
   analogWrite(pwmPin,dvig);
}
  
int secondcode()
{
    if (poslSost==LOW && znachKnopki == HIGH)
      dvig = dvig + 127;
      poslSost=znachKnopki;
    if (dvig > 127)
      dvig = 0;
  analogWrite(pwmPin,dvig);
} 

 

vitar
Offline
Зарегистрирован: 22.11.2014

Всё, всем спасибо, уже разобрался. 

Vanya_87
Offline
Зарегистрирован: 31.03.2015

привет всем. с Arduino несколько дней, хочу собрать БК для своего авто на Arduino Nano v3 и LCD 8x2. код брал от сюда: http://habrahabr.ru/post/135231/ Плата уже собрана, осталось только программу до ума довеси

потом гуляя по просторам интернета наткнулся на этот форум и ещё на вот этот код: http://pastebin.com/eP20LeXX

вообщем вроде обрадовался но не тут то было, при заливки изменённного кода полезли ошибки. собственно вот такой код у меня получился. ну и там где switch (selmon) Case0 и Case1. вообщем в идеале у меня будет 4 экрана. программы по отдельности работают: основная программа, программа с датчика температуры. по сути я так понимаю что сперво пишутся все программы и формулы а в конце идет вывод на экран. экран у меня должен менятся одной кнопкой и пролистываться по кругу. ПРИ этом все программы и формулы должны работать всегда, т.к. будет зависимость у разных экранов. Начало кода я опустил, т.к. там ничего нет)))

в данном коде хотел выводить в первом экране ср и mgn расход и на втором экране скорость и слово TEMP. 

#define AVG_REFRESH_TICKS ( AVG_REFRESH_LENGTH / RANGE_FACTOR ) // Число импульсов датчика скорости между обновлениями среднего расхода

// Строковые константы
#define STR_AVG String(" Cp:")
#define STR_CUR String("Mgn:")
#define STR_NA String(" \xBD/\xE3")
#define STR_KMH String("\xBA\xBC/\xC0")

LiquidCrystal lcd(12, 10, 5, 4, 3, 2);

unsigned long dur;
unsigned long dur_t;
unsigned long t;

boolean last_injector_state;
boolean last_speed_state;

unsigned long total_duration;
unsigned long total_ticks;
unsigned long total_avg_duration;
unsigned long total_avg_ticks;
unsigned long d_avg_duration;
unsigned long d_avg_ticks;
int period_counter;
// int period_counter2;

byte count_display=2; // Количество экранов бк     я добавил
byte pin=9;  // пины кнопок                        я добавил

// Структура, описывающая данные для усреднения
struct consumption_data {
  unsigned int duration;
  word ticks; 
};

struct consumption_data data[AVG_LENGTH];
int avg_counter;

void setup() {
  // Serial.begin(9600);
  lcd.begin(8, 2);
  t = micros() + PERIOD;
  pinMode(INJECTOR_PIN, INPUT);
  pinMode(SPEED_PIN, INPUT);
  last_injector_state = analogRead(INJECTOR_PIN) > 500;
  last_speed_state = analogRead(SPEED_PIN) > 500;
  
  dur = 0;
  dur_t = micros();
  total_duration = 0;
  total_ticks = 0;
  total_avg_duration = total_duration;
  total_avg_ticks = total_ticks;
  d_avg_duration = total_duration;
  d_avg_ticks = total_ticks;
  
  // Инициализация данных для усреднения
  for (int i=0; i < AVG_LENGTH; ++i) {
    data[i].duration = 0;
    data[i].ticks = 0;
  }
  
  period_counter = 0;
//  period_counter2 = 0;
  avg_counter = 0;
}

void loop() {
  boolean injector_state = analogRead(INJECTOR_PIN) > 500;
  boolean speed_state = analogRead(SPEED_PIN) > 500;
  unsigned long new_t = micros();
  
  // Вычисление мгновенных значений
  
  if (injector_state != last_injector_state) {
    if (injector_state) {
      dur = new_t - dur_t;
      if (dur) dur += DURATION_CORR; // Поправочка
      total_duration += dur;
    } else {
      dur_t = new_t;
      dur = 0;
    }
    
    last_injector_state = injector_state;
  }
  
  if (speed_state != last_speed_state) {
    total_ticks++;
    
    last_speed_state = speed_state;
  }
  
  // Действия, которые выполняются раз в секунду
  
  if (new_t >= t) {
    if (!dur) {
      dur = new_t - dur_t;
      if (dur) dur += DURATION_CORR; // Поправочка
      total_duration += dur;
    }
    
    // Отладочная установка значений
    
//    if (period_counter2 < AVG_LENGTH * AVG_REFRESH_PERIODS) {
//      total_duration = 100000;
//      total_ticks = 56;
//    } else if (period_counter2 < 2 * AVG_LENGTH * AVG_REFRESH_PERIODS) {
//      total_duration = 20000;
//      total_ticks = 1;
//    } else {
//      total_duration = 100000;
//      total_ticks = 56;
//    }
    
    d_avg_duration += total_duration;
    d_avg_ticks += total_ticks;
    
    ++period_counter;
//    ++period_counter2;
    
    if (d_avg_ticks >= AVG_REFRESH_TICKS || period_counter >= AVG_REFRESH_PERIODS) {
      // Вычисление средних значений
      
      // total_avg_duration += d_avg_duration - data[avg_counter].duration;
      /// total_avg_ticks += d_avg_ticks - data[avg_counter].ticks;
      
      data[avg_counter].duration = d_avg_duration;
      data[avg_counter].ticks = d_avg_ticks;

      total_avg_duration = 0;
      total_avg_ticks = 0;
      
      for (int i=0; i < AVG_LENGTH; i++) {
        total_avg_duration += data[i].duration;
        total_avg_ticks += data[i].ticks;
      }
      
      period_counter = 0;
      d_avg_duration = 0;
      d_avg_ticks = 0;

      ++avg_counter;
      if (avg_counter >= AVG_LENGTH)
        avg_counter = 0;
    }
    
    // Конвертация значений в физические единицы и вывод на экран

    String s1, s2, s3;
    unsigned int consumption = 0;
    unsigned int avg_consumption = 0;
    
    if (total_ticks > TICKS_TRESHOLD) {
      consumption = 10.0 * CONSUMPTION_FACTOR * total_duration / total_ticks;
    }

    if (total_avg_ticks > TICKS_TRESHOLD) {
      avg_consumption = 10.0 * CONSUMPTION_FACTOR * total_avg_duration / total_avg_ticks;
    }
    
    unsigned int hour_consumption = 10.0 * FUEL_FACTOR * total_duration * HOUR_PERIODS;
    unsigned int spd = RANGE_FACTOR * total_ticks * HOUR_PERIODS;
    
    s1 = String(total_duration, DEC);

    if (total_ticks > TICKS_TRESHOLD) {
      s1 = STR_CUR + format(consumption);
      // s1 = format(consumption);
    } else {
      s1 = STR_CUR + STR_NA;
      // s1 = "n/a ";
    }

    if (total_avg_ticks > TICKS_TRESHOLD) {
      s2 = STR_AVG + format(avg_consumption);
      // s2 = format(avg_consumption);
    } else {
      s2 = STR_AVG + STR_NA;
      // s2 = "n/a ";
    }

    // s2 = "hr: " + format(hour_consumption);
    // s2 = format(hour_consumption);
    
    // s3 = "sp: " + String(spd, DEC);
    // s3 = String(spd, DEC);
    // s3 = String(total_ticks, DEC);
    
    // int iters = 3 - s3.length();
    // int iters = 8 - s3.length();
    
    // for(int i = 0; i < iters; ++i)
    //  s3 = " " + s3;
      
    // int iters2 = 8 - s1.length();
    
    // for(int i = 0; i < iters2; ++i)
    //  s1 = " " + s1;
    
    // s3 += STR_KMH;
    
  }

switch (selmon) {
  case 0:
 
    lcd.setCursor(0,0);
    lcd.print(s2);
    
    lcd.setCursor(0,1);
    lcd.print(s1);
    
    total_duration = 0;
    total_ticks = 0;
    t = new_t + PERIOD;;
    } 
 
String format(unsigned int dec) {
  if (dec > 1000) return String("##.#");
  
  unsigned int intPart = dec / 10;
  unsigned int fracPart = dec % 10;
  String result = String(intPart, DEC) + "," + String(fracPart, DEC);

  int iters = 4 - result.length();  
  for(int i = 0; i < iters; ++i)
    result = " " + result; 
    break;
 
  case 1:
 
    value=digitalRead(pin);  // проверка состояния кнопки для переключения экрана
    
    if ((value==LOW){
 
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print(spd);
    lcd.print(" km/h");
    lcd.setCursor(0,1);
    lcd.print("TEMP"); 
 
    }
 
 
    break;
}
 
  
  return result;
}

Надеюсь на Вашу помощь. заранее благодарен. ткните пожалуйста что не правильно в моём коде. и по возможности исправте его.

stakan1986
Offline
Зарегистрирован: 17.02.2015

Vanya_87

скобка в строке 217 закрывает switch, а скобка в строке 219 не закрыта

как-то в строках 27 и 28 логичнее было бы видеть int а не byte

откуда взялась и где задается переменная selmon

цикл for в строке 227 тоже не мешало бы открыть и закрыть, в строке 235 - две левых скобки.

Короче перед тем как скидывать не мешало бы и самому проверить что да как

Vanya_87
Offline
Зарегистрирован: 31.03.2015

спасибо. попробую. я просто говорю же с программами пару дней только)))

Vanya_87
Offline
Зарегистрирован: 31.03.2015

selmon вообще убрать? просто это было скопировано с другого кода

 
Vanya_87
Offline
Зарегистрирован: 31.03.2015

вот что выдала arduino после всех изменений:

sketch_apr02a.ino: In function 'void loop()':
sketch_apr02a:191: error: 'format' was not declared in this scope
sketch_apr02a:199: error: 'format' was not declared in this scope
sketch_apr02a:228: error: expected primary-expression before ')' token
sketch_apr02a:232: error: 's2' was not declared in this scope
sketch_apr02a:235: error: 's1' was not declared in this scope
sketch_apr02a:242: error: a function-definition is not allowed here before '{' token
sketch_apr02a:253: error: break statement not within loop or switch
sketch_apr02a:255: error: case label '1' not within a switch statement
sketch_apr02a:257: error: 'value' was not declared in this scope
sketch_apr02a:259: error: expected `)' before '{' token
sketch_apr02a.ino: At global scope:
sketch_apr02a:275: error: expected unqualified-id before 'return'
sketch_apr02a:276: error: expected declaration before '}' token
Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

stakan1986 пишет:

как-то в строках 27 и 28 логичнее было бы видеть int а не byte

Логичнее там было бы uint8_t, зачем там 16-битные переменные? Врядли количество экранов и пинов будет больше 255 ;-)

Тип данных byte кстати тоже 8-ми битное беззнаковое целое число. Тоже самое, что uint8_t.

Vanya_87
Offline
Зарегистрирован: 31.03.2015

так мне назад byte вернуть? 

и что с кодом делать? ошибки вылазиют и не дают прошиться

Vanya_87
Offline
Зарегистрирован: 31.03.2015
#include <LiquidCrystal.h>

#define SPEED_PIN A6 // Номер ноги для датчика скорости
#define INJECTOR_PIN A7 // Номер ноги для форсунки
#define PERIOD 1000000 // Период усреднения текущего расхода и обновления дисплея (микросекунды) - пять секунд

#define IDLE_STROKE_DURATION 21000 // Суммарное время открытия форсунок (милисекунды) за период на холостом ходу
#define IDLE_STROKE_HOUR_CONSUMPTION 0.7 // Часовой расход топлива на холостом ходу (литры в час)
#define TEST_SPEED 60.0 // Контрольная скорость (километры в час) для расчёта коэффициента пробега
#define TEST_TICKS 84 // Число импульсов с датчика скорости за период на контрольной скорости

#define HOUR_PERIODS ( 3600000000.0 / PERIOD ) // Число периодов в часу
#define FUEL_FACTOR ( IDLE_STROKE_HOUR_CONSUMPTION / HOUR_PERIODS / IDLE_STROKE_DURATION ) // Коэффициент расхода топлива (литры) за период
#define RANGE_FACTOR ( TEST_SPEED / TEST_TICKS / HOUR_PERIODS ) // Коэффициент пробега (километры) за период
#define CONSUMPTION_FACTOR ( 100.0 * FUEL_FACTOR / RANGE_FACTOR ) // Коэффициент километрового расхода топлива (литры на 100 км)

#define TICKS_TRESHOLD 1 // Порог (импульсы датчика скорости) за период, выше которого можно считать километровый расход
#define DURATION_CORR 0 // Поправка при измерении длительности времени открытия одной форсунки (микросекунды)
#define AVG_LENGTH 10 // Число периодов для усреднения

#define AVG_REFRESH_TIME 1 // Время в часах, после которого сбрасывается усреднённый километровый расход, если не было сброса по расстоянию (1 час)
#define AVG_REFRESH_LENGTH 0.1 // Расстояние в километрах, после которого сбрасывается усреднённый километровый расход (100 м)
#define AVG_REFRESH_PERIODS ( AVG_REFRESH_TIME * HOUR_PERIODS ) // Число периодов между обновлениями среднего расхода
#define AVG_REFRESH_TICKS ( AVG_REFRESH_LENGTH / RANGE_FACTOR ) // Число импульсов датчика скорости между обновлениями среднего расхода

// Строковые константы
#define STR_AVG String(" Cp:")
#define STR_CUR String("Mgn:")
#define STR_NA String(" \xBD/\xE3")
#define STR_KMH String("\xBA\xBC/\xC0")

LiquidCrystal lcd(12, 10, 5, 4, 3, 2);

unsigned long dur;
unsigned long dur_t;
unsigned long t;

boolean last_injector_state;
boolean last_speed_state;

unsigned long total_duration;
unsigned long total_ticks;
unsigned long total_avg_duration;
unsigned long total_avg_ticks;
unsigned long d_avg_duration;
unsigned long d_avg_ticks;
int period_counter;
// int period_counter2;

int count_display=2; // Количество экранов бк
int pin=9;  // пины кнопок

// Структура, описывающая данные для усреднения
struct consumption_data {
  unsigned int duration;
  word ticks; 
};

struct consumption_data data[AVG_LENGTH];
int avg_counter;

void setup() {
  // Serial.begin(9600);
  lcd.begin(8, 2);
  t = micros() + PERIOD;
  pinMode(INJECTOR_PIN, INPUT);
  pinMode(SPEED_PIN, INPUT);
  last_injector_state = analogRead(INJECTOR_PIN) > 500;
  last_speed_state = analogRead(SPEED_PIN) > 500;
  
  dur = 0;
  dur_t = micros();
  total_duration = 0;
  total_ticks = 0;
  total_avg_duration = total_duration;
  total_avg_ticks = total_ticks;
  d_avg_duration = total_duration;
  d_avg_ticks = total_ticks;
  
  // Инициализация данных для усреднения
  for (int i=0; i < AVG_LENGTH; ++i) {
    data[i].duration = 0;
    data[i].ticks = 0;
  }
  
  period_counter = 0;
//  period_counter2 = 0;
  avg_counter = 0;
}

void loop() {
  boolean injector_state = analogRead(INJECTOR_PIN) > 500;
  boolean speed_state = analogRead(SPEED_PIN) > 500;
  unsigned long new_t = micros();
  
  // Вычисление мгновенных значений
  
  if (injector_state != last_injector_state) {
    if (injector_state) {
      dur = new_t - dur_t;
      if (dur) dur += DURATION_CORR; // Поправочка
      total_duration += dur;
    } else {
      dur_t = new_t;
      dur = 0;
    }
    
    last_injector_state = injector_state;
  }
  
  if (speed_state != last_speed_state) {
    total_ticks++;
    
    last_speed_state = speed_state;
  }
  
  // Действия, которые выполняются раз в секунду
  
  if (new_t >= t) {
    if (!dur) {
      dur = new_t - dur_t;
      if (dur) dur += DURATION_CORR; // Поправочка
      total_duration += dur;
    }
    
    // Отладочная установка значений
    
//    if (period_counter2 < AVG_LENGTH * AVG_REFRESH_PERIODS) {
//      total_duration = 100000;
//      total_ticks = 56;
//    } else if (period_counter2 < 2 * AVG_LENGTH * AVG_REFRESH_PERIODS) {
//      total_duration = 20000;
//      total_ticks = 1;
//    } else {
//      total_duration = 100000;
//      total_ticks = 56;
//    }
    
    d_avg_duration += total_duration;
    d_avg_ticks += total_ticks;
    
    ++period_counter;
//    ++period_counter2;
    
    if (d_avg_ticks >= AVG_REFRESH_TICKS || period_counter >= AVG_REFRESH_PERIODS) {
      // Вычисление средних значений
      
      // total_avg_duration += d_avg_duration - data[avg_counter].duration;
      /// total_avg_ticks += d_avg_ticks - data[avg_counter].ticks;
      
      data[avg_counter].duration = d_avg_duration;
      data[avg_counter].ticks = d_avg_ticks;

      total_avg_duration = 0;
      total_avg_ticks = 0;
      
      for (int i=0; i < AVG_LENGTH; i++) {
        total_avg_duration += data[i].duration;
        total_avg_ticks += data[i].ticks;
      }
      
      period_counter = 0;
      d_avg_duration = 0;
      d_avg_ticks = 0;

      ++avg_counter;
      if (avg_counter >= AVG_LENGTH)
        avg_counter = 0;
    }
    
    // Конвертация значений в физические единицы и вывод на экран

    String s1, s2, s3;
    unsigned int consumption = 0;
    unsigned int avg_consumption = 0;
    
    if (total_ticks > TICKS_TRESHOLD) {
      consumption = 10.0 * CONSUMPTION_FACTOR * total_duration / total_ticks;
    }

    if (total_avg_ticks > TICKS_TRESHOLD) {
      avg_consumption = 10.0 * CONSUMPTION_FACTOR * total_avg_duration / total_avg_ticks;
    }
    
    unsigned int hour_consumption = 10.0 * FUEL_FACTOR * total_duration * HOUR_PERIODS;
    unsigned int spd = RANGE_FACTOR * total_ticks * HOUR_PERIODS;
    
    s1 = String(total_duration, DEC);

    if (total_ticks > TICKS_TRESHOLD) {
      s1 = STR_CUR + format(consumption);
      // s1 = format(consumption);
    } else {
      s1 = STR_CUR + STR_NA;
      // s1 = "n/a ";
    }

    if (total_avg_ticks > TICKS_TRESHOLD) {
      s2 = STR_AVG + format(avg_consumption);
      // s2 = format(avg_consumption);
    } else {
      s2 = STR_AVG + STR_NA;
      // s2 = "n/a ";
    }

    // s2 = "hr: " + format(hour_consumption);
    // s2 = format(hour_consumption);
    
    // s3 = "sp: " + String(spd, DEC);
    // s3 = String(spd, DEC);
    // s3 = String(total_ticks, DEC);
    
    // int iters = 3 - s3.length();
    // int iters = 8 - s3.length();
    
    // for(int i = 0; i < iters; ++i)
    //  s3 = " " + s3;
      
    // int iters2 = 8 - s1.length();
    
    // for(int i = 0; i < iters2; ++i)
    //  s1 = " " + s1;
    
    // s3 += STR_KMH;
    
  }

switch () {
  case 0:
 
    lcd.setCursor(0,0);
    lcd.print(s2);
    
    lcd.setCursor(0,1);
    lcd.print(s1);
    
    total_duration = 0;
    total_ticks = 0;
    t = new_t + PERIOD;;
    } 
 
String format(unsigned int dec) {
  if (dec > 1000) return String("##.#");
  
  unsigned int intPart = dec / 10;
  unsigned int fracPart = dec % 10;
  String result = String(intPart, DEC) + "," + String(fracPart, DEC);

  int iters = 4 - result.length();  
  for(int i = 0; i < iters; ++i)
    result = " " + result; 
    }
  break;
 
  case 1:
 
    value=digitalRead(pin);  // проверка состояния кнопки для переключения экрана
    
    if ((value==LOW){
 
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print(spd);
    lcd.print(" km/h");
    lcd.setCursor(0,1);
    lcd.print("TEMP"); // Весь потраченный бензин
 
    }
 
 
    break;
}
 
  
  return result;
}

 

Vanya_87
Offline
Зарегистрирован: 31.03.2015

вот так переделал код, вылезла две ошибки!


#include <LiquidCrystal.h>

#define SPEED_PIN A6 // Номер ноги для датчика скорости
#define INJECTOR_PIN A7 // Номер ноги для форсунки
#define PERIOD 1000000 // Период усреднения текущего расхода и обновления дисплея (микросекунды) - пять секунд

#define IDLE_STROKE_DURATION 21000 // Суммарное время открытия форсунок (милисекунды) за период на холостом ходу
#define IDLE_STROKE_HOUR_CONSUMPTION 0.7 // Часовой расход топлива на холостом ходу (литры в час)
#define TEST_SPEED 60.0 // Контрольная скорость (километры в час) для расчёта коэффициента пробега
#define TEST_TICKS 84 // Число импульсов с датчика скорости за период на контрольной скорости

#define HOUR_PERIODS ( 3600000000.0 / PERIOD ) // Число периодов в часу
#define FUEL_FACTOR ( IDLE_STROKE_HOUR_CONSUMPTION / HOUR_PERIODS / IDLE_STROKE_DURATION ) // Коэффициент расхода топлива (литры) за период
#define RANGE_FACTOR ( TEST_SPEED / TEST_TICKS / HOUR_PERIODS ) // Коэффициент пробега (километры) за период
#define CONSUMPTION_FACTOR ( 100.0 * FUEL_FACTOR / RANGE_FACTOR ) // Коэффициент километрового расхода топлива (литры на 100 км)

#define TICKS_TRESHOLD 1 // Порог (импульсы датчика скорости) за период, выше которого можно считать километровый расход
#define DURATION_CORR 0 // Поправка при измерении длительности времени открытия одной форсунки (микросекунды)
#define AVG_LENGTH 10 // Число периодов для усреднения

#define AVG_REFRESH_TIME 1 // Время в часах, после которого сбрасывается усреднённый километровый расход, если не было сброса по расстоянию (1 час)
#define AVG_REFRESH_LENGTH 0.1 // Расстояние в километрах, после которого сбрасывается усреднённый километровый расход (100 м)
#define AVG_REFRESH_PERIODS ( AVG_REFRESH_TIME * HOUR_PERIODS ) // Число периодов между обновлениями среднего расхода
#define AVG_REFRESH_TICKS ( AVG_REFRESH_LENGTH / RANGE_FACTOR ) // Число импульсов датчика скорости между обновлениями среднего расхода

// Строковые константы
#define STR_AVG String(" Cp:")
#define STR_CUR String("Mgn:")
#define STR_NA String(" \xBD/\xE3")
#define STR_KMH String("\xBA\xBC/\xC0")

LiquidCrystal lcd(12, 10, 5, 4, 3, 2);

int count_display=2; // Количество экранов бк
int pin=9;  // пины кнопок

 value=digitalRead(pin);  // проверка состояния кнопки для переключения экрана    вот здесь ошибка
  if (value==LOW) { и вот тут ошибка
    if (selmon==count_display-2) {
      lcd.clear();
      selmon=0;
    }  
    else {
      lcd.clear();                                                                                                                
      selmon++;  
    }
    tone(13, 3000, 100);
    delay(150);
  }

unsigned long dur;
unsigned long dur_t;
unsigned long t;

boolean last_injector_state;
boolean last_speed_state;

unsigned long total_duration;
unsigned long total_ticks;
unsigned long total_avg_duration;
unsigned long total_avg_ticks;
unsigned long d_avg_duration;
unsigned long d_avg_ticks;
int period_counter;
// int period_counter2;


// Структура, описывающая данные для усреднения
struct consumption_data {
  unsigned int duration;
  word ticks; 
};

struct consumption_data data[AVG_LENGTH];
int avg_counter;

void setup() {
  // Serial.begin(9600);
  lcd.begin(8, 2);
  t = micros() + PERIOD;
  pinMode(INJECTOR_PIN, INPUT);
  pinMode(SPEED_PIN, INPUT);
  last_injector_state = analogRead(INJECTOR_PIN) > 500;
  last_speed_state = analogRead(SPEED_PIN) > 500;
  
  dur = 0;
  dur_t = micros();
  total_duration = 0;
  total_ticks = 0;
  total_avg_duration = total_duration;
  total_avg_ticks = total_ticks;
  d_avg_duration = total_duration;
  d_avg_ticks = total_ticks;
  
  // Инициализация данных для усреднения
  for (int i=0; i < AVG_LENGTH; ++i) {
    data[i].duration = 0;
    data[i].ticks = 0;
  }
  
  period_counter = 0;
//  period_counter2 = 0;
  avg_counter = 0;
}

void loop() {
  boolean injector_state = analogRead(INJECTOR_PIN) > 500;
  boolean speed_state = analogRead(SPEED_PIN) > 500;
  unsigned long new_t = micros();
  
  // Вычисление мгновенных значений
  
  if (injector_state != last_injector_state) {
    if (injector_state) {
      dur = new_t - dur_t;
      if (dur) dur += DURATION_CORR; // Поправочка
      total_duration += dur;
    } else {
      dur_t = new_t;
      dur = 0;
    }
    
    last_injector_state = injector_state;
  }
  
  if (speed_state != last_speed_state) {
    total_ticks++;
    
    last_speed_state = speed_state;
  }
  
  // Действия, которые выполняются раз в секунду
  
  if (new_t >= t) {
    if (!dur) {
      dur = new_t - dur_t;
      if (dur) dur += DURATION_CORR; // Поправочка
      total_duration += dur;
    }
    
    // Отладочная установка значений
    
//    if (period_counter2 < AVG_LENGTH * AVG_REFRESH_PERIODS) {
//      total_duration = 100000;
//      total_ticks = 56;
//    } else if (period_counter2 < 2 * AVG_LENGTH * AVG_REFRESH_PERIODS) {
//      total_duration = 20000;
//      total_ticks = 1;
//    } else {
//      total_duration = 100000;
//      total_ticks = 56;
//    }
    
    d_avg_duration += total_duration;
    d_avg_ticks += total_ticks;
    
    ++period_counter;
//    ++period_counter2;
    
    if (d_avg_ticks >= AVG_REFRESH_TICKS || period_counter >= AVG_REFRESH_PERIODS) {
      // Вычисление средних значений
      
      // total_avg_duration += d_avg_duration - data[avg_counter].duration;
      /// total_avg_ticks += d_avg_ticks - data[avg_counter].ticks;
      
      data[avg_counter].duration = d_avg_duration;
      data[avg_counter].ticks = d_avg_ticks;

      total_avg_duration = 0;
      total_avg_ticks = 0;
      
      for (int i=0; i < AVG_LENGTH; i++) {
        total_avg_duration += data[i].duration;
        total_avg_ticks += data[i].ticks;
      }
      
      period_counter = 0;
      d_avg_duration = 0;
      d_avg_ticks = 0;

      ++avg_counter;
      if (avg_counter >= AVG_LENGTH)
        avg_counter = 0;
    }
    
    // Конвертация значений в физические единицы и вывод на экран

    String s1, s2, s3;
    unsigned int consumption = 0;
    unsigned int avg_consumption = 0;
    
    if (total_ticks > TICKS_TRESHOLD) {
      consumption = 10.0 * CONSUMPTION_FACTOR * total_duration / total_ticks;
    }

    if (total_avg_ticks > TICKS_TRESHOLD) {
      avg_consumption = 10.0 * CONSUMPTION_FACTOR * total_avg_duration / total_avg_ticks;
    }
    
    unsigned int hour_consumption = 10.0 * FUEL_FACTOR * total_duration * HOUR_PERIODS;
    unsigned int spd = RANGE_FACTOR * total_ticks * HOUR_PERIODS;
    
    s1 = String(total_duration, DEC);

    if (total_ticks > TICKS_TRESHOLD) {
      s1 = STR_CUR + format(consumption);
      // s1 = format(consumption);
    } else {
      s1 = STR_CUR + STR_NA;
      // s1 = "n/a ";
    }

    if (total_avg_ticks > TICKS_TRESHOLD) {
      s2 = STR_AVG + format(avg_consumption);
      // s2 = format(avg_consumption);
    } else {
      s2 = STR_AVG + STR_NA;
      // s2 = "n/a ";
    }

    // s2 = "hr: " + format(hour_consumption);
    // s2 = format(hour_consumption);
    
    // s3 = "sp: " + String(spd, DEC);
    // s3 = String(spd, DEC);
    // s3 = String(total_ticks, DEC);
    
    // int iters = 3 - s3.length();
    // int iters = 8 - s3.length();
    
    // for(int i = 0; i < iters; ++i)
    //  s3 = " " + s3;
      
    // int iters2 = 8 - s1.length();
    
    // for(int i = 0; i < iters2; ++i)
    //  s1 = " " + s1;
    
    // s3 += STR_KMH;
    
  }

switch (selmon) {
  case 0:
 
    lcd.setCursor(0,0);
    lcd.print(s2);
    
    lcd.setCursor(0,1);
    lcd.print(s1);
    
    total_duration = 0;
    total_ticks = 0;
    t = new_t + PERIOD;;
    } 
 
String format(unsigned int dec) {
  if (dec > 1000) return String("##.#");
  
  unsigned int intPart = dec / 10;
  unsigned int fracPart = dec % 10;
  String result = String(intPart, DEC) + "," + String(fracPart, DEC);

  int iters = 4 - result.length();  
  for(int i = 0; i < iters; ++i)
    result = " " + result; 
    }
  break;
 
  case 1:
 
    value=digitalRead(pin);  // проверка состояния кнопки для переключения экрана
    
    if ((value==LOW){
 
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print(spd);
    lcd.print(" km/h");
    lcd.setCursor(0,1);
    lcd.print("TEMP"); 
 
    }
 
 
    break;
}
 
  
  return result;
}
Vanya_87
Offline
Зарегистрирован: 31.03.2015

вот ошибки в предущем коде-сообщении:

sketch_apr02a:37: error: expected constructor, destructor, or type conversion before '=' token
sketch_apr02a:38: error: expected unqualified-id before 'if'
Vittorio
Offline
Зарегистрирован: 02.02.2015

у тебя переменная value не объявлена нигде.

Вставь строку 36: byte value;

stakan1986
Offline
Зарегистрирован: 17.02.2015

ага и весь код с 37 по 49 строку непонятно в чем находится, то ли функция то ли видение.
Уважаемый Vanya_87 ну изучите Вы матчасть потом пытайтесь что-то делать, а по принципу нафигачу чего нить и найду дурака который из этого конфетку сделает...

X-Dron
Offline
Зарегистрирован: 24.01.2015

stakan1986

+1000 :)

Vanya_87
Offline
Зарегистрирован: 31.03.2015

не ищу я дурака, просто прошу помощи у знающих людей.

вот поискал в инете, нашёл скетч где все описано по каждой строчке, кстате на этом же форуме))) переделал свой код, ошибок нет, но при загрузки кода пустой экран.

вот код:


#include <LiquidCrystal.h>

#define SPEED_PIN A6 // Номер ноги для датчика скорости
#define INJECTOR_PIN A7 // Номер ноги для форсунки
#define PERIOD 1000000 // Период усреднения текущего расхода и обновления дисплея (микросекунды) - пять секунд

#define IDLE_STROKE_DURATION 21000 // Суммарное время открытия форсунок (милисекунды) за период на холостом ходу
#define IDLE_STROKE_HOUR_CONSUMPTION 1.2 // Часовой расход топлива на холостом ходу (литры в час)
#define TEST_SPEED 60.0 // Контрольная скорость (километры в час) для расчёта коэффициента пробега
#define TEST_TICKS 74 // Число импульсов с датчика скорости за период на контрольной скорости

#define HOUR_PERIODS ( 3600000000.0 / PERIOD ) // Число периодов в часу
#define FUEL_FACTOR ( IDLE_STROKE_HOUR_CONSUMPTION / HOUR_PERIODS / IDLE_STROKE_DURATION ) // Коэффициент расхода топлива (литры) за период
#define RANGE_FACTOR ( TEST_SPEED / TEST_TICKS / HOUR_PERIODS ) // Коэффициент пробега (километры) за период
#define CONSUMPTION_FACTOR ( 100.0 * FUEL_FACTOR / RANGE_FACTOR ) // Коэффициент километрового расхода топлива (литры на 100 км)

#define TICKS_TRESHOLD 1 // Порог (импульсы датчика скорости) за период, выше которого можно считать километровый расход
#define DURATION_CORR 0 // Поправка при измерении длительности времени открытия одной форсунки (микросекунды)
#define AVG_LENGTH 10 // Число периодов для усреднения

#define AVG_REFRESH_TIME 1 // Время в часах, после которого сбрасывается усреднённый километровый расход, если не было сброса по расстоянию (1 час)
#define AVG_REFRESH_LENGTH 0.1 // Расстояние в километрах, после которого сбрасывается усреднённый километровый расход (100 м)
#define AVG_REFRESH_PERIODS ( AVG_REFRESH_TIME * HOUR_PERIODS ) // Число периодов между обновлениями среднего расхода
#define AVG_REFRESH_TICKS ( AVG_REFRESH_LENGTH / RANGE_FACTOR ) // Число импульсов датчика скорости между обновлениями среднего расхода

// Строковые константы
#define STR_AVG String(" Cp:")
#define STR_CUR String("Mgn:")
#define STR_NA String(" \xBD/\xE3")
#define STR_KMH String("\xBA\xBC/\xC0")

LiquidCrystal lcd(12, 10, 5, 4, 3, 2);

unsigned long dur;
unsigned long dur_t;
unsigned long t;

boolean last_injector_state;
boolean last_speed_state;

unsigned long total_duration;
unsigned long total_ticks;
unsigned long total_avg_duration;
unsigned long total_avg_ticks;
unsigned long d_avg_duration;
unsigned long d_avg_ticks;
int period_counter;
// int period_counter2;

// Структура, описывающая данные для усреднения
struct consumption_data {
  unsigned int duration;
  word ticks; 
};

struct consumption_data data[AVG_LENGTH];
int avg_counter;

void setup() {
  // Serial.begin(9600);
  lcd.begin(8, 2);
  t = micros() + PERIOD;
  pinMode(INJECTOR_PIN, INPUT);
  pinMode(SPEED_PIN, INPUT);
  last_injector_state = analogRead(INJECTOR_PIN) > 500;
  last_speed_state = analogRead(SPEED_PIN) > 500;
  
  dur = 0;
  dur_t = micros();
  total_duration = 0;
  total_ticks = 0;
  total_avg_duration = total_duration;
  total_avg_ticks = total_ticks;
  d_avg_duration = total_duration;
  d_avg_ticks = total_ticks;

  
  // Инициализация данных для усреднения
  for (int i=0; i < AVG_LENGTH; ++i) {
    data[i].duration = 0;
    data[i].ticks = 0;
  }
  
  period_counter = 0;
//  period_counter2 = 0;
  avg_counter = 0;
}

void loop() {
  boolean injector_state = analogRead(INJECTOR_PIN) > 500;
  boolean speed_state = analogRead(SPEED_PIN) > 500;
  unsigned long new_t = micros();
  
  // Вычисление мгновенных значений
  
  if (injector_state != last_injector_state) {
    if (injector_state) {
      dur = new_t - dur_t;
      if (dur) dur += DURATION_CORR; // Поправочка
      total_duration += dur;
    } else {
      dur_t = new_t;
      dur = 0;
    }
    
    last_injector_state = injector_state;
  }
  
  if (speed_state != last_speed_state) {
    total_ticks++;
    
    last_speed_state = speed_state;
  }
  
  // Действия, которые выполняются раз в секунду
  
  if (new_t >= t) {
    if (!dur) {
      dur = new_t - dur_t;
      if (dur) dur += DURATION_CORR; // Поправочка
      total_duration += dur;
    }
    
    // Отладочная установка значений
    
//    if (period_counter2 < AVG_LENGTH * AVG_REFRESH_PERIODS) {
//      total_duration = 100000;
//      total_ticks = 56;
//    } else if (period_counter2 < 2 * AVG_LENGTH * AVG_REFRESH_PERIODS) {
//      total_duration = 20000;
//      total_ticks = 1;
//    } else {
//      total_duration = 100000;
//      total_ticks = 56;
//    }
    
    d_avg_duration += total_duration;
    d_avg_ticks += total_ticks;
    
    ++period_counter;
//    ++period_counter2;
    
    if (d_avg_ticks >= AVG_REFRESH_TICKS || period_counter >= AVG_REFRESH_PERIODS) {
      // Вычисление средних значений
      
      // total_avg_duration += d_avg_duration - data[avg_counter].duration;
      /// total_avg_ticks += d_avg_ticks - data[avg_counter].ticks;
      
      data[avg_counter].duration = d_avg_duration;
      data[avg_counter].ticks = d_avg_ticks;

      total_avg_duration = 0;
      total_avg_ticks = 0;
      
      for (int i=0; i < AVG_LENGTH; i++) {
        total_avg_duration += data[i].duration;
        total_avg_ticks += data[i].ticks;
      }
      
      period_counter = 0;
      d_avg_duration = 0;
      d_avg_ticks = 0;

      ++avg_counter;
      if (avg_counter >= AVG_LENGTH)
        avg_counter = 0;
    }
    
    // Конвертация значений в физические единицы и вывод на экран

    String s1, s2, s3;
    unsigned int consumption = 0;
    unsigned int avg_consumption = 0;
    
    if (total_ticks > TICKS_TRESHOLD) {
      consumption = 10.0 * CONSUMPTION_FACTOR * total_duration / total_ticks;
    }

    if (total_avg_ticks > TICKS_TRESHOLD) {
      avg_consumption = 10.0 * CONSUMPTION_FACTOR * total_avg_duration / total_avg_ticks;
    }
    
    unsigned int hour_consumption = 10.0 * FUEL_FACTOR * total_duration * HOUR_PERIODS;
    unsigned int spd = RANGE_FACTOR * total_ticks * HOUR_PERIODS;
    
    s1 = String(total_duration, DEC);

    if (total_ticks > TICKS_TRESHOLD) {
      s1 = STR_CUR + format(consumption);
      // s1 = format(consumption);
    } else {
      s1 = STR_CUR + STR_NA;
      // s1 = "n/a ";
    }

    if (total_avg_ticks > TICKS_TRESHOLD) {
      s2 = STR_AVG + format(avg_consumption);
      // s2 = format(avg_consumption);
    } else {
      s2 = STR_AVG + STR_NA;
      // s2 = "n/a ";
    }

    // s2 = "hr: " + format(hour_consumption);
    // s2 = format(hour_consumption);
    
    // s3 = "sp: " + String(spd, DEC);
    // s3 = String(spd, DEC);
    // s3 = String(total_ticks, DEC);
    
    // int iters = 3 - s3.length();
    // int iters = 8 - s3.length();
    
    // for(int i = 0; i < iters; ++i)
    //  s3 = " " + s3;
      
    // int iters2 = 8 - s1.length();
    
    // for(int i = 0; i < iters2; ++i)
    //  s1 = " " + s1;
    
    // s3 += STR_KMH;
    
    total_duration = 0;
    total_ticks = 0;
    t = new_t + PERIOD;
  }
}
byte s1;
byte s2;
byte KMH;
byte TEMP;

String format(unsigned int dec) {
  if (dec > 1000) return String("##.#");
  
  unsigned int intPart = dec / 10;
  unsigned int fracPart = dec % 10;
  String result = String(intPart, DEC) + "," + String(fracPart, DEC);

  int iters = 4 - result.length();  
  for(int i = 0; i < iters; ++i)
    result = " " + result;

  return result;
}

byte digitalPin = 9;            // пин входа кнопок
int val;                    // знач. АЦП при нажатой кнопке
byte butPush = 0;           // код нажатой кнопки
boolean butRel=1;           // отпущена ли сейчас кнопка
int butval[8]={0,255,251,228,136,29,0,0};   // АЦП кнопок
byte butsens=20;            // чувствительность кнопок
byte menu=0;                // переменная хранящая номер текущего экрана

int button () {                // подпрограмма считывания кнопок
    int exitMenu = 1;          // если exitMenu истина то выходим из меню
    butPush = 0;               // код нажатой кнопки
    delay(15);     // задержка для устранения дребезга контактов
    val = digitalRead(digitalPin); // читаем АЦП порта кнопок (значение от 0 до 1023)
    if (val > (butval[3]-butsens) && val < (butval[3]+butsens)) {butPush = 3;}  // если считанное значение около (на величину butsens)
    // значения соответствующего кнопке 3 то считаем что она и нажата
    
    butRel=0;                  // эта переменная нужна для проверки в главной программе
    return butPush;            // возвращаем значение нажатой кнопки
}


void Menu(int butPush) {           // Функция показа меню
     lcd.clear();                  // очищаем дисплей
     switch (menu) {               // оператор switch переключает на нужную секцию в зависимости от значения menu
      case 0:                      // показываем все температуры      
     lcd.setCursor(0,0);
     lcd.print("s2");
     lcd.setCursor(0,1);
     lcd.print("s1");
        if (butPush == 3) {menu++; Menu(0);}  // если нажата кнопка вниз - идем к следующему экрану. Далее эти кнопки не комментирую
      break;

      case 1: // меню настроек
        lcd.setCursor(0,0);
        lcd.print("KMH");
        lcd.setCursor(0,1);
        lcd.print("TEMP");
     if (butPush == 3) {menu=0; Menu(0);}  // если нажать "ОК" в этом экране то пойдем к меню номер 0
        
      break; 
    }
}

что у меня прописано не правильно?

stakan1986
Offline
Зарегистрирован: 17.02.2015

строка 256 - если "подпрограмма" то по идее должна начинаться void а не int.

строка 260 - digitalRead выдаст вам только 2 значения - 0 и 1. но не тот непонятный набор который забит в butval

я может конечно чего-то не замечаю, но где Вы хоть что-то выводите на экран, чтоб хотеть что-то увидеть. Если бы вы как раз таки изучали матчасть то узнали бы что void setup выполняется при старте, а далее void loop выполняется по кругу, и чтобы запустить функцию void Menu в которой у Вас что то выводится на экран надо к ней обратиться внутри loop, аналогично и для других функций. Они вспомогательные и просто так - потому что есть в вашем коде - не запускаются.

Vanya_87
Offline
Зарегистрирован: 31.03.2015

stakan1986 пишет:

строка 256 - если "подпрограмма" то по идее должна начинаться void а не int.

строка 260 - digitalRead выдаст вам только 2 значения - 0 и 1. но не тот непонятный набор который забит в butval

я может конечно чего-то не замечаю, но где Вы хоть что-то выводите на экран, чтоб хотеть что-то увидеть. Если бы вы как раз таки изучали матчасть то узнали бы что void setup выполняется при старте, а далее void loop выполняется по кругу, и чтобы запустить функцию void Menu в которой у Вас что то выводится на экран надо к ней обратиться внутри loop, аналогично и для других функций. Они вспомогательные и просто так - потому что есть в вашем коде - не запускаются.

я впринципе это понял, на счет void setup и void loop)) 

с 272 строки на экран вывод - я так думал)))

X-Dron
Offline
Зарегистрирован: 24.01.2015

Народ, вы вообще где язык учили?
256 - 266 это описание функции, которая обрабатывает клавиши, подключенные через делители напряжения на аналоговый вход. Функция возвращает целочисленное значение нажатой клавиши. (return butPush;) Но почему считывание считывание делается как digitalRead, а не analogRead(), да еще и подключено на 9-й пин - для меня вообще не понятно. butPush объявлена как глобальная, а ее пытаются выводить как значение функции - бардак. В этом смысле соглашусь, что button () нет никакого смысла возвращать значение. Функция должна быть void. 

Если у вас делитель для кнопок не соответствует оригинальному - кнопки работать не будут. С какой стати что-то должно показываться, если функция Menu(int) ниоткуда(кроме самой себя не вызывается). Надо 10 раз подумать прежде чем использовать рекурсию.

Вообще в коде полный бардак.

Vanya_87
Offline
Зарегистрирован: 31.03.2015

вот подправил код. брал из примера ардуины и "программирования" этого сайта. у меня два вопроса по коду: в 249 строке какая команда выводит на экран следующий Case в Switch-е и в 251 строке какая команда останавливает эти самые casы при отпущенной кнопки?? я нашёл что останавливает только break, но она у меня в case, или можно вообще строки с 249-251 удалить?

и ещё можете посмотреть 60 строку - правильно там "int" или нужна какая то другая команда??


#include <LiquidCrystal.h>

#define SPEED_PIN A6 // Номер ноги для датчика скорости
#define INJECTOR_PIN A7 // Номер ноги для форсунки
#define PERIOD 1000000 // Период усреднения текущего расхода и обновления дисплея (микросекунды) - пять секунд

#define IDLE_STROKE_DURATION 21000 // Суммарное время открытия форсунок (милисекунды) за период на холостом ходу
#define IDLE_STROKE_HOUR_CONSUMPTION 1.2 // Часовой расход топлива на холостом ходу (литры в час)
#define TEST_SPEED 60.0 // Контрольная скорость (километры в час) для расчёта коэффициента пробега
#define TEST_TICKS 74 // Число импульсов с датчика скорости за период на контрольной скорости

#define HOUR_PERIODS ( 3600000000.0 / PERIOD ) // Число периодов в часу
#define FUEL_FACTOR ( IDLE_STROKE_HOUR_CONSUMPTION / HOUR_PERIODS / IDLE_STROKE_DURATION ) // Коэффициент расхода топлива (литры) за период
#define RANGE_FACTOR ( TEST_SPEED / TEST_TICKS / HOUR_PERIODS ) // Коэффициент пробега (километры) за период
#define CONSUMPTION_FACTOR ( 100.0 * FUEL_FACTOR / RANGE_FACTOR ) // Коэффициент километрового расхода топлива (литры на 100 км)

#define TICKS_TRESHOLD 1 // Порог (импульсы датчика скорости) за период, выше которого можно считать километровый расход
#define DURATION_CORR 0 // Поправка при измерении длительности времени открытия одной форсунки (микросекунды)
#define AVG_LENGTH 10 // Число периодов для усреднения

#define AVG_REFRESH_TIME 1 // Время в часах, после которого сбрасывается усреднённый километровый расход, если не было сброса по расстоянию (1 час)
#define AVG_REFRESH_LENGTH 0.1 // Расстояние в километрах, после которого сбрасывается усреднённый километровый расход (100 м)
#define AVG_REFRESH_PERIODS ( AVG_REFRESH_TIME * HOUR_PERIODS ) // Число периодов между обновлениями среднего расхода
#define AVG_REFRESH_TICKS ( AVG_REFRESH_LENGTH / RANGE_FACTOR ) // Число импульсов датчика скорости между обновлениями среднего расхода

// Строковые константы
#define STR_AVG String(" Cp:")
#define STR_CUR String("Mgn:")
#define STR_NA String(" \xBD/\xE3")
#define STR_KMH String("\xBA\xBC/\xC0")

LiquidCrystal lcd(12, 10, 5, 4, 3, 2);

unsigned long dur;
unsigned long dur_t;
unsigned long t;

boolean last_injector_state;
boolean last_speed_state;

unsigned long total_duration;
unsigned long total_ticks;
unsigned long total_avg_duration;
unsigned long total_avg_ticks;
unsigned long d_avg_duration;
unsigned long d_avg_ticks;
int period_counter;
// int period_counter2;

// Структура, описывающая данные для усреднения
struct consumption_data {
  unsigned int duration;
  word ticks; 
};

struct consumption_data data[AVG_LENGTH];
int avg_counter;
const int buttonPin = 5;
int buttonState = 0;
int disp = 1;

void setup() {
  // Serial.begin(9600);
  lcd.begin(8, 2);
  t = micros() + PERIOD;
  pinMode(INJECTOR_PIN, INPUT);
  pinMode(SPEED_PIN, INPUT);
  pinMode(buttonPin, INPUT);
  last_injector_state = analogRead(INJECTOR_PIN) > 500;
  last_speed_state = analogRead(SPEED_PIN) > 500;
  
  dur = 0;
  dur_t = micros();
  total_duration = 0;
  total_ticks = 0;
  total_avg_duration = total_duration;
  total_avg_ticks = total_ticks;
  d_avg_duration = total_duration;
  d_avg_ticks = total_ticks;
  
  // Инициализация данных для усреднения
  for (int i=0; i < AVG_LENGTH; ++i) {
    data[i].duration = 0;
    data[i].ticks = 0;
  }
  
  period_counter = 0;
//  period_counter2 = 0;
  avg_counter = 0;
}

void loop() {
  buttonState = digitalRead(buttonPin);
  
  boolean injector_state = analogRead(INJECTOR_PIN) > 500;
  boolean speed_state = analogRead(SPEED_PIN) > 500;
  unsigned long new_t = micros();
  
  // Вычисление мгновенных значений
  
  if (injector_state != last_injector_state) {
    if (injector_state) {
      dur = new_t - dur_t;
      if (dur) dur += DURATION_CORR; // Поправочка
      total_duration += dur;
    } else {
      dur_t = new_t;
      dur = 0;
    }
    
    last_injector_state = injector_state;
  }
  
  if (speed_state != last_speed_state) {
    total_ticks++;
    
    last_speed_state = speed_state;
  }
  
  // Действия, которые выполняются раз в секунду
  
  if (new_t >= t) {
    if (!dur) {
      dur = new_t - dur_t;
      if (dur) dur += DURATION_CORR; // Поправочка
      total_duration += dur;
    }
    
    // Отладочная установка значений
    
//    if (period_counter2 < AVG_LENGTH * AVG_REFRESH_PERIODS) {
//      total_duration = 100000;
//      total_ticks = 56;
//    } else if (period_counter2 < 2 * AVG_LENGTH * AVG_REFRESH_PERIODS) {
//      total_duration = 20000;
//      total_ticks = 1;
//    } else {
//      total_duration = 100000;
//      total_ticks = 56;
//    }
    
    d_avg_duration += total_duration;
    d_avg_ticks += total_ticks;
    
    ++period_counter;
//    ++period_counter2;
    
    if (d_avg_ticks >= AVG_REFRESH_TICKS || period_counter >= AVG_REFRESH_PERIODS) {
      // Вычисление средних значений
      
      // total_avg_duration += d_avg_duration - data[avg_counter].duration;
      /// total_avg_ticks += d_avg_ticks - data[avg_counter].ticks;
      
      data[avg_counter].duration = d_avg_duration;
      data[avg_counter].ticks = d_avg_ticks;

      total_avg_duration = 0;
      total_avg_ticks = 0;
      
      for (int i=0; i < AVG_LENGTH; i++) {
        total_avg_duration += data[i].duration;
        total_avg_ticks += data[i].ticks;
      }
      
      period_counter = 0;
      d_avg_duration = 0;
      d_avg_ticks = 0;

      ++avg_counter;
      if (avg_counter >= AVG_LENGTH)
        avg_counter = 0;
    }
    
    // Конвертация значений в физические единицы и вывод на экран

    String s1, s2, s3;
    unsigned int consumption = 0;
    unsigned int avg_consumption = 0;
    
    if (total_ticks > TICKS_TRESHOLD) {
      consumption = 10.0 * CONSUMPTION_FACTOR * total_duration / total_ticks;
    }

    if (total_avg_ticks > TICKS_TRESHOLD) {
      avg_consumption = 10.0 * CONSUMPTION_FACTOR * total_avg_duration / total_avg_ticks;
    }
    
    unsigned int hour_consumption = 10.0 * FUEL_FACTOR * total_duration * HOUR_PERIODS;
    unsigned int spd = RANGE_FACTOR * total_ticks * HOUR_PERIODS;
    
    s1 = String(total_duration, DEC);

    if (total_ticks > TICKS_TRESHOLD) {
      s1 = STR_CUR + format(consumption);
      // s1 = format(consumption);
    } else {
      s1 = STR_CUR + STR_NA;
      // s1 = "n/a ";
    }

    if (total_avg_ticks > TICKS_TRESHOLD) {
      s2 = STR_AVG + format(avg_consumption);
      // s2 = format(avg_consumption);
    } else {
      s2 = STR_AVG + STR_NA;
      // s2 = "n/a ";
    }

    // s2 = "hr: " + format(hour_consumption);
    // s2 = format(hour_consumption);
    
    // s3 = "sp: " + String(spd, DEC);
    // s3 = String(spd, DEC);
    // s3 = String(total_ticks, DEC);
    
    // int iters = 3 - s3.length();
    // int iters = 8 - s3.length();
    
    // for(int i = 0; i < iters; ++i)
    //  s3 = " " + s3;
      
    // int iters2 = 8 - s1.length();
    
    // for(int i = 0; i < iters2; ++i)
    //  s1 = " " + s1;
    
    // s3 += STR_KMH;
 total_duration = 0;
    total_ticks = 0;
    t = new_t + PERIOD;
  
 
 switch (disp) {
   case 1:
    lcd.setCursor(0,0);
    lcd.print(s2);
    
    lcd.setCursor(0,1);
    lcd.print(s1);
    break;
    
    case 2:
    lcd.setCursor(0,0);
    lcd.print("privet");
    break;  
 }}
  if (buttonState == HIGH) {
  ?????????(disp++)};
 else {
    ?????????(disp); 
  } 
  
}

String format(unsigned int dec) {
  if (dec > 1000) return String("##.#");
  
  unsigned int intPart = dec / 10;
  unsigned int fracPart = dec % 10;
  String result = String(intPart, DEC) + "," + String(fracPart, DEC);

  int iters = 4 - result.length();  
  for(int i = 0; i < iters; ++i)
    result = " " + result;

  return result;
}
stakan1986
Offline
Зарегистрирован: 17.02.2015

246 строка - зачем2 скобки

команда switch (disp) берет значение переменной disp и сравнивает с вариантами перечисленными в case -соответственно 1 или 2, если совпадает то выполняет весь код до брэйка. то есть если disp = 1 то выполняет 235-239 строки и переходит к 247, а вот что там написано не понятно совсем - поясните. 

И все таки никак не допру что и для чего делается в строках 255-267

Vanya_87
Offline
Зарегистрирован: 31.03.2015

stakan1986 пишет:

246 строка - зачем2 скобки

команда switch (disp) берет значение переменной disp и сравнивает с вариантами перечисленными в case -соответственно 1 или 2, если совпадает то выполняет весь код до брэйка. то есть если disp = 1 то выполняет 235-239 строки и переходит к 247, а вот что там написано не понятно совсем - поясните. 

И все таки никак не допру что и для чего делается в строках 255-267

 

246 строка - одна закрывает switch (disp) а вторая закрывает "if (new_t >= t)"- 122 строка

247 строка - я так понимаю действия которые происходят по нажатию кнопки и отпусканию её. если это так, а это должно быть так(взято с примера проги ардуины 1,0,5-r2 установленной у меня на компе), то нужно указать что бы при нажатии кнопки у меня переключилось на case 2 и потом обратно, своего рода счетчик что бы был не прерывный между 1 и 2 casом и соответсвенно выводом на экран инфы.

а в строках 255-267 я так понимаю что то типо вывода значений на дисплее если значение больше 1000 то вместо того значения выводятся решетки и ещё что то делается, ссылается оно на строку 195 и 203 там "format". код не я писал я только пытаюсь его дополнить что бы у меня кнопкой менялись экраны. 

 

кстати загрузил код без 247-251 строки - на дисплее вышел сразу case 1, при чем рабочий, т.е. значения считаются))) а case 2 не могу включить, т.к. не прописано программно условия после нажатия кнопки 

 

 

Vanya_87
Offline
Зарегистрирован: 31.03.2015

всё, разобрался я со счетчиком. меняется 3 экрана(сделал 3) и по кругу, вообщем то что и хотел)))

кнопку подключил на 9 пин цифрового выхода. только при нажатии на кнопку экраны скачат друг за другом а потом останавливаются - это наверное потому что у меня подключение без всяких резисторов, подключил на GND(землю) и D9, я прав?

правда когда вкл. "Подтягивающий (нагрузочный) резистор" - digitalWrite(9,HIGH);- вставляю на 69 строчку и if(digitalRead(9)==LOW) - на 256 строчку вместо моего if ничего не происходит, наоборот кнопка отказывается менять экраны. 

если что, вот ссылка на работу с кнопками и подключения их к цифровому входу (16 пост):

http://arduino.ru/forum/programmirovanie/rabota-s-knopkami-v-pomoshch-novichku

stakan1986
Offline
Зарегистрирован: 17.02.2015

экраны скачут из-за так называемого "дребезга" контактов кнопки - с ним можно бороться программно или аппаратно. Погуглите

А почему  не работает хз. Но если работает один вариант зачем биться над другим. Дребезг он будет в любом случае и с ним придется бороться

Vanya_87
Offline
Зарегистрирован: 31.03.2015

избавился я от дребезга. с кнопкой проблем нет, работает как часы.

 

stakan1986
Offline
Зарегистрирован: 17.02.2015

дайте хоть на ваш код посмотреть

а вообще - переменную disp при нажатии кнопки увеличивать на единицу с проверкой: если disp==2 то disp =0 иначе disp++

Vanya_87
Offline
Зарегистрирован: 31.03.2015

сообщение на изменении висело, а на него уже ответили)))

у меня два варианта кода. один как у автора - минус в том что долго всё обрабатывается и бешеные значения выводятся на экран в машине. второй вариант пока не проверял, щас загружу его в друину и как проверю потом скажу)))

Vanya_87
Offline
Зарегистрирован: 31.03.2015

всё сделал. вместо delay которая тормозила всю программу ввел millis. вот такой вот вариант кода:

if (millis() - previousMillis > 300) {
     //Запоминаем время первого срабатывания
     previousMillis = millis();
  if (buttonState == 0)
     {disp++;}}
 else if (disp > 3)
    {disp = 1;}
300 мс - потому что у меня большая кнопка, она будет у меня выведена на панель)))
 
Вообще код перебрал и сделал вариант как у автора, а точнее подсказавший ему вариант))):
swich(счетчик) 
{
case 1 : {firstcode(); break}
case 2 : {secondcode(); break}
case 3 : {thirdcode(); break}
}
}
потом 3 своих функций
int firstcode ()
{
...
}
...
вообщем всем откликнувшимся большое спасибо!!!
Denisich2012
Offline
Зарегистрирован: 19.02.2017

Здравствуйте знатоки Ардуино, хотел бы тоже попросить помощи т.к. у самого уже мозги закипают. Итак есть два скейтча:

1. Авто подсос на карбюраторную машину, контроль через датчик хола и термометр, управление через сервопривод, вывод на OLED экран.

2. Ручное управление через энкодер.

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

Скейтч №1.

#include <Wire.h>        // подключение библиотеки для ds18b20
#include <OneWire.h>
//DS18b20
OneWire ds(10);   //подключаем датчик ds18b20 к 10 цифровому входу
#include <OLED_I2C.h>
OLED  myOLED(8, 9, 8); // 8pin - SDA , 9pin - SCL
extern uint8_t RusFont[]; // Русский шрифт
extern uint8_t MegaNumbers[]; // Подключение больших шрифтов
extern uint8_t SmallFont[]; // Базовый шрифт без поддержки русскийх символов.
#include <Servo.h>      //подключение библиотеки для сервопривода
Servo servo;
int potPin = 2; // Порт для провода от датчика холла
int now = 0;// последнее значение сигнала с датчика
long time = 0; // для сохранения времени начала счета импульсов
int count = 0; // колличество импльсов
int val; //временная переменная для считывания сигнала с датчика
bool LampState4 = false;
int flg_push; //флаг прихода импульса
float Temp;
float volts;
int i;
int n;
int analogPin = A0;// порт потенциометра сервопривода
#define LCD_UPDATE_TIME  1000
unsigned long lcdLastUpdateTime = 0;
long updtime = 0;

void setup()
{
  Wire.begin();
  servo.attach(11,130,175);   //подключаем сервопривод к 11 цифровому порту
  myOLED.begin();

}

void loop()
{
  setTemperature(); // вызываем функцию работы с DS18b20
  setOboroti();
}
int setTemperature() // DS18B20
{ byte type_s;
  type_s = 0;
  byte data[2];
  ds.reset();
  ds.write(0xCC);
  ds.write(0x44);

  // обращаемся к датчикам раз в 1000 мс, т.к. 750 может быть недостаточно
  if (millis() - lcdLastUpdateTime > LCD_UPDATE_TIME)
  { lcdLastUpdateTime = millis();

    ds.reset();
    ds.write(0xCC);
    ds.write(0xBE);
    data[0] = ds.read();
    data[1] = ds.read();
    Temp = (data[1] << 8) + data[0];
    Temp = (float)Temp / 16.0;;
  int rawReading = analogRead(analogPin);
float volts = (rawReading-360.0)/106*100;
    // Температура
    
  myOLED.clrScr(); // очищаем экран
  myOLED.setFont(RusFont); // Устанавливаем русский шрифт
  myOLED.print("NTVGTHFNEHF", LEFT, 0); // Выводим надпись "Температура"
  myOLED.print("GJLCJC", LEFT, 55); // Выводим надпись "Обороты"
  myOLED.setFont(SmallFont);
  myOLED.printNumF(Temp,1, RIGHT, 0); // Температура
  myOLED.printNumI(volts, RIGHT, 55); // подсос
  myOLED.setFont(MegaNumbers);
  myOLED.printNumI(i, CENTER, 10); // Обороты
  myOLED.update();
  }
  return Temp;
}
int setOboroti()
{
  //считываем данные с датчика холла
  val = digitalRead(potPin);

  //если пришел импульс
  if ((val == HIGH) && (flg_push == 0))  {
    //флаг ставим в 1
    flg_push = 1;
  }
  //если импульс ушел, то увеличиваем счетчик
  if ((val == LOW) && (flg_push == 1))  {
    //флаг ставим в 0
    flg_push = 0;
    count++;
  }
  //если прошло 500 милисекунд
  now = (millis() - time) / 500;
  if (now == 1) {

    //выводим кол импульсов из расчета (об/мин)
    int i = count * 60;
    if (i == 0)
    { if (Temp <= 30) {
        servo.write(130);
      }
      if ((Temp > 30) && (Temp <= 35))
      {
        servo.write(145);
      }
      if ((Temp > 35) && (Temp <= 40))
      {
        servo.write(155);
      }
      if ((Temp > 40) && (Temp <= 50))
      {
        servo.write(165);
      }
      if (Temp > 50)
      {
        servo.write(175);
      }
    }
    else
    {
      if ((Temp <= 30))
      {

        if (i > 1900)
        {
          n = servo.read();
          n--;
          servo.write(n);
        }
      }
      if ((Temp > 30) && (Temp <= 35))
      {
        if (i > 1600)
        {
          n = servo.read();
          n--;
          servo.write(n);
        }
      }
      if ((Temp > 35) && (Temp <= 40))
      {
        if (i > 1400)
        {
          n = servo.read();
          n--;
          servo.write(n);
        }
      }

      if ((Temp > 40) && (Temp <= 50))
      {
        if (i > 1200)
        {
          n = servo.read();
          n--;
          servo.write(n);
        }
      }

      if (Temp > 50)
      {
        servo.write(175);
        servo.detach();
      }
    }
    //сбрасываем начальный счетчик
    time = millis();
    //сбрасываем количество импульсов
    count = 0;
  }
  return i;
}

Скейтч №2.

#include <Servo.h> //Подключаем библиотеку для сервопривода.
Servo Servo;//"Называем" сервопривод.
int ServoPos = 145; //Угол поворота сервопривода.    
int PosLevel = 3; //Значение, на которое будет изменятся угол сервопривода.
unsigned long currentTime;
unsigned long loopTime;
const int pin_A = 7;    //Пин, к которому подключен энкодер.  
const int pin_B = 6;    //Пин, к которому подключен энкодер.  
unsigned char encoder_A;
unsigned char encoder_B;
unsigned char encoder_A_prev=0;
 
void setup()  
{
  Servo.attach(11,117,175);//Инициализация серво.
  pinMode(pin_A, INPUT);
  pinMode(pin_B, INPUT);
  currentTime = millis();
  loopTime = currentTime; 
} 
 
void loop()  {
  currentTime = millis();
  if(currentTime >= (loopTime + 5)){
    encoder_A = digitalRead(pin_A);    
    encoder_B = digitalRead(pin_B);      
    if((!encoder_A) && (encoder_A_prev)){ 
      if(encoder_B) {
        if(ServoPos + PosLevel <= 175) ServoPos += PosLevel;               
      }   
      else {
        if(ServoPos - PosLevel >= 117) ServoPos -= PosLevel;               
      }   
 
    }   
    encoder_A_prev = encoder_A;     
     
      MyServo.write(ServoPos); //Вращаем сервопривод в зависимости от переменной.
      
    loopTime = currentTime;
    
  }      
            
}
Обьедененый скейтч.
#include <Wire.h>        // подключение библиотеки для ds18b20
#include <OneWire.h>
//DS18b20
OneWire ds(10);   //подключаем датчик ds18b20 к 10 цифровому входу
#include <OLED_I2C.h>
OLED  myOLED(8, 9, 8); // 8pin - SDA , 9pin - SCL
extern uint8_t RusFont[]; // Русский шрифт
extern uint8_t MegaNumbers[]; // Подключение больших шрифтов
extern uint8_t SmallFont[]; // Базовый шрифт без поддержки русскийх символов.
#include <Servo.h>      //подключение библиотеки для сервопривода
Servo servo;
int ServoPos = 145; //Угол поворота сервопривода.    
int PosLevel = 3; //Значение, на которое будет изменятся угол сервопривода.
unsigned long currentTime;
unsigned long loopTime;
const int pin_A = 7;    //Пин, к которому подключен энкодер.  
const int pin_B = 6;    //Пин, к которому подключен энкодер.  
unsigned char encoder_A;
unsigned char encoder_B;
unsigned char encoder_A_prev=0;
int potPin = 2; // Порт для провода от датчика холла
int now = 0;// последнее значение сигнала с датчика
long time = 0; // для сохранения времени начала счета импульсов
int count = 0; // колличество импльсов
int val; //временная переменная для считывания сигнала с датчика
bool LampState4 = false;
int flg_push; //флаг прихода импульса
float Temp;
float volts;
int i;
int n;
int analogPin = A0;// порт потенциометра сервопривода
#define LCD_UPDATE_TIME  1000
unsigned long lcdLastUpdateTime = 0;
long updtime = 0;
const int knopkaPin = 4;
const int swichButtonPin=5;
boolean poslSost = LOW;
boolean znachKnopki = LOW;
int dvig = 0;
int counter = 1;

void setup()
{
  Wire.begin();
  servo.attach(11,130,175);   //подключаем сервопривод к 11 цифровому порту
  myOLED.begin();
  pinMode(knopkaPin, INPUT);
  pinMode(swichButtonPin, INPUT);
  pinMode(pin_A, INPUT);
  pinMode(pin_B, INPUT);
  currentTime = millis();
  loopTime = currentTime;
}
boolean debounce(boolean posl)
{
  boolean znach = digitalRead(knopkaPin);
  if (posl!=znach)
  {
    delay(5);
    znach = digitalRead(knopkaPin);
  }
  return znach;
}
void loop()
{ 
if (digitalRead(swichButtonPin) == HIGH)
counter++;
else if (counter > 2)
counter = 1;
znachKnopki = debounce(poslSost);
switch (counter)
{
case 1: {setOboroti(); break;}
case 2: {secondcode(); break;}
}
  setTemperature(); // вызываем функцию работы с DS18b20
  setOboroti();
}
int setTemperature() // DS18B20
{ byte type_s;
  type_s = 0;
  byte data[2];
  ds.reset();
  ds.write(0xCC);
  ds.write(0x44);

  // обращаемся к датчикам раз в 1000 мс, т.к. 750 может быть недостаточно
  if (millis() - lcdLastUpdateTime > LCD_UPDATE_TIME)
  { lcdLastUpdateTime = millis();

    ds.reset();
    ds.write(0xCC);
    ds.write(0xBE);
    data[0] = ds.read();
    data[1] = ds.read();
    Temp = (data[1] << 8) + data[0];
    Temp = (float)Temp / 16.0;;
  int rawReading = analogRead(analogPin);
float volts = (rawReading-360.0)/106*100;
    // Температура
    
  myOLED.clrScr(); // очищаем экран
  myOLED.setFont(RusFont); // Устанавливаем русский шрифт
  myOLED.print("NTVGTHFNEHF", LEFT, 0); // Выводим надпись "Температура"
  myOLED.print("GJLCJC", LEFT, 55); // Выводим надпись "Обороты"
  myOLED.setFont(SmallFont);
  myOLED.printNumF(Temp,1, RIGHT, 0); // Температура
  myOLED.printNumI(volts, RIGHT, 55); // подсос
  myOLED.setFont(MegaNumbers);
  myOLED.printNumI(i, CENTER, 10); // Обороты
  myOLED.update();
  }
  return Temp;
}
int setOboroti()
{
  //считываем данные с датчика холла
  val = digitalRead(potPin);

  //если пришел импульс
  if ((val == HIGH) && (flg_push == 0))  {
    //флаг ставим в 1
    flg_push = 1;
  }
  //если импульс ушел, то увеличиваем счетчик
  if ((val == LOW) && (flg_push == 1))  {
    //флаг ставим в 0
    flg_push = 0;
    count++;
  }
  //если прошло 500 милисекунд
  now = (millis() - time) / 500;
  if (now == 1)
  {
    int i = count * 60;    //выводим кол импульсов из расчета (об/мин)
    
    if (i == 0)
    { if (Temp <= 30) {
        servo.write(ServoPos=130);
      }
      if ((Temp > 30) && (Temp <= 35))
      {
        servo.write(ServoPos=145);
      }
      if ((Temp > 35) && (Temp <= 40))
      {
        servo.write(ServoPos=155);
      }
      if ((Temp > 40) && (Temp <= 50))
      {
        servo.write(ServoPos=165);
      }
      if (Temp > 50)
      {
        servo.write(ServoPos=175);
      }
    }
    else
    {
      if ((Temp <= 30))
      {

        if (i > 1900)
        {
          ServoPos = servo.read();
          ServoPos--;
          servo.write(ServoPos);
        }
      }
      if ((Temp > 30) && (Temp <= 35))
      {
        if (i > 1600)
        {
          ServoPos = servo.read();
          ServoPos--;
          servo.write(ServoPos);
        }
      }
      if ((Temp > 35) && (Temp <= 40))
      {
        if (i > 1400)
        {
          ServoPos = servo.read();
          ServoPos--;
          servo.write(ServoPos);
        }
      }

      if ((Temp > 40) && (Temp <= 50))
      {
        if (i > 1200)
        {
          ServoPos = servo.read();
          ServoPos--;
          servo.write(ServoPos);
        }
      }

      if (Temp > 50)
      {
        servo.write(175);
        servo.detach();
      }
    }
    //сбрасываем начальный счетчик
    time = millis();
    //сбрасываем количество импульсов
    count = 0;
  }
  return i;
}
int secondcode()
{
  currentTime = millis();
  if(currentTime >= (loopTime + 5)){
    encoder_A = digitalRead(pin_A);    
    encoder_B = digitalRead(pin_B);      
    if((!encoder_A) && (encoder_A_prev)){ 
      if(encoder_B) {
        if(ServoPos + PosLevel <= 175) ServoPos += PosLevel;               
      }   
      else {
        if(ServoPos - PosLevel >= 117) ServoPos -= PosLevel;               
      }   
     }   
    encoder_A_prev = encoder_A;     
    servo.write(ServoPos); //Вращаем сервопривод в зависимости от переменной.
    loopTime = currentTime;  
            
}
}

 

 

Van
Van аватар
Offline
Зарегистрирован: 04.10.2016

vitar пишет:

Всё, всем спасибо, уже разобрался. 

Добрый день! Если не секрет... Как решили проблему?