два 8-ми сегментных индикаторов

vk007
Offline
Зарегистрирован: 16.06.2015

Ничего не зря. Учитывая все выше изложенное, 100 Ом вполне могут подойти. ЕвгенийП немного опередил меня насчет того, что еще немного напряжения откусит транзистор.

Не нашли вы, поищем мы - марку индикатора в студию.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

d13lider пишет:
переменная currentDigit не была объявлена добавил uint8_t и поменял цифры местами все заработало что такое виртуальные экраны? хочу знать)

Отлично! Правильно сделал. Работает и хорошо. Сейчас продолжим в сторону таймера таймер.

Виртуальные экраны это вот что такое. Вот представьте ради-часы или автомагнитолу - у этих устройств частенько один и тот ;е экран используется для разных целей. То показывает время, то частоту радиостанции, то настройки громкости и баланса и т.п. в зависимости от нажатия каких-то кнопок. так ведь?

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

А теперь представьте как бы Вы это программировали.

Если "в лоб", то получается очень геморойно. Допустим, сменилась минута. Надо бы отобразить, но программа должна сначала проверить, а что в данный момент показывается на экране. Если время, то отображаем, а если температура, то ничего не делаем. Или наоборот, температурный датчик получил новую температуру (он может это раз в минуту делать). И что ему делать? Кидаться показывать? Нет! Сначала нужно проверить? что в данный момент должно быть на экране. Если температура, то да - показывать, а если время, то не надо.

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

Гораздо проще скзать, что к одному физическому экрану у меня привязано N виртуальных. На каждую функцию свой собственный виртуальный экран. Тогда допустим, часы ничего не проверяют, а тупо выводят время на свой собственный экран всегда. Тоже самое термометр ничего не проверяет, а просто всегда выводит температуру на свой собственный экран. То есть всё упростилось. Всё выглядит так, как будто у них в вправду собственные экраны. Они (часы или термометр) вообще-то понятия не имеют и знать не хотят, что именно сейчас показывается на реальном экране - они выводят свои данные на виртуальный экран и не парятся ни о чём.

Ну и есть функция, которая по каким-то нажатиям кнопок или ещё по каким командам, просто переключает физический экран с одного виртуального на другой.

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

Концепция понятна? 

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

Ну, мы до этого ещё доберёмся если интересно. ЕСйчас давайте про таймер. Сейчас напишу отдельынй пост.

d13lider
d13lider аватар
Offline
Зарегистрирован: 19.10.2015

vk007 пишет:

Ничего не зря. Учитывая все выше изложенное, 100 Ом вполне могут подойти. ЕвгенийП немного опередил меня насчет того, что еще немного напряжения откусит транзистор.

Не нашли вы, поищем мы - марку индикатора в студию.

KEM-5361AG

d13lider
d13lider аватар
Offline
Зарегистрирован: 19.10.2015

ЕвгенийП пишет:

 

 

Виртуальные экраны 

все понял. ну я думаю такая функция мне не нужна, но если придумаю зачем, то идея отличная. 5-6 экранов создать, но это думаю для компьютера в машину или на мотоцикл более полезно. а в данном проекте максимум можно 2 экрана. и то для токового ограничения споттера, тоже режима 3-4. но у меня споттер не очень сильный поэтому его вссегда на максимум использовать буду. и в следствии эта функция тоже отпадает

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

О таймерах. Я буду говорить о т.н. нормально режиме работы таймера (Normal Mode). Есть и другие режимы.

Это такая штука, которая будучи включённой (их иногда выключают для экономии энергии) постоянно тикает и увеличивает свой счётчик от нуля до максимального значения. Когда счётчик достигает максимального значения, он сбрасывается в ноль и продолжает тикать дальше. И так бесконечно.

В тот момент, когда счётчик сбрасывается в 0, происходит прерывание по переполнению таймера, его можно обработать (что-то сделать программно).

Каково максимальное значение? Для 8-битового таймера это 256, для 16-битового – 65536.

Всего в ATmega328 три таймера. 0-ой, 1-ый и 2-ой. Нулевой и второй – восьмибитовые, первый – 16-тибитовый.

Нулевой таймер в Ардуино занят. На нём сидят millis, delay и прочие вещи, связанные со временем. Так что его лучше не трогать. А то всё это добро сломается.

Что касается остальных двух, они тоже не совсем свободны, но это уже предмет «торга» - что нам нужнее.

Итак, что мы потеряем если начнём крутить какой-то таймер.

Таймер 1: обслуживает ШИМ на пинах 9 и 10.

Таймер 2: обслуживает ШИМ на пинах 3 и 11

Кроме того на таймеры завязана функуция tone.

Наконец, разные библиотеки используют тот или иной таймер, а такая библиотека как TLC5940 умудряется занять их ВСЕ и ничего нам не оставить.

Каким таймером пользоваться нам? Это зависит от того. какие у нас ещё есть библиотеки (надо смотреть чем они пользуются, чтобы с ними не «подраться») и от того ШИМом на каких ногах мы готовы пожертвовать.

В моём примере я буду использовать таймер 1. Если Вам реально нужен таймер 2, то Вам нужно сделать ровно те же самые вещи, только немного с другими названиями. Откроете даташит микросхемы ATmega328 на стр. 141 там всё написано.

Итак, поехали.

Вы уже поняли, что таймер тупо увеличивает свой счётчик от 0 до Максимального значения (для нашего таймера 1 это 65536, т.к. он шестнадцатибитовый), затем генерирует прерывание по переполнению, сбрасывает счётчик в 0 и всё повторяется.

Как часто он тикает?

Тикает таймер через каждые P тактов процессора, где P (prescaler) – делитель частоты. Делитель частоты устанавливается для каждого таймера независимо. Таймер №1, с которым мы работаем, имеет следующие делители частоты: 1 (тикает на каждом тикает процессора), 8, 64, 128, 1024.

Сколько тиков процессора умещается в 10мс? При частоте 16МГц, 16 тиков это микросекунда, стало быть 16000 тиков – 1 миллисекунда. Ну, а 10 мс, очевидно 160000 тиков. Столько мы отсчитать на таймере не можем (переполнимся нахрен), на помощь приходит делитель частоты. Например, возьмём делитель 8. Один тик таймера будет равен восьми тикам процессора. Значит в 10 миллисекундах будет 160 000 / 8 = 20 000 тысяч тиков таймера. Столько мы можем себе позволить.

Алгоритм работы с таймером такой.

1.       Настроить режим и делитель частоты.

2.       Записать в счётчик таймера число 45536 ( = 65536 – 20000).

Всё, через 20000 тиков таймера (т.е. через 10 миллисекунд) наступит переполнение. Мы должны обработать прерывание, а именно сделать следующее:

1.       Переключить нашу цифру

3.       Записать Записать в счётчик таймера число 45536 ( = 65536 – 20000).

Всё.

Опять через 20000 тиков таймера (т.е. через 10 миллисекунд) наступит переполнение. Мы должны снова обработать прерывание, а именно снова сделать тоже самое!

При таком подходе у нас цифры будут переключаться каждые 10мс без нашего участия и никак нас не напрягая! Наш loop будет пустым. Мы может там делать что угодно – хоть ставить delay(100500) – таймеру плевать на наши делэи, он будет делать своё дело.

Ну, вот такова теория. Изучите пока, если что непонятно, поройтесь в сети.

Завтра с утра напишу пример, который будет реально работать. Сейчас ардуины под рукой нет, потому не могу написать и проверить.

d13lider
d13lider аватар
Offline
Зарегистрирован: 19.10.2015

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

d13lider
d13lider аватар
Offline
Зарегистрирован: 19.10.2015

вот еще чего не понял, почему именно  8, 64, 128, 1024. когда мы 160000 можем разделить на 100 допустим. тогда получиться 1600. и когда от точки 1600 будет доходить до "нуля" записываем "1" потом снова до нуля "2" и т.д. до 100 когда будет 100-й цикл то значит пора выполнять команду. или я что-то не понял? 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

d13lider пишет:

вот еще чего не понял, почему именно  8, 64, 128, 1024. 

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

d13lider
d13lider аватар
Offline
Зарегистрирован: 19.10.2015

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

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Так, ну смотрите. Берёте последний работающий пример. В нём все оставляете на месте, только очищаете loop() (всё из него выбрасываете).

В начало добавляете всё добро из нынешнего кода по 38 строку.Только заметьте. что строка 4 у Вас там уже есть. Дублировать не надо.

В setup() добавляете строчку «setupTimer2();» как здесь.

Наконец, в данном примере в loop() живёт простейший секундомер. Когда запустите – на экране будут меняться числа раз в секунду.

Надеюсь, Вы понимаете, код секундомера не имеет никакого отношения к показу числа на экране. Всё, что требуется – это присвоить переменной numberToShow значение и это значение и будет показываться. Сам секундомер написан исключительно для примера.

#define	PRESACLER	(1 << CS11)	//	Соответствует делителю частоты 8
#define	TICKS		((uint16_t)(65536ul - 20000ul))	// Оставляет 20000 тиков до переполнения

volatile uint8_t numberToShow = 0; 	// число для показа

//
// Инициализация таймера. делается один раз
//
void setupTimer2(void) {
	PRR &= ~(1 << PRTIM1);	// Убедимся, что таймер 1 не отключен
	TCCR1A = 0;					// Установим Normal режим
	TCCR1B = PRESACLER;		// Установим делитель частоты 
	TCNT1 = TICKS;				// Установим счётчик
	TIMSK1 |= (1 << TOIE1);	// Разрешим прерывание по переполнению
	TIFR1 = 1;					//	Очистим Очистим флаг прерывания (если он взведён)
}

//
// Обработка прерывания по переполнению
//
ISR(TIMER1_OVF_vect) {
	TCNT1 = TICKS;				// Установим счётчик для следующего прерывания
	//
	//	Покажем очередную цифру, как мы это делали раньше
	//
	static uint8_t currentDigit = 0;
	const uint8_t digitToShow = (currentDigit) ? numberToShow / 10 : numberToShow % 10;
	showDigit(digitToShow, currentDigit);
	currentDigit = (currentDigit + 1) % 2;	// В следующий раз показываем другую цифру
}

//
//	Всё, что выше  - это своя жизнь. От основной программы требуется только 
//	положить число для показа в numberToShow и оно будет показываться.
//	Больше основная программа ни о чём не заботится
//
///////////////////////////////////////////////////////////////////////////////////

void setup() {
	setupTimer2();
}


//
// Здесь реализован простейший секундомер
//
void loop() {
	static int8_t counter = 0;
	numberToShow = counter;	//	теперь это число будет показываться
	counter = (counter + 1) % 100;
	delay(1000);
}

Разбирайтесь.

Надеюсь, на три цифры Вы теперь и сами сможете переделать.

d13lider
d13lider аватар
Offline
Зарегистрирован: 19.10.2015

ЕвгенийП пишет:

Разбирайтесь.

Надеюсь, на три цифры Вы теперь и сами сможете переделать.

спасибо большое! будем тестировать, и понимать. вы случайно не преподаете в каком нибудь МГУ?)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

В разное время я преподавал в разных местах (и даже странах), в том числе и читал лекции в МГУ. Сейчас - нет.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Отпишитесь как заработает / нет. Но, вроде, должно. То, что мы не ошиблись в подсчётах времени, я проверил на осциллографе - точно 10мс.

Если потребуется совет по переделке на три разряда, выложите полный текст работающего скетча на два. Так будет удобнее разговаривать (номера строк там, то, сё). Ну. я думаю, Вы справитесь.

d13lider
d13lider аватар
Offline
Зарегистрирован: 19.10.2015

ЕвгенийП пишет:

Отпишитесь как заработает / нет. Но, вроде, должно. То, что мы не ошиблись в подсчётах времени, я проверил на осциллографе - точно 10мс.

Если потребуется совет по переделке на три разряда, выложите полный текст работающего скетча на два. Так будет удобнее разговаривать (номера строк там, то, сё). Ну. я думаю, Вы справитесь.

хорошо, спасибо!

d13lider
d13lider аватар
Offline
Зарегистрирован: 19.10.2015

а как сделать делитель частоты 64? какая строка отвечает я понял, там просто написанно 1 << CS11, а что это значит я не понимаю(

d13lider
d13lider аватар
Offline
Зарегистрирован: 19.10.2015

просто хочу задать 50мс а для этого надо делитель выставить на 64 а составить тиков 12500

 

d13lider
d13lider аватар
Offline
Зарегистрирован: 19.10.2015

d13lider пишет:

просто хочу задать 50мс а для этого надо делитель выставить на 64 а составить тиков 12500

 

нашел, разобрался.

#define  PRESACLER (0<<CS12)|(1<<CS11)|(1<<CS10) 
#define TICKS   ((uint16_t)(65536ul - 12500ul)) 

но 

(0<<CS12)

можно опустить, т.к. в дефолте и так стоит в нуле 

d13lider
d13lider аватар
Offline
Зарегистрирован: 19.10.2015

ЕвгенийП пишет:

Отпишитесь как заработает / нет. Но, вроде, должно. То, что мы не ошиблись в подсчётах времени, я проверил на осциллографе - точно 10мс.

Если потребуется совет по переделке на три разряда, выложите полный текст работающего скетча на два. Так будет удобнее разговаривать (номера строк там, то, сё). Ну. я думаю, Вы справитесь.

все заработало, но не могу понять как переделать на 3 цифры. добавил 3 знак на пин 12 и добавил его в строку 

void showDigit(const uint8_t d, const uint8_t pos) {
  static const uint8_t all_postions[] = { PIN_DIG0, PIN_DIG1, PIN_DIG2 }; 

весь код который получился



//
//  Определение пинов для сегментов
//  (поставьте Ваши пины, у меня мелкий экран и плохо видно какие там у Вас)
//
#define PIN_A 9
#define PIN_B 8
#define PIN_C 7
#define PIN_D 6
#define PIN_E 5
#define PIN_F 4
#define PIN_G 3
#define PIN_DP  2

//
//
//
#define  PRESACLER (1<<CS11)|(1<<CS10) //  Соответствует делителю частоты 8
#define TICKS   ((uint16_t)(65536ul - 12500ul)) // Оставляет 20000 тиков до переполнения



//
//  Определение пинов для цифр
//  (поставьте Ваши пины, у меня мелкий экран и плохо видно какие там у Вас)
//
#define PIN_DIG0  10
#define PIN_DIG1  11
#define PIN_DIG2  12

//
//  Определение масок для сегментов
//
#define MASK_A  (1 << 0)
#define MASK_B  (1 << 1)
#define MASK_C  (1 << 2)
#define MASK_D  (1 << 3)
#define MASK_E  (1 << 4)
#define MASK_F  (1 << 5)
#define MASK_G  (1 << 6)
#define MASK_DP   (1 << 7)

//
//  Определение цифр через маски сегментов
//
#define D0  (MASK_A | MASK_B | MASK_C | MASK_D | MASK_E | MASK_F)
#define D1  (MASK_B | MASK_C)
#define D2  (MASK_A | MASK_B | MASK_G | MASK_D | MASK_E)
#define D3  (MASK_A | MASK_B | MASK_C | MASK_D | MASK_G)
#define D4  (MASK_B | MASK_C | MASK_G | MASK_F)
#define D5  (MASK_A | MASK_C | MASK_D | MASK_F | MASK_G)
#define D6  (MASK_A | MASK_C | MASK_D | MASK_E | MASK_F | MASK_G)
#define D7  (MASK_A | (MASK_B | MASK_C))
#define D8  (MASK_A | MASK_B | MASK_C | MASK_D | MASK_E | MASK_F | MASK_G)
#define D9  (MASK_A | MASK_B | MASK_C | MASK_D | MASK_F | MASK_G)

volatile uint8_t numberToShow = 00;

//
//  Функция устанавливает по маске - параметру (HIGH-горит, LOW-не горит)
//
void setRawSegments(const int8_t mask) {
  digitalWrite(PIN_A, mask & MASK_A);
  digitalWrite(PIN_B, mask & MASK_B);
  digitalWrite(PIN_C, mask & MASK_C);
  digitalWrite(PIN_D, mask & MASK_D);
  digitalWrite(PIN_E, mask & MASK_E);
  digitalWrite(PIN_F, mask & MASK_F);
  digitalWrite(PIN_G, mask & MASK_G);
  digitalWrite(PIN_DP, mask & MASK_DP);
}

//
//  Функция устанавливает все сегменты для цифры-параметра (HIGH-горит, LOW-не горит)
//
void setSegments(const int8_t digit) {
  static const uint8_t all_digits[] = { D0, D1, D2, D3, D4, D5, D6, D7, D8, D9,}; 
  setRawSegments(all_digits[digit]);
}

//
//  Функция зажигает цифру d в позиции pos
//  При этом ставит пин соответсвующий позиции pos в LOW
//
void showDigit(const uint8_t d, const uint8_t pos) {
  static const uint8_t all_postions[] = { PIN_DIG0, PIN_DIG1, PIN_DIG2 }; 
  for (register uint8_t i = 0; i < sizeof(all_postions) / sizeof(all_postions[0]); i++) {
    digitalWrite(all_postions[i], pos != i);
  }
  setSegments(d);
}

//
// Инициализация таймера. делается один раз
//
void setupTimer2(void) {
  PRR &= ~(1 << PRTIM1);  // Убедимся, что таймер 1 не отключен
  TCCR1A = 0;         // Установим Normal режим
  TCCR1B = PRESACLER;   // Установим делитель частоты 
  TCNT1 = TICKS;        // Установим счётчик
  TIMSK1 |= (1 << TOIE1); // Разрешим прерывание по переполнению
  TIFR1 = 1;          //  Очистим Очистим флаг прерывания (если он взведён)
}
//
// Обработка прерывания по переполнению
//
ISR(TIMER1_OVF_vect) {
  TCNT1 = TICKS;        // Установим счётчик для следующего прерывания
  //
  //  Покажем очередную цифру, как мы это делали раньше
  //
  static uint8_t currentDigit = 0;
  const uint8_t digitToShow = (currentDigit) ?  numberToShow % 10 :  numberToShow / 10;
  showDigit(digitToShow, currentDigit);
  currentDigit = (currentDigit + 1) % 2;  // В следующий раз показываем другую цифру
}

//
//  Всё, что выше  - это своя жизнь. От основной программы требуется только 
//  положить число для показа в numberToShow и оно будет показываться.
//  Больше основная программа ни о чём не заботится
//
///////////////////////////////////////////////////////////////////////////////////


void setup() {
  setupTimer2();
    // ... задайте все pinMode как раньше 
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
pinMode(8, OUTPUT);
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
pinMode(11, OUTPUT);
pinMode(12, OUTPUT);
pinMode(13, OUTPUT);

                            
}

//  
//  я считаю, что нулевая цмфра слева (единицы), а первая справа (десятки)
//  если у Вас по-другому - поменяйте.
//
void loop() {
 
 static int8_t counter = 0;
 static int8_t storona = 0;
   //  теперь это число будет показываться
   if (counter == 1000)
{
  storona =1;
}
else if (counter == 0)
{
  storona = 0;
}
if (storona == 0)
{
  counter = counter +1;
}
else 
counter = counter -1;

  
numberToShow = counter;
delay (250);
}

правда изменил счетчик от 0 до 1000 и потом в обратном направлении

d13lider
d13lider аватар
Offline
Зарегистрирован: 19.10.2015

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

currentDigit = (currentDigit + 1) % 2;

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

d13lider пишет:

а как сделать делитель частоты 64? какая строка отвечает я понял, там просто написанно 1 << CS11, а что это значит я не понимаю(

Давайте. я Вм лучше "удочку дам". 

Скачайте даташит клонтроллера ATmega328p и на стр. 134 найдёте таблицу всех делителей для таймера 1 (у других другие).

В частности для 64 там указано CS11 и CS10. Записывается это так:

(1 << CS11) | (1 << CS10)

если потребуются другие делители, то по аналогии.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

d13lider пишет:

но 

(0<<CS12)

можно опустить, т.к. в дефолте и так стоит в нуле 

Более того, это вообще бессмысленная записть - она всегда равна 0

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

d13lider пишет:

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

currentDigit = (currentDigit + 1) % 2;

 

Ну, двойку-то здесь надо на тройку менять - это же остаток от деления.

Но это не всё.

Сейчас посмотрю и отпишусь.

d13lider
d13lider аватар
Offline
Зарегистрирован: 19.10.2015

ЕвгенийП пишет:

d13lider пишет:

но 

(0<<CS12)

можно опустить, т.к. в дефолте и так стоит в нуле 

Более того, это вообще бессмысленная записть - она всегда равна 0

ну я тоже самое сказал) дефолт это же "изначальное состояние" т

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Итак. меняем на три цифры.

1. Строка 56.

Тип uint8_t однобайтовый. Максимальное число, которое в него влазит - 256. А раз у Вас три цифры, Вам надо. чтобы влазило до 999. Заменяем тип uint8_t на unsigned

2. строка 112. 

Это разделение на десятки и 1. Смотрите

digitToShow = (currentDigit) ?  numberToShow % 10 :  numberToShow / 10;

Буквально это значит ЕСЛИ (currentDigit == 0) ТО digitToShow получет значение ( numberToShow / 10) - это количество десятков
ИНАЧЕ digitToShow получет значение ( numberToShow % 10) - это количество единиц

 

Теперь Вам надо сделать чуть сложнее, а именно

ЕСЛИ (currentDigit == 0) ТО digitToShow получет значение ( numberToShow / 100) - это количество сотен
ИНАЧЕ 
ЕСЛИ (currentDigit == 1digitToShow получет значение ( numberToShow % 100) / 10 - это количество десятков
ИНАЧЕ 
digitToShow получет значение ( numberToShow % 10) - это количество единиц

Ну, как-то так и надо написать. например, вместо этой строки такую конструкцию.

uint8_t digitToShow;
if (currentDigit == 0) digitToShow = numberToShow / 100;
else if (currentDigit == 1) digitToShow = (numberToShow % 100) / 10;
else digitToShow = numberToShow % 10;

 

3. Строка 114.
 
Запись

currentDigit = (currentDigit + 1) % 2;

означает что к currentDigit надо прибавить 1 и взять остаток от деления на 2. Т.е. он будет принимать значения 0, 1, 0, 1, 0, ... А Вам теперь надо, чтобы он принимал значения  0, 1, 2, 0, 1, 2, 0, ... Т.е. надо брать остаток от деления на 3. Стало быть в этой строке двойку заменяем на тройку.

Кажется, всё. Ну, если чего забыл, потом подправим. Проверьте.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

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

d13lider
d13lider аватар
Offline
Зарегистрирован: 19.10.2015


//
//  Определение пинов для сегментов
//  (поставьте Ваши пины, у меня мелкий экран и плохо видно какие там у Вас)
//
#define PIN_A 9
#define PIN_B 8
#define PIN_C 7
#define PIN_D 6
#define PIN_E 5
#define PIN_F 4
#define PIN_G 3
#define PIN_DP  2

//
//
//
#define  PRESACLER (1<<CS11)|(1<<CS10) //  Соответствует делителю частоты 8
#define TICKS   ((uint16_t)(65536ul - 12500ul)) // Оставляет 20000 тиков до переполнения



//
//  Определение пинов для цифр
//  (поставьте Ваши пины, у меня мелкий экран и плохо видно какие там у Вас)
//
#define PIN_DIG0  10
#define PIN_DIG1  11
#define PIN_DIG2  12

//
//  Определение масок для сегментов
//
#define MASK_A  (1 << 0)
#define MASK_B  (1 << 1)
#define MASK_C  (1 << 2)
#define MASK_D  (1 << 3)
#define MASK_E  (1 << 4)
#define MASK_F  (1 << 5)
#define MASK_G  (1 << 6)
#define MASK_DP   (1 << 7)

//
//  Определение цифр через маски сегментов
//
#define D0  (MASK_A | MASK_B | MASK_C | MASK_D | MASK_E | MASK_F)
#define D1  (MASK_B | MASK_C)
#define D2  (MASK_A | MASK_B | MASK_G | MASK_D | MASK_E)
#define D3  (MASK_A | MASK_B | MASK_C | MASK_D | MASK_G)
#define D4  (MASK_B | MASK_C | MASK_G | MASK_F)
#define D5  (MASK_A | MASK_C | MASK_D | MASK_F | MASK_G)
#define D6  (MASK_A | MASK_C | MASK_D | MASK_E | MASK_F | MASK_G)
#define D7  (MASK_A | (MASK_B | MASK_C))
#define D8  (MASK_A | MASK_B | MASK_C | MASK_D | MASK_E | MASK_F | MASK_G)
#define D9  (MASK_A | MASK_B | MASK_C | MASK_D | MASK_F | MASK_G)

volatile unsigned numberToShow = 0;

//
//  Функция устанавливает по маске - параметру (HIGH-горит, LOW-не горит)
//
void setRawSegments(const int8_t mask) {
  digitalWrite(PIN_A, mask & MASK_A);
  digitalWrite(PIN_B, mask & MASK_B);
  digitalWrite(PIN_C, mask & MASK_C);
  digitalWrite(PIN_D, mask & MASK_D);
  digitalWrite(PIN_E, mask & MASK_E);
  digitalWrite(PIN_F, mask & MASK_F);
  digitalWrite(PIN_G, mask & MASK_G);
  digitalWrite(PIN_DP, mask & MASK_DP);
}

//
//  Функция устанавливает все сегменты для цифры-параметра (HIGH-горит, LOW-не горит)
//
void setSegments(const int8_t digit) {
  static const uint8_t all_digits[] = { D0, D1, D2, D3, D4, D5, D6, D7, D8, D9}; 
  setRawSegments(all_digits[digit]);
}

//
//  Функция зажигает цифру d в позиции pos
//  При этом ставит пин соответсвующий позиции pos в LOW
//
void showDigit(const uint8_t d, const uint8_t pos) {
  static const uint8_t all_postions[] = { PIN_DIG0, PIN_DIG1, PIN_DIG2 }; 
  for (register uint8_t i = 0; i < sizeof(all_postions) / sizeof(all_postions[0]); i++) {
    digitalWrite(all_postions[i], pos != i);
  }
  setSegments(d);
}

//
// Инициализация таймера. делается один раз
//
void setupTimer2(void) {
  PRR &= ~(1 << PRTIM1);  // Убедимся, что таймер 1 не отключен
  TCCR1A = 0;         // Установим Normal режим
  TCCR1B = PRESACLER;   // Установим делитель частоты 
  TCNT1 = TICKS;        // Установим счётчик
  TIMSK1 |= (1 << TOIE1); // Разрешим прерывание по переполнению
  TIFR1 = 1;          //  Очистим Очистим флаг прерывания (если он взведён)
}
//
// Обработка прерывания по переполнению
//
ISR(TIMER1_OVF_vect) {
  TCNT1 = TICKS;        // Установим счётчик для следующего прерывания
  //
  //  Покажем очередную цифру, как мы это делали раньше
  //
static uint8_t currentDigit = 0;
uint8_t digitToShow ;
  if (currentDigit == 0) digitToShow = numberToShow / 100;
else if (currentDigit == 1) digitToShow = (numberToShow % 100) / 10;
else digitToShow = numberToShow % 10;
  showDigit(digitToShow, currentDigit);
  currentDigit = (currentDigit + 1)%3;   // В следующий раз показываем другую цифру

}

//
//  Всё, что выше  - это своя жизнь. От основной программы требуется только 
//  положить число для показа в numberToShow и оно будет показываться.
//  Больше основная программа ни о чём не заботится
//
///////////////////////////////////////////////////////////////////////////////////


void setup() {
  setupTimer2();
    // ... задайте все pinMode как раньше 
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
pinMode(8, OUTPUT);
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
pinMode(11, OUTPUT);
pinMode(12, OUTPUT);
pinMode(13, OUTPUT);

                            
}

//  
//  я считаю, что нулевая цмфра слева (единицы), а первая справа (десятки)
//  если у Вас по-другому - поменяйте.
//
void loop() {
 

numberToShow = 987;

}

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

 

единственное что я не правильно делал. в строке uint8_t digitToShow; было const. и у меня ругался компилятор. я не понял почему а теперь разобрался. константа не сожет меняться же.а я ее пытался поменять. понял

в общем все работает, как оптимизировать? 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Сейчас я тут чуто занят, через пару часов вернусь. Но в принципе суть оптимизации вот в чём.

Вот смотрите, допустим Вы вывели число и оно там минуту показывается не меняясь.

Но при этом каждые 10мс мы исполняем строки 113-115, т.е. делаем кучу операций деления для разделения числа на сотни, десятки и единицы. Нафига столько раз его делить? Нужно делить его один раз при занесении, а потом только показывать готовые разряды.

Через пару часов освобожуь и если не увиже здест Вышего решения, то покажу как это просто и легко сделать.

d13lider
d13lider аватар
Offline
Зарегистрирован: 19.10.2015

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

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Хорошо, тогда не буду подсказывать пока. Удачи!

d13lider
d13lider аватар
Offline
Зарегистрирован: 19.10.2015

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

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, я бы проще сделал.

В основной программе я бы это число для показаза не присваивал прямо, а вызывал бы функцию "показать число".

Она бы всё разделяла на сотни, единицы и десятки и складывала бы в массив из трёх байтов. Причём складывала бы не сами числа, а уже готовые маски. Это был бы масси масок

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

Это дало бы дополнительный плюс. Можно было бы при надобности, ничего не меняе, показывать заодно и не только числа, а всякие C, H и прочие символы, т.к. их маски можно было бы прямо складывать в этот массив масок.

d13lider
d13lider аватар
Offline
Зарегистрирован: 19.10.2015

ЕвгенийП пишет:

Ну, я бы проще сделал.

В основной программе я бы это число для показаза не присваивал прямо, а вызывал бы функцию "показать число".

Она бы всё разделяла на сотни, единицы и десятки и складывала бы в массив из трёх байтов. Причём складывала бы не сами числа, а уже готовые маски. Это был бы масси масок

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

Это дало бы дополнительный плюс. Можно было бы при надобности, ничего не меняе, показывать заодно и не только числа, а всякие C, H и прочие символы, т.к. их маски можно было бы прямо складывать в этот массив масок.

что то "сделал проще" я вообще не понимаю)))) можно по подробнее?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, давайте начнём полировку.

для начала.

Отуда Вы взяли число в строке 19. Как Вы его считали? Можете описать?

d13lider
d13lider аватар
Offline
Зарегистрирован: 19.10.2015

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

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ладно, как бы Вы это число не считали, оно посчитано неправильно. Давайте ещё раз разберём, как оно считается.

Исходными данными будет:

Find – частота обновления индикатора в герцах. Эта величина связана с особенностями зрения и равна 50Гц. Если взять меньше, то изображение будет заметно «мерцать».
Fcpu – частота процессора в герцах
N – количество разрядов индикатора
Pre – делитель частоты таймера

Будем искать количество тиков таймера, в течение которых должна светиться цифра.

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

Теперь давайте рассуждать.

  1. Период обновления индикатора, очевидно обратная величина частоты:

    image001.png

  2. Длительность свечения одной цифры, очевидно равна периоду обновления, делённому на количество цифр:

    image002.png

  3. Длительность одного такта процессора, очевидно обратная величина тактовой частоты,

    image003.png

  4. Длительность одного тика таймера, очевидно равна длительности такта процессора, умноженной на делитель частоты:

    image004.png

  5. Наконец, количество тиков таймера, в течение которых должна светиться цифра равно длительности свечения одной цифры, поделённой на длительность одного тика таймера:

    image005.png

Вот и весь расчёт. Если вспомнить 5-6 класс средней школы, то всё вышесказанное можно привести к одной формуле:

image006.png

Давайте подставим сюда Fcpu = 16 000 000, Find=50, N=3 и Pre=64.

Результат:1 666,(6).

Округлять надо всегда вниз – пусть лучше частота обновления будет чуть больше, чем чуть меньше.

Потому, окончательный результат: 1 666.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Сейчас займусь собственно скетчем. Делов-то там на копейку, но писать пояснения занимает в разы больше времени, чем собственно делать - так что это может занять время.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

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

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

Пример сдлеан так: сначала показывается число 666, а через три секунды начинается "велосипед".


//
//  Определение пинов для сегментов
//  (поставьте Ваши пины, у меня мелкий экран и плохо видно какие там у Вас)
//
#define PIN_A 9
#define PIN_B 8
#define PIN_C 7
#define PIN_D 6
#define PIN_E 5
#define PIN_F 4
#define PIN_G 3
#define PIN_DP  2

//
//
//
#define  PRESACLER (1<<CS11)|(1<<CS10) //  Соответствует делителю частоты 64
#define TICKS   ((uint16_t)(65536ul - 1666ul)) // Оставляет 1666 тиков до переполнения ( 64*1666/16000 == 6,664 миллисекунды)


//
//  Определение пинов для цифр
//  (поставьте Ваши пины, у меня мелкий экран и плохо видно какие там у Вас)
//
#define PIN_DIG0  10
#define PIN_DIG1  11
#define PIN_DIG2  12

//
//  Определение масок для сегментов
//
#define MASK_A  (1 << 0)
#define MASK_B  (1 << 1)
#define MASK_C  (1 << 2)
#define MASK_D  (1 << 3)
#define MASK_E  (1 << 4)
#define MASK_F  (1 << 5)
#define MASK_G  (1 << 6)
#define MASK_DP   (1 << 7)

//
//  Определение цифр через маски сегментов
//
#define D0  (MASK_A | MASK_B | MASK_C | MASK_D | MASK_E | MASK_F)
#define D1  (MASK_B | MASK_C)
#define D2  (MASK_A | MASK_B | MASK_G | MASK_D | MASK_E)
#define D3  (MASK_A | MASK_B | MASK_C | MASK_D | MASK_G)
#define D4  (MASK_B | MASK_C | MASK_G | MASK_F)
#define D5  (MASK_A | MASK_C | MASK_D | MASK_F | MASK_G)
#define D6  (MASK_A | MASK_C | MASK_D | MASK_E | MASK_F | MASK_G)
#define D7  (MASK_A | (MASK_B | MASK_C))
#define D8  (MASK_A | MASK_B | MASK_C | MASK_D | MASK_E | MASK_F | MASK_G)
#define D9  (MASK_A | MASK_B | MASK_C | MASK_D | MASK_F | MASK_G)

#define	TOTAL_DIGITS	3

volatile uint8_t maskArray[TOTAL_DIGITS] = { MASK_G, MASK_G, MASK_G };

//
// Функция складывает готовую маску в массив масок
//
inline void putMask(const uint8_t mask, const uint8_t pos) {
	if (pos < TOTAL_DIGITS) maskArray[pos] = mask;
}

//
// Функция разделяет число на сотни, десятки и единицы и складывает в массив масок
//	сотни в позицию 2
//	десятки в позицию 1
//	единицы в позицию 0
//
void putNumber(const unsigned number) {
	static const uint8_t allDigits[] = { D0, D1, D2, D3, D4, D5, D6, D7, D8, D9 }; 
	div_t divRes = div(number, 100);
	putMask(allDigits[divRes.quot], 2);
	divRes = div(divRes.rem, 10);
	putMask(allDigits[divRes.quot], 1);
	putMask(allDigits[divRes.rem], 0);
}

//
//  Функция устанавливает по маске - параметру (HIGH-горит, LOW-не горит)
//
void setRawSegments(const int8_t mask) {
  digitalWrite(PIN_A, mask & MASK_A);
  digitalWrite(PIN_B, mask & MASK_B);
  digitalWrite(PIN_C, mask & MASK_C);
  digitalWrite(PIN_D, mask & MASK_D);
  digitalWrite(PIN_E, mask & MASK_E);
  digitalWrite(PIN_F, mask & MASK_F);
  digitalWrite(PIN_G, mask & MASK_G);
  digitalWrite(PIN_DP, mask & MASK_DP);
}

//
// Инициализация таймера. делается один раз
//
void setupTimer2(void) {
  PRR &= ~(1 << PRTIM1);  // Убедимся, что таймер 1 не отключен
  TCCR1A = 0;         // Установим Normal режим
  TCCR1B = PRESACLER;   // Установим делитель частоты 
  TCNT1 = TICKS;        // Установим счётчик
  TIMSK1 |= (1 << TOIE1); // Разрешим прерывание по переполнению
  TIFR1 = 1;          //  Очистим Очистим флаг прерывания (если он взведён)
}
//
// Обработка прерывания по переполнению
//
ISR(TIMER1_OVF_vect) {
  TCNT1 = TICKS;        // Установим счётчик для следующего прерывания
  //
  //  Покажем очередную цифру, как мы это делали раньше
  //
	static uint8_t currentDigit = 0;
	static const uint8_t all_postions[] = { PIN_DIG0, PIN_DIG1, PIN_DIG2 }; 
	for (register uint8_t i = 0; i < TOTAL_DIGITS; i++) {
		digitalWrite(all_postions[i], currentDigit != i);
	}
	setRawSegments(maskArray[currentDigit]);
	currentDigit = (currentDigit + 1) % TOTAL_DIGITS;   // В следующий раз показываем другую цифру
}

//
//  Всё, что выше  - это своя жизнь. От основной программы требуется только 
//  положить число для показа в numberToShow и оно будет показываться.
//  Больше основная программа ни о чём не заботится
//
///////////////////////////////////////////////////////////////////////////////////


void setup() {
  setupTimer2();
    // ... задайте все pinMode как раньше 
	pinMode(2, OUTPUT);
	pinMode(3, OUTPUT);
	pinMode(4, OUTPUT);
	pinMode(5, OUTPUT);
	pinMode(6, OUTPUT);
	pinMode(7, OUTPUT);
	pinMode(8, OUTPUT);
	pinMode(9, OUTPUT);
	pinMode(10, OUTPUT);
	pinMode(11, OUTPUT);
	pinMode(12, OUTPUT);
	pinMode(13, OUTPUT);
	putNumber(666);
	delay(2000);
	putMask(MASK_G, 1); //  это нужно для велосипеда - рисует центральную ось
}

//  
//  велосипед
//
void loop() {
	static unsigned long millis0 = millis() - 120;
	unsigned long curMillis = millis();
	static uint8_t maskIndex = 0;
	const static uint16_t masks [] = { MASK_A, MASK_G, MASK_D }; 
	if (curMillis - millis0 >= 120) {
		millis0 = curMillis;
		putMask(masks[maskIndex], 0);
		putMask(masks[2 - maskIndex], 2);
		maskIndex = (maskIndex + 1) % (sizeof(masks) / sizeof(masks[0]));
	}
}

 

d13lider
d13lider аватар
Offline
Зарегистрирован: 19.10.2015

Прошу прощения, все выходные был занят ремонтом блока зажигания на катер. и вообще мозги в эту сторону не соображали. поэтому смотрел по возможности. 

 

ЕвгенийП пишет:

 

Сколько тиков процессора умещается в 10мс? При частоте 16МГц, 16 тиков это микросекунда, стало быть 16000 тиков – 1 миллисекунда. Ну, а 10 мс, очевидно 160000 тиков. Столько мы отсчитать на таймере не можем (переполнимся нахрен), на помощь приходит делитель частоты. Например, возьмём делитель 8. Один тик таймера будет равен восьми тикам процессора. Значит в 10 миллисекундах будет 160 000 / 8 = 20 000 тысяч тиков таймера. Столько мы можем себе позволить.

 

вот исходя из этого я понял как считать. вы сказали 10мс это 160 000 тиков. значит 50 мс(почему 50? потому что протеус не может быстрее генерировать, и на реальном железе я конечно буду выставлять такую скорость, при которой  у меня не будут мерцать цифры) 50мс это 160000х5 = 800 000 и потом разделил на делитель частоты 64, и получил число 12 500. и Записал в счётчик таймера число 53036 ( = 65536 – 12500). но за полную формулу рассчета спасибо) 

ЕвгенийП пишет:

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

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

 

Пример сдлеан так: сначала показывается число 666, а через три секунды начинается "велосипед".

все заработало, и 666, и велосипед. все есть. не понимаю правда половину, ну как не понимаю, понимаю какая строчка за что отвечает, а вот за что отвечает  div_t и div, и вообще что это такое? я наверно достал такими вопросами. и может у вас есть какой нибудь источник, где можно посмотреть все такие команды, просто нет на сайте ардуины этого)))

d13lider
d13lider аватар
Offline
Зарегистрирован: 19.10.2015

P.s.

изменил строки, т.к. рисовал цифры не правильно, допустим число 254 рисовал как 452

072 void putNumber(const unsigned number) {
073     static const uint8_t allDigits[] = { D0, D1, D2, D3, D4, D5, D6, D7, D8, D9 };
074     div_t divRes = div(number, 100);
075     putMask(allDigits[divRes.quot], 2);
076     divRes = div(divRes.rem, 10);
077     putMask(allDigits[divRes.quot], 1);
078     putMask(allDigits[divRes.rem], 0);
079

}

изменил на 

072 void putNumber(const unsigned number) {
073     static const uint8_t allDigits[] = { D0, D1, D2, D3, D4, D5, D6, D7, D8, D9 };
074     div_t divRes = div(number, 100);
075     putMask(allDigits[divRes.quot], 0);
076     divRes = div(divRes.rem, 10);
077     putMask(allDigits[divRes.quot], 1);
078     putMask(allDigits[divRes.rem], 2);
079 }

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

d13lider пишет:

вот исходя из этого я понял как считать. вы сказали 10мс это 160 000 тиков. значит 50 мс(почему 50? 

Вот здесь "перепутка". Не 50 мс, а 50 герц частота - обновления экрана. Это не из-за протеуса, а из-за физиологии зрения. С такой частотй мерцать не будет, можете смело использовать.

Надеюсь, подробный разбор в посте №135 понятен и больше на эту тему вопросов нет?

d13lider пишет:
а вот за что отвечает  div_t и div, и вообще что это такое?

Это вовсе не ардуиновская фишка - это "обще-Сишное", т.е. стнандартная библиотека языка С.

дело в том, что если при операции деления Вам нужен и остаток и частное, то на честном С деление нужно быполнять дважды, т.к. что-то одно обязательно теряется. Функция div закрывает эту пролему, т.к. она выполняет деление один раз и возвращает структуру div_t в которой есть и частное (quot) и остаток (rem). Вот я и пользуюсь ею, чтобы два раза не делить.

А полный список функций, которые есть в данной версии С-шной библиотеки можно посмотреть на сайте AtmelВ частности, вот про функцию div, а вот про структуру div_t.

 

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

d13lider пишет:
изменил строки, т.к. рисовал цифры не правильно, допустим число 254 рисовал как 452

Ну, отлично, так и надо.

d13lider
d13lider аватар
Offline
Зарегистрирован: 19.10.2015

ЕвгенийП пишет:

d13lider пишет:

вот исходя из этого я понял как считать. вы сказали 10мс это 160 000 тиков. значит 50 мс(почему 50? 

Вот здесь "перепутка". Не 50 мс, а 50 герц частота - обновления экрана. Это не из-за протеуса, а из-за физиологии зрения. С такой частотй мерцать не будет, можете смело использовать.

Надеюсь, подробный разбор в посте №135 понятен и больше на эту тему вопросов нет?

 

это я понял, но говорю протеус не может правильно отобразить индикатор, и если ставишь быстрее скорость обновления, просто пропадает цифра. и все, 50мс я ставил для тестов. что бы видить какие цифры будут отображаться. а на реальном железе будет совсем по другому. и то, что моргать они будут это я понял. но тогда я поставлю частоту обновления выше. ну т.е. как вы и сказали 50гц.

 

ЕвгенийП пишет:

 

Это вовсе не ардуиновская фишка - это "обще-Сишное", т.е. стнандартная библиотека языка С.

дело в том, что если при операции деления Вам нужен и остаток и частное, то на честном С деление нужно быполнять дважды, т.к. что-то одно обязательно теряется. Функция div закрывает эту пролему, т.к. она выполняет деление один раз и возвращает структуру div_t в которой есть и частное (quot) и остаток (rem). Вот я и пользуюсь ею, чтобы два раза не делить.

А полный список функций, которые есть в данной версии С-шной библиотеки можно посмотреть на сайте AtmelВ частности, вот про функцию div, а вот про структуру div_t.

 
спасибо большое буду глубже изучать. в общем выложу прибор который получился через пару дней, и еще вопрос, по схеме силовой части сможете подсказать? в общем хочу управление нагрузкой 220v сделать через симистор, либо 2 тиристора, что можете посоветовать, нагрузка около 30-35А
ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

d13lider пишет:

спасибо большое буду глубже изучать. в общем выложу прибор который получился через пару дней, и еще вопрос, по схеме силовой части сможете подсказать? в общем хочу управление нагрузкой 220v сделать через симистор, либо 2 тиристора, что можете посоветовать, нагрузка около 30-35А

Подсказать-то могу, но лучше не стоит. Дело в том,  что в программированнии я профессионал, а в электронике - любитель-самоучка. Так что такие подсказки - лучше не надо.

d13lider
d13lider аватар
Offline
Зарегистрирован: 19.10.2015

ЕвгенийП пишет:

 

Подсказать-то могу, но лучше не стоит. Дело в том,  что в программированнии я профессионал, а в электронике - любитель-самоучка. Так что такие подсказки - лучше не надо.

подскажите, в области электроники я смотрю у вас "любитель" получается лучше чем некоторые "проффесионалы" 

d13lider
d13lider аватар
Offline
Зарегистрирован: 19.10.2015

d13lider пишет:

ЕвгенийП пишет:

 

Подсказать-то могу, но лучше не стоит. Дело в том,  что в программированнии я профессионал, а в электронике - любитель-самоучка. Так что такие подсказки - лучше не надо.

подскажите, в области электроники я смотрю у вас "любитель" получается лучше чем некоторые "проффесионалы" 

ладно я думаю с этой темой мы разобрались, я наверное свой вопрос перенесу в " Аппаратные вопросы"

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

d13lider пишет:

подскажите, в области электроники я смотрю у вас "любитель" получается лучше чем некоторые "проффесионалы" 

Я бы сделал вот так, только с учётом замечания коллеги в посте №18 там же.

d13lider
d13lider аватар
Offline
Зарегистрирован: 19.10.2015

одного такого симистора я не найду. а возможно запаралелить их? или это уже 2 обвязки для каждого симистора делать?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Почему не найдёте? На 30-35А? Ну, вот, например - http://www.chipdip.ru/product/bta41-700b/

Они доставляют в Евросеть - очень быстро.

d13lider
d13lider аватар
Offline
Зарегистрирован: 19.10.2015

ЕвгенийП пишет:

Почему не найдёте? На 30-35А? Ну, вот, например - http://www.chipdip.ru/product/bta41-700b/

Они доставляют в Евросеть - очень быстро.

я просто не уверен что там ток 30-35А. а если 50? что бы запасик был) по рассчетам 30-35А

и они реально на таких тонких ножках смогут секунд 5-6 держать 40А?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Думаю, да. Симисторы на пользовал на таких токах, но вот полевой транзистор IRFZ44N (по даташиту - 49А) в таком же точно корпусе у меня работает и до 42 ампер отлично держит, только радиатор хороший нужен.