Кухонный таймер

18GT19HT
Offline
Зарегистрирован: 23.08.2014

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

lazy-fox
Offline
Зарегистрирован: 22.08.2014

Предполагал использовать часы на DS1307. Устанавливать их пока при включении:

DS1307 clock; //define a object of DS1307 class
void setup() 
{
	clock.fillByYMD(2013,1,19);//Jan 19,2013
	clock.fillByHMS(15,28,30);//15:28 30"
	clock.fillDayOfWeek(SAT);//Saturday
	clock.setTime();//write time to the RTC chip
}
clock.getTime();

В дальнейшем #18 думал получать от центрального таймера по SPI:

lazy-fox пишет:

Например, если у меня будет центральный таймер в коридоре с выходом в интернет, и я захочу с него обмениваться информацией с периферийными таймерами - кухонным (сварились ли пельмени), комнатным(будильник прикроватный с монитором сна), и балконным(телескоп следящий за положением тел в альфа-центавре), а так же таймерами робота-пылесоса и робота-пивовара, - тогда да без SPI не обойтись, а тут?

18GT19HT
Offline
Зарегистрирован: 23.08.2014

Нет, ты меня не понял: Как войти в режим установки времени?

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013
rtc.adjust(DateTime(2014, 8, 28, 17, 29, 0));

 

lazy-fox
Offline
Зарегистрирован: 22.08.2014

Понял. Повторяю: в модуле setup {} мы устанавливаем время. Один раз. И больше прибор не выключаем. До тех пор пока не приделаю коррекцию по SPI.

lazy-fox
Offline
Зарегистрирован: 22.08.2014

jeka_tm пишет:

rtc.adjust(DateTime(2014, 8, 28, 17, 29, 0));

Так короче. Только сегодня 27 августа... Или это с учётом дня на размышления ;)

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

с учетом конечно)) хотя может мало добавил

lazy-fox
Offline
Зарегистрирован: 22.08.2014

Про представление времени и альтернативные (бинарные) часы была хорошая статья на Хабре, и не менее чудные комменты:

Ocelot, 9 марта 2012 в 15:35#
zero_trigger, вы молодец! Сделано красиво, аккуратно и с любовью к мелочам. Скажите, после некоторой тренеровки удается с одного взгляда определять время по таким часам, или все равно нужно тупить полминуты, переводя в уме bin->dec?
+1

zero_trigger, 9 марта 2012 в 15:47#

За неделю можно научиться определять секунд за 5-15. Честно говоря, я немного тормоз, поэтому наверняка у многих получится быстрее. Собственно, создание часов, таки преследовало цель научиться быстро понимать бин =). Спасибо)
+4

Ocelot, 9 марта 2012 в 15:50#

Тогда следующая ступень хардкора — 32 светодиода, показывающие POSIX-time. Заодно и вопрос с датой решается =)
+12

IkaR49, 9 марта 2012 в 17:31#

Если научиться с утра понимать такое время — можно начинать взглядом сгибать ложки :)

 

lazy-fox
Offline
Зарегистрирован: 22.08.2014

А это мысль! Давай как во всех электронных будильниках при включении если (clock.getTime() = 0,0,0,0,0,0) тогда горят пробелы (- - . - -), мы вводим номеронабирателем время (17.46) и часы запускаются: rtc.adjust(DateTime(2014,0,0,17,46,0)); Год нужен что бы каждую полночь в этот режим не вываливались. А в дальнейшем я заменю этот блок на авто коррекцию.

18GT19HT
Offline
Зарегистрирован: 23.08.2014

lazy-fox пишет:

jeka_tm пишет:

rtc.adjust(DateTime(2014, 8, 28, 17, 29, 0));

Так короче. Только сегодня 27 августа... Или это с учётом дня на размышления ;)

Эй, а про календарь ты ничего не говорил.

И если я тебя правильно понял, то часы устанавливаются при первом включении и если ты захочешь перевести время не фига не западло передернуть питание?

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

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

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

lazy-fox
Offline
Зарегистрирован: 22.08.2014

Календарь не нужен.

Про время. Нужно при включении установить текущее время с номеронабирателя. Я предложил по условию что год не заполнен (неважно какой, хоть 1234), после набора пишем в поле год - какой угодно год.  И когда наступит полночь, то условие 0,0,0,0,0,0 не выполнится, по тому что будет 1234,0,0,0,0,0!

18GT19HT
Offline
Зарегистрирован: 23.08.2014

как это сделать в смысле где этому место в алгоритме?

lazy-fox
Offline
Зарегистрирован: 22.08.2014

Напиши пока в setup{}, это не главный вопрос. Я пока не получил с ебея DS1307 толком не знаю подводных камней. Просто выведи статичное время. Пусть get time получает 0,0,0,18,12,0. Получу часы - буду думать. 

18GT19HT
Offline
Зарегистрирован: 23.08.2014

Я кодить не успеваю, в то время как новые функции меняют алгоритмы, а изменения схемы рушат всю концепцию.

lazy-fox
Offline
Зарегистрирован: 22.08.2014

Изначально предполагалось текущее время. Как именно с ним работать я пока точно не знаю, и буду дорабатывать его на финальном этапе разработки. Пока выведем статичное число 00.00 и все. Как его устанавливать и как корректировать на данном этапе не важно.

Сам концепт подразумевает собой исключительную простоту конструкции (как утюг или дисковый телефон). По этому регулировочные и корректирующие инструменты должны быть скрыты от неподготовленного пользователя.

18GT19HT
Offline
Зарегистрирован: 23.08.2014

Закодил часы. Если сегодня доделаю таймер, то завтра дам на тестирование в железе

lazy-fox
Offline
Зарегистрирован: 22.08.2014

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

При вращении диска цикл loop{} останавливается и выполняется подпрограмма номеронабирателя. Но обратно возвращается единица, а не количество единиц. Видимо прерыванием считается каждый импульс номеронабирателя. Такое ощущение что нужно считать количество вызовов подпрограммы номеронабирателя. В общем это возможно(count запихнуть внутрь подпрограммы прерывания), но как тогда разделять цифры номера (сбрасывать count)? По разнице во времени? 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

конечно по времени

18GT19HT
Offline
Зарегистрирован: 23.08.2014

отвечаю не вникая - возможно проблема в областе видимости переменных...

Я могу реализовать это без прерываний.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

и при этом будет работать не останавливаясь динамическая инидикация индикатора?

18GT19HT
Offline
Зарегистрирован: 23.08.2014

jeka_tm пишет:

и при этом будет работать не останавливаясь динамическая инидикация индикатора?

конечно

lazy-fox
Offline
Зарегистрирован: 22.08.2014

А пусть останавливается на время набора номера. Я про прерывания думал, что бы это красиво оформить. Ну и пропусков избежать ;)

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

чтобы не было пропусков конечно

хотелось бы доказательств. напишите код и проверим так ли все хорошо без прерываний и индикация при этом не портится

lazy-fox
Offline
Зарегистрирован: 22.08.2014

18GT19HT пишет:

Закодил часы. Если сегодня доделаю таймер, то завтра дам на тестирование в железе

По ходу занял я тебя сверхурочно своим прожектом. 

lazy-fox
Offline
Зарегистрирован: 22.08.2014

jeka_tm пишет:

чтобы не было пропусков конечно

хотелось бы доказательств. напишите код и проверим так ли все хорошо без прерываний и индикация при этом не портится

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

Пока меня смущает тот факт что прерывания могут использоваться только для получения импульса, а не для получения цифры номера. Думается возврат к millis() сведет на нет все старания.

Вспоминается правило Парето: 20% затрат дают 80% результата, и наоборот.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

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

18GT19HT
Offline
Зарегистрирован: 23.08.2014
на следующем этапе планирую добавить: селектор режимов и номеронабиратель

в целях тестирования таймер выставлен на 3 минуты, по истечении выводяться часы

 

lazy-fox
Offline
Зарегистрирован: 22.08.2014

Тест завтра, в два по полудни! 

18GT19HT
Offline
Зарегистрирован: 23.08.2014

В строке 157 неправильно отрабатывает правило

if (varDisplayNextTime <= micros() && varDisplayNextTime > micros() - varDisplayRefreshTime)

если заменить на

if (varDisplayNextTime <= micros())

должно работать, но небудет защиты от переполнения счетчика micros()

18GT19HT
Offline
Зарегистрирован: 23.08.2014


//Объявление глобальных переменных

//Сегменты табло через сдвиговый регистр 74HC595:
int latchPin = 7;  //to ST_CP
int clockPin = 6;  //to SH_CP
int dataPin = 5;  //to DS

//Выводы выбора разряда индикатора
int digit1Pin = 12;  //еденицы
int digit2Pin = 11;  //десятки
int digit3Pin = 10;  //сотни
int digit4Pin = 9;  //тысячи

//звуковая индикация
int buzzerPin = 3;

//номеронабиратель
int dialPin = 2;

//рычаг
int switchPin = 8;

//термодатчик
//int termoPin = ;

//varDisplayRefreshTime - время индикации символа в микросекундах
//чем больше тем ярче, при значительно больших значениях - проявиться мерцание
unsigned int varDisplayRefreshTime = 5000;

//varDisplayNextTime - расчетное время очередной индикации
unsigned long varDisplayNextTime = 0;

//varDysplayPosition - отображаемый разряд
byte varDysplayPosition = 0;

//varMode - режим работы
//0 - температура
//1 - N/U
//2 - таймер
//3 - часы
//4 - N/U
byte varMode = 3;

//varModeOld - предыдущий режим работы
byte varModeOld = 3;

//varSetMode - ожидание установки таймера
byte varSetMode = 0;

//Десятки секунд
unsigned long varTenSec;

//последнее состояние десятков секунд
byte varTenSecLast;

//минута
byte varMinuteCounter = 0;

//arrDysplaySymbols[11] - массив знакосинтезирующий
byte arrDysplaySymbols[11] = 
  {
  252,
  96,
  218,
  242,
  102,
  182,
  190,
  224,
  254,
  246,
  0
  };

//arrCounter[5] - массив показаний для различных режимов работы
int arrCounter[5];

//vardialPinState - состояние на входе dialPin
byte vardialPinState = 1;

//vardialPinLastState - последнее состояние на входе dialPin
byte vardialPinLastState = 1;

//vardialCount - текущее количество циклов опроса dialPin
int vardialCount = 0;

//vardialCountMin - минимальное количество циклов для защиты от дребезга контактов
int vardialCountMin = 10;

//vardialCountDigitNext - минимальное количество циклов для перехода к следующему разряду
int vardialCountDigitNext = 100;

//vardialCountEndOfSet - минимальное количество циклов для завершения ввода
int vardialCountEndOfSet = 500;



void setup()
{
//конфигурирование портов ввода/вывода
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(digit1Pin, OUTPUT);
  pinMode(digit2Pin, OUTPUT);
  pinMode(digit3Pin, OUTPUT);
  pinMode(digit4Pin, OUTPUT);

  pinMode(buzzerPin, OUTPUT);
  pinMode(dialPin, INPUT_PULLUP);
  pinMode(switchPin, INPUT_PULLUP);

//формирование на выводах начальных состояний
  digitalWrite(digit1Pin, HIGH);
  digitalWrite(digit2Pin, HIGH);
  digitalWrite(digit3Pin, HIGH);
  digitalWrite(digit4Pin, HIGH);

  Serial.begin(9600);  //отладка
//  arrCounter[2] = 20;  //отладка
  
//  dial(3);
}



void loop()
{
  varTenSec = millis()/10000;
  varTenSec = varTenSec%10;
  Display();
  Clock();
//контроль снятия с рычага
  if (digitalRead(switchPin) == LOW && varSetMode == 0)
  {
    if (varMode != 0)
	{
      varModeOld = varMode;
	}
    varMode = 0;
//вызов подпрограммы измерения температуры
  }
  else
  {
    varMode = varModeOld;
  }
//  dial(2);
//отладка>
  if (digitalRead(dialPin) == LOW)
  {
    arrCounter[1] ++;
    arrCounter[4] = 0;
  }
  else
  {
    arrCounter[1] = 0;
    arrCounter[4] ++;
  }
  Serial.print (arrCounter[1]);
  Serial.print ("\t");
  Serial.println (arrCounter[4]);
//<отладка
}



//dial() - подпрограмма номеронабирателя
void dial(byte varModeDial)
{
  if (digitalRead(dialPin) == LOW)
  {
    if (varSetMode == 0)
    {
      varSetMode = 1;
      varMode = varModeDial;
      vardialCount = 0;
    }
    vardialPinState = 1;
  }
  else
  {
    if (varSetMode == 0)
    {
      return;
    }
    vardialPinState = 0;
  }
//определение импульса
  if (vardialPinLastState == vardialPinState)
  {
    vardialCount ++;
  }
  else
  {
    vardialCount = 0;
  }

  if (vardialPinLastState == 0 && vardialPinState == 1 && vardialCount > vardialCountMin)
  {
//увеличить показания
    arrCounter[varModeDial] += 10;
//если десять импульсов, то ноль
    int varCounterDigitZero = arrCounter[varMode]%10;
    if (varCounterDigitZero == 0)
    {
      arrCounter[varModeDial] = arrCounter[varModeDial] - 100;
    }
    vardialPinLastState = 1;
  }

//переход к следующему разряду
  if (vardialPinLastState == 1 && vardialPinState == 0 && vardialCount > vardialCountDigitNext)
  {
    arrCounter[varModeDial] *= 10;
    vardialPinLastState = 0;
  }

//определение конца ввода
  if (vardialPinLastState == 0 && vardialPinState == 0 && vardialCount > vardialCountEndOfSet)
  {
    varSetMode = 0;
  }
}



//Clock() - подпрограмма часов
void Clock()
{
  if (varTenSecLast != varTenSec)
  {
    varTenSecLast = varTenSec;
    varMinuteCounter += 10;
    if (varMinuteCounter == 6)
    {
      varMinuteCounter = 0;
      arrCounter[3] ++;
      if (arrCounter[3]/10%10 == 6)
      {
        arrCounter[3] += 40;
      }
      if (arrCounter[3]/100%10 == 4 && arrCounter[3]/1000%10 == 2)
      {
        arrCounter[3] = 0;
      }
    }
    if (arrCounter[2] != 0 && varSetMode == 0)
    {
      Timer();
    }
  }
}



//Timer() - подпрограмма таймера
void Timer()
{
  arrCounter[2] --;
  if (arrCounter[2]%10 >= 6)
  {
    arrCounter[2] = arrCounter[2] - 4;
  }
  if (arrCounter[2] == 20)
  {
    beepOn();
  }
  if (arrCounter[2] == 14)
  {
    beepOff();
  }
  if (arrCounter[2] < 2)
  {
    beepOn();
  }
  if (arrCounter[2] == 0)
  {
    varMode = 3;
    beepOff();
  }
}



//beepOn() - подпрограмма звуковой индикации
void beepOn()
{
  analogWrite(buzzerPin, 127);
}



//beepOff() - подпрограмма звуковой индикации
void beepOff()
{
  analogWrite(buzzerPin, 0);
}



//Display() - подпрограмма индикации
void Display()
{
  int digitPinOff;
  int digitPinOn;
  int DisplayDigital;
//  if (varDisplayNextTime <= micros() && varDisplayNextTime > micros() - varDisplayRefreshTime)
  if (varDisplayNextTime <= micros())
  {
    varDisplayNextTime += varDisplayRefreshTime;
    varDysplayPosition = varDysplayPosition + 1;
    if (varDysplayPosition > 4)
    {
      varDysplayPosition = 1;
    }
    switch (varDysplayPosition)
    {
      case 1:
        DisplayDigital = arrCounter[varMode]*10%10;
        DisplayDigital = arrDysplaySymbols[DisplayDigital];
        digitPinOff = digit4Pin;
        digitPinOn = digit1Pin;
      break;
      case 2:
        if (arrCounter[varMode] > 9 || varMode == 3)
        {
          DisplayDigital = arrCounter[varMode]%10;
          DisplayDigital = arrDysplaySymbols[DisplayDigital];
        }
        else
        {
          DisplayDigital = arrDysplaySymbols[11];
        }
        digitPinOff = digit1Pin;
        digitPinOn = digit2Pin;
      break;
      case 3:
        if (arrCounter[varMode] > 99 || varMode == 3)
        {
          DisplayDigital = arrCounter[varMode]/10%10;
          DisplayDigital = arrDysplaySymbols[DisplayDigital];
        }
        else
        {
          DisplayDigital = arrDysplaySymbols[11];
        }
        digitPinOff = digit2Pin;
        digitPinOn = digit3Pin;
      break;
      case 4:
        if (arrCounter[varMode] > 999)
        {
          DisplayDigital = arrCounter[varMode]/100%10;
          DisplayDigital = arrDysplaySymbols[DisplayDigital];
        }
        else
        {
          DisplayDigital = arrDysplaySymbols[11];
        }
        digitPinOff = digit3Pin;
        digitPinOn = digit4Pin;
      break;
    }
    if (varMode == varDysplayPosition)
    {
      unsigned long varPointBlinkTime = millis()/500;
      varPointBlinkTime = varPointBlinkTime%10;
      varPointBlinkTime = varPointBlinkTime & B00000001;
      if (varPointBlinkTime == 1 || varSetMode == 1)
      {
        DisplayDigital = DisplayDigital ^ B00000001;
      }
    }
    digitalWrite(digitPinOff, HIGH);
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, LSBFIRST, DisplayDigital);
    digitalWrite(latchPin, HIGH);
    digitalWrite(digitPinOn, LOW);
  }
}

нужно сделать натурное испытание:

1. подключить номеронабиратель между землей и pin 2

2. набрать 1 и посотреть в консоли какое число будет выведено последним

Исправил ошибки.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

когда испытания?

lazy-fox
Offline
Зарегистрирован: 22.08.2014
Вся неделя в разъездах, по сему сорри за таймаут. 
 
Выкладываю монитор пора по результатам теста. 

18GT19HT пишет:

нужно сделать натурное испытание:

Кстати разряды, перевернуть?  ;)

//Выводы выбора разряда индикатора
int digit1Pin = 9;  //единицы
int digit2Pin = 10;  //десятки
int digit3Pin = 11;  //сотни
int digit4Pin = 12;  //тысячи

 

18GT19HT
Offline
Зарегистрирован: 23.08.2014




//Объявление глобальных переменных

//Сегменты табло через сдвиговый регистр 74HC595:
const int latchPin = 7;  //to ST_CP
const int clockPin = 6;  //to SH_CP
const int dataPin = 5;  //to DS

//Выводы выбора разряда индикатора
const int digit1Pin = 9;  //еденицы
const int digit2Pin = 10;  //десятки
const int digit3Pin = 11;  //сотни
const int digit4Pin = 12;  //тысячи

//звуковая индикация
const int buzzerPin = 3;

//номеронабиратель
const int dialPin = 2;

//рычаг
const int switchPin = 8;

//термодатчик
//const int termoPin = ;

//varDisplayRefreshTime - время индикации символа в микросекундах
//чем больше тем ярче, при значительно больших значениях - проявиться мерцание
const unsigned int varDisplayRefreshTime = 5000;

//varDisplayNextTime - расчетное время очередной индикации
unsigned long varDisplayNextTime = 0;

//varDysplayPosition - отображаемый разряд
byte varDysplayPosition = 0;

//varMode - режим работы
//0 - температура
//1 - N/U
//2 - таймер
//3 - часы
//4 - N/U
byte varMode = 3;

//varModeOld - предыдущий режим работы
byte varModeOld = 3;

//varSetMode - ожидание установки таймера
byte varSetMode = 0;

//Десятки секунд
unsigned long varTenSec;

//последнее состояние десятков секунд
byte varTenSecLast;

//минута
byte varMinuteCounter = 0;

//arrDysplaySymbols[11] - массив знакосинтезирующий
const byte arrDysplaySymbols[11] = 
  {
  252,
  96,
  218,
  242,
  102,
  182,
  190,
  224,
  254,
  246,
  0
  };

//arrCounter[5] - массив показаний для различных режимов работы
long arrCounter[5];

//vardialPinState - состояние на входе dialPin
byte vardialPinState = 1;

//vardialPinLastState - последнее состояние на входе dialPin
byte vardialPinLastState = 1;

//vardialReadyDigitNext - готовность к вводу следующего разряда
byte vardialReadyDigitNext = 0;

//vardialPinPulseLock - имульс зафиксирован
byte vardialPinPulseLock = 0;

//vardialCount - текущее количество циклов опроса dialPin
word vardialCount = 0;

//vardialCountMin - минимальное количество циклов для защиты от дребезга контактов
const word vardialCountMin = 3;

//vardialCountDigitNext - минимальное количество циклов для перехода к следующему разряду
const word vardialCountDigitNext = 100;

//vardialCountEndOfSet - минимальное количество циклов для завершения ввода
const word vardialCountEndOfSet = 15000;


//vardialChangeTime
long vardialChangeTime = 0;



void setup()
{
//конфигурирование портов ввода/вывода
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(digit1Pin, OUTPUT);
  pinMode(digit2Pin, OUTPUT);
  pinMode(digit3Pin, OUTPUT);
  pinMode(digit4Pin, OUTPUT);

  pinMode(buzzerPin, OUTPUT);
  pinMode(dialPin, INPUT_PULLUP);
  pinMode(switchPin, INPUT_PULLUP);

//формирование на выводах начальных состояний
  digitalWrite(digit1Pin, HIGH);
  digitalWrite(digit2Pin, HIGH);
  digitalWrite(digit3Pin, HIGH);
  digitalWrite(digit4Pin, HIGH);

  Serial.begin(9600);  //отладка
//arrCounter[2] = 1234;  //отладка
//varMode = 2;  //отладка
//установка часов
  do
  {
    Display();
    dial(3);
    if (arrCounter[3] == 0) varSetMode = 1;
  } while (varSetMode == 1);
}



void loop()
{
  varTenSec = millis()/10000;
  varTenSec = varTenSec%10;
  Display();
  Clock();
  thermo();
  Display();
  dial(2);

//checkDialer();  //отладка
//out2con();  //отладка
}



//dial(*) - подпрограмма номеронабирателя
//* - режим работы для которого осуществляется ввод
void dial(byte varModeDial)
{
  vardialPinState = digitalRead(dialPin);
  if (vardialPinState != vardialPinLastState)
  {
    vardialChangeTime = millis();
  }
  if (vardialPinState == 1)
  {// вход врежим установки и подсчет импульсов
    if (varSetMode == 0)
    {// вход врежим установки
      varSetMode = 1;
      varMode = varModeDial;
      vardialCount = 0;
      arrCounter[varModeDial] = 0;
    }
    else
    {// подсчет импульсов
      if ((millis() - vardialChangeTime) > vardialCountMin && vardialPinPulseLock == 0)
      {
        if (vardialReadyDigitNext == 0 && varModeDial == 3)
        {
          arrCounter[varModeDial] *= 10;
        }
        arrCounter[varModeDial] ++;
        word varCounterDigitZero = arrCounter[varModeDial]%10;

        if (varCounterDigitZero == 0)
        {
          arrCounter[varModeDial] = arrCounter[varModeDial] - 10;
        }
        vardialPinPulseLock = 1;
        vardialReadyDigitNext = 1;
      }
    }
  }
  else
  {
    if (varSetMode == 0)
    {
      return;
    }
    else
    {// паузы и выход из режима установки
      if ((millis() - vardialChangeTime) > vardialCountMin)
      {
        vardialPinPulseLock = 0;
      }
      if ((millis() - vardialChangeTime) > vardialCountEndOfSet)
      {// выход из режима установки
        varSetMode = 0;
      }
      else if ((millis() - vardialChangeTime) > vardialCountDigitNext && vardialReadyDigitNext == 1)
      {// паузы
        if (varModeDial == 2)
        {
          arrCounter[varModeDial] *= 10;
        }
        //выполнить усечение arrCounter[varModeDial] до трех разрядов
        arrCounter[varModeDial] = arrCounter[varModeDial]%10000;
        vardialReadyDigitNext = 0;
      }
    }
  }
  vardialPinLastState = vardialPinState;
}



//thermo() - подпрограмма измерения температуры
void thermo()
{
  if (varSetMode == 1)
  {
    return;
  }
//контроль снятия с рычага
  if (digitalRead(switchPin) == LOW)
  {
    if (varMode != 0)
    {
      varModeOld = varMode;
      varMode = 0;
    }
//подпрограммы измерения температуры
  }
  else
  {
    if (varMode == 0)
    {
      varMode = varModeOld;
    }
  }
}



//Clock() - подпрограмма часов
void Clock()
{
  if (varTenSecLast != varTenSec)
  {
    varTenSecLast = varTenSec;
    varMinuteCounter ++;
    if (varMinuteCounter == 6)
    {
      varMinuteCounter = 0;
      arrCounter[3] ++;
      if (arrCounter[3]/10%10 == 6)
      {
        arrCounter[3] += 40;
      }
      if (arrCounter[3] >= 2400)
      {
        arrCounter[3] = 0;
      }
    }
    if (arrCounter[2] != 0)
    {
      if (varSetMode == 0)
      {
        Timer();
      }
    }
    else
    {
      if (varMode == 2)
      {
        varMode = 3;
      }
    }
  }
}



//Timer() - подпрограмма таймера
void Timer()
{
  arrCounter[2] --;
  if (arrCounter[2]%10 >= 6)
  {
    arrCounter[2] = arrCounter[2] - 4;
  }
  if (arrCounter[2] == 20)
  {
    beepOn();
  }
  if (arrCounter[2] == 14)
  {
    beepOff();
  }
  if (arrCounter[2] < 1)
  {
    beepOn();
  }
  if (arrCounter[2] == 0)
  {
//    varMode = 3;
    beepOff();
  }
}



//beepOn() - подпрограмма звуковой индикации
void beepOn()
{
  analogWrite(buzzerPin, 127);
}



//beepOff() - подпрограмма звуковой индикации
void beepOff()
{
  analogWrite(buzzerPin, 0);
}



//Display() - подпрограмма индикации
void Display()
{
  int digitPinOff;
  int digitPinOn;
  int DisplayDigital;
//  if (varDisplayNextTime <= micros() && varDisplayNextTime > micros() - varDisplayRefreshTime)
  if (varDisplayNextTime <= micros())
  {
    varDisplayNextTime += varDisplayRefreshTime;
    varDysplayPosition = varDysplayPosition + 1;
    if (varDysplayPosition > 4)
    {
      varDysplayPosition = 1;
    }
    switch (varDysplayPosition)
    {
      case 1:
        DisplayDigital = arrCounter[varMode]%10;
        DisplayDigital = arrDysplaySymbols[DisplayDigital];
        digitPinOff = digit4Pin;
        digitPinOn = digit1Pin;
      break;
      case 2:
        if (arrCounter[varMode] > 9 || varMode == 3)
        {
          DisplayDigital = arrCounter[varMode]/10%10;
          DisplayDigital = arrDysplaySymbols[DisplayDigital];
        }
        else
        {
          DisplayDigital = arrDysplaySymbols[11];
        }
        digitPinOff = digit1Pin;
        digitPinOn = digit2Pin;
      break;
      case 3:
        if (arrCounter[varMode] > 99 || varMode == 3)
        {
          DisplayDigital = arrCounter[varMode]/100%10;
          DisplayDigital = arrDysplaySymbols[DisplayDigital];
        }
        else
        {
          DisplayDigital = arrDysplaySymbols[11];
        }
        digitPinOff = digit2Pin;
        digitPinOn = digit3Pin;
      break;
      case 4:
        if (arrCounter[varMode] > 999)
        {
          DisplayDigital = arrCounter[varMode]/1000%10;
          DisplayDigital = arrDysplaySymbols[DisplayDigital];
        }
        else
        {
          DisplayDigital = arrDysplaySymbols[11];
        }
        digitPinOff = digit3Pin;
        digitPinOn = digit4Pin;
      break;
    }
    if (varMode == varDysplayPosition)
    {
      unsigned long varPointBlinkTime = millis()/500;
      varPointBlinkTime = varPointBlinkTime%10;
      varPointBlinkTime = varPointBlinkTime & B00000001;
      if (varPointBlinkTime == 1 || varSetMode == 1)
      {
        DisplayDigital = DisplayDigital ^ B00000001;
      }
    }
    digitalWrite(digitPinOff, HIGH);
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, LSBFIRST, DisplayDigital);
    digitalWrite(latchPin, HIGH);
    digitalWrite(digitPinOn, LOW);
  }
}



//отладка
void checkDialer()
{
  if (digitalRead(dialPin) == LOW)
  {
    arrCounter[1] ++;
    arrCounter[4] = 0;
  }
  else
  {
    arrCounter[1] = 0;
    arrCounter[4] ++;
  }
  Serial.print (arrCounter[1]);
  Serial.print ("\t");
  Serial.println (arrCounter[4]);
}



//отладка
void out2con()
{
  Serial.print ("Mode=");
  Serial.print (varMode);
  Serial.print ("\tt=");
  Serial.print (arrCounter[0]);
  Serial.print ("\tTimer=");
  Serial.print (arrCounter[2]);
  Serial.print ("\tClock=");
  Serial.print (arrCounter[3]);
  Serial.print ("\tSetMode=");
  Serial.print (varSetMode);
  Serial.print ("\tdialCount=");
  Serial.print (vardialCount);
  Serial.print ("\tdialPinLS=");
  Serial.print (vardialPinLastState);
  Serial.print ("\tdialPinS=");
  Serial.print (vardialPinState);
  Serial.print ("\t");
  Serial.println ();
}

 

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

lazy-fox
Offline
Зарегистрирован: 22.08.2014

Собственно долгожданные результаты испытания на видео. http://youtu.be/rNMIFLJr7cg

За разработку кода благодарю уважаемого 18GT19HT, ибо он решил задачу не используя SPI и прерывания.

Далее перехожу от настольного прототипа к опытной модели.

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

Это позволит в полевых условиях определить параметры функций и элементов конструкции прибора.

lazy-fox
Offline
Зарегистрирован: 22.08.2014

Опытный аппарат собран и запущен. Проводятся проверки работы точности часов на встроенном таймере, точности отсчёта таймера, общего энергопотребеления устройства, стабильности работы в целом.

Результаты: часы убегают незначительно, точность отсчёта и работа индикации на высоте, но за сутки батарея 9V 6LR61 была посажена с 9,21 до 6,53 вольта. 

По питанию предполагалось два варианта: первый - автономное от кроны на год, второе - встроенный блок питания от 220V.

Первый был предпочтительнее, с экономической точки зрения, не смотря на то что при втором варианте можно перейти к более раритетным индикаторам ИН-12Б. С индикаторами тоже не всё оптимистично. время наработки на отказ 5000 часов = 208 дней. Для увеличения ресурса нужно гасить индикацию. Тогда фактически мы теряем функцию отображения часов. Пример газоразрядной индикации:

18GT19HT
Offline
Зарегистрирован: 23.08.2014

Батарея типа "крона" имеет емкость (по паспорту) 0,5 А*ч. А у тебя фонарик на светодиодах работающий круглосуточно... Выход: внешнее питание или переход на ЖКИ. На форуме где-то видел предложение использовать несколько батареек АА - это вариант удвоения/утроения времени эксплуатации (у разных батареек емкость разная). Еще можно немного растянуть время работы уйдя на более низкие частоты, но тогда вопрос с индикацией, возможно, возникнет, но тогда можно метнуться в сторону SPI или исключить регистр...

 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

выложи куда нибудь фото часов в более высоком качетве. по моему классно смотрится. хочу получше рассмотреть

lazy-fox
Offline
Зарегистрирован: 22.08.2014

jeka_tm пишет:

выложи куда нибудь фото часов в более высоком качетве. по моему классно смотрится. хочу получше рассмотреть

Первая картинка по поиску ИН-12Б на яндексе. 500х265.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

да тоже мелко)) как на форуме

lazy-fox
Offline
Зарегистрирован: 22.08.2014

А что конкретно понравилось? корпус - прозрачная "хлебница", синяя светодиодная подсветка, сами индикаторы или фоновый фольгированный текстолит к которому припаяны лампы?

Я сейчас прорабатываю свой корпус и ломаю голову над тем как в 19 веке могли бы оформить индикацию будь у них лампы и светодиоды.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

чем то похоже на ламповый усилитель

18GT19HT
Offline
Зарегистрирован: 23.08.2014

Вряд ли в 19 веке рескнули сделать прозрачные стенки "кишки наружу", медь/латунь/бронза на худой конец жесть... но светодиодный индикатор не впишется - люменисцентный еще куда нешло. Отвлекись от того что есть, возми чистый лист и простой карандаш, сделай серию набросков - посмотрим может чего и выйдет из этого.

lazy-fox
Offline
Зарегистрирован: 22.08.2014

jeka_tm пишет:

чем то похоже на ламповый усилитель

"... чем-то на казино. Чем-то на караван-сарай, чем-то – на отряды Махно."

Придя к ламповой индикации, я не смог пройти мимо соблазна встроить что нибудь этакое в функционал своего девайса. Такой изюминкой мог стать FM-радиоприёмник. Ламповый. Но после непродолжительного гугления выяснилось что смогу собрать лишь ламповый усилитель типа, но не тюнер с синтезатором частот. И пока решил воздержаться.

18GT19HT
Offline
Зарегистрирован: 23.08.2014

lazy-fox пишет:

jeka_tm пишет:

чем то похоже на ламповый усилитель

"... чем-то на казино. Чем-то на караван-сарай, чем-то – на отряды Махно."

Придя к ламповой индикации, я не смог пройти мимо соблазна встроить что нибудь этакое в функционал своего девайса. Такой изюминкой мог стать FM-радиоприёмник. Ламповый. Но после непродолжительного гугления выяснилось что смогу собрать лишь ламповый усилитель типа, но не тюнер с синтезатором частот. И пока решил воздержаться.

но можно же сделать цифровой и замаскировать под ламповый, или УНЧ сделать ламповым, ВЧ части на однокристальном FM приемнике

lazy-fox
Offline
Зарегистрирован: 22.08.2014

А если говорить про ретро, часы и лампы - то 18GT19HT как никогда прав: 

Наручные часы на газоразрядных индикаторах 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

а при чем тут 19 век

http://radioskot.ru/_fr/4/7860783.jpg

красиво же. именно чтобы было похоже на часы не нашел

lazy-fox
Offline
Зарегистрирован: 22.08.2014

18GT19HT пишет:

но можно же сделать цифровой и замаскировать под ламповый, или УНЧ сделать ламповым, ВЧ части на однокристальном FM приемнике

Это будет зависеть от того смогу ли увеличить ресурс ИН-12Б скажем до 25 лет. Корпус должен соответствовать содержанию. Может в полнакала тлеть пока газоанализатор на нуле, или гасить ночью или днём по будням.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

18GT19HT пишет:

но можно же сделать цифровой и замаскировать под ламповый, или УНЧ сделать ламповым, ВЧ части на однокристальном FM приемнике

уже делают вроде того))

http://radio-hobby.org/modules/newbb/viewtopic.php?topic_id=611&forum=11

lazy-fox
Offline
Зарегистрирован: 22.08.2014

jeka_tm пишет:

а при чем тут 19 век

Ибо телефоны получили распространение в 19 веке и их концепт отлично впишется в мой функционал