Прошу помочь со скетчем
- Войдите на сайт для отправки комментариев
Ср, 23/01/2013 - 23:22
Скачал, залил скетч StopWatch - секундометр отлично работает, результат пишет в SERIAL_MONITOR
/* StopWatch
* Paul Badger 2008
* Demonstrates using millis(), pullup resistors,
* making two things happen at once, printing fractions
*
* Physical setup: momentary switch connected to pin 4, other side connected to ground
* LED with series resistor between pin 13 and ground
*/
#define ledPin 13 // LED connected to digital pin 13
#define buttonPin 4 // button on pin 4
int value = LOW; // previous value of the LED
int buttonState; // variable to store button state
int lastButtonState; // variable to store last button state
int blinking; // condition for blinking - timer is timing
long interval = 100; // blink interval - change to suit
long previousMillis = 0; // variable to store last time LED was updated
long startTime ; // start time for stop watch
long elapsedTime ; // elapsed time for stop watch
int fractional; // variable used to store fractional part of time
void setup()
{
Serial.begin(9600);
pinMode(ledPin, OUTPUT); // sets the digital pin as output
pinMode(buttonPin, INPUT); // not really necessary, pins default to INPUT anyway
digitalWrite(buttonPin, HIGH); // turn on pullup resistors. Wire button so that press shorts pin to ground.
}
void loop()
{
// check for button press
buttonState = digitalRead(buttonPin); // read the button state and store
if (buttonState == LOW && lastButtonState == HIGH && blinking == false){ // check for a high to low transition
// if true then found a new button press while clock is not running - start the clock
startTime = millis(); // store the start time
blinking = true; // turn on blinking while timing
delay(5); // short delay to debounce switch
lastButtonState = buttonState; // store buttonState in lastButtonState, to compare next time
}
else if (buttonState == LOW && lastButtonState == HIGH && blinking == true){ // check for a high to low transition
// if true then found a new button press while clock is running - stop the clock and report
elapsedTime = millis() - startTime; // store elapsed time
blinking = false; // turn off blinking, all done timing
lastButtonState = buttonState; // store buttonState in lastButtonState, to compare next time
// routine to report elapsed time
Serial.print( (int)(elapsedTime / 1000L)); // divide by 1000 to convert to seconds - then cast to an int to print
Serial.print("."); // print decimal point
// use modulo operator to get fractional part of time
fractional = (int)(elapsedTime % 1000L);
// pad in leading zeros - wouldn't it be nice if
// Arduino language had a flag for this? :)
if (fractional == 0)
Serial.print("000"); // add three zero's
else if (fractional < 10) // if fractional < 10 the 0 is ignored giving a wrong time, so add the zeros
Serial.print("00"); // add two zeros
else if (fractional < 100)
Serial.print("0"); // add one zero
Serial.println(fractional); // print fractional part of time
}
else{
lastButtonState = buttonState; // store buttonState in lastButtonState, to compare next time
}
// blink routine - blink the LED while timing
// check to see if it's time to blink the LED; that is, the difference
// between the current time and last time we blinked the LED is larger than
// the interval at which we want to blink the LED.
if ( (millis() - previousMillis > interval) ) {
if (blinking == true){
previousMillis = millis(); // remember the last time we blinked the LED
// if the LED is off turn it on and vice-versa.
if (value == LOW)
value = HIGH;
else
value = LOW;
digitalWrite(ledPin, value);
}
else{
digitalWrite(ledPin, LOW); // turn off LED when not blinking
}
}
}
Хотелось бы сделать из этого секундомера реле времени с возможным ручным стопом той же кнопкой. Уровень - чайник, так что - как понимаю - нужно добавить константу "long myDelay = моя уставка" в Setup и как то воткнуть if((millis() > (startTime + myDelay)).
Голову сломал. Help me please!!!
Общие направление мысли - верное.
Но ведь проще "написать с нуля", особенно если не нужны все красивости подравненого вывода в Serial и проч.
Если нужно просто "реле с кнопкой".
Но тут нужно будет уточнить постановку задачи.
Нужен ли вообще выводв Serial?
Когда оно запускается, при старте контроллера или по кнопке? Что оно делает по прошествии времени включает какой-то пин или выключает? Или "меняет ему состояние"? Возможны ли повторные запуски?
Вот самый простеший вариант: включаем светик. Выключаем его или если прошло 5 секунд от включения контроллера или по нажатию кнопку (что-бы опять его включить - перегружаем кнопкой Reset).
#define LED 13 #define BUTTON 2 #define ON_PERIOD 5000 // будем светить светиком 5-ть. секунд unsigned long onTime; // тут храним время когда включили светик void setup(){ pinMode(LED,OUTPUT); digitalWrite(BUTTON,HIGH); // включаем подтяжку для кнопки // digitalWrite(LED,OUTPUT); // включили светик onTime=millis(); // запомнили время включения } void loop(){ if(millis()-onTime>ON_PERIOD){ // пора выключать digitalWrite(LED,LOW); } if(!digitalRead(BUTTON)){ // или нажата кнопка digitalWrite(LED,LOW); // тоже выключаем } }На самом деле onTime тут и не нужна. Она всегда будет 0 (так как setup() выполнится быстрее чем 1 мсек). Просто показал ее как принцип "засекать момент включения", может в будущем захотите "зажигать по кнопке", тогда в нее нестесвенно уже что-то не нулевое будет попадать.
P.S. На будущие постарайтесь называть свои темы более информативно. Вообщем-то все темы на этом сайте в итоге сводятся к "нужно помощь со скетчем" и "нужно помощь с железом". Но не называть же их все одинаково?
Спасибо за ответ, leshak! Добавило уверенности. StopWatch мне интересен и выводом времени - хочу подобраться к выводу на LCD. Поэтому продолжил долбить его. Вот что получилось: (добавленное выделено)
/* StopWatch * Paul Badger 2008 * Demonstrates using millis(), pullup resistors, * Делать две вещи одновременно, printing fractions * * Физическая установка: мгновенный переключатель, подключенный к выводу 4, другая сторона подключен к земле * Светодиод с резистором между выводом 13 и землей */ #define ledPin 13 // LED подключен к цифровому выводу 13 #define buttonPin 8 // кнопка на контакт 4 int value = LOW; // предыдущее значение LED int buttonState; // переменная для хранения состояния кнопки int lastButtonState; // переменная для хранения последнего состояния кнопки int blinking; // условие мигает - таймер времени long interval = 50; // интервал мигания - изменить в соответствии long previousMillis = 0; // переменная для хранения последнего времени обновления светодиода long startTime ; // время старта секундомер long elapsedTime ; // истекшее время секундомера int fractional; // переменная используется для хранения дробной части времени long myDelay = 15000 ; // переменная определяющая уставку времени void setup() { Serial.begin(9600); pinMode(ledPin, OUTPUT); // sets the digital pin as output pinMode(buttonPin, INPUT); // не обязательно, контакты по умолчанию как входы digitalWrite(buttonPin, HIGH); // включить подтягивающий резистор. Wire button so that press shorts pin to ground. } void loop() { // Проверка на нажатие кнопки buttonState = digitalRead(buttonPin); // считывание состояния кнопки и сохранение if (buttonState == LOW && lastButtonState == HIGH && blinking == false){ // check for a high to low transition // if true then found a new button press while clock is not running - start the clock //Если так, то нашел новую кнопку во время пресс часы не запущен - запустить часы startTime = millis(); // store the start time blinking = true; // turn on blinking while timing delay(5); // короткая задержка на дребезг переключателя lastButtonState = buttonState; // store buttonState in lastButtonState, для сравнения в следующий раз } else if ((buttonState == LOW && lastButtonState == HIGH && blinking == true) || (millis() == (startTime + myDelay))) { // check for a high to low transition // if true then found a new button press while clock is running - stop the clock and report //Если так, то нашел новую нажать кнопку в то время как часы работает - остановить часы и отчет elapsedTime = millis() - startTime; // store elapsed time - прошедшее время blinking = false; // turn off blinking, all done timing lastButtonState = buttonState; // store buttonState in lastButtonState, to compare next time_сохранить buttonState в lastButtonState, для сравнения в следующий раз // routine to report elapsed time Serial.print( (int)(elapsedTime / 1000L)); // делим на 1000, чтобы преобразовать в секунды - затем преобразуем в целое число для печати Serial.print("."); // print decimal point_Вывод десятичной точки // use modulo operator to get fractional part of time_Использовать модуль оператор, чтобы получить дробную часть времени fractional = (int)(elapsedTime % 1000L); // pad in leading zeros - wouldn't it be nice if // Arduino language had a flag for this? :) if (fractional == 0) Serial.print("000"); // add three zero's_Добавьте три ноля else if (fractional < 10) // if fractional < 10 the 0 is ignored giving a wrong time, so add the zeros Serial.print("00"); // add two zeros else if (fractional < 100) Serial.print("0"); // add one zero Serial.println(fractional); // print fractional part of time_дробная часть времени } else{ lastButtonState = buttonState; // store buttonState in lastButtonState, to compare next time } // blink routine - blink the LED while timing_мигает светодиод при отсчете времени // check to see if it's time to blink the LED; that is, the difference // between the current time and last time we blinked the LED is larger than // the interval at which we want to blink the LED. if ( (millis() - previousMillis > interval) ) { if (blinking == true){ previousMillis = millis(); // remember the last time we blinked the LED // if the LED is off turn it on and vice-versa.Если светодиод не горит, включите его и наоборот. if (value == LOW) value = HIGH; else value = LOW; digitalWrite(ledPin, value); } else{ digitalWrite(ledPin, LOW); // turn off LED when not blinking_Выключите СВЕТОДИОД при не мигании } } }З.Ы.
Все работает - определяем уставку времени "long myDelay =хххх", по первому нажатию тактовой кнопки включаем нагрузку-(у меня пока это люминисцентная лампа на 220 v включенная через твердотельное реле). По истечению времени уставки или при повторном нажатии кнопки нагрузка отключается и время во включенном состоянии (сек/мсек) видим в Serial Monitor.
З.З.Ы.
Иногда глючит кнопка - надо править Debounce?
Плойхо.
Во первых, через 49-девять дней будет переполнение и "все поломается".
Во вторых грабли вылезут раньше. Что будет если мы прийдем к этой срочке не точно в нужную миллисекунду? Чуть где-то "задуплились" и все. Привет. часы не остановсятся. Поезд ушел. Так что лучше, преобразовать это условие в
(хе. хе. вспоминается школа и уравнения/неравества? ;)
А еще "вывод на печать" я бы порекомендовал вам вынести в отдельную функцию. Не замусоривать ей основную "бизнес логику".
Сделайте функцию, скажем printTime(unsgined long tm) и упихайте в нее строки с 066 по 082.
Когда доберетесь до экрана, то просто напишете еще printTimeLCD(unsgined long tm). И основная логику у вас уже не будет затрагиватся.
А еще почитайте про типы. Нужно ими пользоватся более аккуратно. Не нужно int, там где хватит byte. Нужно различать long и unsigned long. То есть "пока это не критично" и "и так сойдет", но подобной небрежностью вы себе большие головняки на будущие закладываете.
А еще lastButtonState = buttonState; можно просто в конце loop делать, а не раскидывать по if/else (а потом выискавать "где мы забыли сделать сохранение"). Зачем нам его писать в трех местах если можно в одном?
leshak, я за вами не успеваю! Еще раз спасибо! Будем думать. И "работать, работать, и еще раз работать"!
:)
А еще вот это
// if the LED is off turn it on and vice-versa.Если светодиод не горит, включите его и наоборот. if (value == LOW) value = HIGH; else value = LOW;можно спокойно заменить (будет в точности тот же самый резульат) на
А если почесать репу, то и весь
if ( (millis() - previousMillis > interval) ) { if (blinking == true){ previousMillis = millis(); // remember the last time we blinked the LED // if the LED is off turn it on and vice-versa.Если светодиод не горит, включите его и наоборот. if (value == LOW) value = HIGH; else value = LOW; digitalWrite(ledPin, value); } else{ digitalWrite(ledPin, LOW); // turn off LED when not blinking_Выключите СВЕТОДИОД при не мигании } }На
if ( (millis() - previousMillis > interval) ) { previousMillis = millis(); // remember the last time we blinked the LED value=!value; digitalWrite(ledPin, blinking && value); }"Во первых, через 49-девять дней будет переполнение и "все поломается"."-
- Я не рассматриваю варианты с курятниками - перепелятниками -мне до них как до луны пешком. Для меня достаточно чтобы девайс работал в течение суток. И правильно я понимаю, что на следующий день если я включу свой таймер по схеме:
1) Включаем питание ардуино
2) Через 30 сек включаем силу - то все должно быть OK?
"Во первых, через 49-девять дней будет переполнение и "все поломается"."-
- Я не рассматриваю варианты с курятниками - перепелятниками -мне до них как до луны пешком. Для меня достаточно чтобы девайс работал в течение суток. И правильно я понимаю, что на следующий день если я включу свой таймер по схеме:
А не нужно "рассматирвать" лучше сразу привыкать правильно работать со временем. Тем более что из-за жесткого равенства чудеса у нас могут начать намного раньше.
2) Через 30 сек включаем силу - то все должно быть OK?
Ну проверте. Скетч же у вас. Это я вас должен спрашивать все ли работает, а не вы меня. Я просто указал вам "тонкие места", которые "я бы делал по другому". А что дальше делать с этими советами - ваше дело.
Вообщем не проверял, но я бы все это писал примерно так:
#define ledPin 13 // LED подключен к цифровому выводу 13 #define buttonPin 8 // кнопка на контакт D8 #define BLINK_INTERVAL 50 // интервал мигания - изменить в соответствии bool lastButtonState; // переменная для хранения последнего состояния кнопки bool blinking; // условие мигает - таймер времени unsigned long startTime ; // время старта секундомер long myDelay = 15000 ; // переменная определяющая уставку времени void setup() { Serial.begin(9600); pinMode(ledPin, OUTPUT); // sets the digital pin as output pinMode(buttonPin, INPUT); // не обязательно, контакты по умолчанию как входы digitalWrite(buttonPin, HIGH); // включить подтягивающий резистор. Wire button so that press shorts pin to ground. } void loop() { // Проверка на нажатие кнопки bool buttonState = digitalRead(buttonPin); // считывание состояния кнопки и сохранение if (lastButtonState && !buttonState){ // check for a high to low transition if(!blinking)startTimer(); //Если так, то нашел новую кнопку во время пресс часы не запущен - запустить часы else stopAndPrintTime(); // часы уже идут. останавливаем и выводим на экран } // остановка/старт по кнопке if (blinking && (millis() - startTime >= myDelay)) stopAndPrintTime(); // остановка по времени blinkLed();// мигаем диодом если blinking==true; lastButtonState = buttonState; // store buttonState in lastButtonState, to compare next time } void blinkLed(){ static bool value=LOW; // предыдущее значение LED static unsigned long previousMillis = 0; // переменная для хранения последнего времени обновления светодиода if ( (millis() - previousMillis > BLINK_INTERVAL) ) { previousMillis = millis(); // remember the last time we blinked the LED value=!value; digitalWrite(ledPin, blinking && value); } } void startTimer(){ // Serial.print(millis());Serial.println(": Timer Started!!!"); // для отладки startTime = millis(); // store the start time blinking = true; // turn on blinking while timing } void stopTimer(){ // Serial.print(millis());Serial.println(": Timer Stopped!!!"); // для отладки blinking = false; } void stopAndPrintTime(){ stopTimer(); unsigned long elapsedTime = millis() - startTime; // store elapsed time - прошедшее время printTime(elapsedTime); // выводим который час //printTimeLCD(elapsedTime); // когда-нибудь и на экран выведем } void printTime(unsigned long mTime){ // routine to report elapsed time Serial.print( (int)(mTime / 1000L)); // делим на 1000, чтобы преобразовать в секунды - затем преобразуем в целое число для печати Serial.print("."); // print decimal point_Вывод десятичной точки // use modulo operator to get fractional part of time_Использовать модуль оператор, чтобы получить дробную часть времени int fractional = (int)(mTime % 1000L); // переменная используется для хранения дробной части времени // pad in leading zeros - wouldn't it be nice if // Arduino language had a flag for this? :) if (fractional == 0) Serial.print("000"); // add three zero's_Добавьте три ноля else if (fractional < 10) // if fractional < 10 the 0 is ignored giving a wrong time, so add the zeros Serial.print("00"); // add two zeros else if (fractional < 100) Serial.print("0"); // add one zero Serial.println(fractional); // print fractional part of time_дробная часть времени }Мне кажется, что
printTime(unsignedlongmTime) занимается какими-то нечеловеческими преобразованиями. Есть жеМне кажется, что
printTime(unsignedlongmTime) занимается какими-то нечеловеческими преобразованиями. Есть жеВы правы. Только только сейчас рассказывать еще про "откуда взялась dtostrf?", что это за current_value[10] . К тому же на чем же всякие for/if/switch изучать как не на таких задачах типа "подравнять строку"?
К тому же, ну вот в дальшенйшем подрубит, скажем, сегментный индикатор. Как он потом dtostrf с ним заиспользует? А там где "сами разбирали ручками" (тут важнее "понять") - уже есть шанс адаптировать под индикатор.
P.S. Но я не хочу сказать что "вы зря про это сказали". Пусть и ваш вариант будет. Кто захочет - погуглит что это за dtostrf, не сейчас так потом пригодится знание