// Генератор импульсов, ksiman © //
int flag = 0; //объявление переменных и их тип
int mode = 1;
unsigned long time1 = 0;
unsigned long time2 = 0;
void setup()
{
pinMode(3, INPUT); //настройка входа
pinMode(1, OUTPUT); //настройка выхода
}
void loop()
{
if (digitalRead(3) == LOW && flag == 0) //проверка нажатой кнопки и флага
{
delay(500); //задержка для контроля удержания кнопки 500мс
mode++; //следующий режим работы
flag = 1; //установка флага
if (digitalRead(3) == LOW) //кнопка всё ещё нажата?
{
delay(50); //защита от дребезга контакта 50мс
mode = 1; //возврат в 1 режим работы
}
if (mode > 6) //количество режимов работы
{
mode = 1; //зацикливание смены режимов работы
}
}
if (digitalRead(3) == HIGH && flag == 1) //проверка не нажатой кнопки и флага
{
flag = 0; //сброс флага
}
//---------------------------------------------------------------------
if (mode == 1) //1 режим работы
{
digitalWrite(1, HIGH); //постоянный сигнал на выходе
}
//---------------------------------------------------------------------
if (mode == 2) //2 режим работы
{
if (millis() - time1 > 2000) //период следования импульсов 2000мс
{
time1 = millis();
digitalWrite(1, LOW);
time2 = millis();
}
if (millis() - time2 > 1000) //длительность импульсов 1000мс
{
digitalWrite(1, HIGH);
time2 = millis();
}
}
//---------------------------------------------------------------------
if (mode == 3) //3 режим работы
{
if (millis() - time1 > 1000) //период следования импульсов 1000мс
{
time1 = millis();
digitalWrite(1, LOW);
time2 = millis();
}
if (millis() - time2 > 100) //длительность импульсов 100мс
{
digitalWrite(1, HIGH);
time2 = millis();
}
}
//---------------------------------------------------------------------
if (mode == 4) //4 режим работы
{
if (millis() - time1 > 1000) //период следования импульсов 1000мс
{
time1 = millis();
digitalWrite(1, LOW);
time2 = millis();
}
if (millis() - time2 > 900) //длительность импульсов 900мс
{
digitalWrite(1, HIGH);
time2 = millis();
}
}
//---------------------------------------------------------------------
if (mode == 5) //5 режим работы
{
if (millis() - time1 > 200) //период следования импульсов 200мс
{
time1 = millis();
digitalWrite(1, LOW);
time2 = millis();
}
if (millis() - time2 > 100) //длительность импульсов 100мс
{
digitalWrite(1, HIGH);
time2 = millis();
}
}
//---------------------------------------------------------------------
if (mode == 6) //6 режим работы
{
if (millis() - time1 > 100) //период следования импульсов 100мс
{
time1 = millis();
digitalWrite(1, LOW);
time2 = millis();
}
if (millis() - time2 > 50) //длительность импульсов 50мс
{
digitalWrite(1, HIGH);
time2 = millis();
}
}
}
// Генератор импульсов, © yurok //
// конфигурация пинов
#define BUTTON_PIN 3
#define SIGNAL_PIN 1
#define BOUNCE_PROTECTION_TIME 50 // защита от дребезга, мс
#define LONG_BUTTON_TIME 500 // длительность длинного нажатия, мс
byte CurrentMode = 0; // начинаем с первого режима
byte MaxMode = 0; // максимальное количество режимов в приборе
unsigned long TimePeriod = 0; // время последней фиксации периода
bool ButtonFlag = false; // нажата ли клавиша сейчас
bool PulseFlag = false; // признак того, что в текущем периоде импульс уже выдавали
// создаем тип данных "режим"
typedef struct
{
unsigned long Period; // период
unsigned long Duration; // длительность импульса
}
ModeType;
ModeType MT[] = { // массив структур режимов
{1, 0}, // 1 режим (постоянный сигнал)
{2000, 1000}, // 2 режим (меандр 0,5Гц)
{1000, 100}, // 3 режим (короткий импульс)
{1000, 900}, // 4 режим (короткая пауза)
{200, 100}, // 5 режим (меандр 5Гц)
{100, 50} // 6 режим (меандр 10Гц)
};
// определение количества элементов в массиве произвольного типа
template<typename T, size_t n> inline size_t arraySize(const T (&arr)[n])
{
return n;
}
////////////////////////////////////////////////////////////////////////////////
// предварительная настройка программы
////////////////////////////////////////////////////////////////////////////////
void setup()
{
pinMode(BUTTON_PIN, INPUT); // кнопка
pinMode(SIGNAL_PIN, OUTPUT); //сигнал
MaxMode = arraySize(MT) - 1; // вычисляем максимальный доступный режим
}
////////////////////////////////////////////////////////////////////////////////
// функция для генерации импульсов в зависимости от режима
////////////////////////////////////////////////////////////////////////////////
void mode_control(byte in_mode) // первый режим не требует контроля времени, поэтому отработаем его тут
{
if (in_mode == 0)
{
digitalWrite(SIGNAL_PIN, HIGH);
return;
}
// все другие режимы отрабатываются одинаково
unsigned long CurrentTime = millis(); // текущее время
// проверка окончания прошлого периода
if (CurrentTime - TimePeriod > MT[in_mode].Period)
{
digitalWrite(SIGNAL_PIN, HIGH); // начинаем новый импульс
TimePeriod = CurrentTime; // отсечку периода приводим к текущему времени
PulseFlag = false; // сбрасываем флаг текущего периода (в данном периоде импульс еще не завершали)
}
// проверка на окончание импульса
if ((CurrentTime - TimePeriod > MT[in_mode].Duration) && !PulseFlag)
{
digitalWrite(SIGNAL_PIN, LOW); // заканчиваем текущий импульс
PulseFlag = true; // ставим флаг, что импульс завершили в этом периоде
}
}
// основной цикл
void loop()
{
////////////////////////////////////////////////////////////////////////////////
// контроль кнопки
////////////////////////////////////////////////////////////////////////////////
// проверка на нажатие с флагом для исключения повторной отработки
if (digitalRead(BUTTON_PIN) == LOW && !ButtonFlag)
{
delay(LONG_BUTTON_TIME); // задержка для проверки долгого нажатия кнопки
PulseFlag = false; //сбрасываем флаг сброса текущего импульса
CurrentMode++; // переходим к следующему режиму
ButtonFlag = true; // установка флага текущего нажатия кнопки
// проверка долгого нажатия
if (digitalRead(BUTTON_PIN) == LOW)
{
delay(BOUNCE_PROTECTION_TIME); // защита от дребезга кнопки
CurrentMode = 0; // начинаем с первого режима
}
// проверка на достижение максимального режима
if (CurrentMode > MaxMode)
{
CurrentMode = 0; // начинаем с первого режима
}
}
// если кнопка была нажата, а сейчас отпущена - сбрасываем флаг
if (ButtonFlag && digitalRead(BUTTON_PIN) == HIGH)
{
ButtonFlag = false;
}
////////////////////////////////////////////////////////////////////////////////
// исполнение функции для текущего режима
////////////////////////////////////////////////////////////////////////////////
mode_control(CurrentMode);
}
+17 |
3686
102
|
Так он меня своим микрописком просто добил.
А что это еще на входе?
На схеме красным эта доработка не обозначена…
и во много раз энергоэффективнее — выставил регистры в обработчике кнопок и тинька сама будет дрыгать ногой, можно в обработчике ещё и спать её отправлять до следующего прерывания
Так я и использовал программный таймер.
Код конечно «жестковат» — выглядит странно и с++ тут нет, простой c, для начала изучения вполне норм
У меня вот есть потребность питать от 18650 некую поделку, которой требуется 5 и 12 В. Потребление по 5 В составит в районе 300 мА, потребление по 12 В порядка 500 мА. Устройство от батарейки должно уметь работать часа 3 для одного заряда. Вот думаю сколько мне батареек потребуется параллельно соединить чтобы их смогла зарядить народная платка зарядки и как лучше сформировать необходимые 12 В.
Покажите как надо в образовательных целях.
Можно легко прикинуть — у меня получилось не менее 3х банок по 2600мАч. Лучше брать с запасом 4шт
Да, действительно можно сэкономить целых 2 байта :)
Пока не представляю как так сделать
Привычка — вторая натура. Лучше сразу привыкнуть брать переменные по минимуму занимаемого места, магические числа описывать как константы /define, делать отступы и писать код который сможешь понять через полгода после окончания проекта.
Банальности, но очень сильно помогают в работе с программой.
Но вот только может старшее поколение пояснит мне такую любовь к использованию МГТФ провода?
Я еще в детстве, в радиокружке его люто невзлюбил, потому как разделывать — гемор.
Но ладно, тогда у нас проводов особо не было, сейчас и продаются, и у меня, как у админа — куча пучков от дохлых БП и прочего.
Разноцветные, красивые, сразу понятно. что куда идет. А тут — один цвет, и капризный в разделке.
Поясните — зачем?!
Я часто просто подплавляю изоляцию жалом (плоское), и потом кусачками…
Видите как, неудачный детский опыт до сих пор жив…
А если у кого в руках замечали кусачки… казнь была медленной и мучительной. 8)
А в домашних условиях я использую обычную «турбо» зажигалку.
А кусачками все равно жилы и изоляция повреждаются. Да и края потом лохматые.
Ну и МГТФ 0.03 кусачками у меня не получается зачистить.
хуже, да, но там где не нужен мгтф, где нет вибраций, высокой температуры и устройство не подвергается мех возд, паяю ide жилами, тем более прототипы навесным монтажом, которые все равно потом разберутся. Не вижу смысла в такие места резать мгтф.
Патчам из комлекта сетевых устройств находится прямое применение все время.
Зачищать надо УМЕТЬ! Даже кусачками не проблема, а уж спец инструментом…
Долговечность! После вымачивания в солёной океанской воде.Даже через 50 лет провод из жгута -как новый.
Королёв не смог запустить Р-1 копию Фау-2, пока не наладили выпуск проводов в фторопластовой изоляции.По немецкой естественно! технологии и оборудовании.
Гуттаперчевая отечественная -горела.
Вас никто и не просит пользоваться МГТФ, есть полно китайского барахла.Нам больше останется.
Я отрезками МГТФ собирал свой первый компьютер по типу Радио-80 на крейте.А Специалиста уже эмалированным проводом -пайкой перегретым паяльником к контактным площадкам макетной платы.
Я что-то сомневаюсь, что 90% местных самоделок требуют такой пресловутой надежности, о которой вы говорить.
А вот простоты «чтения» конструкции, чтобы было видно сразу, что куда идет — да.
Да, муж сестры, старше меня на 10 лет — тоже свой первый «спектрум» так паял, но это же мазохизм чистой воды, по мне.
А у вас почему-то сразу, если кому-то что-то неудобно, так человек не умеет, да? Может, он сексом предпочитает по-другому заниматься? ;)
Пользовались теми проводами, что были на производстве самыми лучшими и удобными-для себя любимого.
Были и ПВХ провода в двойной «шёлковой» изоляции.Были и одножильные, были и в шёлковой изоляции -много всего было.Так у них концы оболочки плавились, плавилась изоляция обнажая жилу и угрожая замыканием.А монтаж на плате ПК ну очень плотный.Представте себе ткнули вы в гущу паутины проводов горячим паяльником, чтобы подпаяться к похороненному в глубине пятачку?
И все провода проплавились до жил-замыкание и Сизифов труд на смарку!!! Если вы видели подобные конструкции то за проводами платы было не видно!
А МГТФ был всех толщин в наличии и зачистка проблем не представляла.
Мазохизм и адский труд.А куда деваться если готовые платы были дифсит и стоили пару-тройку зарплат? А сколько стоил Синклер или советский Эппл(3600-9000 от комплектации рублей в 86 году при зарплате в 130, Волга 10 000)??? Память 48килобайт стоила ДОРОЖЕ самого ПК.
ЛУТ технологии не существовало(платы разводили рейсфедерами нитрокраской или цапон лаком даже для пром телевизоров Электрон, Рубин итд 3УСЦТ), лазерных принтеров ещё не было даже на производстве, персональных ПК дома с программами разводки тоже.Были только отечественные и американские Ксероксы под роспись в 1 отделе с перечислением копированного материала.Только промышленные установки проектирования и производства плат, занятые ТОЛЬКО военным производством-не многие имели к ним доступ и знания пользования программами.Заказать печать плат официально для себя или мелкой партией было не возможно(до НЭПА Меченого), только по блату через задний проход за большие деньги, от предприятия итд.Китая ещё не было.
Есть и были конечно американские фторопластовые ЦВЕТНЫЕ провода не хуже МГТФ, но вы ЦЕНЫ на них видели??? Потому что они только МИЛИТАРИ класса.
Многие к тому же имеют старые запасы с работы, а барыги торгуют на радиорынках запасами со складов(кто что охранял то и имел).
И на сегодня по соотношению цена/качество ничего лучше у нас на рынке НЕТ.
Ваш Кэп О.
Действительно интересный комментарий!
А вот последовательно с затвором я бы крайне рекомендовал поставить резистор, хоть 100 ом. Иначе рано или поздно спалите контроллер.
поддерживать такой код приятнее, помоему. Для добавления и изменения режимов достаточно менять инициализацию массива структур, остальные все настройки вверху. Это наверно не конкретный код реализации — мне просто приятнее так смотреть )
конкретный код посмотрите и поймете почему и что я написал )
в остальном, все настолько просто, что комментарии лишние тут помоему
0- режим выключено
1-всегда присутствует сигнал
это два необычных режима которые нуждаются в спец обработке, другие все обрабатываются по типовому алгоритму
— при запуске, выход неактивен, что не позволяет отследить запуск программы до нажатия кнопки
— появился дополнительный режим со случайной частотой моргания. Видимо вылет за границу диапазона.
Как работает эта программа — пока не понял…
byte CurrentMode=0;
bool ButtonFlag=false;
это сделали?
или CurrentMode=1; — тогда начнет с первого
if (CurrentMode > MaxMode){
попробуйте заменить на
if (CurrentMode > MaxMode-1){
либо жестко задать MaxMode = 6 и убрать
MaxMode = arraySize(MT);
Помогло :)
границы надо посмотреть
вообще доберусь до компа — могу потестить у меня есть спарк, это все писал с телефона
Теперь по USB не связывается…
Предстоит весёлая процедура подключения к ISP программатору и восстановление загрузчика.
ладно хоть это не роутер, где подпаиваться нужно
в общем, жду обратной связи — если что соберу сам такое
Загрузил Вашу программу со всеми изменениями
Результаты:
— начинает с 1 режима :)
— нулевой режим пропал :)
— 2 и 3 режимы поменялись местами, пытаюсь понять почему так
p.s. кажись разобрался — второй параметр почему-то программирует паузу вместо импульса
p.p.s. как работает программа так и не понял :(
можете сейчас строчек в инициализации добавить с любыми другими режимами :)
Это тоже проверил — работает :)
Как работает программа так и не понял, надо С++ изучать, а мозги уже не те :(
Привык писать на Ассемблер, Basic, LAD, STL, FBD,…
И, собственно, это все, что следует сказать про эти два кода. :)
кому захочется понять — наверно поймут — он очень простой
При этом даже моя маленькая метеостанция (темп, давление, влажность дома и на улице), с дисплеем от кассового аппарата, выводом данных на narodmon, с радиоканалом на IRF до кухни с датчикми газа и протечки, спокойно влезла в 328 контроллер вот таким вот последовательным кодом и место осталось, и читается легко, и менять код просто, когда видно сразу куда чего дописать при изменениях.
Я на ESP-12 собрал. Пока один датчик для пробы, остальные жду с Китая. По NRF можно вопрос в личку?
поддерживать приведенный код для меня проще, и раз уж писать на языке предстоит и использовать в дальнейшем программу — немного времени потратить на базовые принципы совсем не повредит.
Хотя… большинство программистов из Индии с вами согласятся :)
littlewire.cc/
PS
Упс! Не получится так запитать. Увидел в схеме Digispark диод, включенный встречно между +5V и USB. Ну, тогда можно вместо переключателя поставить тумблер с двумя независимыми группами перекидных контактов. Вы подобный уже пристраивали в эту коробочку в предыдущем отзыве
… Хотя, наверное, лишний весь этот «огород». Провода к MicroUSB разъемам припаивать… Бр-р-р. «Лучшее враг хорошего» © Лучше оставить как есть.
Сделать маленькое отверстие проще, чем переделывать.
… значит это совсем иное устройство.
они похожи, как дробовик деда и автомат… оба стреляют
— первый параметр период, второй длительность импульса (в коде автора обзора, также как и в моем предложенном, контролировалось пространство без импульса)
— расписал почти каждую строчку комментариями
— ввел флаг окончания импульса, чтобы лишний раз не дергать
— убрал лишнюю переменную последней длительности импульса
— нулевой режим удален в принципе
— мелкие правки
Попробую сам разобраться
нулевой удалил — теперь надо:
byte CurrentMode = 0;
// начинаем с первого режима
CurrentMode = 0; — два раза там
// первый режим не требует контроля времени, поэтому отработаем его тут
if (in_mode == 0) {
на один режим меньше стало и первый стал нулевым
Ваш скетч немного отформатировал и добавил в статью.
Листинг и скомпилированная программа стали немного короче, но как она работает до конца не понял
может кому-то пригодится :)
там еще можно оптимизировать — но смысла нет
А для не-сигнальных задач — Enable вход :)