Ситуёвина следующая:
Загружаю калькулятор, считаю делители для частоты 100 кГц.
Enter desired frequency in Hz
(use decimal point for fractions. I.e. 0.12 means 0,12Hz):
Results for frequency: 100000.00Hz
(0,1,2,3) Prescaler: 8; MaxValue: 9; Frequency: 100000.00Hz; Diff: 0.00Hz
(0,1,2,3) Prescaler: 1; MaxValue: 79; Frequency: 100000.00Hz; Diff: 0.00Hz
(2) Prescaler: 32; MaxValue: 2; Frequency: 83333.34Hz; Diff: 16666.66Hz
(0,1,2,3) Prescaler: 64; MaxValue: 0; Frequency: 125000.00Hz; Diff: 25000.00Hz
(2) Prescaler: 128; MaxValue: 0; Frequency: 62500.00Hz; Diff: 37500.00Hz
Prescaler: 256 - Not possible
Prescaler: 1024 - Not possible
Enter desired frequency in Hz
(use decimal point for fractions. I.e. 0.12 means 0,12Hz):
Далее использую этот скетч:
#ifndef CONSTANTS
#include "ConstTimers.h"
// Параметры для работы таймера/счётчика №2 на частоте 100kГц
//
constexpr uint8_t timerBits2 = getPrescalerBits(2, 100000);
constexpr uint8_t timerTicks2 = getTimerTicks(2, 100000);
//
#endif
unsigned long counter = 0;
void setup() {
Serial.begin(115200);
pinMode(13, OUTPUT);
pinMode(11, OUTPUT);
TCCR2A = 0x42; // Инвертирование пина 11 по сравнению и режим CTC то OCR2A
TCCR2B = 0x00 | timerBits2; // Установить СТС режим и делитель частоты
OCR2A = timerTicks2; // установить TOP равным topValue
Serial.print("TCCR2B = 0x00 | timerBits2 = ");
Serial.println(timerBits2);
Serial.print("OCR2A = timerTicks2 : = ");
Serial.println(timerTicks2);
Serial.println();
}
void loop() {
while(digitalRead(11)==LOW);
counter++;
if(counter==100000){
digitalWrite(13,!digitalRead(13));
counter = 0;}
}
И смотрю вывод в порт. Вижу когнитивный диссонанс.
Не понял в чём именно Ваш когнитивный диссонанс. Вроде всё правильно. Ну, разве что в строке 6 должно быть по идее 80, а не 79, ну там всё во float считается, где-то неаккуратно огругляется, можно полезть посмотреть. А так, с точнотью до этого округлённого тика, всё правильно. В чём проблема-то?
Вы путаете два понятия. Тот старый калькулятор и это библиотека считаю разные вещи. Они всегда отличаются в два раза.
Тот старый калькулятор был для "меандров", т.е. он считал через какое время надо "инвертировать" пин, чтобы получить нужную частоту меандра. Вот он и насчитал 80.
Эта же библиотека просто считает задержку для прерываний с нужной частотой. Вот у этой библиотеки получается 160 (=80х2). Т.е. она считает задержку не для меандра нужной частоты, а для прерываний с нужной частотой.
Вы же осциллографом измеряете опять же меандр. Получается, что Вы с частотой 100кГц инверитуете пин. Ну и какова частота меандра? Правильно - 50 кГц.
Понятно?
Правильность величины 160 легко проверить даже в уме. Давайте. При частоте 100кГц каким будет период? 10 микросекунд. Сколько тиков укладывается в 10мкс при тактовой 16МГц? 160. Всё правильно, как видите.
А это.. может я, конечно, не совсем по теме спрошу... Ежели таймером нога перекидывается на хардварном уровне (flip-flop) и происходит остановка генерации (через зануление COM1A1 и COM1A0, например), то нога же остаётся в текущем состоянии? Есть какой-то волшебный регистр, который инструктирует МК перевести её в какой-то совершенно определённый LOW или HIGH?
Зарапортовался немного. COM1A1 + COM1A0 таймер не останавливают, конечно, а просто ногу отстёгивают от управления.
Не знаю, насколько это корректно, но я пока придумал только изменить режим генерации через COM1A1; - это должно на следующем совпадении ногу в LOW перевести.
Есть какой-то волшебный регистр, который инструктирует МК перевести её в какой-то совершенно определённый LOW или HIGH?
Волшебный регистр есть, но только для не-PWM режимов , FOC "Force Output Compare". С помощью него удобно делать всякие одиночные импульсы, типа как тут.
Ну, так... у меня других не было. Корпус крепкий (можно в гараж взять), два луча. Генератором dimax-а проверял - показания сходятся. Под музыку с линейного выхода тоже бодро дрыгается. Скриншоты делает, но достать их - ещё тот геморрой (быстрее так зафоткать). Управление кнопками, так что для постоянной работы неудобен, но для эпизодических применений - более, чем. Триггеры, развертки - всё на месте. Есть ещё какие-то режимы сложений луча... но я туда не лез, мне не надо пока что.
Основная проблема - аккумулятор литиевый подобрать. Которые с защитой - могут не влезть по длине, а без защиты... Я так и не понял из документации - сам девайс контролирует разряд или нет. Поэтому решил не рисковать и теперь сую прокладку между контактом акк. и бат. блока - он сделан жопоруким проектировщиком каким-то. Комплектное зарядное не советую - рвануло на третий день. Взял LitoKala, ей заряжаю.
Добавил поддержку ATtiny 25/45/85 и чуток причесал код. Теперь, там кстати, видно как добавлять новые микроконтроллеры, если кому надо.
#ifndef CONSTTIMERS_H
#define CONSTTIMERS_H
///////////////////////////////////////////////////////////////////////////////
//
// Недобиблиотека вычисления битов конфигурации делителя частоты и
// количества тиков таймера по заданной частоте.
//
// Предназначена для использования с микроконтроллером ATmega328P
// (например, в Ардуино или в AVR-студии). Модификация для других
// микроконтроллеров возможна и несложна, как будет показано ниже.
//
// Основная особенность: ВСЕ ВЫЧИСЛЕНИЯ ПРОИСХОДЯТ ВО ВРЕМЯ КОМПИЛЯЦИИ.
// В РЕЗУЛЬТИРУЮЩИЙ КОД НЕ ПОПАДАЕТ НИ ОДНОГО БАЙТА НИ КОДА, НИ ДАННЫХ.
//
// замечание о точности:
// гарантировать точность произвольной частоты невозможно, т.к. требуемый период
// может элементарно не являться делителем тактовой частоты микроконтроллера или
// его, может быть, невозможно подобрать имеющимися делителями частоты.
// Недобиблиотека ВСЕГДА выдаёт наилучший из возможных результатов для заданной частоты
// на заданном таймере. Но при этом нет никакой возможности узнать насколько хорош
// результат и какова погрешность. Если требуется инструмент для «зрячего» выбора
// частот, следует взять «калькулятор таймеров» (их много, например, есть и у автора).
// конец замечания о точности.
//
// ИСПОЛЬЗОВАНИЕ
//
// Обязательна опция -std=c++11 или -std=gnu++11 (или больше - 14, 17). В свежих IDE она
// стоит по умолчанию, а в AVR Studio 7.0 - нет. Если нет, то надо поставить.
//
// Для использования необходимо включить файл «ConstTimers.h» и определить константы с
// модификатором constexpr для нужных конфигурационных битов и количества тиков, которым
// присвоить значения, возвращаемые функциям getPrescalerBits и getTimerTicks соответсвенно.
// Обе функции принимают два параметра – номер таймера и требуемую частоту. Функция
// getPrescalerBits возвращает результат типа uint8_t. Функция getTimerTicks возвращает результат
// типа uint16_t, т.к. таймер может быть 16-битным, для 8-битных таймеров значение не превышает 255.
//
// Например:
//
// #include <ConstTimers.h>
// //
// // Параметры для работы таймера/счётчика №2 на частоте 1кГц
// //
// constexpr uint8_t timerBits2 = getPrescalerBits(2, 1000);
// constexpr uint8_t timerTicks2 = getTimerTicks(2, 1000);
// //
// // Параметры для работы таймера/счётчика №1 на частоте 500Гц
// //
// constexpr uint8_t timerBits1 = getPrescalerBits(1, 500);
// constexpr uint16_t timerTicks1 = getTimerTicks(1, 500);
// .............
// //
// // Конфигурация таймеров
// // таймер №2
// TCCR2B = timerBits2;
// OCR2A = timerTicks2;
// // таймер №1
// TCCR1B = timerBits1;
// OCR1B = timerTicks1;
//
//Результат работы будет точно такой же, как если написать константы вместо вызовов функций:
//
// TCCR2B = 4;
// OCR2A = 250;
// TCCR1B = 1;
// OCR1B = 32000;
//
// Ни на один байт код не изменится.
//
// КОФИГУРАЦИЯ:
//
// 1. расчёт производится для текущей тактовой частоты микроконтроллера. Если нужно
// считать для какой-то другой частоты, измените константу FCPU.
//
// 2. STimerParameters - массив конфигурации таймеров. Количество элементов массива
// соответсвует количеству таймеров. Нулевой элемент описывает нулевой таймер,
// первый элемент – первый таймер и т.д. Если требуется расширить недобиблиотеку для других
// микроконтроллеров, нужно изменить именно этот массив и больше изменять ничего не надо.
//
// В массиве для каждого таймера указано:
// 1) разрядность таймера в виде максимально возможного значения количества тиков
// (для 8-разрадных таймеров – 0xFF, для 16-разрядных – 0xFFFF.
// 2) указатель на массив делителей частоты. Делители начинаются с 1 (делитель 0 писать не нужно)
// 3) количество делителей частоты у данного таймера.
//
// ЛИЦЕНЗИЯ
//
// Данный код поставляется по лицензии ПНХ.
//
// 1. Вы можете свободно использовать или не использовать его в коммерческих,
// некоммерческих, и любых иных, не запрещённых законом, целях.
//
// 2. Автор не несёт решительно никакой ответственности за любые положительные
// или отрицательные результаты использования или неиспользования данного кода.
//
// 3. Если Вам таки хочется сделать автору предъяву, то Вы знаете, куда
// Вам следует обратиться. А если не знаете, то см. название лицензии.
//
// 4. Если данный код вдруг Вам пригодился (как учебник или ещё как что) и Вам
// почему-либо (ну, приболели, может) захотелось отблагодарить автора рублём,
// то это всегда пожалуйста – WebMoney, кошелёк № R626206676373
//
// 5. Возникновение или невозникновение у Вас желаний, обозначенных в п.4
// настоящей лицензии никак не связано с п.1, который действует безусловно
// и независимо от п.4.
//
// 6. Если данный код нужен Вам с какой-либо другой лицензией, например, с
// сопровождением или Вы нуждаетесь во внесении изменений, свяжитесь с автором
// на предмет заключения договора гражданско-правового характера.
//
///////////////////////////////////////////////////////////////////////////////
#define ATtiny85Detected (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__))
#define ATmega328Detected (defined(__AVR_ATmega48A__) || defined(__AVR_ATmega48PA__) || defined(__AVR_ATmega88A__) || defined(__AVR_ATmega88PA__) || defined(__AVR_ATmega168A__) || defined(__AVR_ATmega168PA__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__))
#define FCPU F_CPU
struct STimerParameters {
const uint32_t maxValue;
const int * prescalers;
const uint8_t totalPrescalers;
};
static constexpr uint32_t bits8 = 0x000000FFul;
static constexpr uint32_t bits16 = 0x0000FFFFul;
#if ATmega328Detected
static constexpr int prescalers01[] = { 1, 8, 64, 256, 1024 };
static constexpr int prescalers2[] = { 1, 8, 32, 64, 128, 256, 1024 };
static constexpr STimerParameters timerParameters[] = {
{bits8, prescalers01, sizeof(prescalers01) / sizeof(prescalers01[0])},
{bits16, prescalers01, sizeof(prescalers01) / sizeof(prescalers01[0])},
{bits8, prescalers2, sizeof(prescalers2) / sizeof(prescalers2[0])},
};
#elif ATtiny85Detected
static constexpr int prescalers0[] = { 1, 8, 64, 256, 1024 };
static constexpr int prescalers1[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384 };
static constexpr STimerParameters timerParameters[] = {
{bits8, prescalers0, sizeof(prescalers0) / sizeof(prescalers0[0])},
{bits8, prescalers1, sizeof(prescalers1) / sizeof(prescalers1[0])},
};
#else
#error The library does not seem to support your MCU
#endif
constexpr int8_t totalTimers = sizeof(timerParameters) / sizeof(timerParameters[0]);
static constexpr uint32_t getPeriod(const uint32_t frequency) {
return (FCPU + frequency / 2) / frequency;
}
static constexpr uint16_t prValue(const int8_t prescalerId, const int8_t nTimer) {
return timerParameters[nTimer].prescalers[prescalerId];
}
static constexpr uint32_t getDesiredTicks(const uint32_t frequency, const int8_t prescalerId, const int8_t nTimer) {
return (getPeriod(frequency) + prValue(prescalerId, nTimer) / 2) / prValue(prescalerId, nTimer);
}
static constexpr uint32_t correctTicks(uint32_t dTicks, const uint32_t maxValue) {
//if (dTicks > maxValue) return maxValue; else return dTicks; // начиная с C++14
return dTicks > maxValue ? maxValue : dTicks;
}
static constexpr uint32_t getTicks(const uint32_t frequency, const int8_t prescalerId, const int8_t nTimer) {
return prescalerId >= timerParameters[nTimer].totalPrescalers ? 0x1FFFFFFF :
correctTicks(getDesiredTicks(frequency, prescalerId, nTimer), timerParameters[nTimer].maxValue);
}
static constexpr uint32_t getBits(const int8_t prescalerId, const int8_t nTimer) {
return prescalerId >= timerParameters[nTimer].totalPrescalers ? timerParameters[nTimer].totalPrescalers : prescalerId + 1;
}
static constexpr int32_t absError(const uint32_t frequency, const int8_t prescalerId, const int8_t nTimer) {
return abs(prescalerId >= timerParameters[nTimer].totalPrescalers ? 0x1FFFFFFF :
static_cast<int32_t>(getTicks(frequency, prescalerId, nTimer) * prValue(prescalerId, nTimer)) -
static_cast<int32_t>(getPeriod(frequency)));
}
static constexpr uint8_t getPrescalerId(const uint32_t error, const uint32_t newError, const uint8_t prId, const uint8_t candidate, const uint32_t frequency, const int8_t nTimer) {
return
(prId >= timerParameters[nTimer].totalPrescalers) ? candidate
: getPrescalerId(newError, absError(frequency, prId+1, nTimer), prId+1, (error <= newError) ? candidate : prId, frequency, nTimer);
}
static constexpr uint16_t getTimerTicks(const int8_t nTimer, const uint32_t freq) {
return getTicks(freq, getPrescalerId(0x1FFFFFul, absError(freq, 0, nTimer), 0, 0, freq, nTimer), nTimer);
}
static constexpr uint8_t getPrescalerBits(const int8_t nTimer, const uint32_t freq) {
return getBits(getPrescalerId(0x1FFFFFul, absError(freq, 0, nTimer), 0, 0, freq, nTimer), nTimer);
}
#endif // CONSTTIMERS_H
Так и не понял... нафига весь этот бесконечный и беспросветный Си++ гемор??? В итоге... дело, оказывается, в знаниях камня и даташита... а не в Си++... с которого толку аж никакого... Попытка была конечно очень смешная... но состоявшаяся...
Не понял, значит не дано: «Многие вещи нам непонятны не потому, что наши понятия слабы, но потому, что сии вещи не входят в круг наших понятий» (К.П. Прутков).
Во избежания срача, все дальнейшие посты на темы "нахрена это нужно" и т.п., а также ответы на них, будут тереться без предупреждения.
Есть что обсуждать - обсуждаем, хочется покакать - туалет прямо и направо, а здесь нехрен.
Есть какой-то волшебный регистр, который инструктирует МК перевести её в какой-то совершенно определённый LOW или HIGH?
Волшебный регистр есть, но только для не-PWM режимов , FOC "Force Output Compare". С помощью него удобно делать всякие одиночные импульсы, типа как тут.
поинтересуюсь!
А можно ли этот способ применить для отсчитывания очень точного интервала, к примеру 1 секунда, в том же частотомере, вместо delay(1000)
Для точных ворот лучше использовать что то постабильнее, нежели системный кварц. Хотя бы 32 кгц, лучше с термостабилизацией. Ну и формировать железно, с выхода таймера-делителя.
Ну, для того что бы измерить входную частоту с точностью 1 гц (не будем о фазе)) нужны ворота в 1 сек, не менее. ds3231 выдаёт на выходе SQW только период в 1 с, т.е. полупериод будет 500 мс. О длительных интервалах с помощью аларма не задумывался.) Но обычно, индикация (ворота) свыше 2 сек. уже несколько раздражает.
Евгений, ни в коей мере на являясь "апологетом идеи неприменимости С++ для МК", тем не менее рискну предположить, что если заменить constexpr на inline и включить оптимизацию, то результат будет точно таким же - все промежуточные константные выражения свернутся и останутся голые результаты.
Но! в случае с inline данный результат ни фига не гарантируется на других компиляторах и в других режимах оптимизации, так что несомненная польза от Вашено подхода наличествует.
рискну предположить, что если заменить constexpr на inline и включить оптимизацию, то результат будет точно таким же - все промежуточные константные выражения свернутся и останутся голые результаты.
Неа! По крайней мере при опциях «из коробки». Можете проверить сами и убедиться.
Вполне допускаю, что если поиграться опциями, то, может быть, и получится (а, может, и нет). Но главное здесь не в том, что (как Вы совершенно справедливо отметили) constexpr - стандартизованное средство языка, которое обязано работать по стандарту, а оптимизация – «как получится». Разница гораздо глубже. Разница в том, что здесь открываются новые возможности, которых там нет.
Вот смотрите, например, чтобы сделать эту библиотеку реально полезной, надо бы устранить в ней одну недоработку, которая вполне реализуема на constexpr и абсолютно никак не реализуема на inline.
А доработка такая. В описании я отмечал, что библиотека выдаёт наилучшее возможное приближение к точному временному интервалу. Для каких-то интервалов – оно просто точное, а для каких-то «точнее никак». Так вот хотелось бы иметь возможность контролировать точность. Например, указывать, что если погрешность выходит за некоторую величину, то компиляция должна быть прекращена с соответствующим сообщением.
Согласитесь, полезная фича. Но на inline не делается никак.
А чё не так с лицензией? Там же сказано, что импользовать или не использовать можно с любыми целями, кроме незаконных. Так что модифицируйте на здоровье, в WM удаляйте, если мешает.
А чё не так с лицензией? Там же сказано, что импользовать или не использовать можно с любыми целями, кроме незаконных. Так что модифицируйте на здоровье, в WM удаляйте, если мешает.
Не возражаю. Я уже не в первый код на форуме WM вставляю. На сегодняшний день, общая сумма полученых транзакций 0 рублей и столько же копеек. Пусть теперь и Ворота разбогатеет, не всё ж мне одному.
Ладно, застыдили, попробую сегодня добавить контроль точности, а заодно и задание времени не частотой, а периодом (в смысле просто временным интервалом). А то нужно, скажем 150мс интервал, а хрен его задашь - частота нецелая получается. Лучше иметь возможность задавать и так, и так - как удобнее в данный момент.
Вот и Блинк на 3-ем Таймере на плате WAVGAT на вашей библиотеке:
Ситуёвина следующая:
Загружаю калькулятор, считаю делители для частоты 100 кГц.
Далее использую этот скетч:
И смотрю вывод в порт. Вижу когнитивный диссонанс.
Как говорил DIMAX если что-то может не заработать, оно у вас обязательно не заработает.
PS скетч ваял из этой старой заготовки:
Не понял в чём именно Ваш когнитивный диссонанс. Вроде всё правильно. Ну, разве что в строке 6 должно быть по идее 80, а не 79, ну там всё во float считается, где-то неаккуратно огругляется, можно полезть посмотреть. А так, с точнотью до этого округлённого тика, всё правильно. В чём проблема-то?
В чём проблема-то?
Так библиотека рассчитала и загрузила 160 как бы )
Мой асилограф-милипильметр показывает частоту 50 килогерц...
Вы путаете два понятия. Тот старый калькулятор и это библиотека считаю разные вещи. Они всегда отличаются в два раза.
Тот старый калькулятор был для "меандров", т.е. он считал через какое время надо "инвертировать" пин, чтобы получить нужную частоту меандра. Вот он и насчитал 80.
Эта же библиотека просто считает задержку для прерываний с нужной частотой. Вот у этой библиотеки получается 160 (=80х2). Т.е. она считает задержку не для меандра нужной частоты, а для прерываний с нужной частотой.
Вы же осциллографом измеряете опять же меандр. Получается, что Вы с частотой 100кГц инверитуете пин. Ну и какова частота меандра? Правильно - 50 кГц.
Понятно?
Правильность величины 160 легко проверить даже в уме. Давайте. При частоте 100кГц каким будет период? 10 микросекунд. Сколько тиков укладывается в 10мкс при тактовой 16МГц? 160. Всё правильно, как видите.
Просто эти две программы разные вещи считают.
Просто эти две программы разные вещи считают.
я то думал, что это одно и тоже, то-есть если нам надо сделать меандр частотой 100 кгц, значение должно быть 200000?!
Ок!
Ну, таки да. Для 200 она Вам выдаст не 160, а 80. Но само прерывание будет тикать именно с частотой 200кГц. ну, Вы уже поняли, так ведь?
А это.. может я, конечно, не совсем по теме спрошу... Ежели таймером нога перекидывается на хардварном уровне (flip-flop) и происходит остановка генерации (через зануление COM1A1 и COM1A0, например), то нога же остаётся в текущем состоянии? Есть какой-то волшебный регистр, который инструктирует МК перевести её в какой-то совершенно определённый LOW или HIGH?
Ну, таки да. Для 200 она Вам выдаст не 160, а 80. Но само прерывание будет тикать именно с частотой 200кГц. ну, Вы уже поняли, так ведь?
я не совсем безнадёжный )))
sadman41, dimax его знает!
Зарапортовался немного. COM1A1 + COM1A0 таймер не останавливают, конечно, а просто ногу отстёгивают от управления.
Не знаю, насколько это корректно, но я пока придумал только изменить режим генерации через COM1A1; - это должно на следующем совпадении ногу в LOW перевести.
Типа того, вобщем:
Если отключаешь режим toggle переходом в нормальный режим, то уровень на выходе определяется состояние бита порта. К примеру, OC1A = PB1.
Ну да, свиду норм. Ну и наверно TCCR1A |= 1<<COM1A1, всё ж таки.)
Если отключаешь режим toggle переходом в нормальный режим, то уровень на выходе определяется состояние бита порта. К примеру, OC1A = PB1.
Ну, digitalWrite(.., LOW) любой напишет. Я хотел чисто таймером поманипулировать.
Ну и наверно TCCR1A |= 1<<COM1A1, всё ж таки.
Так-то там ещё надо COM1A0 сбросить, иначе нога в HIGH пойдёт.
Так-то там ещё надо COM1A0 сбросить, иначе нога в HIGH пойдёт.
Значит 2 действия для low, либо весь TCCR1A за раз.)
Есть какой-то волшебный регистр, который инструктирует МК перевести её в какой-то совершенно определённый LOW или HIGH?
Волшебный регистр есть, но только для не-PWM режимов , FOC "Force Output Compare". С помощью него удобно делать всякие одиночные импульсы, типа как тут.
dimax, накинул такого вот на вентилятор...
Субъективно - нога в 0 скидывается с запозданием в секунду-две. Вроде и не PWM-mode и FOC применён... Или это цифро-осциллограф притормаживает?
UPD:
Сделал так и вторым лучом на D3 присел:
Похоже, что всё ОК, просто Джихан долго думает.
Похоже, что всё ОК, просто Джихан долго думает.
Вопрос немного не потеме, по твоему осциллографу, можешь порекомендовать к покупке?
Ну, так... у меня других не было. Корпус крепкий (можно в гараж взять), два луча. Генератором dimax-а проверял - показания сходятся. Под музыку с линейного выхода тоже бодро дрыгается. Скриншоты делает, но достать их - ещё тот геморрой (быстрее так зафоткать). Управление кнопками, так что для постоянной работы неудобен, но для эпизодических применений - более, чем. Триггеры, развертки - всё на месте. Есть ещё какие-то режимы сложений луча... но я туда не лез, мне не надо пока что.
Основная проблема - аккумулятор литиевый подобрать. Которые с защитой - могут не влезть по длине, а без защиты... Я так и не понял из документации - сам девайс контролирует разряд или нет. Поэтому решил не рисковать и теперь сую прокладку между контактом акк. и бат. блока - он сделан жопоруким проектировщиком каким-то. Комплектное зарядное не советую - рвануло на третий день. Взял LitoKala, ей заряжаю.
да мой С1-65 загудел, а ремонтировать приборы то ещё дело )))
Есть приставка Хантек, двухлучевая, но там всё кривое, начиная от щупов,
вот неспешно подбираю, чтобы на столе вертикально стояло, брать как ЕвгенийП дороговато
Не сразу дошло, почему вместо строк №№ 12-13 нельзя просто в HIGH 9-ый пин загнать. Но, потом таки вроде устаканилось.
Добавил поддержку ATtiny 25/45/85 и чуток причесал код. Теперь, там кстати, видно как добавлять новые микроконтроллеры, если кому надо.
неожиданно вдруг узнал, что у 85 с предделителями побогаче
Так и не понял... нафига весь этот бесконечный и беспросветный Си++ гемор??? В итоге... дело, оказывается, в знаниях камня и даташита... а не в Си++... с которого толку аж никакого... Попытка была конечно очень смешная... но состоявшаяся...
Не понял, значит не дано: «Многие вещи нам непонятны не потому, что наши понятия слабы, но потому, что сии вещи не входят в круг наших понятий» (К.П. Прутков).
Во избежания срача, все дальнейшие посты на темы "нахрена это нужно" и т.п., а также ответы на них, будут тереться без предупреждения.
Есть что обсуждать - обсуждаем, хочется покакать - туалет прямо и направо, а здесь нехрен.
IMHO не обязательно только дальнейшие.
С++ - это инструмент, а не религия.
Есть какой-то волшебный регистр, который инструктирует МК перевести её в какой-то совершенно определённый LOW или HIGH?
Волшебный регистр есть, но только для не-PWM режимов , FOC "Force Output Compare". С помощью него удобно делать всякие одиночные импульсы, типа как тут.
поинтересуюсь!
А можно ли этот способ применить для отсчитывания очень точного интервала, к примеру 1 секунда, в том же частотомере, вместо delay(1000)
ua6em, этот способ для дрыганья ногой таймера, так что вместо delay() не подойдёт.
Почему не подойдёт? Если ждать "дрыга" прерыванием или даже просто while'ом, то вполне подойдёт.
ЕвгенийП, тогда получается незачем и ногой "дрыгать" ;-)
Да, но использовать вместо делэя-то вполне можно.
Для точных ворот лучше использовать что то постабильнее, нежели системный кварц. Хотя бы 32 кгц, лучше с термостабилизацией. Ну и формировать железно, с выхода таймера-делителя.
Green, ds3231 ? Точнее него только дорогие TCXO генераторы.
Можно и его, только у SQW ПЕРИОД 1 сек, а значит нужно делить ещё чем то. Это если до герца (двух).
Можно и его, только у SQW ПЕРИОД 1 сек, а значит нужно делить ещё чем то. Это если до герца (двух).
Ну, там же есть пин "32kHz Output". Да и частота SQW не всегда 1 Гц - она может быть 1024, 4096 и 8192 Гц если настроить.
Или речь о частотах меньших, чем 1 Гц? Но разве их нельзя смоделировать алармом?
Ну, для того что бы измерить входную частоту с точностью 1 гц (не будем о фазе)) нужны ворота в 1 сек, не менее. ds3231 выдаёт на выходе SQW только период в 1 с, т.е. полупериод будет 500 мс. О длительных интервалах с помощью аларма не задумывался.) Но обычно, индикация (ворота) свыше 2 сек. уже несколько раздражает.
Евгений, ни в коей мере на являясь "апологетом идеи неприменимости С++ для МК", тем не менее рискну предположить, что если заменить constexpr на inline и включить оптимизацию, то результат будет точно таким же - все промежуточные константные выражения свернутся и останутся голые результаты.
Но! в случае с inline данный результат ни фига не гарантируется на других компиляторах и в других режимах оптимизации, так что несомненная польза от Вашено подхода наличествует.
ds3231 выдаёт на выходе SQW только период в 1 с, т.е. полупериод будет 500 мс.
Вывсёврёти!!! и килогерц там есть и 4 и 8
рискну предположить, что если заменить constexpr на inline и включить оптимизацию, то результат будет точно таким же - все промежуточные константные выражения свернутся и останутся голые результаты.
Неа! По крайней мере при опциях «из коробки». Можете проверить сами и убедиться.
Вполне допускаю, что если поиграться опциями, то, может быть, и получится (а, может, и нет). Но главное здесь не в том, что (как Вы совершенно справедливо отметили) constexpr - стандартизованное средство языка, которое обязано работать по стандарту, а оптимизация – «как получится». Разница гораздо глубже. Разница в том, что здесь открываются новые возможности, которых там нет.
Вот смотрите, например, чтобы сделать эту библиотеку реально полезной, надо бы устранить в ней одну недоработку, которая вполне реализуема на constexpr и абсолютно никак не реализуема на inline.
А доработка такая. В описании я отмечал, что библиотека выдаёт наилучшее возможное приближение к точному временному интервалу. Для каких-то интервалов – оно просто точное, а для каких-то «точнее никак». Так вот хотелось бы иметь возможность контролировать точность. Например, указывать, что если погрешность выходит за некоторую величину, то компиляция должна быть прекращена с соответствующим сообщением.
Согласитесь, полезная фича. Но на inline не делается никак.
И хде???
Не знаю, почему Вы до сих пор не сделали и не выложили :)
Лицензия не позволяет :)
Вывсёврёти!!! и килогерц там есть и 4 и 8
Там много чего есть. Но нам то нужна 1 сек.
Лицензия не позволяет :)
Вы всё врёте, лицензия позволяет, просто не все тут танцоры )))
Сами Вы фсёврёти! Там WM указана. Мне надо её либо удалять, либо "работать на дядю" :)
Сами Вы фсёврёти!
Вот так и думал, не нужно упоминать ворота всуе.)
А чё не так с лицензией? Там же сказано, что импользовать или не использовать можно с любыми целями, кроме незаконных. Так что модифицируйте на здоровье, в WM удаляйте, если мешает.
А чё не так с лицензией? Там же сказано, что импользовать или не использовать можно с любыми целями, кроме незаконных. Так что модифицируйте на здоровье, в WM удаляйте, если мешает.
ВОРОТА хочет, чтобы там его WM был )))
Не возражаю. Я уже не в первый код на форуме WM вставляю. На сегодняшний день, общая сумма полученых транзакций 0 рублей и столько же копеек. Пусть теперь и Ворота разбогатеет, не всё ж мне одному.
Всё б вам на бедном мне наживаться :(
Ладно, застыдили, попробую сегодня добавить контроль точности, а заодно и задание времени не частотой, а периодом (в смысле просто временным интервалом). А то нужно, скажем 150мс интервал, а хрен его задашь - частота нецелая получается. Лучше иметь возможность задавать и так, и так - как удобнее в данный момент.