31.12.2008

Семисегментный индикатор для Arduino (4)

Часть IV

(окончание, см. Часть III, Часть II и Часть I)


Итак, время брать в руки паяльник. Используем стандартную макетную плату для пайки с шагом 2,54мм (шаг важен, поскольку надо установить вилку PLS, чтобы попасть ей в розетку PBS на Arduino - а там именно такое расстояние между контактами). Выбираем размер так, чтобы она не закрывала второй ряд колодок с цифровыми pin-ами, например, у меня получился размер 96 x 52 мм.

Я использовал двустороннюю макетку без дорожек, но зато с металлизацией всех отверстий. Вот что получилось в итоге:




Чтобы не паять лишний разъем ICSP для ATMEGA8, я поставил панельку. Кнопка сброса - чисто декоративная, и на самом деле, ее можно и не ставить вовсе. Длинная гребенка голубого цвета - это резисторная сборка (6 резисторов по 330 Ом). Вещь удобная, но, будучи поставлено вертикально, постоянно гнется при неосторожном обращении с бескорпусным изделием. Зато - опять-таки - экономия места.

Паяем проводники, глядя в принципиальную схему. Поскольку LED-ы индикаторов соединены в шину, напрашивается тривиальное решение по расположению:



Конденсатор по питанию довольно компактно влез между вилкой PLS и панелькой:



Если вы попробуете сразу запустить плату после пайки - у вас ничего не выйдет. Причина - отсутствие кварца, на который рассчитывает ATMEGA. Если вы уже отлаживались с ним в составе Arduino, программатор вместе с bootloader-ом прошил весьма определенные FUSE-биты, в том числе отвечающие за выбор схемы тактирования: внешний кварц на 16 МГц. У нас используется внутренний на 8 МГц, поэтому FUSE-биты надо изменить.

Поместите ATMEGA8 в устройство с ICSP-гребенкой (тот же Arduino), подключитесь к ней с помощью программатора и поменяйте fuses следующим образом (подробное описание битов - в документации):

Fuse High Byte: SPIEN=0, CKOPT = 1, BOOTSZ = 01, BOOTRST = 0;
Fuse Low Byte: SUT = 01, CKSEL = 0100;

Остальные биты стоит оставить незапрограммированными, получаем шестнадцатиричные значения: hfuse = 0xda, lfuse = 0xd4.

Например, если вы используете Parallel Programmer и Arduino IDE, надо запустить avrdude со следующими параметрами:

avrdude -p m8 -c dapa -t

где m8 - это тип контроллера, ATMEGA8; dapa - это тип программатора, а -t - войти в терминальный режим. Находясь в оном (avrdude> - это приглашение), набираем:

avrdude> write hfuse 0 0xda
avrdude> write lfuse 0 0xd4
avrdude> q

Вот теперь - точно должно заработать! Но будьте терпеливы: Arduino bootloader понятия не имеет, что теперь его тактовая частота понизилась в 2 раза. Его алгоритм предполагает ожидание около 10 секунд после старта (мало ли - думает он - может новый sketch сейчас зальют?!). Теперь же, после подачи питания, bootloader будет ждать 20 секунд. Дальше на экране появится три минуса, затем будет отображаться то, что передается по TWI.

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

Последние штрихи: вернемся к fuse-битам. Наверное, стоит сделать так, чтобы bootloader не запускался вовсе, а сразу стартовал наш sketch. Это довольно просто: достаточно сообщить об этом ATMEGA через hfuse: установить флаг BOOTRST в 1. Проделываем всё тоже самое, что и выше, только вместо 0xda пишем 0xdb.

Конечно же, первым делом я соорудил градусник. Датчик подключается к цифровым pin-ам, которые не перекрыты макетной платой:






Подведем итоги.
  1. Контроллером дисплея служит ATMEGA8, как и хотелось;
  2. Программа написана на Wiring-е, отлажена в Arduino, легко менятеся, расширяется по числу индикаторов, а также типу (переделывается под общий анод).
  3. Число деталей минимизировано - кроме контроллера восемь резисторов 330 Ом и один - 10К, а также сами индикаторы.
  4. Интерфейс взаимодействия по TWI (I2C) получился относительно простым, хотя и пришлось в итоге поставить задержку 100 мс между посылками информационных блоков. Для человеческого глаза - вполне приемлемо.
Чего хотелось бы еще?
  1. Неплохо было бы сделать печатную плату, повысив компактность;
  2. Оформить ввод-вывод в виде библоитеки и подключать ее, чтобы не писать каждый раз одно и то же;
  3. Сделать полноценный алфавитно-цифровой дисплей.

23.12.2008

Семисегментный индикатор для Arduino (3)

Часть III

(продолжение, см. Часть II и Часть I)


Очень удобно экспериментировать с макеткой без пайки, например:



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

Готово, самое время написать sketch для ATMEGA8, который будет у нас исполнять роль последовательного приемника, защелки, знакогенератора, декодера и отображателя ;)

Для начала надо определить массив знакогенератора. Будем хранить в нем карту отображения сегментов a,b,c,d,e,f,g побитно (я выбрал старший бит с весом 0x80 для сегмента a, 0x40 для сегмента b и так далее):

byte d_map[MAX_SYMBOLS];

Также потребуется защелка - для хранения кодов символов, которые мы отображаем в настоящий момент:

byte latch[SEG_NUM];

Чтобы ввести немного универсальности, я сделал промежуточные массивы, в которых задаются pin-ы Arduino, к которым подключены сегменты шины:

byte l_pin[8];

(восемь - так как есть еще сегмент DP - десятичная точка). Ну и тогда уж пины общих катодов каждого индикатора:

byte s_pin[SEG_NUM];

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

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

boolean point[SEG_NUM];

Массив обновляется только при поступлении кода символа с включенным старшим битом (0x80), после чего остальные биты трактуются как включение или выключение точки на соответствующем знакоместе и переписываются в массив point.

Самое время определиться с символами, которые мы собрались загнать в знакогенератор (содержимое массива d_map и значение константы MAX_SYMBOLS). Для простоты (а чего экономить-то?) определяем каждому символу 8 бит (старший занят на признак позиций точек, см. выше, так что максимум 128 символов). У меня хватило фантазии на такой набор:





Последним угадывается истинно пелевинский символ-пустота.

Самое время - показать программу по мотивам вышеизложенного:

#define CPU_FREQ 8000000L
#include <Wire.h>

#define ADDR 0x69 // I2C device address (change if need, note: 7-bit)
#define SEG_NUM 3 // total digits in a display
#define delayms 1 // time for displaying one digit, ms

byte latch[SEG_NUM]; // защелка состояний
boolean point[SEG_NUM]; // десятичные точки
byte s_pin[SEG_NUM]; // пины общих катодов
byte l_pin[8]; // мап пинов на сегменты знакоместа
byte d_map[24]; // память знакогенератора

void receive_handler(int numbytes) {
for (unsigned int i=0;i<numbytes;i++) {
byte r = Wire.receive();
if (r<0x80) {
// ordinary symbol
for (byte k=(SEG_NUM-1);k!=0;k--) latch[k] = latch[k-1];
latch[0] = r;
} else {
// DP code
for (byte k=0;k<SEG_NUM;k++) point[k] = (r >> k) & 0x1;
}
}
}

void setup() {
s_pin[0] = 4; // 2;
s_pin[1] = 12; //12;
s_pin[2] = 2; // 4;

l_pin[0] = 5;
l_pin[1] = 6;
l_pin[2] = 7;
l_pin[3] = 8;
l_pin[4] = 9;
l_pin[5] = 10;
l_pin[6] = 11;
l_pin[7] = 3;

for (byte i=0;i<SEG_NUM;i++) {
point[i] = false;
pinMode(s_pin[i],OUTPUT);
digitalWrite(s_pin[i],LOW);
}
for (byte i=0;i<8;i++) pinMode(l_pin[i],OUTPUT);

//
d_map[0] = 0b00000011; // 0
d_map[1] = 0b10011111; // 1
d_map[2] = 0b00100101; // 2
d_map[3] = 0b00001101; // 3
d_map[4] = 0b10011001; // 4
d_map[5] = 0b01001001; // 5
d_map[6] = 0b01000001; // 6
d_map[7] = 0b00011111; // 7
d_map[8] = 0b00000001; // 8
d_map[9] = 0b00001001; // 9
d_map[10] = 0b00010001; // A
d_map[11] = 0b11000001; // b
d_map[12] = 0b01100011; // C
d_map[13] = 0b10000101; // d
d_map[14] = 0b01100001; // E
d_map[15] = 0b01110001; // f
d_map[16] = 0b10010001; // H
d_map[17] = 0b11110111; // i
d_map[18] = 0b11100011; // L
d_map[19] = 0b00110001; // P
d_map[20] = 0b10000011; // U
d_map[21] = 0b00111001; // градус
d_map[22] = 0b11111101; // минус
d_map[23] = 0xff; // пустой

// initial display state - empty
latch[0] = 22;
latch[1] = 22;
latch[2] = 22;

// start wiring library
Wire.begin(ADDR);
Wire.onReceive(receive_handler);
}

//
// Set LED bus in order to display symbol 'd'
//

void set_digit(byte d) {
byte i=0;
for (byte mask=0x80;mask!=1;mask>>=1)
digitalWrite(l_pin[i++],(d_map[d]&mask) ? HIGH : LOW );
}

void indicate() {
for (byte k=0;k<SEG_NUM;k++) {
digitalWrite(s_pin[k],HIGH);
set_digit(latch[k]);
digitalWrite(l_pin[7],point[k] ? LOW : HIGH); // DP segment
delay(delayms);
digitalWrite(s_pin[k],LOW);
}
}

void loop() {
indicate();
}


Теперь рассмотрим программу на передающем "конце". Эксперименты с TWI показывают, что для стабильной работы надо снабдить окончание передачи небольшими задержками. Соответственно, получаем две функции:

void od(byte d) {
Wire.beginTransmission(ADDR);
Wire.send(d);
Wire.endTransmission();
delayMicroseconds(100);
}

void od3(byte d1, byte d2, byte d3) {
Wire.beginTransmission(ADDR);
Wire.send(d1);
Wire.send(d2);
Wire.send(d3);
Wire.endTransmission();
delayMicroseconds(100);
}


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

(окончание см. в Части IV)

21.12.2008

Семисегментный индикатор для Arduino (2)

Часть II

(продолжение, см. начало в Части I)

Первым делом, нарисуем схему. TWI работает на аналоговых пинах A4, A5 - именно там разместили аппаратную поддержку авторы ATMEGA8 (это 27 и 28 выводы микроконтроллера в корпусе PDIP).

Что внутри? Три семисегментных LED-знакоместа, у которых pin-ы светодиодов соединены между собой в шину на 8 проводов (не забудем про десятичную точку).

Надо иметь ввиду, что семисегментные индикаторы бывают двух типов - там, где у LED-ов один общий анод и, наоборот, где один общий катод. Я для своих экспериментов выбрал индикаторы Agilent HDSP-5501 и HDSP-5521 с общим катодом, оставляю желающим возможность доработать микропрограмму для общего анода - ничего сложного, а в качестве тренировки очень даже полезно.

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

Микроконтроллеру нужно питание, сброс, тактирование, микропрограмма.

Кварц стоит недорого, но зачем? Экономим место и деньги - используем внутренний
неточный откалиброванный, для частоты 8МГц. Точность его не скажется на работе TWI, поскольку тактовые импульсы генерирует master, а мы будем работать в режиме slave.

Питание - стандартно, не забываем про конденсатор 0,1 мкФ между Vcc и GND. Схема сброса - тоже стандартная, притянуть к Vcc через R=10К. Получается элементарная схема (прошу прощения за качество, это мой первый опыт с Eagle, кликабельно для увеличения):


Микропрограмму напишем при помощи Arduino, так быстрее, хоть и менее эффективно с точки зрения энергопотребления и объема программы. Главное - чтобы заработало, а потом при желании энтузиасты улучшат, не правда ли?

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

Токоограничительные резисторы надо либо рассчитать по закону Ома (зная сопротивление источника питания, LED-ов, схему каскадов на I/O pin-ах ATMEGA и максимальный ток - 40mA), либо практическим путем - амперметром, последовательно в цепь. Например, у меня при подключении нагрузочного R=1К последовательно в цепь каждого из 8-ми выводов, ток на одном светодиоде составлял 2 mA, следовательно максимально - 16mA. В итоге, я остановился на 330 Ом, но видел схемы и со 100 Ом. Можно подстраховаться: подавать групповой уровень через транзистор. Но зачем нам лишние элементы на плате? Стоит заморачиваться только если предельное значение нагрузочного резистора не соответствует желаемой яркости свечения (например, надо рассматривать индикатор в солнечную погоду с пяти метров).

Теперь надо написать программу. Конечно, удобнее всего иметь под рукой два Arduino (часто один из них заменяет набор ArduinoMinimum, например такой). Соединяем их a4, a5, GND и снабжаем программами:

Приемник (slave):

#include <Wire.h>
#define ADDR 0x69

void receive_handler(int numbytes) {
  for (int i=0;i<numbytes;i++) {
    Serial.print(Wire.receive());
  }
}

void setup() {
  Serial.begin(38400);
  Wire.begin(ADDR);
  Wire.onReceive(receive_handler);
}

void loop() {}

Передатчик (master):

#include <Wire.h>
#define ADDR  0x69

void setup() {
  Wire.begin();
}

void loop() {
  Wire.beginTransmission(ADDR);
  Wire.send("Hello, world!");
  Wire.endTransmission();
  delayMicroseconds(1000);
}

После запуска обоих sketch-ей, подключитесь к serial-соединению на приемнике. Если все правильно, то раз в секунду будет приезжать "Hello, world!". 

Если нет - проверьте, выставили ли вы порт на скорость 38400, правильно ли соединены провода. Адрес 0x69 я выбрал произвольно, не исключено, что он пересекается скаким-либо существующим устройством. В любом случае, его всегда можно поменять. 

Заработало? Можно переходить на следующий уровень - сборка на макетной плате и написанию полноценной микропрограммы отображения для приемника.

(см. продолжение в Части III)

14.12.2008

Семисегментный индикатор для Arduino

Часть I

Цифровой индикатор может пригодиться во многих приложениях, особенно связанных с робототехникой. Библиотека Serial позволяет Arduino передавать и принимать данные через последовательный порт, но носить с собой компьютер просто для того, чтобы иметь возможность посмотреть пару цифр - мягко говоря, неудобно.

Допустим, у вас под рукой случайно оказались семисегментные светодиодные дисплеи - почему бы их не пустить в дело? Знатоки неодобрительно покачают головой: довольно расточительно тратить целых 8 пинов микроконтроллера (семь сегментов и одна десятичная точка) на такое удовольствие.



Но что такое индикатор на один разряд? Смех, да и только: даже температуру не показать. Поэтому, хочется хотя бы три:



Вырисовывается довольно прозрачная задача: разработка компактной Shield-платы со светодиодными индикаторами. Однако, прежде чем перейти к фантазированию проектированию, поставим себе ограничения:
  1. Контроллер Arduino должен быть разгружен от тупой работы по поддержанию информации на дисплее => один раз вывел и дальше занимается своими делами, а данные удерживаются до обновления в "защелке" (latch) на Shield-е.
  2. Использовать минимальное количество корпусов микросхем на Shield-е.
  3. Использовать минимальное число ножек для взаимодействия Arduino с Shield, при минимальных издержках. Например, неплохой вариант с последовательным интерфейсом (SPI, TWI).
  4. По-возможности, минимизировать стоимость Shield-а.
Есть масса микросхем-дешифраторов, уже заточенная под индикацию на семисегментном дисплее: те же 541ИД1, ИД2. У них параллельный ввод в BCD-коде - это 4 бита, да еще по биту на каждый разряд, итого 7.



Многовато, да и от циклического сканирования не избавляет, а ставить регистр-защелку - лишний корпус. Зато дешево стоят - 4-5 руб. за штуку.

Наиболее полно нашим условиям удовлетворяют микросхемы MAX7219 и MAX7221: DIP24, порт SPI, защелка присутствует. Однако в розницу они стоят порядка 150 и 250 рублей соответственно, и дешевого решения уже не получается.

А что, если?

Использовать для этих целей ATMEGA8? Связать с контроллером по TWI (Two Wire Interface, полностью совместимый с шиной I2C) - при использовании библиотеки Wire это не представляет труда, к тому же можно расширить диапазон выводимых символов (не только цифры, но и какие-то буквы и прочие символы).

Плюсы:
  • стоит минимум в 2 раза дешевле MAX7219;
  • температурный диапазон шире MAX7221 (а это уже в 4 раза дешевле, можно использовать при температурах ниже нуля, например в непрогретом авто ;)
  • использование I2C дает шанс сделать полноценную Shield, потому что не надо использовать колодку с цифровыми пинами 9-12 - следовательно подойдет макетка со стандартным шагом 2,54 мм!
Минусы:
  • ног больше на 4
  • придется повозиться с программированием ;)

Если жалко времени - однозначно MAX, или вообще готовый последовательный дисплей купить. Но мы же - "бедные студенты" ;) времени - много, денег лишних платить не хочется, а уж программирование мы как-нибудь одолеем!

(продолжение следует - Часть II)

28.11.2008

Arduino своими руками

Часть III

(окончание, см. начало - Часть I и Часть II)

Итак, микроконтроллер заработал, но нам этого мало: теперь надо сделать интерфейс для COM-порта, чтобы Arduino мог общаться с PC, в первую очередь для заливания sketch-ей.

Глядим в схему, подбираем детали:
  • Разъем DRB9F на плату, угловой - 12,5 руб.
  • Транзистор T1 - BC547 - 3,8 руб.
  • Транзистор T2 - BC557 - 3,5 руб.
  • Два диода D2,D3 1N4148 - 2 x 2,5 = 5 руб.
  • Два светодиода LED0, LED1 - 2 x 3,3 = 6,6 руб.
  • Резисторы 10K - R5,R8,R7,R10 - 4 x 0,95 = 3,8 руб.
  • Резистор 4К7 R9 - 0,95 руб.
  • Резисторы 1K R1,R2,R6 - 3 x 0,95 = 2,85 руб.
  • Неполярный электролит C9 10 мкФ - 3 руб.
  • Штыревой соединитель PLS40 (из него кусачками отделяется три пина для джампера выключения порта, остальные 37 обязательно пригодятся ;) - 13 руб.
  • Джамперы (стоит поискать на старых материнках, и только если нет под рукой - покупать) - 8,5 руб.
Итого: 63,5 руб.

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

Придется достать сверло на 4..5 мм и просверлить пару дырок для креплений разъема COM-порта (если только вы не купили чудо-макетку с посадочным местом под разъем DRB9F).

Как говорит автор схемы, "иногда поступающая по COM-порту от PC информация может препятствовать запуску скетча", поэтому предусмотрен джампер JP0. У него три положения - "COM-порт работает" - к VСС, "COM-порт блокирован" - к GND и, если снять его вовсе - получили 2 свободных цифровых входа.


Завершающий штрих: подключение внешнего источника питания, например батарейки "Крона". Продолжаем подбирать компоненты:
Итого: 86 руб.



Как и в случае с DRB9F, в плате надо сверлить дополнительные дырки для разъема питания ("плюс" обычно делают в центре). Если подключить выход 7805 к ранее запланированному джамперу (см. Часть II, сборка узла микроконтроллера), то можно переключаться между питанием от батарейки и от USB. Внешний источник может выдавать от +7В до +20В, но больше +16В не рекомендуется, а еще лучше +9В, чтобы не очень сильно грелся собственно стабилизатор.


Вот и все, готово. Перед тем, как приступить к написанию собственных sketch-ей,  осуществим финальную проверку:

File -> Sketchbook -> Examples -> Digital -> Blink

Дальше - Verify/Compile (Ctrl-R), после окончания жмите на кнопку сброса на Arduino, затем File -> Upload to I/O board (Ctrl-U). Полюбуйтесь, как весело перемигиваются светодиоды Rx и Tx, подождите 6 секунд и наблюдайте мигание LED13.

Что еще добавить?
  1. Бюджет разработки, включая программатор не превышает 500 рублей. Цены имеют свойство меняться со временем - может быт, что-то будет дороже, что-то дешевле (некоторые компоненты вообще могут оказаться под рукой или аккуратно демонтированы с ненужных устройств);
  2. Если мало 8К памяти программ, используйте ATmega168-20PU. Микроконтроллеры имеют различный объем Flash и SRAM, но полностью совместимы по корпусам. Тип платы надо будет переставить на Tools -> Board -> Ardiono NG or older w/ATmega168, прошить соответствующий bootloader. С корректно установленным типом платы ArduinoIDE будет правильно учитывать тип МК при компиляции, а текст скетча при этом никак не изменится. Правда, по стоимости будет чуть дороже;
  3. Можно попробовать подключить схему автосброса - Arduino умеет ненадолго устанавливать сигнал DTR перед заливанием sketch-а, и если он соединен со схемой сброса, отпадает необходимость нажимать Reset перед каждой загрузкой скетча. Функция имеет побочный эффект - Arduino может быть сброшен в любой момент программой, которая дергает DTR и даже при отключении или подключении кабеля к COM-порту.
  4. Можно добавить гребенку для непосредственного подключения USB/Serial Converter, если оно у вас есть:


27.11.2008

Arduino своими руками

Часть II

(продолжение, см. начало - Часть I)

Итак, программатор готов. Теперь надо выбрать ту схему Arduino, которая лучше всего подходит для самостоятельной реализации (а существует их приличное количество).

По сути, Arduino представляет собой два устройства: интерфейс последовательного порта и микроконтроллер ATMEGA. Последние модификации Ardiono подключаются к PC по USB, используя для преобразования в последовательный порт с TTL-уровнями микросхему FTDI 232R, а у нее неприятная особенность - шаг ножек всего 0,65 мм (варианта в PDIP не выпускается). Я не говорю уже об ArduinoBT, на котором стоит Bluegiga WT11 - не самый легкодоставаемый и дешевый компонент. Наконец, у некоторых Arduino вообще отсутствует интерфейсная микросхема (примеры - Arduino Mini, LilyPad Arduino Main Board) последовательного порта, которым пожертвовали ради миниатюризации. Но в этом случае для загрузки sketch-ей все равно нужен USB Serial Converter, уже готовый модуль с чипом FTDI 232R, что снова возвращает нас к проблеме монтажа 0,65 мм ножек.

Остается Arduino Serial, где используется "настоящий" COM-порт. Цена вопроса - пара диодов и транзисторов, дешево и сердито. Хотя существуют более простые версии 1 и 2, для самостоятельного изготовления наиболее подходит третья версия - Severino.

Если нет желания самостоятельно травить плату хлорным железом, берем "макетку". Я выбрал готовую плату размером 160 х 100 мм, односторонней печатью и стандартным шагом дырок 2,54 мм. Чтобы немного сократить объем пайки, большинство дырок "сдвоено":



Также неплохо иметь группу дырок с шахматным порядком, потому что именно так расположены выводы разъема DB9 для COM-порта. Мне помогла специальная секция на краю платы для монтажа SOIC-корпусов (шаг выводов 1,27мм):



В крайнем случае, можно брать макетку и без такого изыска - на DB9 используется только один ряд контактов 1-5, остальные (4-9) можно смело откусывать.

Вооружаемся принципиальной схемой Severino (я буду ссылаться на нее), начинаем со сборки модуля микроконтроллера. Потребуются детали:
  • Макетная плата - 150 руб.
  • IC1 ATMEGA8-16PU (в корпусе PDIP-28) - 60 руб.
  • Панелька SCS28 (узкая DIP28S) - 3 руб.
  • Кварц Q1 16.0 МГц - 6 руб.
  • Две керамических емкости для кварца по 22pF (C1, C2) - 1 x 2 = 2 руб.
  • Кнопка тактовая 6х6 мм (S1, сброс) - 2 руб.
  • R11 резистор 10К для притягивания сброса к Vcc - 1 руб.
  • Емкость на шину питания 100nF (С6) - 1 руб.
  • Гребенка PLD-6 (разъем ICSP) - 5 руб.
  • Розетки PBS - две 08, две 06 - 5 х 4 = 20 руб.
  • Светодиод LED14 PWR - 2 руб.
  • Светодиод LED13 - 2 руб.
  • Ограничители тока светодиодов - R3,R4 - 1 x 2 = 2 руб.
  • Электролит C5 100uF (мкФ) для фильтрации помех по питанию - 2 руб.
  • Разъем USB-B 1J - 15 руб.
  • Гребенка PLS-3 для джампера "Выбор питания" - 1 руб.
Итого - 274 руб.

Лично я решил не ставить дроссель L1 на плату (уж больно громоздким мне показался приобретенный экземпляр) и использовал решение из версий 1, 2 - один конденсатор 100nF между соединенными попарно лапками Vcc (7) и Aref (21) - к +5В, и GND (22 и 8) - к земле. Вроде работает нормально. Питаться пока придется от USB, поэтому пришлось установить дополнительный разъем и подключить его "+" через джампер-блок, чтобы иметь возможность выбирать источник питания (от USB или от батарейки).

Пара слов по поводу розеток и гребенок с шагом 2,54. С гребенками все просто - из длинной PLS-40 или PLD-80 можно накусать любое количество ножек (и наоборот - составить одну большую гребенку из мелких).



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

Розетки PBS служат для стыковки с платами расширения (т.н. Shields), если вы собираетесь пристыковывать их к Arduino без лишней возни, надо соблюсти в точности расположение розеток согласно чертежу платы - это стандарт Arduino. Но на макетке с фиксированным шагом 2,54 это сделать практически невозможно, и я просто раскидал их по плате в произвольном порядке, в надежде снабдить в последующем наклейками или надписями.



Итак, собираем все это, уделяя повышенное внимание гребенке ICSP. Подключаем к LPT-программатору (см. первую часть). Запускаем предварительно скачанный софт, в меню ставим Tools -> Board -> Ardiono NG or older w/ATmega8. Потом - Tools -> Burn bootloader -> w/Parallel Programmer. Дожидаемся завершения операции.

Если все правильно, то при каждом нажатии на тактовую кнопку SC1 светодиод LED13 будет радостно помаргивать - так сигнализирует о своем запуске bootloader. Если этого добиться не удалось, проверьте еще раз:
  • правильность монтажа светодиода LED13
  • не подключено ли питание через USB - для ICSP оно не требуется
  • проверить монтаж вообще. пока элементов мало - это несложно
(окончание следует, Часть III)

26.11.2008

Arduino своими руками

Часть I.

Как быть, если надо поэкспериментировать с Arduino, но покупать (по каким-то неуважительным причинам) совершенно не охота? Если вы умеете держать в руках паяльник, не составит большого труда соорудить его самостоятельно. Продвинутые пользователи, имеющие опыт травления печатных плат, могут воспользоваться Severino. Но для начала вполне можно ограничиться "макеткой".

"Сердце" всех плат Arduino - это микроконтроллер ATmega (точнее, ATmega8, ATmega168 или ATmega328P), который требует прошивки, поэтому для начала надо обзавестись программатором. Готовый программатор стоит недорого, но ведь его еще надо заказать и дождаться! Давайте соорудим простейший - на LPT-порту:


Девайс предназначен для программирования контроллера прямо в родной схеме (т.н. In Circuit Serial Programming или ICSP ) - надо организовать на плате гребенку 2x3 контакта, подключить к ней этот программатор и один раз зашить bootloader - специальную короткую программу инициализации, которая принимает по последовательному порту микропрограмму (sketch), прошивает ее в свободную память ATmega, а затем запускает.

Стоимость деталей:
  • разъем DB25 - 10 руб.
  • корпус разъема - 10 руб.
  • три резистора - 1 х 3 = 3 руб.
  • три колодки PBS02 - 2 х 3 = 6 руб.
  • проводки - ну добавьте еще 10 руб.
Итого, 39 рублей. Наверное, вы спросите: где подвох? Не скрою, не без него: на вашей машине должен быть LPT-порт.

Процесс сборки программатора подробно описан в статье на сайте Arduino. Вот что получилось у меня:



Отдельного внимания заслуживает история одинокого желтого проводка.

Как видно из первого рисунка, на оригинальной схеме pin2 разъема ICSP "висит в воздухе". На самом деле, там должно быть Vcc +5В, которое отсутствует в LPT-порту в виде отдельной питающей шины. Авторы предлагают запитать программируемую схему отдельно (я взял +5В с разъема USB того же компьютера, к которому были подключен LPT).

В таком варианте схема работать отказалась, из порта программирования систематически читались 0xff. Когда я снял питание, то с удивлением обнаружил, что контроллер все равно умудрялся что-то высасывать из активных пинов LPT-разъема и - о чудо! - даже начал проявлять признаки жизни: пытался осмысленно отвечать на Power-up sequence. Однако, дальше дело не шло: avrdude удивленно сообщал о том, что обнаруженный процессор имеет нестандартную сигнатуру - 0, 1, 2.

Это натолкнуло меня на мысль покопаться в конфигурационном файле avrdude.conf и внимательно изучить секцию, посвященную моему дешевому программатору:

programmer
id = "dapa";
desc = "Direct AVR Parallel Access cable";
type = par;
vcc = 3;
reset = 16;
sck = 1;
mosi = 2;
miso = 11;


Все элементарно: слева - название сигнала, справа - номер контакта на LPT. Таким образом, предполагается, что программатор использует третий контакт для подачи питающего напряжения Vcc.

Так и появился желтый проводок. Как только я соединил им шину +5В микроконтроллера и DB25 pin3, bootloader для ATMEGA8 прошился на "ура".

Признаюсь, было несколько стремно (перед включением я мысленно помолился за здоровье своего LPT-порта), но, видимо потребность в питании одного-единственного МК в данном случае вполне допустима.

(продолжение следует, Часть II)

18.11.2008

Увеличение объема памяти РК-86

Немного не по теме - копался в гараже и нашел гору манускриптов. Один из них можно датировать 1989-90 годами, когда нынешний рынок Юнона еще назывался "толпа" и обитал в Автово, почти в лесу, на кочках - короче полностью неблагоустроенный.

Статья повествует о том, как пытливому радиолюбителю, неудовлетворенному расширением ОЗУ в Радио-86РК до 32К, получить почти в 2 раза больше:



Полный скан статьи можно скачать здесь.

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

14.11.2008

Вид МК-90 изнутри

Изначально калькулятор достался мне с неработающим звуком. Твердо решив докопаться до причины, я полез за отверткой. Калькулятор разобрался на две аккуратных половинки:



Вверху слева - плата ЖКИ, вверху справа - плата клавиатуры. Снизу - видна плата процессора, она же чуть крупнее:



Как видите, это те самые ПЗУ микропрограмм КА588ВУ2А, с номерами 001-004. Слева вверху в белом корпусе - по-моему, резисторная сборка.

Колесико регулировки контрастности крупным планом:



Если откинуть плату процессора "на себя", под ней скрывается плата устройств:



В блестящих корпусах элементы процессора - АЛУ КА588ВС2, контроллер ВГ1 и последняя ПЗУ с микрокомандами контроллера - за номером 005. Справа в однорядном корпусе ПЗУ с BASIC-ом - КА1835РЕ1. Где тут перемычки, которые надо перерезать для программирования (а потом восстанавливать) - понятия не имею, если честно. Видно только пустое посадочное место для "бутербродного" монтажа (как в модуле СМП).



Плата устройств немного не в резкости, но достаточно ясно видно, что сверху к ней подключен единственный наружный разъем, справа - два для модулей СМП.




Красный и белые проводки не случайно такие длинные. Это позволяет без потери контакта откинуть "на себя" и плату устройств тоже:



Динамик - пьезоэлектрический, он виден только наполовину. Как я понимаю, такие вещи не ломаются в принципе. Зато два лепестка, которые припаяны на плату (видите, по центру два контакта один над другим?) за последние лет 15 немного потеряли пружинистость. Я немного отогнул их, и.... после сборки звук снова заработал!

Напоследок, крупным планом кусочек платы от разъема питания. Вверху - контроллер , отвечающий за клавиатуру.