Прошу совета, так как своих знаний еще не хватает.
Есть код стробоскопа, управляемого от энкодера (частота и скважность), все работает, только вот дрожание импульса довольно большое. Особенно это заметно на верхних частотах. Смотрел осциллографом.
Пробовал вот этот код
#include <avr/io.h>
#include <util/delay.h>
long k = 1;
#define LED_PIN 5
int main( void )
{
DDRB |= 1 << LED_PIN; // вывод 9 как выход
while (1) { // вечный цикл, аналог loop()
PORTB &= ~(1 << LED_PIN); // низкий уровень на выводе
_delay_us(834 * k); // задержка
PORTB |= 1 << LED_PIN; // высокий уровень на выводе
_delay_us(48 * k);
}
return 0;
}
Импульс стоит как вкопанный, но при вставке в основной код вместо цикла с micros, не компилится.
Возможно ли, если не победить, то хотя бы уменьшить дрожание импульса?
Сам код
// Выводы ЭНКОДЕРА
#define CLK 3 // Clock Подключаем к INT1, нельзя переназначать
#define DT 4 // второй вывод энкодера
#define SW 5 // switch кнопка энкодера, скважность при вращении
#define Min 66 // минимальное значение
#define Max 1135 //максимальное значение
#define led_pin 13 // светодиод
#define step_freq 66.667 // шаг изменения частоты
volatile uint32_t freq = 66.667; // нач. частота в Гц
volatile uint32_t paus;
volatile uint32_t time_light=819; // нач.время свечения светодиода в мкс
uint32_t oldcount;
boolean DT_last; // последнее состояние энкодера
void setup()
{
pinMode(CLK, INPUT_PULLUP); // Clock Подключаем к INT1, нельзя переназначать
pinMode(DT, INPUT_PULLUP); // второй вывод энкодера
pinMode(SW, INPUT_PULLUP); // кнопка энкодера
pinMode(led_pin, OUTPUT); // светодиод
attachInterrupt(1, encoderTick, CHANGE); // прерывания от Энкодера
DT_last = digitalRead(CLK); // считываем положение CLK
}
void loop()
{
paus = 17.31667*time_light;
time_light=(28500/freq);
digitalWrite(led_pin, 1);
oldcount = micros();
while ( (micros() - oldcount) < time_light) {} // длительность импульса светодиода
digitalWrite(led_pin, 0);
while ( (micros() - oldcount) < paus) {} // положительный полупериод
oldcount = micros();
while ( (micros() - oldcount) < paus) {} //отрицательный полупериод
}
//********************обработчики прерываний Энкодера*******************************
void encoderTick() // Обратка прерываний от Энкодера
{
uint8_t DT_now = digitalRead(CLK); // считываем текущее положение CLK
if (DT_now != DT_last && digitalRead(SW)) // если предыдущее и текущее положение не равны, значит был поворот
{
if (digitalRead(DT) != DT_now) // если DT не равен CLK, значит вращение по часовой стрелке
{
if ( freq < Max ) freq += step_freq; // прибавить
} else { // если DT равен CLK, значит вращение против часовой
if ( freq > Min ) freq -= step_freq; // убавить
}
}
}
Понял свою ошибку, " Важно — параметр указанных функций может быть только константой!". Так что этот код не удастся вставить, т.к. энкодер изменяет параметры volatile
Понял свою ошибку, " Важно — параметр указанных функций может быть только константой!". Так что этот код не удастся вставить, т.к. энкодер изменяет параметры volatile
Не, не понял. Вернее, это-то верно, но ошибка в другом.
Главная проблема не в том, константы там или нет, можено переписать код так, чтобы были переменные (или наоборот, обйтись константами, Вы же не будете номера ног по ходу работы менять). Проблема в том, что Вы пытаетесь брать код, написанный для голого контроллера и вставляете есго в среду Ардуино. А это две большие разницы.
Что имеем:
1. Каждые 4 мкс Вашу программу прерывают и говорят: "ты покури пока, тут миллис-сервису надо свои дела подсчитать, чтобы миллис правильно пказывался".
2. Если захотите использовать Serial, то там тоже Ваша программа будет периодически прерываться и "курить" пока Serial делает свои дела.
Ну и как же её быть стабильной, если её в каждый момент могут неожиданно прервать на неопределённый период времени (он там не постоянный).
Почитайте пост #9 в этой теме, там это прямо на осциллограмме показано. Потом гляньте пост #19, всё поймёте.
Поймите, когда говорят, что ардуина - среда для блондинок, то имеется в виду "помигать светодиодом, желательно розовым". А если Вы используете слова "стробоскоп", "энкодер", "частота", "скважность" (которые с точки зрения любой блондинки, разумеется, ругательные), да ещё хотите, чтобы импульс не дрожал, так будьте любезны вести себя как мужчина, а не как блондинка. Вырубайте нахрен все ардуиновские "облегчалки жизни" и управляйте контроллером сами - держите ситуацию полностью под контролем, а не полагайтесь, что кто-то за Вас волшебным образом миллис подсчитает.
Помогите разобраться с Timer1. Не пойму, где затык :(
Генерирую импульсы переменной частоты на 9-м пине. К пину подключена пьезопищалка компьютерная. При работе скетча ясно слышны провалы в последовательности импульсов. Не могу понять, откуда они возникают. Если менять переменные "vStart", "vFinish", "a" то меняется минимальная, максимальная частота и скорость изменения частоты. Вся работа с таймером в функции mySetPeriod()
Вот скетч:
// Имитируется воспроизведение данных, полученных с датчика скорости мотоцикла
// при равномерном разгоне/торможении мотоцикла
// С ускорением а
// От скорости vStart
// До скорости vFinish
// С интервалом между замерами tInterval (миллисекунды - float)
// Данные по частотам предварительно собираются в массив, затем с помощью
// Timer1 на 9 пине генерируются импульсы переменной частоты (которые слушаем пьезопищалкой)
// За основу взяты библиотека TimerOne (расчет прескалера)
// и скетчи из "Этюдов для начинающих (blink без delay и millis)"
#define RESOLUTION 65536 // Timer1 is 16 bit
// Глобальные константы
const float a = 0.2; // Задаем ускорение (м/с2)
const float vStart = 0.0; // Начальная скорость (км/ч)
const float vFinish = 10.0; // Конечная скорость (км/ч)
const float tInterval = 100.0; // Интервал между измерениями (миллисекунды)
const float roundOfWheel = 1.956; // Длина окружности колеса
const float gearRatio = 2.733; // Передаточное число колесо -> вторичный вал коробки
const float numberOfPulsesPerRevolution = 4.0; // Количество импульсов на один оборот вала
void initial()
{
TCCR1A = 0x40; //00101000 Переключение пина 9 по сравнению
TCCR1B = 0x08; //00001000 Установить СТС режим (Mode 4) и остановить таймер
}
void mySetPeriod(long microseconds) {
char oldSREG; // To hold Status Register while ints disabled
unsigned char clockSelectBits = 0; // 00000000
long cycles = (F_CPU / 2000000) * microseconds;
// the counter runs backwards after TOP, interrupt is at BOTTOM so divide microseconds by 2
if (microseconds > 0) {
if (cycles < RESOLUTION) clockSelectBits = _BV(CS10); // no prescale, full xtal 00000001 или
else if ((cycles >>= 3) < RESOLUTION) clockSelectBits = _BV(CS11); // prescale by /8 00000010 или
else if ((cycles >>= 3) < RESOLUTION) clockSelectBits = _BV(CS11) | _BV(CS10); // prescale by /64 00000011 или
else if ((cycles >>= 2) < RESOLUTION) clockSelectBits = _BV(CS12); // prescale by /256 00000100 или
else if ((cycles >>= 2) < RESOLUTION) clockSelectBits = _BV(CS12) | _BV(CS10); // prescale by /1024 00000101 или
else cycles = RESOLUTION - 1, clockSelectBits = _BV(CS12) | _BV(CS10); // request was out of bounds, set as maximum 00000101
}
//oldSREG = SREG; // Сохраняем состояние регистра (?всех регистров)
//cli(); // Запрещаем прерывания для записи 2-х байтового числа
//OCR1A = cycles; // OCR1A is TOP in CTM mode (4)
//SREG = oldSREG; // Восстанавливаем состояние регистра (?всех регистров)
TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12)); // 00001000
OCR1A = cycles; // OCR1A is TOP in CTM mode (4)
if (microseconds > 0) {
TCCR1B |= clockSelectBits;
}
//OCR1A = cycles; // OCR1A is TOP in CTM mode (4)
}
void setup() {
unsigned long currentMillis; // для организации паузы вместо delay()
unsigned long previousMillis = 0; // храним время последнего измерения
bool myDirection = true; // увеличиваем (истина) или уменьшаем (ложь) значение адреса массива i
unsigned long rpm;
// Предварительная подготовка массива
float vStartMS = vStart * 1000.0 / 3600.0; // Начальная скорость в м/с
float vFinishMS = vFinish * 1000.0 / 3600.0; // Конечная скорость в м/с
float vTMP = vStartMS; // Текущая скорость в м/с
//Serial.begin(115200);
// Сначала подсчитаем каким будет размер массива
int j = 0;
while (vTMP <= vFinishMS) {
vTMP = vTMP + a * tInterval / 1000.0; // Новая скорость в м/с ч/з tInterval миллисекунд
j++;
}
// Создаем массив для данных размером j
long arrayPeriod[j];
// Заполняем массив данными
vTMP = vStartMS;
j = 0;
while (vTMP <= vFinishMS) {
float newV = vTMP + a * tInterval / 1000.0; // Новая скорость в м/с ч/з tInterval миллисекунд
float sTMP = (newV * newV - vTMP * vTMP)/(2.0 * a); // Путь в м, пройденный за tInterval миллисекунд
float numberOfPulses = sTMP / roundOfWheel * gearRatio * numberOfPulsesPerRevolution; // Количество импульсов, сгенерированных за интервал tInterval
long lengthOfImpuls = long(1000.0 / (numberOfPulses / tInterval)); // Средняя длина одного импульса в интервале (в микросекундах)
//Serial.println( lengthOfImpuls );
arrayPeriod[j] = lengthOfImpuls;
vTMP = newV; // Запомнили новую скорость
j++;
}
//Serial.println( "===========" );
// И запоминаем количество элементов в массиве
int i = j;
// Начинаем пищать в пищалку
pinMode(9, OUTPUT);
initial();
j = 0;
unsigned long longInterval = long(tInterval);
// Serial.println(k);
while (true) {
currentMillis = millis();
if (currentMillis - previousMillis > longInterval) {
previousMillis = currentMillis;
rpm = arrayPeriod[j];
//Serial.println( rpm );
mySetPeriod(rpm);
if (j == (i - 1)) { // Последний элемент массива, меняем направление на обратное ("тормозим")
myDirection = false;
}
if (j == 0) { // Первый элемент массива, меняем направление на прямое ("разгоняемся")
myDirection = true;
}
if (myDirection) {
j++;
}
else {
j--;
}
}
}
}
void loop() {
}
А с чего ему гаснуть? Условие в строке №31 всегда ложно. Вы же только что присволили currentTime = millis(), двумя строками выше, ну и с какого перепугу условие в №31 вдруг истинным станет?
А с чего ему гаснуть? Условие в строке №31 всегда ложно. Вы же только что присволили currentTime = millis(), двумя строками выше, ну и с какого перепугу условие в №31 вдруг истинным станет?
Добрый Вы, Евгений Петрович, я бы пня дал. К этюду, как включение реле к кнопкам. ИМХО.
Ошибка SMTP: не удается подключиться к серверу SMTP. Ошибка SMTP: не удается подключиться к серверу SMTP. Ошибка SMTP: не удается подключиться к серверу SMTP.
Значит так, будем тактировать таймер №1 от внешнего сигнала.
Это всегда делается через пин 5 и ни через какой другой.
Тактироваться будем по нисходящему фронту, т.е. когда пин переходит с HIGH на LOW (по восходящему фронту тоже можно, в программе это закомментировано - см. текст)
Чтобы не не дергать проводочком на землю, я для теста соединил пин 5 с пином 9 через резистор и подаю сигнал на пин 9 (простым digitalWrite), а т.к. он соединён с пином 5, таймер должен этот сигнал посчитать.
Вот текст
// Источник внешнего тактирования таймера 1 - ВСЕГДА пин 5!
static const uint8_t pinT1 = 5;
// на этом пине мы иммитируем сигнал - любой пин
static const uint8_t pinSignal = 9;
//
// Инициализация таймера для внешнего тактирования
//
static void timerOneInit(void) {
TCCR1A = 0; // на всякий сулчай, если кто-то до нас туда что-то записал
TIMSK1 = 0; // на всякий сулчай, если кто-то до нас туда что-то записал
//
// Тактирование с пина T1 по ниспадающему фронту
TCCR1B = bit(CS12) | bit(CS11);
// Тактирование с пина T1 по восходящему фронту
//TCCR1B = bit(CS12) | bit(CS11) | bit(CS10);
}
//
// Сброс счётчика таймера 1
//
static inline void clearTimerOne(void) {
TCNT1 = 0;
}
//
// Чтение и, если надо, сброс счётчика таймера 1
//
static inline uint16_t readTimerOne(const bool clear = true) {
const uint16_t res = TCNT1;
if (clear) clearTimerOne();
return res;
}
//
// Выдать сигнал
// (пин "pinSignal" соединён с пятым пином через резистор)
//
static void issueSignal(void) {
digitalWrite(pinSignal, HIGH);
digitalWrite(pinSignal, LOW);
}
void setup() {
pinMode(pinT1, INPUT_PULLUP);
pinMode(pinSignal, OUTPUT);
Serial.begin(115200);
Serial.println("Fun begins!");
timerOneInit(); // Подготовить таймер
clearTimerOne(); // очистить таймер
issueSignal(); // выдать сигнал
issueSignal(); // выдать сигнал
issueSignal(); // выдать сигнал
issueSignal(); // выдать сигнал
Serial.print("Signals captured:");
Serial.println(readTimerOne()); // напечатать количество пойманных сигналов.
}
void loop() {
}
Печатает число 4, т.к. мы подаём 4 сигнала (строки 52-55). Размножьте эти строки, скажем до 9 - будет печатать число 9.
Техника работы понятна?
Теперь спокойно конфигурируете таймер, подключаете свой источник сигнала, а секунду считаете хоть через millis, хоть другим таймером - и все дела.
Позапускайте, поменяйте и убедитесь, что пример понятен.
Smith2007 пишет:
И если не затруднит - второй пример как вместо управления пинами (none, toggle, clear, set) инициировать программное прерывание и выполнить указанную процедуру.
На каком таймере?
А такая схема как реализуется? (используем Таймер 1 и Таймер 2), тактировать Таймер 2 от Таймера 1 настроенного на выдачу меандра нужной частоты, при этом таймер 2 тоже выдает меандр, кратный меандру 1-го Таймера, к примеру делим частоту тактирования на 10, тактирование по переднему фронту, для синхронизации частот
И еще вопрос, если тактировать по восходящему сигналу, надо ли пин тактирования (5) подтягивать вверх?
не, ну правда, Вы радиолюитель, а я программист - кто кому должен вопросы задавать про пины и сигналы? Думаю, Вы лучше меня знаете.
Я неплохо знаком с ТТЛ логикой, там неиспользуемые пины тянут к питанию, для снижения энергопотребления и улучшения помехозащищенности, ток то вытекающий, рабочие пины соединяют напрямую и никаких подтяжек, подумалось, что есть особенности применения при стороннем тактировании, там жеж у нутрях коммутатор видимо )))
Был стандартный контроллер Arduino Uno на 328Р. Приобрел Arduino micro на 32U4. Там, как я понял работа с таймерами осуществляется по другому. Раньше таймер 2 был настроен на прерывание с частотой 2500 раз в секунду.
Сейчас этот код естественно не работает. Как я понял необходимо перейти на таймер 4 и настроить на частоту тактирования 48 мгц. Пока нашел только это. На английском.
Может кто нибудь отосласть к описанию с конкретнымы примерами в коде на русском языке? Из описания на английском ничего не понятно. На русском нашел только описание регистров таймера . Но с непонятными примерами.
Поскольку примеры на буржуинском вместе с описанием. Вернемся к стандартным контроллерам с внешней микросхемой usb. Лучше использовать старое оборудование, чем непонятное новое.
Вначале выражаю благодарность ЕвгенийП за создание данной темы сблагодаря ей почти разобрался в работе таймеров но остались некоторые вопросы которые прошу пояснить. Как заставить работать два выхода на одном таймере работать с разной частотой. То есть один пин допустим 46 (использую Мегу) работал с регистром OCR5A а второй 45 работал с регистром OCR5B. Пока знаний хватило что бы два выхода работали с одинаковой частотой.
Вначале выражаю благодарность ЕвгенийП за создание данной темы сблагодаря ей почти разобрался в работе таймеров но остались некоторые вопросы которые прошу пояснить. Как заставить работать два выхода на одном таймере работать с разной частотой. То есть один пин допустим 46 (использую Мегу) работал с регистром OCR5A а второй 45 работал с регистром OCR5B. Пока знаний хватило что бы два выхода работали с одинаковой частотой.
В таблице 17-2 не увидел возможности такого режима, хотя несколько выше писалось - На рис. 17-4 показана структурная схема блока сравнения выходных данных. Маленькая буква " n” в именах регистров и битов указывает на то, что номер устройства (n = n для таймера / счетчика n), а “x” обозначает выходной блок сравнения (A/B/C). То
элементы структурной схемы, которые не являются непосредственно частью выходного блока сравнения, заштрихованы серым цветом.
Ждём, знающие уточнят.
Иван_, вот подумайте сами, как работает СТС режим?
Допустим, что мы управляем длительностью через ICRn.
Тогда счётчик ходит от 0 до ICRn, затем снова сбрасывается в 0. Уровни же на пинах OCnA/B/C изменяются в момент достижения счётчиком значений, сохранённых в регистрах OCRnA/B/C соответственно.
Это всё. Получается, что разные частоты на пинах OCnA/B/C Вы не получите, правда, можно поиграть фазами. Например, если в OCRnA лежит значение вдвое меньшее, чем в OCRnВ, то он будет изменять вдвое раньше, но и ждать следующего изменения будет дольше. Т.е. частота останется одинаковой, а вот фазу мы сдвинули.
Вот в этом скетче OCR5C вдвое меньше, чем OCR5B и втрое меньше, чем OCR5А. Цвета линий на осциллограмме прописаны в комментариях. Полюбуйтесь на сигнал (на сдвиг фаз)
Что же касается того, можно ли их заставить работать с разной частотой, то, как мы уже выяснили, без дополнительных телодвижений - нет, нельзя. А вот, с дополнительными - есть у меня одно идейка, но сейчас я в гостиничном номере и живой меги у меня нет, есть только протеус. На симуляторе моя идея не заработала - то ли идея тухлая, то ли симулятор кривой. Могу вернуться к экспериментам, когда доберусь домой и возьму живую, железную мегу, если Вам это будет всё ещё актуально.
Не, ну это-то понятно, речь-то как СТС заставить. Я вот попробовал было из прерывания по совпадению для одной форсить совпадения для других через биты FOCnA/B/C - не обломилось (по крайней мере, в протеусе).
Про FOC я думал, но что-то мне внутренний голос говорит, что все равно нужно OCR-ы хитро и связно рассчитывать. Это, конечно, в итоге уменьшило бы время нахождения в обработчике, но не исключило его. А так, как требуемая частота неизвестна, то и неясен и смысл упираться в этот алгоритм. Мошт там вообще блинка хватит.
ЕвгенийП спасибо за ответ. Вопрос весьма интересен и актуален но быстрых ответов от меня ждать не стоит так как что бы дойти до сути ответов мне их надо перечитать не один раз и не в один день. Перечитать даташиты поэкспериментировать и обдумать не спеша.
Узрей чудо - вот она истинная многозадачность (правда из другого манускрипта).
PORTD |=B00110000, правда количество задач ограничено восемью.))))
Нещитова! Это еретическое, "внеардуинное" читерство!
И с внешним регистером сколько хош можно задач иметь. Без читерства.)
И с внешним регистером сколько хош можно задач иметь. Без читерства.)
аппаратные хаки не пердлогать. О_О
Прошу совета, так как своих знаний еще не хватает.
Есть код стробоскопа, управляемого от энкодера (частота и скважность), все работает, только вот дрожание импульса довольно большое. Особенно это заметно на верхних частотах. Смотрел осциллографом.
Пробовал вот этот код
Понял свою ошибку, " Важно — параметр указанных функций может быть только константой!". Так что этот код не удастся вставить, т.к. энкодер изменяет параметры volatile
А по вопросу: Возможно ли, если не победить, то хотя бы уменьшить дрожание импульса?,
Видимо простыми средствами победить джиттер не получится.
По поводу - " не, не понял" есть какие-либо подсказки, как встроить управление портами через регистры?
Главная проблема не в том, константы там или нет, можено переписать код так, чтобы были переменные (или наоборот, обйтись константами, Вы же не будете номера ног по ходу работы менять). Проблема в том, что Вы пытаетесь брать код, написанный для голого контроллера и вставляете есго в среду Ардуино. А это две большие разницы.
Что имеем:
1. Каждые 4 мкс Вашу программу прерывают и говорят: "ты покури пока, тут миллис-сервису надо свои дела подсчитать, чтобы миллис правильно пказывался".
2. Если захотите использовать Serial, то там тоже Ваша программа будет периодически прерываться и "курить" пока Serial делает свои дела.
Ну и как же её быть стабильной, если её в каждый момент могут неожиданно прервать на неопределённый период времени (он там не постоянный).
Почитайте пост #9 в этой теме, там это прямо на осциллограмме показано. Потом гляньте пост #19, всё поймёте.
Поймите, когда говорят, что ардуина - среда для блондинок, то имеется в виду "помигать светодиодом, желательно розовым". А если Вы используете слова "стробоскоп", "энкодер", "частота", "скважность" (которые с точки зрения любой блондинки, разумеется, ругательные), да ещё хотите, чтобы импульс не дрожал, так будьте любезны вести себя как мужчина, а не как блондинка. Вырубайте нахрен все ардуиновские "облегчалки жизни" и управляйте контроллером сами - держите ситуацию полностью под контролем, а не полагайтесь, что кто-то за Вас волшебным образом миллис подсчитает.
Спасибо, примерно так и думал, когда писал что просто сделать не получится.
Это сначала надо подучить Си и asm, а потом курить Datasheet 328
Проще покурить таймер1 и получать сигнал с его выхода. Где то тут в проектах есть генератор, только там исходник безобразный.(
AndreyTU, в принципе есть готовый пример стробоскопа на таймере. Но лучше конечно самостоятельно до этого дорости :)
Свою проблему решил, поэтому снимаю вопрос. Успехов!
да. или
О_О
я же хочу пример многозадачности, как в манускрипте...
Узрей чудо - вот она истинная многозадачность (правда из другого манускрипта).
PORTD |=B00110000, правда количество задач ограничено восемью.))))
Не только! Смотрим процессор BI-671
Исполнение до 4-х инструкций в такт
Для проверки возможности управления блинком набросал простенький скетч, всё работает как надо:
Помогите разобраться с Timer1. Не пойму, где затык :(
Генерирую импульсы переменной частоты на 9-м пине. К пину подключена пьезопищалка компьютерная. При работе скетча ясно слышны провалы в последовательности импульсов. Не могу понять, откуда они возникают. Если менять переменные "vStart", "vFinish", "a" то меняется минимальная, максимальная частота и скорость изменения частоты. Вся работа с таймером в функции mySetPeriod()
Вот скетч:
Да, забыл сказать. IDE версии 1.8.7. Плата клон Arduino UNO на 328P, USB на CH340G (вроде правильно выразился)
Да, забыл сказать. IDE версии 1.8.7. Плата клон Arduino UNO на 328P, USB на CH340G (вроде правильно выразился)
Таймер работает сам по себе, то-есть асихронно от вашего скетча, это данность
Здравствуйте форумчане. Подскажите пожалуйста, почему в этом коде не гаснет второй диод с задержкой? Обычная кнопка и простая временная задержка.
А с чего ему гаснуть? Условие в строке №31 всегда ложно. Вы же только что присволили currentTime = millis(), двумя строками выше, ну и с какого перепугу условие в №31 вдруг истинным станет?
потому что условие в строке 31 не выполнится никогда !
строка 29 не на своем месте.
что то форум глючит .... дубль за дублем
Весь день сегодня
А с чего ему гаснуть? Условие в строке №31 всегда ложно. Вы же только что присволили currentTime = millis(), двумя строками выше, ну и с какого перепугу условие в №31 вдруг истинным станет?
Добрый Вы, Евгений Петрович, я бы пня дал. К этюду, как включение реле к кнопкам. ИМХО.
Весь день сегодня
Он не глючит, походу его заломали )))
Ошибка SMTP: не удается подключиться к серверу SMTP. Ошибка SMTP: не удается подключиться к серверу SMTP. Ошибка SMTP: не удается подключиться к серверу SMTP.
Попробовал новый калькулятор от ЕвгенияП!
Хочется примеров для таймера 0 и 2 в режиме CTC
Так, сделайте! :)))
И дополните топик!
Так, сделайте! :)))
И дополните топик!
Так Евгений Петрович для Таймера2 уже точно сделал, смысл?
А впрочем для Таймера два надо для начала изменить предделители:
Останавливать таймер, можно загрузив в предделитель значение 0
Значит так, будем тактировать таймер №1 от внешнего сигнала.
Это всегда делается через пин 5 и ни через какой другой.
Тактироваться будем по нисходящему фронту, т.е. когда пин переходит с HIGH на LOW (по восходящему фронту тоже можно, в программе это закомментировано - см. текст)
Чтобы не не дергать проводочком на землю, я для теста соединил пин 5 с пином 9 через резистор и подаю сигнал на пин 9 (простым digitalWrite), а т.к. он соединён с пином 5, таймер должен этот сигнал посчитать.
Вот текст
Печатает число 4, т.к. мы подаём 4 сигнала (строки 52-55). Размножьте эти строки, скажем до 9 - будет печатать число 9.
Техника работы понятна?
Теперь спокойно конфигурируете таймер, подключаете свой источник сигнала, а секунду считаете хоть через millis, хоть другим таймером - и все дела.
Позапускайте, поменяйте и убедитесь, что пример понятен.
И если не затруднит - второй пример как вместо управления пинами (none, toggle, clear, set) инициировать программное прерывание и выполнить указанную процедуру.
На каком таймере?
А такая схема как реализуется? (используем Таймер 1 и Таймер 2), тактировать Таймер 2 от Таймера 1 настроенного на выдачу меандра нужной частоты, при этом таймер 2 тоже выдает меандр, кратный меандру 1-го Таймера, к примеру делим частоту тактирования на 10, тактирование по переднему фронту, для синхронизации частот
И еще вопрос, если тактировать по восходящему сигналу, надо ли пин тактирования (5) подтягивать вверх?
не, ну правда, Вы радиолюитель, а я программист - кто кому должен вопросы задавать про пины и сигналы? Думаю, Вы лучше меня знаете.
не, ну правда, Вы радиолюитель, а я программист - кто кому должен вопросы задавать про пины и сигналы? Думаю, Вы лучше меня знаете.
Я неплохо знаком с ТТЛ логикой, там неиспользуемые пины тянут к питанию, для снижения энергопотребления и улучшения помехозащищенности, ток то вытекающий, рабочие пины соединяют напрямую и никаких подтяжек, подумалось, что есть особенности применения при стороннем тактировании, там жеж у нутрях коммутатор видимо )))
Таймер 2 тоже видимо можно внешне тактировать?
Вопрос по таймерам.
Был стандартный контроллер Arduino Uno на 328Р. Приобрел Arduino micro на 32U4. Там, как я понял работа с таймерами осуществляется по другому. Раньше таймер 2 был настроен на прерывание с частотой 2500 раз в секунду.
TCCR2A = (0<<COM2A1)|(1<<COM2A0)|(1<<WGM21)|(0<<WGM20); //CTC mode
TCCR2B = (0<<CS22) |(1<<CS21)| (1<<CS20);//делитель CLK/32
OCR2A = 199 ; //Регистр сравнения. частота таймера 2 2500 Гц.
TIMSK2 |= (1 << OCIE2A); //enable timer compare interrupt
Сейчас этот код естественно не работает. Как я понял необходимо перейти на таймер 4 и настроить на частоту тактирования 48 мгц. Пока нашел только это. На английском.
http://forum.arduino.cc/index.php?topic=261869.0
Может кто нибудь отосласть к описанию с конкретнымы примерами в коде на русском языке? Из описания на английском ничего не понятно. На русском нашел только описание регистров таймера . Но с непонятными примерами.
http://microsin.net/programming/avr/10-bit-high-speed-timer-counter4.html
По-русски не знаю.
Но имейте в виду, что с таймерами на 32U4 есть засада. Там их то ли 4, то ли 5: в одних даташитах описаны 4 (0,1,3 и 4), а в других ещё и 2-ой есть.
Работают все пять. Ссылку на даташиты могу дать. Но он не по-русски.
Про таймер2 в 32u4 как то обсуждали. Он там есть, но не для всех :)
Он там есть, но не для всех :)
Для нормальных пацанов :)
Поскольку примеры на буржуинском вместе с описанием. Вернемся к стандартным контроллерам с внешней микросхемой usb. Лучше использовать старое оборудование, чем непонятное новое.
Лучше использовать старое оборудование, чем непонятное новое.
Лучше освоить язык, чтобы не ограничивать себя.
Можно было просто сказать что таймер1 32u4 работает аналогично 328P. И ничего менять не надо.
int n;
void setup(){
pinMode(17, OUTPUT);
//---Настройка таймера 1--------------------------------------------
TCCR1A = 0;TCCR1B = 0;TCNT1 = 0;
TCCR1B |= (1<<WGM12); // Режим CTC (сброс по совпадению)
TCCR1B |= (1<<CS10)|(1<<CS11); // Тактирование от CLK/64.
OCR1A=24999; //отсчитать 2 5000 входных импульсов до прерывания F=10 гц.
TIMSK1 |= (1 << OCIE1A); // Разрешить прерывание по совпадению
}
//---Прерывание по таймеру 1----------------------------------------
ISR(TIMER1_COMPA_vect) // timer compare interrupt service routine
{
if (n<2) digitalWrite(17, LOW) ;
if (n>=2) {digitalWrite(17, HIGH);n=0;}
n=n+1;
}
void loop(){}
Вначале выражаю благодарность ЕвгенийП за создание данной темы с благодаря ей почти разобрался в работе таймеров но остались некоторые вопросы которые прошу пояснить. Как заставить работать два выхода на одном таймере работать с разной частотой. То есть один пин допустим 46 (использую Мегу) работал с регистром OCR5A а второй 45 работал с регистром OCR5B. Пока знаний хватило что бы два выхода работали с одинаковой частотой.
Вначале выражаю благодарность ЕвгенийП за создание данной темы с благодаря ей почти разобрался в работе таймеров но остались некоторые вопросы которые прошу пояснить. Как заставить работать два выхода на одном таймере работать с разной частотой. То есть один пин допустим 46 (использую Мегу) работал с регистром OCR5A а второй 45 работал с регистром OCR5B. Пока знаний хватило что бы два выхода работали с одинаковой частотой.
В таблице 17-2 не увидел возможности такого режима, хотя несколько выше писалось - На рис. 17-4 показана структурная схема блока сравнения выходных данных. Маленькая буква " n” в именах регистров и битов указывает на то, что номер устройства (n = n для таймера / счетчика n), а “x” обозначает выходной блок сравнения (A/B/C). То
элементы структурной схемы, которые не являются непосредственно частью выходного блока сравнения, заштрихованы серым цветом.
Ждём, знающие уточнят.
Иван_, вот подумайте сами, как работает СТС режим?
Допустим, что мы управляем длительностью через ICRn.
Тогда счётчик ходит от 0 до ICRn, затем снова сбрасывается в 0. Уровни же на пинах OCnA/B/C изменяются в момент достижения счётчиком значений, сохранённых в регистрах OCRnA/B/C соответственно.
Это всё. Получается, что разные частоты на пинах OCnA/B/C Вы не получите, правда, можно поиграть фазами. Например, если в OCRnA лежит значение вдвое меньшее, чем в OCRnВ, то он будет изменять вдвое раньше, но и ждать следующего изменения будет дольше. Т.е. частота останется одинаковой, а вот фазу мы сдвинули.
Вот в этом скетче OCR5C вдвое меньше, чем OCR5B и втрое меньше, чем OCR5А. Цвета линий на осциллограмме прописаны в комментариях. Полюбуйтесь на сигнал (на сдвиг фаз)
Что же касается того, можно ли их заставить работать с разной частотой, то, как мы уже выяснили, без дополнительных телодвижений - нет, нельзя. А вот, с дополнительными - есть у меня одно идейка, но сейчас я в гостиничном номере и живой меги у меня нет, есть только протеус. На симуляторе моя идея не заработала - то ли идея тухлая, то ли симулятор кривой. Могу вернуться к экспериментам, когда доберусь домой и возьму живую, железную мегу, если Вам это будет всё ещё актуально.
... если Вам это будет всё ещё актуально.
Это и мне интересно, получить на одном таймере с разных пинов частоту отличающуюся в два - два с половиной раза, сама возможность интересна
Если колхозить, то выбрал кратную частоту и сиди в обработчике, перебрасывай биты на раз-два-три ;)
Не, ну это-то понятно, речь-то как СТС заставить. Я вот попробовал было из прерывания по совпадению для одной форсить совпадения для других через биты FOCnA/B/C - не обломилось (по крайней мере, в протеусе).
Про FOC я думал, но что-то мне внутренний голос говорит, что все равно нужно OCR-ы хитро и связно рассчитывать. Это, конечно, в итоге уменьшило бы время нахождения в обработчике, но не исключило его. А так, как требуемая частота неизвестна, то и неясен и смысл упираться в этот алгоритм. Мошт там вообще блинка хватит.
ЕвгенийП спасибо за ответ. Вопрос весьма интересен и актуален но быстрых ответов от меня ждать не стоит так как что бы дойти до сути ответов мне их надо перечитать не один раз и не в один день. Перечитать даташиты поэкспериментировать и обдумать не спеша.
Это и мне интересно, получить на одном таймере с разных пинов частоту отличающуюся в два - два с половиной раза, сама возможность интересна
Да никаких проблем:
При указанных параметрах с 11 ноги пойдёт частота ~60 Герц, с 3й ноги ~120 Герц
Ну, в режиме ШИМ - типа да, спасибо. Я вот не въеду что у меня там в режиме СТС не вышло. Но это уж дома - на железе.
ЕвгенийП, а в СТС это невозможно :)
Да никаких проблем:
При указанных параметрах с 11 ноги пойдёт частота ~60 Герц, с 3й ноги ~120 Герц
а как с предделителем поиграться - TCCR2B=(1<<WGM22)|(3<<CS20);?
Вот так по крупицам и собираются приёмчики программирования )))
Вам верю. Но понять-то всё равно хочу. Что не так с попыткой форсить матчи через FOC биты?
Вам верю. Но понять-то всё равно хочу. Что не так с попыткой форсить матчи через FOC биты?
У меня чесс гря не хватает соображалки понять как это возможно, в смысле изменить частоту фок-ами..