Изменение программ по нажатию кнопки
- Войдите на сайт для отправки комментариев
Всем добрый день. По стандарту: Я новичек, с Ардуино разбираюсь гдето пятый день. Вот в чем вопрос.
Есть три отдельные программы. 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.
В итоге застрял. Прошу помощи у знатоков.
выложи отдельно 2 кода
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); }Как видно они отличаются только одной цифрой. Третюю программу пока не ложу, она не готова, там тоже свои вопросы, но пока что надо сделать хоть это.
vitar, Ну так и меняйте одну цифру. Сделайте для неё переменную, вставьте её в код, и от дополнительной кнопки меняйте значение переменной.
Но это если бы мне надо было только эти 2 программы чередовать. Я же писал, что будет третяя, и она сильно отличается от этих двух. Тоесть надо создать какуюто глобальную подпрограмму, которая будет чередовть 3 цикла по нажатию кнопки. Я думал сделать void loop1, void loop2 и void loop3, и их менять по очереди в void swap. Но я не знаю как можно вызвать их в другом цикле и можно ли вообще.
vitar, вы мутите что-то странное, так можно, но так не делают. Нужно так составить одну программу, что бы она интегрировала в себе все необходимые функции.
Вот поэтому я и написал здесь, так как еще плохо разбираюсь в этих всех командах и не знаю тонкостей программирования на Arduino, а сроки горят. Я написал так, как сам представляю то что должно получится, но может кто-то знает более оптимальный вариант или сталкивался с подобным. В моем представлении есть одна большая программа (код), который состоит из трех основных подпрограмм и одной подпрограммы для переключения их по кругу с помощью кнопки. Представим, что все три подпрограммы разные и их надо всунуть в одну большую. Для этого я и придумал такие цикли, как (для меня) самый очевидный вариант. Естественно код получился топорный и большой, не оптимизированный. Может кто-то что-то подскажет. Буду благодарен.
и забудь о том примере void swap и void loop2 ...
у тебя должно быть 2 основных цикла, которые загружает дуина при работе - это первый void setup и void loop
все остальные функции пиши своими именами и еще если она ничего не возвращает, то пиши int <имя_функции> ()
если нужно ретурн делать - void MyFunction () { code... }
Воо. Спасибо. О такой функции я и не знал. Завтра не смогу, в понедельник попробую.
А кнопку лучше ставить обычную (вроде int button1 = какойто пин) или использовать прерывания (на второй пин)?
И что значит "ничего не возвращает"? Что-то вроде обратной связи? Тоесть в этих двух кодах у меня ее нет, тобишь можно int, а в третей у меня будет Serial.println, которая расчитывает значения из данных, полученных по обратной связи, и там мне надо будет использовать void?
посмотрел свой код 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() и ждать кнопки.
Я просмотрел видео разные, нашел что-то похожее на то, что хотел, вот и решил отталкиватся от этого.
Вот с 9 минуты и дальше вторая часть: http://www.youtube.com/watch?v=wjB2qZ3Zkh0&index=18&list=PLfDmj22jP9S759DT250VVzfZs_4VnJqLa
А так спасибо, как попробую - отпишусь.
Всем привет. Добрался до программы наконецто.
Переделал с использованием 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); }Всё, всем спасибо, уже разобрался.
привет всем. с 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; }Надеюсь на Вашу помощь. заранее благодарен. ткните пожалуйста что не правильно в моём коде. и по возможности исправте его.
Vanya_87
скобка в строке 217 закрывает switch, а скобка в строке 219 не закрыта
как-то в строках 27 и 28 логичнее было бы видеть int а не byte
откуда взялась и где задается переменная selmon
цикл for в строке 227 тоже не мешало бы открыть и закрыть, в строке 235 - две левых скобки.
Короче перед тем как скидывать не мешало бы и самому проверить что да как
спасибо. попробую. я просто говорю же с программами пару дней только)))
selmon вообще убрать? просто это было скопировано с другого кода
вот что выдала arduino после всех изменений:
как-то в строках 27 и 28 логичнее было бы видеть int а не byte
Логичнее там было бы uint8_t, зачем там 16-битные переменные? Врядли количество экранов и пинов будет больше 255 ;-)
Тип данных byte кстати тоже 8-ми битное беззнаковое целое число. Тоже самое, что uint8_t.
так мне назад byte вернуть?
и что с кодом делать? ошибки вылазиют и не дают прошиться
#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; }вот так переделал код, вылезла две ошибки!
#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; }вот ошибки в предущем коде-сообщении:
у тебя переменная value не объявлена нигде.
Вставь строку 36: byte value;
ага и весь код с 37 по 49 строку непонятно в чем находится, то ли функция то ли видение.
Уважаемый Vanya_87 ну изучите Вы матчасть потом пытайтесь что-то делать, а по принципу нафигачу чего нить и найду дурака который из этого конфетку сделает...
stakan1986
+1000 :)
не ищу я дурака, просто прошу помощи у знающих людей.
вот поискал в инете, нашёл скетч где все описано по каждой строчке, кстате на этом же форуме))) переделал свой код, ошибок нет, но при загрузки кода пустой экран.
вот код:
#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; } }что у меня прописано не правильно?
строка 256 - если "подпрограмма" то по идее должна начинаться void а не int.
строка 260 - digitalRead выдаст вам только 2 значения - 0 и 1. но не тот непонятный набор который забит в butval
я может конечно чего-то не замечаю, но где Вы хоть что-то выводите на экран, чтоб хотеть что-то увидеть. Если бы вы как раз таки изучали матчасть то узнали бы что void setup выполняется при старте, а далее void loop выполняется по кругу, и чтобы запустить функцию void Menu в которой у Вас что то выводится на экран надо к ней обратиться внутри loop, аналогично и для других функций. Они вспомогательные и просто так - потому что есть в вашем коде - не запускаются.
строка 256 - если "подпрограмма" то по идее должна начинаться void а не int.
строка 260 - digitalRead выдаст вам только 2 значения - 0 и 1. но не тот непонятный набор который забит в butval
я может конечно чего-то не замечаю, но где Вы хоть что-то выводите на экран, чтоб хотеть что-то увидеть. Если бы вы как раз таки изучали матчасть то узнали бы что void setup выполняется при старте, а далее void loop выполняется по кругу, и чтобы запустить функцию void Menu в которой у Вас что то выводится на экран надо к ней обратиться внутри loop, аналогично и для других функций. Они вспомогательные и просто так - потому что есть в вашем коде - не запускаются.
я впринципе это понял, на счет void setup и void loop))
с 272 строки на экран вывод - я так думал)))
Народ, вы вообще где язык учили?
256 - 266 это описание функции, которая обрабатывает клавиши, подключенные через делители напряжения на аналоговый вход. Функция возвращает целочисленное значение нажатой клавиши. (return butPush;) Но почему считывание считывание делается как digitalRead, а не analogRead(), да еще и подключено на 9-й пин - для меня вообще не понятно. butPush объявлена как глобальная, а ее пытаются выводить как значение функции - бардак. В этом смысле соглашусь, что button () нет никакого смысла возвращать значение. Функция должна быть void.
Если у вас делитель для кнопок не соответствует оригинальному - кнопки работать не будут. С какой стати что-то должно показываться, если функция Menu(int) ниоткуда(кроме самой себя не вызывается). Надо 10 раз подумать прежде чем использовать рекурсию.
Вообще в коде полный бардак.
вот подправил код. брал из примера ардуины и "программирования" этого сайта. у меня два вопроса по коду: в 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; }246 строка - зачем2 скобки
команда switch (disp) берет значение переменной disp и сравнивает с вариантами перечисленными в case -соответственно 1 или 2, если совпадает то выполняет весь код до брэйка. то есть если disp = 1 то выполняет 235-239 строки и переходит к 247, а вот что там написано не понятно совсем - поясните.
И все таки никак не допру что и для чего делается в строках 255-267
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 не могу включить, т.к. не прописано программно условия после нажатия кнопки
всё, разобрался я со счетчиком. меняется 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
экраны скачут из-за так называемого "дребезга" контактов кнопки - с ним можно бороться программно или аппаратно. Погуглите
А почему не работает хз. Но если работает один вариант зачем биться над другим. Дребезг он будет в любом случае и с ним придется бороться
избавился я от дребезга. с кнопкой проблем нет, работает как часы.
дайте хоть на ваш код посмотреть
а вообще - переменную disp при нажатии кнопки увеличивать на единицу с проверкой: если disp==2 то disp =0 иначе disp++
сообщение на изменении висело, а на него уже ответили)))
у меня два варианта кода. один как у автора - минус в том что долго всё обрабатывается и бешеные значения выводятся на экран в машине. второй вариант пока не проверял, щас загружу его в друину и как проверю потом скажу)))
всё сделал. вместо delay которая тормозила всю программу ввел millis. вот такой вот вариант кода:
Здравствуйте знатоки Ардуино, хотел бы тоже попросить помощи т.к. у самого уже мозги закипают. Итак есть два скейтча:
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; } }Всё, всем спасибо, уже разобрался.
Добрый день! Если не секрет... Как решили проблему?