Перейти к содержанию

Q109

Members
  • Постов

    12
  • Зарегистрирован

  • Посещение

Сообщения, опубликованные Q109

  1. Нет уж, спасибо :lol2: Этот С1-55, даже новый, мне тоже захочется выкинуть через пару лет.

    Дешёвый китайский девайс имеет полосу пропускания 50МГц, экран не сильно меньше, но при этом умещается в карман.

    Да, 20 килорублей. Дороже явно нет никакого смысла брать, а если найдётся нормальный за 5-10к (на алиэкспрессе туева хуча предложений) - буду ещё больше доволен.

  2. Подумываю я выбросить свой С1-68 и прикупить что-нибудь поприличнее.

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

    Роясь по каталогам, обнаружил, что прогресс ушёл далеко вперёд и можно купить вот такую штуку http://www.aliexpres.../626877411.html

    Или не стоит соблазняться портативностью и стоит взять что-нибудь стационарное? В общем, порекомендуйте, в какую сторону смотреть.

    Бюджет, скажем, до 20к. Из обязательного - USB-интерфейс, хотя он, по-моему, уже всюду есть.

  3. Приветствую всех.

    Мне из Китая пришёл планшет. И обнаружилось, что он любит самопроизвольно отрубаться, или вообще не запускаться.

    Выглядит, как будто батарея не тянет, хотя софт показывает 80% заряда. Разобрал его - обнаружил на линии питания, идущей от аккума, 3,3В. Что вроде бы маловато для почти полностью заряженного ли-по.

    Единственное, что смущает - аккум со встроенной схемой защиты, не понижает ли она выходное напряжение? Как можно проверить работоспособность аккума, не выпаивая его?

  4. Никогда не работал с Rainbowduino, но есть 2 замечания.

    По второй схеме, как я понимаю, процессор самой ардуины надо вынимать, иначе он помешает процессу прошивки.

    Ошибка not in sync иногда у меня тоже вылезает, и методов борьбы с ней толком нет - погугли, найдёшь несколько обсуждений. Единственное - помогало перезапустить USB-порт или перезагрузить винду.

  5. Я старался по-максимуму объяснить возможно сложные моменты в коде. Комментариев в самом тексте кода мало, это да.

    Проблема в том, что здесь чутьё не работает - что объяснять, а что и так понятно? Поэтому нужны конкретные вопросы, буду комментить, что надо.

  6. 5. Программируемые выходы и прошивка.

    Сейчас заметил, что не рассказал, для чего нужен блок контактов слева от платы. Верхние шесть - три по два - это и есть выходы, нумерацию которых можно проследить по распиновке и массиву int workpin(). Один раз прописать все 3 порта в начале кода оказалось удобнее, чем писать их явно - иначе легко перепутать и трудно править, если понадобится что-то изменить в схеме. А так их легко даже поменять местами, изменив циферки всего в одном месте. Очередное банальное открытие новичка :)

    Сам МК способн выдавать порядка 15мА на каждый из выводов. Этого достаточно, чтобы запитать любую управляющую схему, включая оптореле на 25А. Для низковольтных нагрузок лучше использовать какой-нибудь MOSFET (некоторые имеют сопротивление в открытом состоянии всего 50мОМ). Была идея поставить мосфеты прямо на эту же плату - оказывается, они бывают не только в здоровых корпусах типа TO-220 или D2PAK, но и в SOT23, как пример - IRLML0030. 30 вольт, 5 ампер постоянного тока, 27миллиом в открытом состоянии, и это при размерах 2*3мм! Кстати, ничто не мешает сделать отдельную плату с мощными мосфетами, к которой будет подключаться внешний мощный источник питания - литиевый аккумулятор, например.

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

    Таким образом, все выводы оказываются задействованы - 3 выхода, 2 под кнопки, 1 под зумер, 6 под дисплей. Остаются ещё 2 неработающих входа - А4 и А5 в правом верхнем углу. Несмотря на то, что изначально они считаются входами АЦП, их можно сконфигурировать в качестве обычных цифровых входом или выходов.

    Чем мне сразу приглянулась Arduino Uno, так это тем, что из неё можно вытащить микроконтроллер. В принципе, можно залить в него код (и бутлодер, если его ещё нет), вытащить и вставить в разъём девайса. Если понадобится - вытащить, вернуть на место, прошить и снова переставить. Это не очень удобно, гораздо проще подвести провода от платы Arduino, которая (со снятым с неё МК) вполне годится как программатор. Проводов нужно 5 штук - земля, Tx, Rx, Reset (!) и +5В. Последний можно не вести, если девайс подключён к собственному питанию. Удобно сразу сделать некое подобие шлейфа, это поможет избегать ошибок при подключении. А если есть программатор AVR, прошивать можно и им.

    IRLML0030_ds.pdf

  7. 4. Измерения

    Самая простая часть. Есть чудесные микросхемы - термометры (одна из них - LM35 http://cxem.net/house/1-341.php ), выдающие 10 или 20 мВ на каждый градус температуры корпуса. Благодаря встроенному в ATMega328 аналого-цифровому преобразователю (и их аж 6 штук!) всё реализуется очень просто. Функция analogRead() требует номер порта (в Arduino они называются A0...A5) в качестве аргумента, а возвращает число от 0 до 1023, пропорциональное напряжению. То есть в теории напряжение можно знать с точностью до процента. Но так не выходит, приходится много раз измерять и усреднять. У меня это происходит 1000 раз, что занимает, кстати говоря, суммарно аж 400мс. И как видно по коду, после каждого 1000-ного измерения сумма всех результатов для каждого сенсора усредняется и переводится в милливольты. Тогда же и проводится отображение на экран - обновлять его чаще нет смысла.

    Необходимость такого достаточно длительного измерения делает задачу чуть сложнее: у Ардуины большие сложности с многозадачностью, поэтому, вместо того, чтобы писать в main() цикл из 1000 повторений, приходится использовать в качестве цикла сам main(), в нём же проверяя каждый раз, не пора ли переключить состояние какого-нибудь из выходов. Банальность, но для новичка всё удивительно :)

    Естественно, нынешний вариант имеет существенные недостатки. Во-первых, та самая длительность измерения. Ничто не мешает усреднять не 1000, а 100 значений, несколько пожертвовав при этом точностью. Но это не самый красивый вариант, поскольку мне самому не очень верится в точность встроенного АЦП, да и допустимая длина проводов весьма ограничена. Вскоре я стал облизываться на цифровые датчики с интерфейсом 1-wire, но они дороже, сложнее в освоении, и, по-моему, не шибко быстрее. Зато двух проводов хватает для неограниченного количества датчиков.

    Есть также режим, про который я уже упоминал - индикатор перегрева. Выставление предела срабатывания (в милливольтах же) идёт в меню последним пунктом, и если напряжение на каком-либо из выходов превышает пороговое, на ноге, названной в коде speaker, выставится высокий уровень. Этого хватит, чтобы запитать пятивольтовую "пищалку". Под неё выделено место на плате, но самой пищалки у меня пока нет, надеюсь это скоро исправится. Кстати, чтобы исключить ложные срабатывания, все неиспользуемые входы АЦП надо заземлить, или сократить количество используемых портов в коде.

  8. 3. Кнопки и меню.

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

    Нужна переменная, которая будет отвечать за то, что отображать на экране - основную информацию, или значение какой-нибудь переменной, или подсказку, какой параметр сейчас будет выставляться. Переменную назовём menu; она будет меняться от 0 (главный экран, типа) до 9. И каждое нажатие кнопки будет увеличивать значение, а по достижении 10 будет производиться сброс обратно в 0.

    if(digitalRead(butOne) == HIGH) {
       enable = 1;
     }
    
     if(enable == 1) { //защита от двойных срабатываний
     if (digitalRead(butOne)==LOW) {
       menu++;
       enable = 0;
       LastPress = millis();
     }
     }
    
     if (menu >= 11) {
       menu = 0;
     }
    

    Вышенаписанный кусок отвечает именно за это. Значение menu увеличиевается, если на входе низкий уровень, то есть он замкнут кнопкой на землю ( если кнопка разомкнута, уровень высокий, т.к в настройках прописано INPUT_PULLUP, что означает, что вход будет подтянут к +5В посредством внутреннего резистора). Следующий раз значение сможет увеличиться только после отпускания и очередного нажатия кнопки, для этого понадобилась новая переменная enable.

    Помимо этого полезной оказалась следующая фича:

    if((millis() - LastPress)>20000 ) { //если последнее нажатие больше 20 секунд назад - сброс
       menu = 0;
       LastPress = millis();
     }
    

    millis() - это функция, возвращающая количество миллисекунд, прошедших с момента запуска. Теперь нет необходимости перещёлкивать обратно в "нулевой" режим, который наиболее информативен. (нажатия кнопок всё-таки утомляют :) )

    Дальше используется волшебное слово case.

    case 1:
       lcd.print("W1"); //длительность работы первого порта
       break;
       case 2:
       lcd.print("R1"); //длительность отдыха первого
       break;
       case 3:
       lcd.print("W2");
       break;
       case 4:
       lcd.print("R2");
       break;
    

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

    int c = sum[0]/20;
       timezero = 1;
       for(int k = 0; k<c;k++) {
      timezero = 1.08*timezero;
       }
       time[0] = (unsigned long)timezero; //переводим в long
    
       lcd.clear();
       lcd.setCursor(0,0);
       if(menu != 0) { //отображаем время только в ненулевом режиме
      if(digitalRead(butTwo) == HIGH) {
        time[0] = time[menu];
      }
      else {
        if (menu==10) {
    	  thres = sum[0];
        }
      }
    
    
       if(time[0]>7200000) {
      lcd.print(time[0]/3600000);
      lcd.print("h");
       }
       else {
       if(time[0]>100000) {
      lcd.print(time[0]/60000);
      lcd.print("min");
       }
       else {
       if (time[0]>5000) {
      lcd.print(time[0]/1000);
      lcd.print("s");
       }
       else {
      lcd.print(time[0]);
      lcd.print("ms");
       }
     }
     }
     }
    

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

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

    Дальше уже просто - в функции loop() (она выполняется циклически всё время работы контроллера) считывается текущее время и проверяется, не пора ли сменить работу на отдых какому-либо выходу. Извращения с переменной percent нужны для того, чтобы видеть, какая часть от отведённого времени уже прошла, что очень полезно.

    Тут я не могу не упомянуть баг, поиск которого занял у меня очень много времени. Утверждается, что значение функции millis() обнуляется каждые 50 дней - банально переполняются все разряды. Я же наблюдал, что по прошествии 10 часов после запуска значение percent становится отрицательным. Не сразу понял, что ошибка в том, что чтобы вычислить, какая часть отведённого времени, скажем, работы, прошла, я брал текущее значение millis(), вычитал из него время, когда выход был переключен на работу, умножал на 100 и делил на отведённое время работы. Так вот, надо было сначала делить, а не умножать - переполнение разрядов происходило не через 50 дней, а ровно в 100 раз быстрее. Просто слишком большое число получалось в процессе.

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

  9. 2. Дисплей.

    Я всё-таки расскажу, как его подключать :) Нужен дисплей с драйвером Hitachi HD44780, они узнаются по 16-пиновому интерфейсу. Я использовал WH1602, даташит на него в аттаче. По факту из 16 пинов нужно 10, а проводов нужно всего 8.

    Питание и земля (Vcc и GND) подключаются понятно куда. Есть 2 контакта, которые в примере на arduino.cc ведутся отдельными проводами, но этого можно не делать. Это R/W (в моём случае 5-ый контакт), который надо замкнуть с тем, на который приходит 5В (первый ), и Contrast Adjustment, напряжение на котором задаст контраст изображения. Менять его (контраст, т.е) в процессе смысла мало, поэтому нужно собрать делитель на 2 резисторах и подбором номиналов найти нужные. Затем этот делитель впаять прямо на плату дисплея, между 5В и землёй. В моём случае это 3КОма на +5В и 760Ом на землю.

    Использоваться же будут следующие контакты: RS, E (H/L), DB0, DB1, DB2, DB3. Итого 6 контактов, к ним удобно припаять кусок шлейфа со штыревым разъёмом на конце. Именно в таком порядке, и развести на любые цифровы пины микроконтроллера. Здесь они идут на 5,8,7,6,9 и 10 пины в представлении Arduino (см. распиновку). Чтобы начать работать с дисплеем, надо до основного кода записать номера этих пинов, как это сделано:

    LiquidCrystal lcd(5, 8, 7, 6, 9, 10);
    

    И в setup (часть кода, выполняющаяся один раз при включении питания или перезагрузке) прописать

    lcd.begin(16,2);

    Если дисплей в длину не 16 символов и/или в высоту не 2 строчки, эти значения надо будет изменить. Всё! Теперь с помощью двух функций - lcd.setCursor() и lcd.print() можно выводить всё, что угодно. Надо только не забыть, что символы и строчки нумеруются с нуля.

    Если дисплей не работает (видно, что контрастность выставлена, но отображается хрень или не отображается ничего) - косяк с проводами. Я сам несколько часов убил на поиски бага с дисплеем, пока не вспомнил, что номера пинов на нижнем разъёме идут не подряд, а я упорно писал в коде LiquidCrystal lcd(5, 6, 7, 8, 9, 10); :)

    Есть, конечно, режим "бегущей строки", TFT дисплей и куча других фич, но уже в самом простом варианте функциональность оказалось достаточна.

    Тварищ Desert _Eagl.5, ты пришёл в раздел Arduino, чтобы кричать, что всё это - хрень? Так пиз .. ва.. почему бы не направиться в раздел AVR и не засорять тему, тем более, что я специально в начале об этом попросил?

    Display_WH1602D.pdf

  10. Начинаю. 1.Схема, код и документация.

    Наверное, первое, что надо знать, это сайт arduino.cc. Он на английском и на нём есть всё, в частности инструкция по установке, параметры платы (напомню, Arduino Uno rev.3) и чертова туча примеров, благодаря которым цель и была достигнута :)

    Давайте пойдём от конца. Печатная плата выглядит так: (фотовид мне не понравился, кстати)

    da24d8c931cd6201b5ccf7c40817b2dc.png

    Это вид сверху "сквозь" текстолит. Соответственно ноги микросхемы будут нумероваться с левой верхней против часовой стрелки.

    Электрическую схему рисовать не вижу смысла - она будет примитивна. Это просто разводка ног микросхемы на разъёмы так, чтобы к ним удобно было подключать всё, что нужно.

    Есть очень удобная картинка выводов микросхемы и ей место здесь:

    d61df15791cf558c95933342a3556d13.png

    Теперь кое-что в схеме должно стать понятно. На левой картинке обозначена линия "GND", то есть минуса питания, на правой - "Vcc", то есть плюс, и не абы сколько, а 5 вольт. Дорожек две и их надо будет не забыть замкнуть перемычкой. Трёхногое нечто слева вверху (корпус TO-220) - линейный регулятор напряжения L7805 (или КРЕН'ка на 5В). Средняя нога - земля, нижняя (на печатке) - вход, куда будет подключаться 9-вольтовая батарейка, верхняя - выход 5-ти вольт. Два смд конденсатора нужны для более стабильной работы, я впаял по 10мкФ на всякий случай.

    4c80be334ef63364a39f05119209c0cb.png51c69670d94a53f7ac86e3f560d495e2.png

    Ряд 5-ти контактов слева вверху - для программирования. Группа шести контактов чуть ниже - выходы, как видно, они идут на 4,5 и 6 ноги микросхемы, т.е цифровые выходы. Девять контактов по другую сторону и есть вольтметры (разъёмы на +5В и землю нужны для подключения датчика LM35, который сам нуждается в питании; каждому под его нужды отведён столбец 3-х контактов). Восемь контактов снизу - под дисплей: шесть сигнальных, +5В и земля. Кварцевый резонатор подключен прямо туда, куда он и предназначается (см. распиновку), а два смд конденсатора на 24пФ настоятельно рекомендуются знающими людьми :)

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

    int z = 0; //зарезервировано для коротких циклов
    long sum[] = {0,0,0,0};
    
    //long sum = 0;
    int sensor[] = {A0,A1,A2,A3};
    int sensors = 4; //всего сенсоров
    unsigned long mm = 0;
    int i = 0;
    int menu = 0; //включенный режим
    int enable = 0; //для кнопки
    int thres = 4000;
    float timezero = 1;
    unsigned long time[] = {1,1,1,1,1,1,1,1}; //время: 0)показание датчика 1,2 - время работы и отдыха
    int work[] = {0,0,0,1}; //изначально работают или нет
    int workpin[] = {2,3,4}; //пины к устройствам
    int ports = 3; //число активных портов
    unsigned long switchtime[] = {0,0,0,0};
    unsigned long LastPress = 0;
    int index = 0;
    int speaker = 11;
    int butOne = 12;
    int butTwo = 13;
    // include the library code:
    #include <LiquidCrystal.h>
    // initialize the library with the numbers of the interface pins
    LiquidCrystal lcd(5, 8, 7, 6, 9, 10);
    void setup() {
    // set up the LCD's number of columns and rows:
    lcd.begin(16, 2);
    // Print a message to the LCD.
    lcd.print("Hello, world!");
    //12,13 - buttons, 10-12 - load
    pinMode(butOne, INPUT_PULLUP);
    pinMode(butTwo, INPUT_PULLUP);
    pinMode(speaker, OUTPUT);
    LastPress = millis();
    for(z=0; z<ports; z++) {
    switchtime[z] = millis();
    pinMode(workpin[z], OUTPUT);
    digitalWrite(workpin[z], LOW);
    }
    for(int z = 1; z<(2*ports + 2); z++) {
    time[z] = 100000000; //в начале время выставляется большим, чтобы порты не переключались бешено
    }
    
    }
    void loop() {
    
    for (int z=0; z<4; z++)
    {
    sum[z] = sum[z] + analogRead(sensor[z]);
    }
    i++;
    //delayMicroseconds(10);
    
    //режим настройки
    if(digitalRead(butOne) == HIGH) {
    enable = 1;
    }
    
    if(enable == 1) { //защита от двойных срабатываний
    if (digitalRead(butOne)==LOW) {
    menu++;
    enable = 0;
    LastPress = millis();
    }
    }
    
    if (menu >= 11) {
    menu = 0;
    }
    
    if(menu >= (2*ports + 1)) {
    menu = 10;
    }
    
    
    if((millis() - LastPress)>20000 ) { //если последнее нажатие больше 20 секунд назад - сброс
    menu = 0;
    LastPress = millis();
    }
    
    //настройка выводов
    if (menu!=0) {
    if(digitalRead(butTwo) == LOW) {
    if (menu <10) {
    time[menu] = time[0];
    }
    }
    }
    
    
    //управление портами
    
    for(int z=0; z<ports; z++) {
    long interval = millis() - switchtime[z];
    int num = 2*z + 1;
    if(work[z]==1) { //если работает, считаем время работы
    if(interval>time[num]) {
    work[z] = 0;
    digitalWrite(workpin[z], LOW);
    switchtime[z] = millis();
    }
    }
    else {
    if(interval>time[num+1]) {
    work[z] = 1;
    digitalWrite(workpin[z], HIGH);
    switchtime[z] = millis();
    }
    }
    
    }
    
    
    
    if (i==999) { //обработка данных по прошествии 1000 циклов
    digitalWrite(speaker, LOW);
    
    for(int z = 0; z<sensors; z++) {
    sum[z] = sum[z]*5/1023;
    
    
    //speaker check
    
    if (sum[z]>thres) {
    digitalWrite(speaker, HIGH);
    }
    }
    
    
    
    
    int c = sum[0]/20;
    timezero = 1;
    for(int k = 0; k<c;k++) {
    timezero = 1.08*timezero;
    }
    time[0] = (unsigned long)timezero; //переводим в long
    
    lcd.clear();
    lcd.setCursor(0,0);
    if(menu != 0) { //отображаем время только в ненулевом режиме
    if(digitalRead(butTwo) == HIGH) {
    time[0] = time[menu];
    }
    else {
    if (menu==10) {
    thres = sum[0];
    }
    }
    
    
    if(time[0]>7200000) {
    lcd.print(time[0]/3600000);
    lcd.print("h");
    }
    else {
    if(time[0]>100000) {
    lcd.print(time[0]/60000);
    lcd.print("min");
    }
    else {
    if (time[0]>5000) {
    lcd.print(time[0]/1000);
    lcd.print("s");
    }
    else {
    lcd.print(time[0]);
    lcd.print("ms");
    }
    }
    }
    }
    lcd.setCursor(10,0);
    //lcd.print(millis() - mm); //пишем время выполнения 1000 циклов
    mm = millis();
    
    for(z = 1; z<sensors; z++) {
    lcd.setCursor(5*(z-1), 1);
    lcd.print(sum[z]);
    }
    /*
    //отладка
    lcd. setCursor(5,1);
    lcd.print(millis());
    */
    
    lcd.setCursor(14,0);
    
    switch (menu) {
    case 0:
    lcd.setCursor(0,0); //в нулевом режиме отображается работа и отдых портов
    for (int z=0; z<ports; z++) {
    lcd.setCursor(5*z,0);
    float percent = (float)(millis() - switchtime[z]);
    percent = 100*percent;
    
    if(work[z] == 0) {
    lcd.print("R");
    index = 2*z+2;
    
    }
    else {
    lcd.print("W");
    index = 2*z + 1;
    }
    percent = percent/time[index];
    lcd.print(percent);
    }
    
    break;
    case 1:
    lcd.print("W1"); //длительность работы первого порта
    break;
    case 2:
    lcd.print("R1"); //длительность отдыха первого
    break;
    case 3:
    lcd.print("W2");
    break;
    case 4:
    lcd.print("R2");
    break;
    case 5:
    lcd.print("W3");
    break;
    case 6:
    lcd.print("R3");
    break;
    case 10:
    
    lcd.print("TH");
    lcd.setCursor(0,0);
    lcd.print(thres);
    lcd.print(" ");
    break;
    }
    
    for (z = 0; z<sensors; z++) {
    sum[z] = 0;
    }
    i = 0;
    }
    }
    

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

    de17f802bd24251d237e66efe18059b9.jpg

    Итак, разжившись платой Arduino Uno, я как-то начал почитывать офсайт, и совершенно незаметно для себя (примерно за полгода) дошёл до того, что сделал девайс со следующими возможностями:

    - 3 независимых вольтметра, отображающие напряжения в милливольтах на LCD-дисплее (изначально подразумевалось использование в качестве термометров посредством микросхемы LM35 или аналогичной) с зумером, сигнализирующем, в случае, если напряжение на каком-либо входе превысило заданное значение

    - 3 управляющих выхода для подключения нагрузки, работающие циклами: работа-отдых-работа-отдых, причём длительность работы и отдыха выставляется отдельно для каждого выхода при помощи одного-единственного (!) переменного резистора и двух кнопок

    - Индикация состояния каждого из выходов на том же LCD-дисплее

    - Отсутствие необходимости в самой плате Arduino для работы.

    По отдельности это несложно. Про подключение дисплея к AVR уже даже специально сказано, что таких статей больше не нужно :), про наличие аналогового входа знают, наверное, все, код не требует особых ухищрений, а статья про ардуино на макетной плате есть на arduino.cc. Но я сам получил огромное удовольствие от разработки устройства и, надеюсь, кто-то тоже получит, повторив этот путь или просто читая про прогресс чайника в микроконтроллерах :)

    О каждой части устройства будет рассказано отдельно и максимально подробно. Существенные вопросы по теме задавать можно и нужно, с несущественными, пожалуйста, подождите окончания повествования :)

×
×
  • Создать...