загвоздка: обратный тамер с режимом ускоренного счёта
- Войдите на сайт для отправки комментариев
День добрый, вечер, ночь, нужное подчеркнуть :)
Решился таки заюзать ардуинку и влип по полной. На сях с прямым доступом к таймерам реализовать могу, но так как это ардуина - не могу )
Помогите пажалста понять, почему независимо от включения тикают оба таймера Т_Т
лишнего кода море, знаю и не оптимально, но для прошивки занимающей от силы 3 кило на 32х не критично :)
Если быть точным, то интересует, как используя millis() можно вести 2 отсчёта с разной скоростью но начинать отсчёт с того места, на котором был остановлен предидущий.
Сейчас имею следущее: переключаю режим с (millis()/1000) на (millis()/100) скорость увеличил время побежало, но при возвращении в штатный режим, время продолжает тикать с того места где переключился (старая версия)
и как сейчас выходит - после активации режима ускорения, после переключения в штатный, ускорение таки тикает... и досчитав до нуля взрывает бедных созданий потоками пара из парогенератора :( хотя на дисплее всё путём и до нуля там ещё почти час...
подскажите пожалуйста, где не прав :)
[code]
int digit1 = 11; //PWM Display pin 1
int digit2 = 10; //PWM Display pin 2
int digit3 = 9; //PWM Display pin 6
int digit4 = 6; //PWM Display pin 8
int segA = 3; //Display pin 14
int segB = 2; //Display pin 16
int segC = 7; //Display pin 13
int segD = 8; //Display pin 3
int segE = 12; //Display pin 5
int segF = 4; //Display pin 11
int segG = 5; //Display pin 15
int LedPin = 13;
int A = 14; //вход цепи на замыкание
int B = 15; //вход цепи на размыкание
int C = 16; //если 0 то ускоряем таймер
int D = 17; //если 0 то ускоряем таймер
int INPUTS;
int Coil_1 = 18;//выход бомба обезврежена
int Coil_2 = 19;//выход бомба 3.14_зданула
int setup_num = 3600;
int start_num;
int num_min;
int num_sec;
int num_time;
long interval = 500;
int ledState = LOW;
long previousMillis = 0;
int In_A;
int In_B;
int In_C;
int In_D;
unsigned long time;
void setup() {
Serial.begin(9600);
pinMode(segA, OUTPUT);
pinMode(segB, OUTPUT);
pinMode(segC, OUTPUT);
pinMode(segD, OUTPUT);
pinMode(segE, OUTPUT);
pinMode(segF, OUTPUT);
pinMode(segG, OUTPUT);
pinMode(digit1, OUTPUT);
pinMode(digit2, OUTPUT);
pinMode(digit3, OUTPUT);
pinMode(digit4, OUTPUT);
pinMode(LedPin, OUTPUT);
pinMode(A, INPUT_PULLUP);
digitalWrite(A, HIGH);
pinMode(B, INPUT_PULLUP);
digitalWrite(B, HIGH);
pinMode(C, INPUT_PULLUP);
digitalWrite(C, HIGH);
pinMode(D, INPUT_PULLUP);
digitalWrite(D, HIGH);
pinMode(Coil_1, OUTPUT);
digitalWrite(Coil_1, HIGH); //закрыли замок
pinMode(Coil_2, OUTPUT);
digitalWrite(Coil_2, LOW); //отключили парогенератор
}
void loop()
{
unsigned long startTime = millis();
unsigned long currentMillis = millis();
if (currentMillis - previousMillis > interval)
{
previousMillis = currentMillis;
if (ledState == LOW)
ledState = HIGH;
else
ledState = LOW;
digitalWrite(LedPin, ledState);
}
In_A = digitalRead(A);
In_B = digitalRead(B);
In_C = digitalRead(C);
In_D = digitalRead(D);
//A - правильно = LOW == соединено с землёй, разрыв - подтянут к питанию
//B - правильно = LOW == соединено с землёй, разрыв - подтянут к питанию
//C - правильно = LOW == соединено с землёй, разрыв - подтянут к питанию
//D - правильно = LOW == соединено с землёй, разрыв - подтянут к питанию
//если А или В и C или D собраны
INPUTS = (((In_A << 2) + (In_B << 1) + (In_C)) * 0x07);
switch (INPUTS)
{
case 0://(A = L) && (B = L) && (C = L) && (D = L))
BOMB_config(250, 100, HIGH, HIGH, HIGH, HIGH);
break;
case 1://(A = L) && (B = L) && (C = L) && (D = H))
BOMB_config(250, 1000, HIGH, HIGH, HIGH, HIGH);
break;
case 2://(A = L) && (B = L) && (C = H) && (D = L))
BOMB_config(250, 1000, HIGH, HIGH, HIGH, HIGH);
break;
case 3://(A = L) && (B = L) && (C = H) && (D = H))
BOMB_config(250, 1000, HIGH, HIGH, HIGH, HIGH);
break;
case 4://(A = L) && (B = H) && (C = L) && (D = L))
BOMB_config(250, 1000, HIGH, HIGH, HIGH, HIGH);
break;
case 5://(A = L) && (B = H) && (C = L) && (D = H))
BOMB_config(250, 1000, HIGH, HIGH, HIGH, HIGH);
break;
case 6://(A = L) && (B = H) && (C = H) && (D = L))
BOMB_config(250, 1000, HIGH, HIGH, HIGH, HIGH);
break;
case 7://(A = L) && (B = H) && (C = H) && (D = H))
BOMB_config(250, 1000, HIGH, HIGH, HIGH, HIGH);
break;
case 8://(A = H) && (B = L) && (C = L) && (D = L))
BOMB_config(250, 1000, HIGH, HIGH, HIGH, HIGH);
break;
}
Serial.println(start_num);
}
//---BOMB-CONFIG--------------------------
void BOMB_config (int blink_time, unsigned long Time_interval, int ledpin_state1, int ledpin_state2, int coil_1_state, int coil_2_state)
{
unsigned long Time_previous_Millis = 0;
unsigned long Time_current_Millis = millis();// прошлое значение времени милисекунд
//Time_interval = 1000;//интервал в милисекундах (минута=60000)
if (Time_current_Millis - Time_previous_Millis >= Time_interval)
{
setup_num -= 1;
Time_previous_Millis = Time_current_Millis;
}
start_num = setup_num;
if (start_num > 0)
{
num_min = start_num / 60;
num_sec = start_num % 60;
num_time = ((num_min * 100) + num_sec);
displayNumber(num_time);
digitalWrite(Coil_1, HIGH);
digitalWrite(Coil_2, LOW);
}
if (start_num <= 0)
{
time = millis();
while (millis() < time + blink_time)
{
displayNumber(0);
digitalWrite(LedPin, ledpin_state1);
digitalWrite(Coil_1, coil_1_state);
digitalWrite(Coil_2, coil_2_state);
}
time = millis();
while (millis() < time + blink_time)
{
lightNumber(10);
digitalWrite(LedPin, ledpin_state2);
digitalWrite(Coil_1, coil_1_state);
digitalWrite(Coil_2, coil_2_state);
}
}
}
////---BOMB-ARM-----------------------------
//void BOMB_Arm()
//{
// if (start_num > 0)
// {
// num_min = start_num / 60;
// num_sec = start_num % 60;
// num_time = ((num_min * 100) + num_sec);
// displayNumber(num_time);
// digitalWrite(Coil_1,HIGH);
// digitalWrite(Coil_2,LOW);
// }
// if(start_num <= 0)
// {
// time = millis();
// while(millis() < time + blink_time)
// {
// displayNumber(0);
// digitalWrite(LedPin,HIGH);
// digitalWrite(Coil_1,LOW);
// digitalWrite(Coil_2,HIGH);
// }
// time=millis();
// while(millis() < time + blink_time)
// {
// lightNumber(10);
// digitalWrite(LedPin,HIGH);
// digitalWrite(Coil_1,LOW);
// digitalWrite(Coil_2,HIGH);
// }
// }
//}
//
////---BOMB-DISARM--------------------------
//void BOMB_Disarm()
//{
// if (start_num > 0)
// {
// num_min = start_num / 60;
// num_sec = start_num % 60;
// num_time = ((num_min * 100) + num_sec);
// time = millis();
// while(millis() < time + blink_time)
// {
// displayNumber(num_time);
// digitalWrite(LedPin,HIGH);
// digitalWrite(Coil_1,LOW);
// digitalWrite(Coil_2,LOW);
// }
// time=millis();
// while(millis() < time + blink_time)
// {
// lightNumber(10);
// digitalWrite(LedPin,LOW);
// digitalWrite(Coil_1,LOW);
// digitalWrite(Coil_2,LOW);
// }
// }
// if(start_num <= 0)
// {
// time = millis();
// while(millis() < time + blink_time)
// {
// displayNumber(0);
// digitalWrite(LedPin,HIGH);
// digitalWrite(Coil_1,LOW);
// digitalWrite(Coil_2,HIGH);
// }
// time=millis();
// while(millis() < time + blink_time)
// {
// lightNumber(10);
// digitalWrite(LedPin,HIGH);
// digitalWrite(Coil_1,LOW);
// digitalWrite(Coil_2,HIGH);
// }
// }
//}
////---BOMB-x2time-ARM----------------------
//void BOMB_x2time_Arm()
//{
// if (start_num > 0)
// {
// num_min = start_num / 60;
// num_sec = start_num % 60;
// num_time = ((num_min * 100) + num_sec);
// displayNumber(num_time);
// digitalWrite(Coil_1,HIGH);
// digitalWrite(Coil_2,LOW);
// }
// if(start_num <= 0)
// {
// time = millis();
// while(millis() < time + blink_time)
// {
// displayNumber(0);
// digitalWrite(LedPin,HIGH);
// digitalWrite(Coil_1,LOW);
// digitalWrite(Coil_2,HIGH);
// }
// time=millis();
// while(millis() < time + blink_time)
// {
// lightNumber(10);
// digitalWrite(LedPin,HIGH);
// digitalWrite(Coil_1,LOW);
// digitalWrite(Coil_2,HIGH);
// }
// }
//}
//-----------------------------------------------------------------------------
void displayNumber(int toDisplay)
{
#define DISPLAY_BRIGHTNESS 200
#define DIGIT_ON HIGH
#define DIGIT_OFF LOW
long beginTime = millis();
for (int digit = 4 ; digit > 0 ; digit--)
{
switch (digit) {
case 1:
digitalWrite(digit1, DIGIT_ON);
break;
case 2:
digitalWrite(digit2, DIGIT_ON);
break;
case 3:
digitalWrite(digit3, DIGIT_ON);
break;
case 4:
digitalWrite(digit4, DIGIT_ON);
break;
}
lightNumber(toDisplay % 10);
toDisplay /= 10;
delayMicroseconds(DISPLAY_BRIGHTNESS);
lightNumber(10);
digitalWrite(digit1, DIGIT_OFF);
digitalWrite(digit2, DIGIT_OFF);
digitalWrite(digit3, DIGIT_OFF);
digitalWrite(digit4, DIGIT_OFF);
}
while ( (millis() - beginTime) < 10) ;
}
void lightNumber(int numberToDisplay) {
#define SEGMENT_ON LOW
#define SEGMENT_OFF HIGH
switch (numberToDisplay) {
case 0:
digitalWrite(segA, SEGMENT_ON);
digitalWrite(segB, SEGMENT_ON);
digitalWrite(segC, SEGMENT_ON);
digitalWrite(segD, SEGMENT_ON);
digitalWrite(segE, SEGMENT_ON);
digitalWrite(segF, SEGMENT_ON);
digitalWrite(segG, SEGMENT_OFF);
break;
case 1:
digitalWrite(segA, SEGMENT_OFF);
digitalWrite(segB, SEGMENT_ON);
digitalWrite(segC, SEGMENT_ON);
digitalWrite(segD, SEGMENT_OFF);
digitalWrite(segE, SEGMENT_OFF);
digitalWrite(segF, SEGMENT_OFF);
digitalWrite(segG, SEGMENT_OFF);
break;
case 2:
digitalWrite(segA, SEGMENT_ON);
digitalWrite(segB, SEGMENT_ON);
digitalWrite(segC, SEGMENT_OFF);
digitalWrite(segD, SEGMENT_ON);
digitalWrite(segE, SEGMENT_ON);
digitalWrite(segF, SEGMENT_OFF);
digitalWrite(segG, SEGMENT_ON);
break;
case 3:
digitalWrite(segA, SEGMENT_ON);
digitalWrite(segB, SEGMENT_ON);
digitalWrite(segC, SEGMENT_ON);
digitalWrite(segD, SEGMENT_ON);
digitalWrite(segE, SEGMENT_OFF);
digitalWrite(segF, SEGMENT_OFF);
digitalWrite(segG, SEGMENT_ON);
break;
case 4:
digitalWrite(segA, SEGMENT_OFF);
digitalWrite(segB, SEGMENT_ON);
digitalWrite(segC, SEGMENT_ON);
digitalWrite(segD, SEGMENT_OFF);
digitalWrite(segE, SEGMENT_OFF);
digitalWrite(segF, SEGMENT_ON);
digitalWrite(segG, SEGMENT_ON);
break;
case 5:
digitalWrite(segA, SEGMENT_ON);
digitalWrite(segB, SEGMENT_OFF);
digitalWrite(segC, SEGMENT_ON);
digitalWrite(segD, SEGMENT_ON);
digitalWrite(segE, SEGMENT_OFF);
digitalWrite(segF, SEGMENT_ON);
digitalWrite(segG, SEGMENT_ON);
break;
case 6:
digitalWrite(segA, SEGMENT_ON);
digitalWrite(segB, SEGMENT_OFF);
digitalWrite(segC, SEGMENT_ON);
digitalWrite(segD, SEGMENT_ON);
digitalWrite(segE, SEGMENT_ON);
digitalWrite(segF, SEGMENT_ON);
digitalWrite(segG, SEGMENT_ON);
break;
case 7:
digitalWrite(segA, SEGMENT_ON);
digitalWrite(segB, SEGMENT_ON);
digitalWrite(segC, SEGMENT_ON);
digitalWrite(segD, SEGMENT_OFF);
digitalWrite(segE, SEGMENT_OFF);
digitalWrite(segF, SEGMENT_OFF);
digitalWrite(segG, SEGMENT_OFF);
break;
case 8:
digitalWrite(segA, SEGMENT_ON);
digitalWrite(segB, SEGMENT_ON);
digitalWrite(segC, SEGMENT_ON);
digitalWrite(segD, SEGMENT_ON);
digitalWrite(segE, SEGMENT_ON);
digitalWrite(segF, SEGMENT_ON);
digitalWrite(segG, SEGMENT_ON);
break;
case 9:
digitalWrite(segA, SEGMENT_ON);
digitalWrite(segB, SEGMENT_ON);
digitalWrite(segC, SEGMENT_ON);
digitalWrite(segD, SEGMENT_ON);
digitalWrite(segE, SEGMENT_OFF);
digitalWrite(segF, SEGMENT_ON);
digitalWrite(segG, SEGMENT_ON);
break;
case 10:
digitalWrite(segA, SEGMENT_OFF);
digitalWrite(segB, SEGMENT_OFF);
digitalWrite(segC, SEGMENT_OFF);
digitalWrite(segD, SEGMENT_OFF);
digitalWrite(segE, SEGMENT_OFF);
digitalWrite(segF, SEGMENT_OFF);
digitalWrite(segG, SEGMENT_OFF);
break;
}
}
[/code]
Поясните подробнее что Вы переключаете, что Вы хотите сделать и что работает не так.
И ещё, каков смысл переменной StartTime В асмом начале функции loop()?
Да, кстати, как долго эта программа должна по идее работать без перезугрузки? Если час-день, то ничего, а если "вечно", то имейте в виду. что millis переполняется и срасывается в ноль каждые 49 с копейками суток. При сбросе millis в 0 у Вас всё неминуемо сломается.
Не сломается, не надо пугать. А вот в строке 308 ошибка, переменная beginTime должна быть unsigned long.
Про то, что что то где то переключается и т.п. я не понял тоже.
не испугали, дяденьки :) работает час, программно мигает нулями при переходе через ноль, конечно все не ансигнед значения будут считаться в минуса вплоть до переполнения, но мигать один фиг будет нолями. меня не испугать. и да я в курсе про милз() и его ширину.
Ну и раз я первый раз кручу эту гадость в руках, соответственно есть бесполезные строки кода :) многое накопипащено.
Про переключения:
пока на входе (условно пусть будет А) лог 1 (подтянут к + питания) - отсчёт времени нормальный, примерно равен стандартному течению времени (короче говоря раз в секунду вычетает секунду), как только Вход А прижимаем к земле, вуаля: таймер начинает отсчитывать время много быстрее, чем в стандартном режиме.
В данном случае по сути вопроса пофиг, что за входы\выходы и что есть управляющие сигналы, не могу для себя внятно вообразить как, вести отсчёт одного времени на два режима, мне думается это какие то закулисные игры со стеком пролетают мимо меня :)
т.е.: допустим в момент переключения было 28 минут 15 секунд, таймер ускорился и досчитал до 11:20, в следующем переключении отсчёт будет вестись не с 28:15 а с 11:20.
убрал из кода лишнее, прошу:
void BOMB_Arm() { start_num = (setup_num - (millis()/1000)); if (start_num > 0) { num_min = start_num / 60; num_sec = start_num % 60; num_time = ((num_min*100)+num_sec); displayNumber(num_time); } if(start_num <= 0) { // reached zero, flash the display time = millis(); while(millis() < time+200) { displayNumber(0); } time=millis(); while(millis() < time+200) { lightNumber(10); } } } void BOMB_Disarm() { start_num = (setup_num - 0); if (start_num > 0) { num_min = start_num / 60; num_sec = start_num % 60; num_time = ((num_min*100)+num_sec); time = millis(); while(millis() < time+500) { displayNumber(num_time); } time=millis(); while(millis() < time+500) { lightNumber(10); } } } void BOMB_Duble_arm() { start_num = (setup_num - (millis()/100 )); if (start_num > 0) { num_min = start_num / 60; num_sec = start_num % 60; num_time = ((num_min*100)+num_sec); // Serial.println(num_time); displayNumber(num_time); } if(start_num <= 0) { time = millis(); while(millis() < time+200) { displayNumber(0); } time=millis(); while(millis() < time+200) { lightNumber(10); } } }отдельно подпрограммы работают как нужно.
Так для этого Вам надо значения времени хранить в собственном регистре, а не использовать регистр millis, который Вы не меняете.
Кстати, а что мешает воспользоваться честным таймером, безо всяких millis'ов? Тогда эта проблема просто не возникла бы.
Задолбали!
Не ломается ничего!
Лешак уже два года обратно как доказал.
Так для этого Вам надо значения времени хранить в собственном регистре, а не использовать регистр millis, который Вы не меняете.
Значение времени хранится в переменной start_num а в setup_num храню константу 3600 секунд. start_num = (setup_num - (millis()/1000)) т.е. каждую итерацию я вычитаю из 3600 текущее значение millis()/1000 ( делю на 1000 для получения секунд)
вот собсно и проблема использования милса:
результат в миллсе постоянно инкрементируется не зависимо от манипуляций с делениями и прочим, соответственно каждый раз вычитая из 3600 энное количество миллсов /100 или /1000 я меняю всего-лишь частное значение start_num. В самом первом сообщении я прибег к такому варианту:
if (Time_current_Millis - Time_previous_Millis >= Time_interval) { setup_num -= 1; Time_previous_Millis = Time_current_Millis; } start_num = setup_num;правда данный кусок кода не учитывает ускорения.
Вообщем запутался и начал ходить кругами, городя кучи ненужного кода.
Кстати, а что мешает воспользоваться честным таймером, безо всяких millis'ов? Тогда эта проблема просто не возникла бы.
Проблема в том, что не понимаю пока, как в ардуине (у меня кстати нано на 328 меге) хоть косвенно воздействовать на таймер, а уж как его настроить вообще для меня сейчас тьма.
И кстати, раз уж я тут начал попрошайничать советов и пинков, скажите пожалуйста, где прописаны все типы переменных, привычнее использовать uint8_t и прочие... и ещё одно: нахре... почему всем переменным везде присваивают тип int ? это примудрость такая ардуины или просто исходя из объема памяти, нет глубокого смысла в оптимальном указании типов?
И это... подскажите пожалуйста, как можно отредактировать первое сообщение, уж больно длинно оно, не увидел вначале спойлер, а теперь найти где редактировать не могу :)
Типы данных , а инты, это извращенная фантазия писателей примеров. Они видят мегамегу с 32000 ног.
про типы данных я в курсе, а где их править в библиотеках или может ещё где, не могу найти :( придётся дефайнить типо того:
кстати, может пригодится кому:
#ifndef GLOBAL_H #define GLOBAL_H //***************************************************************************** // CPU clock speed //#define F_CPU 16000000 // 16MHz //#define F_CPU 14745000 // 14.745MHz //#define F_CPU 12000000 // 12MHz //#define F_CPU 10000000 // 10MHz #define F_CPU 9600000 // 9.6MHz (internal) //define F_CPU 8000000 // 8MHz //#define F_CPU 7372800 // 7.37MHz //#define F_CPU 6000000 // 6MHz //#define F_CPU 4800000 // 4.8MHz (internal) //#define F_CPU 4000000 // 4MHz //#define F_CPU 3686400 // 3.69MHz //***************************************************************************** #define dev_ver 0x01; //версия device x.xx #define dev_sub_ver_hi 0x00;// #define dev_sub_ver_lo 0x00; // #define fw_ver 0x01 //версия firmware x.xx #define fw_sub_ver_hi 0x00 // #define fw_sub_ver_lo 0x00 // //***************************************************************************** enum {PRESSED,RELEASED}; enum {FALSE,TRUE}; //***************************************************************************** typedef unsigned char uint8_t; typedef unsigned int uint16_t; typedef unsigned long int uint32_t; typedef unsigned long long uint64_t; typedef signed char int8_t; typedef signed int int16_t; typedef signed long int int32_t; typedef signed long long int64_t; typedef unsigned char u_char; // 0..255 typedef unsigned int u_int; // 0..65535 typedef unsigned long u_long; // 0..4294967295 typedef unsigned long long u_2long; //0..18446744073709551615 typedef signed char s_char; // -128..127 typedef signed int s_int; // -32768..32767 typedef signed long s_long; // -2147483648..2147483647 typedef signed long long s_2long; // -9223372036854775808..9223372036854775807 //***************************************************************************** //***************************************************************************** #define ClearBit(reg, bit) reg &= (0<<(bit)) // пример: ClearBit(PORTB, 1); //сбросить 1-й бит PORTB #define SetBit(reg, bit) reg |= (1<<(bit)) // пример: SetBit(PORTB, 3); //установить 3-й бит PORTB void SetBitVal(u_char reg, u_char bit, u_char val) { // пример: SetBitVal(PORTB, 3, 1); do //установить 3-й бит PORTB { // SetBitVal(PORTB, 2, 0); if ((val&1)==0) reg &= (~(1<<(bit))); //сбросить 2-й бит PORTB else reg |= (1<<(bit)); } while(0); }; #define BitIsClear(reg, bit) ((reg & (1<<(bit))) == 0) //пример: if (BitIsClear(PORTB,1)) {...} //если бит очищен #define BitIsSet(reg, bit) ((reg & (1<<(bit))) != 0) //пример: if(BitIsSet(PORTB,2)) {...} //если бит установлен #define InvBit(reg, bit) reg ^= (1<<(bit)) //пример: InvBit(PORTB, 1); //инвертировать 1-й бит PORTB //*****************************************************************************/* //eeprom #include <avr/eeprom.h> uint8_t start_eep_addr = 0x01; //начало блока данных uint8_t eeprom_data8 = 0x00;// uint16_t eeprom_data16 = 0x0000; uint32_t eeprom_data32 = 0x00000000; void write_eeprom(void)//запись даных в EEPROM { //все записи ведутся от нуля, при написании программы ПЕРЕРАСЧИТЫВАТЬ //адрес смещения ОБЯЗАТЕЛЬНО! иначе переменные "налезут" друг на друга eeprom_write_byte((uint8_t*)(start_eep_addr + 0), eeprom_data8); eeprom_write_word((uint16_t*)(start_eep_addr + 2), eeprom_data16); eeprom_write_dword((uint32_t*)(start_eep_addr + 4), eeprom_data32); _delay_us(50); }; void read_eeprom(void)//считывание даных из EEPROM { //все записи ведутся от нуля, при написании программы ПЕРЕРАСЧИТЫВАТЬ //адрес смещения ОБЯЗАТЕЛЬНО! иначе переменные "налезут" друг на друга eeprom_data8 = eeprom_read_byte((uint8_t*)(start_eep_addr + 0)); eeprom_data16 = eeprom_read_word((uint16_t*)(start_eep_addr + 2)); eeprom_data32 = eeprom_read_dword((uint32_t*)(start_eep_addr + 4)); _delay_us(50); }; */ #endifred.kaktus.37
SLOM
Именно так, проводки не те резанул и как в том анекдоте: одна нога здесь, другая там :)
подробней читать не знаю где, пока не до конца получилось, код могу скинуть, плату накидал минут за 10 под отладку, так и оставил собсно, это добро тож могу скинуть.
если несложно на мыло slom1@list.ru
для детей делаю праздники, постоянно нахожусь в поиске нового реквезита, есть идея, нужен обратный отсчет, правда хочу его реализовать на точечной матрице
http://arduino.ru/forum/programmirovanie/led-matritsa-max7219-maxmatrixl...
Задолбали!
Не ломается ничего!
Лешак уже два года обратно как доказал.
Да, но когда Вы прекратили ускоряться, Вы же опять к миллисовому буферу возвращаетесь.
А с таймреом. там все несложно, давайте е-майл, пришлю подробный мануал с примерами. Если читаете по английски, могу дать годные ссылки про таймеры - там все и точно и просто одновременно.
ЕвгенийП
за любой пинок в сторону полезной инфы и примеров буду благодарен :) английский читаю, так что и их скидывайте.
red.kaktus.37@gmail.com
Сначала ссылки, читаем вот в таком порядке:
http://maxembedded.com/2011/06/introduction-to-avr-timers/
http://maxembedded.com/2011/06/avr-timers-timer0/
http://maxembedded.com/2011/06/avr-timers-timer1/
http://maxembedded.com/2011/06/avr-timers-timer2/
http://maxembedded.com/2011/07/avr-timers-ctc-mode/
Становится всё понятно, но кое-какие тонкости автор не рассмотрел, например, нигде не сказал, что таймер может быть просто нафиг отключён для экономии энергии и не показал как его включать. А кое-где пишет как принято в примерах, а не в серьёзных разработках, например, нагло вставляет sei() после инициализации таймера.
Но в целом, ссылки годные.
Некоторые из этих тонкостей, рассматриваются в мануале, который сейчас вышлю по почте.
Ну и, наконец, самый кошерный источник информации - datasheet контроллера ATMega328 - там на 650 страницах написано ВСЁ. Взять можно - http://www.atmel.com/images/Atmel-8271-8-bit-AVR-Microcontroller-ATmega48A-48PA-88A-88PA-168A-168PA-328-328P_datasheet_Complete.pdf
Собсно код готов, просивший железку её получил, но для себя всё таки должен разобраться с вопросом :)
[code] uint8_t digit1 = 11; //Анод десятки минут uint8_t digit2 = 10; //Анод единицы минут uint8_t digit3 = 9; //Анод десятки секунд uint8_t digit4 = 6; //Анод единицы секунд uint8_t segA = 3; //Катод сегмента А uint8_t segB = 2; //... uint8_t segC = 7; //... uint8_t segD = 8; //... uint8_t segE = 12; //... uint8_t segF = 4; //... uint8_t segG = 5; //Катод сегмента G uint8_t LedPin = 13; //помигиваем светодиодиком как в сурьёзных часиках uint8_t A = 14; // uint8_t B = 15; // uint8_t C = 16; // uint8_t D = 17; // uint8_t Coil_1 = 18;//выход бомба обезврежена uint8_t Coil_2 = 19;//выход бомба 3.14-зданула int16_t setup_num = 3600; // int16_t start_num; uint8_t num_min; uint8_t num_sec; int16_t num_time; uint16_t Blink_time = 500; static uint16_t last_time; uint16_t intererval = 500; uint8_t ledState = LOW; uint32_t previousMillis = 0; uint8_t In_A; uint8_t In_B; uint8_t In_C; uint8_t In_D; uint8_t flag = LOW; uint32_t time; void setup() { pinMode(segA, OUTPUT); pinMode(segB, OUTPUT); pinMode(segC, OUTPUT); pinMode(segD, OUTPUT); pinMode(segE, OUTPUT); pinMode(segF, OUTPUT); pinMode(segG, OUTPUT); pinMode(digit1, OUTPUT); pinMode(digit2, OUTPUT); pinMode(digit3, OUTPUT); pinMode(digit4, OUTPUT); pinMode(LedPin, OUTPUT); pinMode(A, INPUT_PULLUP); digitalWrite(A, HIGH); pinMode(B, INPUT_PULLUP); digitalWrite(B, HIGH); pinMode(C, INPUT_PULLUP); digitalWrite(C, HIGH); pinMode(D, INPUT_PULLUP); digitalWrite(D, HIGH); pinMode(Coil_1, OUTPUT); digitalWrite(Coil_1, HIGH); //закрыли замок pinMode(Coil_2, OUTPUT); digitalWrite(Coil_2, LOW); //отключили парогенератор } void loop() { uint32_t currentMillis = millis(); if (currentMillis - previousMillis > intererval) { previousMillis = currentMillis; if (ledState == LOW) ledState = HIGH; else ledState = LOW; digitalWrite(LedPin, ledState); } In_A = digitalRead(A);//A - замкнуть на землю (изначально подтянут к питанию) In_B = digitalRead(B);//B - создать разрыв цепи (изначально подтянут к питанию) In_C = digitalRead(C);//C - замкнуть на землю (изначально подтянут к питанию) In_D = digitalRead(D);//D - создать разрыв цепи (изначально подтянут к питанию) uint8_t inputs_state = (((In_A << 3) + (In_B << 2) + (In_C << 1) + (In_D)) * 0x0F); if (flag == LOW) { if (inputs_state == 0) { BOMB_Arm(); } else { flag = HIGH; switch (inputs_state) { case 75:// - timer stop BOMB_Disarm(); break; default:// - timer duble speed BOMB_x2time_Arm(); break; } } } if (flag == HIGH) { switch (inputs_state) { case 75:// - timer stop BOMB_Disarm(); break; default:// - timer duble speed BOMB_x2time_Arm(); break; } } } //---BOMB-ARM----------------------------- void BOMB_Arm() { start_num = (setup_num - (millis() / 1000)); if ((start_num > 0) && (start_num < 3600)) { num_min = start_num / 60; num_sec = start_num % 60; num_time = ((num_min * 100) + num_sec); displayNumber(num_time); digitalWrite(Coil_1, HIGH); digitalWrite(Coil_2, LOW); last_time = start_num; } if ((start_num <= 0) || (start_num > 3600)) { time = millis(); while (millis() < time + Blink_time) { displayNumber(0); digitalWrite(LedPin, HIGH); digitalWrite(Coil_1, LOW); digitalWrite(Coil_2, HIGH); } time = millis(); while (millis() < time + Blink_time) { lightNumber(10); digitalWrite(LedPin, HIGH); digitalWrite(Coil_1, LOW); digitalWrite(Coil_2, HIGH); } } } //---BOMB-DISARM-------------------------- void BOMB_Disarm() { start_num = last_time; if ((start_num > 0) && (start_num < 3600)) { num_min = start_num / 60; num_sec = start_num % 60; num_time = ((num_min * 100) + num_sec); time = millis(); while (millis() < time + Blink_time) { displayNumber(num_time); digitalWrite(LedPin, HIGH); digitalWrite(Coil_1, LOW); digitalWrite(Coil_2, LOW); } time = millis(); while (millis() < time + Blink_time) { lightNumber(10); digitalWrite(LedPin, LOW); digitalWrite(Coil_1, LOW); digitalWrite(Coil_2, LOW); } } if ((start_num <= 0) || (start_num > 3600)) { time = millis(); while (millis() < time + Blink_time) { displayNumber(0); digitalWrite(LedPin, HIGH); digitalWrite(Coil_1, LOW); digitalWrite(Coil_2, HIGH); } time = millis(); while (millis() < time + Blink_time) { lightNumber(10); digitalWrite(LedPin, HIGH); digitalWrite(Coil_1, LOW); digitalWrite(Coil_2, HIGH); } } } //---BOMB-x2time-ARM---------------------- void BOMB_x2time_Arm() { start_num = (setup_num - (millis() / 100)); if ((start_num > 0) && (start_num < 3600)) { num_min = start_num / 60; num_sec = start_num % 60; num_time = ((num_min * 100) + num_sec); displayNumber(num_time); digitalWrite(Coil_1, HIGH); digitalWrite(Coil_2, LOW); last_time = start_num; } if ((start_num <= 0) || (start_num > 3600)) { time = millis(); while (millis() < time + Blink_time) { displayNumber(0); digitalWrite(LedPin, HIGH); digitalWrite(Coil_1, LOW); digitalWrite(Coil_2, HIGH); } time = millis(); while (millis() < time + Blink_time) { lightNumber(10); digitalWrite(LedPin, HIGH); digitalWrite(Coil_1, LOW); digitalWrite(Coil_2, HIGH); } } } //----------------------------------------------------------------------------- void displayNumber(int16_t toDisplay) { #define DISPLAY_BRIGHTNESS 200 #define DIGIT_ON HIGH #define DIGIT_OFF LOW uint32_t begintime = millis(); for (uint16_t digit = 4 ; digit > 0 ; digit--) { switch (digit) { case 1: digitalWrite(digit1, DIGIT_ON); break; case 2: digitalWrite(digit2, DIGIT_ON); break; case 3: digitalWrite(digit3, DIGIT_ON); break; case 4: digitalWrite(digit4, DIGIT_ON); break; } lightNumber(toDisplay % 10); toDisplay /= 10; delayMicroseconds(DISPLAY_BRIGHTNESS); lightNumber(10); digitalWrite(digit1, DIGIT_OFF); digitalWrite(digit2, DIGIT_OFF); digitalWrite(digit3, DIGIT_OFF); digitalWrite(digit4, DIGIT_OFF); } while ( (millis() - begintime) < 10) ; } void lightNumber(uint16_t numberToDisplay) { #define SEGMENT_ON LOW #define SEGMENT_OFF HIGH switch (numberToDisplay) { case 0: digitalWrite(segA, SEGMENT_ON); digitalWrite(segB, SEGMENT_ON); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_ON); digitalWrite(segE, SEGMENT_ON); digitalWrite(segF, SEGMENT_ON); digitalWrite(segG, SEGMENT_OFF); break; case 1: digitalWrite(segA, SEGMENT_OFF); digitalWrite(segB, SEGMENT_ON); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_OFF); digitalWrite(segE, SEGMENT_OFF); digitalWrite(segF, SEGMENT_OFF); digitalWrite(segG, SEGMENT_OFF); break; case 2: digitalWrite(segA, SEGMENT_ON); digitalWrite(segB, SEGMENT_ON); digitalWrite(segC, SEGMENT_OFF); digitalWrite(segD, SEGMENT_ON); digitalWrite(segE, SEGMENT_ON); digitalWrite(segF, SEGMENT_OFF); digitalWrite(segG, SEGMENT_ON); break; case 3: digitalWrite(segA, SEGMENT_ON); digitalWrite(segB, SEGMENT_ON); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_ON); digitalWrite(segE, SEGMENT_OFF); digitalWrite(segF, SEGMENT_OFF); digitalWrite(segG, SEGMENT_ON); break; case 4: digitalWrite(segA, SEGMENT_OFF); digitalWrite(segB, SEGMENT_ON); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_OFF); digitalWrite(segE, SEGMENT_OFF); digitalWrite(segF, SEGMENT_ON); digitalWrite(segG, SEGMENT_ON); break; case 5: digitalWrite(segA, SEGMENT_ON); digitalWrite(segB, SEGMENT_OFF); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_ON); digitalWrite(segE, SEGMENT_OFF); digitalWrite(segF, SEGMENT_ON); digitalWrite(segG, SEGMENT_ON); break; case 6: digitalWrite(segA, SEGMENT_ON); digitalWrite(segB, SEGMENT_OFF); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_ON); digitalWrite(segE, SEGMENT_ON); digitalWrite(segF, SEGMENT_ON); digitalWrite(segG, SEGMENT_ON); break; case 7: digitalWrite(segA, SEGMENT_ON); digitalWrite(segB, SEGMENT_ON); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_OFF); digitalWrite(segE, SEGMENT_OFF); digitalWrite(segF, SEGMENT_OFF); digitalWrite(segG, SEGMENT_OFF); break; case 8: digitalWrite(segA, SEGMENT_ON); digitalWrite(segB, SEGMENT_ON); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_ON); digitalWrite(segE, SEGMENT_ON); digitalWrite(segF, SEGMENT_ON); digitalWrite(segG, SEGMENT_ON); break; case 9: digitalWrite(segA, SEGMENT_ON); digitalWrite(segB, SEGMENT_ON); digitalWrite(segC, SEGMENT_ON); digitalWrite(segD, SEGMENT_ON); digitalWrite(segE, SEGMENT_OFF); digitalWrite(segF, SEGMENT_ON); digitalWrite(segG, SEGMENT_ON); break; case 10: digitalWrite(segA, SEGMENT_OFF); digitalWrite(segB, SEGMENT_OFF); digitalWrite(segC, SEGMENT_OFF); digitalWrite(segD, SEGMENT_OFF); digitalWrite(segE, SEGMENT_OFF); digitalWrite(segF, SEGMENT_OFF); digitalWrite(segG, SEGMENT_OFF); break; } } [/code]за ссылки и мануалы, пасиба, даташыт... тут какбэ не поможет, пока не освоюсь именно на ардуине. на сях повторюсь - не сложно, там то как раз даташит и больше ничего и не нужно. а серьёзные проекты делать на ардуине - мне кажется... странным :)
А почему странно? Контроллер плох или Вас смущает, что его уже на плату впаяли?
Кстати, я отправил e-amil
плюсы большие конечно - не задумываясь шимить выходы, ацпшить входы и прочее, но!
сам факт того, что я не могу без лазанья по всем либам определить время выполнения того или иного макроса, не вижу железных регистров и не могу извращаться, пусть с тем же таймером, без всяких лишних библиотек - вот что странно. да и объём кода... так что сложные проекты только сио вставками асма :) а побаловаться - ардуина )))
найти бы на неё пооолный мануал - не плохо было бы увидеть воочию, что можно вписать (типа того же sei() cli() nop() ) короче говоря, когда вникну полностью в ардуину, тогда и буду говорить точно, а пока - только странно и всё :)
на данный момент хотелось бы вот так писать: (пример под тиньку 13а 2 канала ацп -> шим с арифметическим усреднением результата на выходе шима)
/* * Tiny13_adc2pwm.c * * Created: 02.01.2013 16:16:01 * Author: kaktus */ /****************************************************/ #include "global.h" #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> /****************************************************/ #define count_num 512; //количество замеров #define count_shift 9; //расчёт сдвига от кол-ва замеров: //2^1=2 2^2=4 2^3=8 2^4=16 //2^5=32 2^6=64 2^7=128 2^8=256 //2^9=512 2^10=1024 2^11=2048 2^12=4096 //2^13=8192 2^14= 2^15=16384 2^16=32768 //adc uint32_t conversion_averaging_ADC3_Ch = 0;//накопитель для усреднения результата uint8_t conversion_result = 0;//измерение получаем сюда uint16_t conversion_count = count_num;//производим Х замеров, с последующим их сложением и сдвигом //pwm uint8_t PWM_MIN = 255; uint8_t PWM_MAX = 0 uint8_t PWM_State = 0; //functional enum { ON, OFF}; /****************************************************/ ISR(TIM0_OVF_vect) { InvBit(PORTB,4); }; ISR(ADC_vect) { conversion_result = (ADC >> 8); if (conversion_count !=0) { conversion_averaging_ADC3_Ch += conversion_result; conversion_count--; }; }; /****************************************************/ void adc_conversion(void) { ADMUX |= ((1<<MUX1)|(1<<MUX0)); _delay_us(10); ADCSRA |= (1<<ADSC); while (ADIF == 0); _delay_us(1); return ADIF; }; /****************************************************/ int main (void) { cli(); // RST no use ADC3_Ch no use PWM_ch2 PWM_ch1 PORTB = (1<<PORTB5)|(0<<PORTB4)|(0<<PORTB3)|(0<<PORTB2)|(0<<PORTB1)|(0<<PORTB0); DDRB = (1<<DDB5) |(0<<DDB4) |(0<<DDB3) |(0<<DDB2) |(0<<DDB1) |(0<<DDB0); //тупим много много _delay_ms(500); _delay_ms(500); //ADC initialize ACSR = 0x80; ADCSRA = 0x00; ADMUX = (0<<REFS0)|(1<<ADLAR)|(1<<MUX1)|(1<<MUX0);//MUX=00-PB5(ADC0); 11-PB3(ADC3); ADCSRB = (0<<ACME)|(0<<ADTS2)|(0<<ADTS1)|(0<<ADTS0); ADCSRA = (1<<ADEN)|(0<<ADSC)|(0<<ADATE)|(0<<ADIF)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); DIDR0 = (0<<ADC0D)|(0<<ADC2D)|(0<<ADC3D)|(0<<ADC1D); //FPWM WGM = 3 (TOP = 0xFF) //37,500KHz //NON INVERT (COM0A = 2) TCCR0B = 0x00; OCR0A = PWM_MIN-1; OCR0B = PWM_MIN-1; TCNT0 = 0x00; //FAST PWM -> TOP = 0xFF TCCR0A = (1<<COM0A1)|(0<<COM0A0)|(1<<COM0B1)|(0<<COM0B0)|(1<<WGM01)|(1<<WGM00); TCCR0B = (0<<FOC0A)|(0<<FOC0B)|(0<<WGM02)|(0<<CS02)|(0<<CS01)|(1<<CS00); //Fase Correct PWM -> TOP = 0xFF //TCCR0A = (1<<COM0A1)|(0<<COM0A0)|(0<<COM0B1)|(0<<COM0B0)|(0<<WGM01)|(1<<WGM00); //TCCR0B = (0<<FOC0A)|(0<<FOC0B)|(0<<WGM02)|(0<<CS02)|(0<<CS01)|(1<<CS00); MCUCR = (0<<PUD)|(0<<ISC01)|(0<<ISC00);// 01 - any level change INTn TIMSK0 = (0<<OCIE0B)|(0<<OCIE0A)|(1<<TOIE0);//TIM0_COMPA_vect enable GIMSK = (0<<INT0)|(0<<PCIE); PCMSK = (0<<PCINT5)|(0<<PCINT4)|(0<<PCINT3)|(0<<PCINT2)|(0<<PCINT1)|(0<<PCINT0); //RST -PB5 VCC- 5V //ADC -PB3 PB2- // -PB4 PB1- PWM_2ch //ground -GND PB0- PWM_1ch // RST no use ADC3_Ch no use PWM_ch2 PWM_ch1 PORTB = (1<<PORTB5)|(0<<PORTB4)|(1<<PORTB3)|(0<<PORTB2)|(0<<PORTB1)|(0<<PORTB0); DDRB = (1<<DDB5) |(1<<DDB4) |(0<<DDB3) |(0<<DDB2) |(1<<DDB1) |(1<<DDB0); CLKPR=0x80; CLKPR=0x00; sei(); /****************************************************/ while (1) { adc_conversion(); if (conversion_count == 0) { cli(); //расчёт сдвига от кол-ва замеров: //2^1=2 2^2=4 2^3=8 2^4=16 //2^5=32 2^6=64 2^7=128 2^8=256 //2^9=512 2^10=1024 2^11=2048 2^12=4096 //2^13=8192 2^14= 2^15=16384 2^16=32768 conversion_averaging_ADC3_Ch >>= count_shift; conversion_averaging_ADC3_Ch &= 0x000000ff; PWM_State = conversion_averaging_ADC3_Ch; OCR0A = PWM_State; OCR0B = PWM_State; conversion_count = count_num; sei(); }; }; return 1; }_______________________________
Начал читать ссылки и мануал калл бэк который, стыдно стало :) вроде всё железное есть в прямом доступе :)))))))
Совершенно верно, до любого регистра можно добраться по его адресу, а уж адрес записать обычным С-шным указателем можно безо всякого ассемблера. Так что добираться можно реально до всего.
Шимить и АЦП-шить, так это в контроллере в железе, ардуина тут не при делах. А библиотеки - так пишите напрямую с железом, кто мешает.
Да, нет, контроллер как контроллер а на чём писать ... мне лично разницы нет. В ардуиине сидит полный С++, мало - есть ассемблер, не вижу проблемы.
red.kaktus.37 спасибо за код, скажите а какая схема у вас для него собрана? какие модули использованы?
у меня вот такие:
https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcTtyqn5_vD1t3EsbttTF_DOOnc3GqoM-WU-Yo-32yZpnpHkQRgllQ
http://ru.aliexpress.com/item/1pcs-MAX7219-dot-matrix-module-microcontro...
как на них сделать обратный отсчет, хочу сделать "гаситель звезд" :)
нашел интересную штуку :)
http://cxem.net/mc/mc305.php
и еще
http://www.instructables.com/id/Arduino-defuseable-bomb-perfect-for-airs...
Я думал они тут обычный таймер делают по заказу всяких Махмудов. А они тут Звезду Смерти разрабатывают
SLOM
модуль собсно одни - ардуина нана %) индикаторы KEM-1106BR релюшки TRA1-12 дабы не нагружать usb порт, всё навесное кроме ардуины питается с 7805, ардуина кстати питается тож с неё через диод ( там на платке запаян) собсно всё.
О_О а зачем Вам звёзды гасить? от них же свет и тепло :) нинада нам вечную ночь )))))))))))))
плату и схему в пикаде скину на мыло еси нужно
ЕвгенийП
как раз таки первый раз взяв это чудовище в руки начал тонуть в непонимании чего с чем и куда пихать и как это вообще всё происходит ) глянул мануал, полистал библиотечки - и таки увидел, что и хотел просто из-за макросов не разглядеть реального кода :) по началу путает очень.
в топку террористов, трансформеры рулят :)
red.kaktus.37 да это ненастоящий гаситель звезд :)
реквезит для детского праздника)
red.kaktus.37 да это ненастоящий гаситель звезд :)
реквезит для детского праздника)
Вот врун блин. Звезды на детском празднике гасить собрался. Кого из звезд пригласили? Надеюсь вся Российская попса в списке, :)
самое главное чтоб Киркоров и Пугачиха были их гасить нужно, пора им уже )))
Киркоров кстати это второе название болгарки xD киркоровка блин ))))))))))
мелко плаваете господа, тушить так сразу солнце :)
Гаситель звёзд/"Жнец" (Solar harvester) - огромная установка, которая активируется, чтобы уничтожить какую-либо звезду и взять её энергию. Незаменима в случаях, если нет возможности использовать ресурсы Великой Искры. Создаётся трансформерами, как правило, на естественном спутнике той звезды, которая будет уничтожена.
Да куда уж нам.
SLOM, а что там за контроллер? ARM? AVR?
где там? у меня ардуино нано :)
вот думаю как на нем сделать обратный отсчет...
Там - это в устройстве, изображённом на выложенном Вами фото:)
А что за проблемы обратным отсчётом? Там же типа ... два пальца.
Там - это в устройстве, изображённом на выложенном Вами фото:)
А что за проблемы обратным отсчётом? Там же типа ... два пальца.
там кибертронские технологии, подозреваю что использованы кремниевые нейросети :)
проблемы не с обратным отсчетом, а с тем что я не программист :) в этом вся и проблема :)
моих знаний хватает только на поиски, и небольшую модернизацию готового кода :(
у меня задача такая. на матрице, по типу...
реализовать примерно следующее:
вывод текстовой информации, в виде бегущей строки, для этого я уже наел подходящую библиотеку.
в тексте будет написана угроза глобального уничтожения солнечной системы :)
потом пойдет обратный отсчет на 1,5 или 1 час... переодически отсчет будет прерываться новым текстом... с заданиями. как включать их пока незнаю, возможно ик или р\с пультом дистанционно.
в финале когда дети выполнят все задания они получат энергетический куб, вставят его в гаситель звезд, там замкнеться геркон на магните, или просто какието контакты. в движение прийдут серво приводы, гаситель - "пирамида" откроеться и там внутри подарок именнинику... :)
п.с. в ходе мероприятия ни одна звезда не пострадает, Алла Борисовна и Филип Бедросович могут спать спокойно :)
обратный отсчёт берите хотяб из моего примера -
void BOMB_Arm() - вставляете после цикла луп, там, где все подпрограммы, вызов BOMB_Arm() тыкаете в цикл после какого-то условия. переменные
используемые в подпрограмме так же переносите
либо в луп либо в сэтап либо в секцию
инициализации. setup_num выставляете час.
если больше часа, нужно добавлять пару строк по аналогии.
дальше пересылаете результат в сдвиговый регистр индикатора.
чтоб время тикало постоянно, но была возможность прервать вывод времени и пульнуть в сдвиг Ваш текст, поставьте к примеру флаг, прям
перед вызовом подпрограммы го проверили, если 0, то посчитали и не показали.
ваши слова как мед! на рану :)
в теории все просто, а вот на практике)