27.01.2009

Arduino и Serial Flash

На днях прикрутил к Arduino флешку (микросхема AT24C512 от все того же ATMEL - емкость 65 Кбайт или 512Кбит). В принципе, с аппаратной библиотекой I2C получилось более чем тривиально.

Выводы микросхемы : A0,A1 сажаем на GND, за компанию с WP. SCL и SDA подключаем к аналоговым выводам Arduino (a4,a5) и притягиваем каждый через 5,1К к VCC.

Скетч:

/* 
   Подключение AT2424C15 по I2C
*/ 

#define ADDR  0x50

void setup() {
  Wire.begin();
  Serial.begin(38400);
  randomSeed(analogRead(0));  
}

void readByte(unsigned int addr) {
  Wire.beginTransmission(ADDR);
  Wire.send( (byte) addr >> 8 );
  Wire.send( (byte) addr & 0xff );
  Wire.endTransmission();
  Wire.requestFrom(ADDR, 1);
}

void writeByte(unsigned int addr, byte b) {
  Wire.beginTransmission(ADDR);
  Wire.send( (byte) addr >> 8 );
  Wire.send( (byte) addr & 0xff );
  Wire.send ( b );
  Wire.endTransmission();
}

void loop() {
  if (Wire.available()) {
    Serial.println(Wire.receive(),HEX);
  }
  int cmd = Serial.read();
  if (cmd != -1) {
    if (cmd == 'R') {
      readByte(0);
    }
    if (cmd == 'W') {
      long b = random(0,255);
      writeByte(0,b);
      Serial.println(b,HEX);
    }
  }  
}


Запускаем консольку на 38400, по команде W пишется случайное значение в нулевой адрес, по команде R его можно оттуда же прочитать. Адрес чипа - 0x50, если A0 и A1 притянуты к GND. Если подать на них одну из четырех комбинаций адреса, можно общаться с четырьмя разными чипами, "сидящими" на одной I2C, только надо правильно учитывать адрес (50,51,52,53).

19.01.2009

Ethernet Shield для Arduino (2)

На досуге немного покопался в схемотехническом решении этого Shield-а. На моем варианте Shield-а отсутствует разъем SD (не используется в Arduino):



W5100 подключен в режиме последовательного интерфейса (конечно же: экономим pin-ы).
  • MISO (27) - digital 12
  • MOSI (28) - digital 11
  • SS (29 или SCS) - digital 10
  • SCK (39 или SLCK) - digital 13, на нем же дублирующий светодиод L на Arduino
Если пользоваться разъемом SD, то получается, что:
  • CLK (5) - digital 9
  • DAT0 (7) - digital 3
  • DAT1 (8) - digital 4
  • DAT2 (9) - digital 5
  • DAT3 (1) - digital 6
  • CMD (2) - digital 8
  • WP - analog 0
  • DETECT - analog 1
Теперь по поводу "джамперов":


  • вверху - INT. это не джампер, а посадочное место для SMD резистора-нулевки. Он пропускает сигнал прерывания на digital 2;
  • внизу слева - PROG. это пустое место для 2-х пиновой гребенки. Судя по схеме, ее замыкание сажает ногу SEN (SErial Enable) на землю, запрещая таким образом обмен по последовательному интерфейсу для чипа W5100. Практического смысла в этом крайне мало, поскольку при этом должны использоваться шина данных и адреса (A0-A14, D0-D7), но они победно висят в воздухе.
  • внизу справа - WP - это еще одно место для нулевки. Сажает вывод "WRITE_PROTECT" (а вместе с ним и analog 0) на землю.
Сам по себе W5100 держит все-таки 4 сокета, прерывания Arduino не поддерживаются. Было бы интересно запаять разъем для SD, но его еще надо поискать. Беглый просмотр Инетрнета показал, что есть и отдельные решения на этот счет (автор делал для wireless-сенсора, который пишет туда данные про обнаруженный сигнал).

15.01.2009

Сборка Arduino Serial

В отличие от первой моей попытки, эта обещала быть простой и приятной (так оно в итоге и получилось).

Отправная точка - двусторонняя печатная плата Arduino Serial 2.0a, на которой нанесена маркировка компонентов:


Понадобится паяльник (желательно с конусообразным жалом, некоторые контактные площадки довольно маленькие), припой (например, ПОС-61), канифоль (я использую жидкую ЛТИ-120, для ее удаления потребуется немного спирта, зато качество пайки на порядок круче, чем с помощью обычной сосновой).

Собираем комплектацию в кучку (здесь и далее я буду ссылаться на этот список элементов).

Первым делом, установим резисторы R5, R6, R7, R8, R9, номинал 10 КОм:


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


Теперь ставим R1 (снизу, 4К7), R2 (выше, 220):


(аналогично, надо ними располагаются R3, R4 - по каждый).

Теперь установим диоды, соблюдая полярность - риска на корпусе диода соответствует риске на печатной плате:


Вверху стоят два 1N4148 - D2, D3:


А внизу - высоковольтный 1N4004 - D1 (у меня был 1N4007):


Паяем элементы тактового генератора - кварц Q1 на 16МГц плюс С2, С3 - емкости по 22пФ. Заодно можно установить и фильтр по питанию C1 - также пленочный конденсатор 100мкФ (на нем может быть написано "104"):


Постепенно начинаем поднимать высоту устанавливаемых элементов. Светодиод LED1 устанавливается длинной ножкой в дырочку "+". Транзисторы T1 и T2 (BC547C и BC557C соответственно) безошибочно устанавливаются по профилю корпуса (он нарисован). У 557-го, возможно, придется отогнуть ножки, чтобы они выстроились в линию:


Устанавливаем стабилизатор +5В IC2 7805 таким образом, чтобы первая ножка на корпусе TO-220 соответствовала дырке с точкой на плате. Электролиты C6, C7 - 100мкФ х 16В устанавливаются, так же как и светодиод, длинной ножкой в положительную дырку. Если в комплекте C8 (10 мкФ х 16В) неполярный - написано NP, то его "ориентация" не имеет значения. В противном случае, если он полярный, его тоже надо длинной ножкой в плюс.


Последний радиоэлемент на плате - пленочный конденсатор C5 - 100нФ:


Теперь можно аккуратно установить все разъемы.

Панелька для ATmega - X3 SCS28S (на фото цанговая панелька - она дороже, но дольше служит) - согласно ориентации на плате, гребенка ICSP (2x6, PBS06 - ориентация безразлична) и тактовая кнопка S1. У тактовой кнопки две группы замыкающих контактов, расположенные с двух сторон. Ее надо расположить так, чтобы стороны с лапками смотрели влево и вправо (в сторону кварца и гребенки ICSP):



Далее, устанавливаем разъем X1 - DB09:


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

Далее, устанавливаем разъем X2 - гнездо питания 2,1мм. Вот тут, возможно, надо заменить жало паяльника на "лопатку" и душевно залить олова в три посадочные дырочки.

Последними идут розетки PLD - POWER, J1, J2, J3. Старайтесь паять их аккуратно, чтобы получилось ровно.

Готово? Не совсем. Берем ATmega8P-16PU, слегка подгибаем ножки, чтобы он залез в пенельку:


Устанавливаем ATMEGA в панельку (опять-таки, следите за положением ключа - на микросхеме, панельке и плате оно должно совпадать).

Если ATMEGA еще не прошита, то берем Parallel Programmer, машину с LPT-портом и запускаем на ней Arduino IDE. Выбираем тип платы: "Tools | Board | Arduino NG or older w/ATmega8".

Подключаем питание к плате (можно даже через батарейку) - на Arduino должен загореться LED1, подключаем шлейф Parallel Programmer к пинам ICSP (следите за положением пина 1), наконец запускаем в Arduino IDE "Tools | Burn Bootloader | w/Parallel Programmer".

Теперь внимательно смотрим, что напишется в строке статуса - если IDE сообщает, что все благополучно звершено, то можно отключить Parallel Programmer и приступить к финальной проверке. Для этого потребуется любой светодиод (с видимым диапазоном излучения ;) - воткните его в два соседних гнезда на цифровой колодке - они обозначены как Pin13 и GND.


Подключите COM-порт компьютера к разъему X1 Arduino, выберите подключенный COM в ArduinoIDE: "Tools | Serial Port | ... ". Загрузите исходник тестового sketch-а из комплекта: "File | Sketchbook | Examples | Digital | Blink".

Откомпилируйте программу (Ctrl+R, круглая кнопка со стрелкой, "Sketch | Verify/Compile"), нажмите кнопку сброса S1 на плате Arduino, затем "залейте" sketch (Ctrl+U, квадратная кнопка со стрелкой вправо, "File | Upload to I/O board"). Операция завершится довольно быстро, о чем напишет IDE в строке статуса.

Подождите 15-20 секунд, светодиод должен начать мигать. Если нет, проверьте, хорошо ли вставлен светодиод, при необходимости переверните его ;)

На этом - все. Спаять и запустить можно за 1 вечер, как видите ничего сложного даже для начинающего.

13.01.2009

Ethernet Shield для Arduino

Итак, как я уже писал, ко мне приехала посылка из SmartProjects. Половина стоимости пришлась на Ethernet Shield:



... который я тут же начал испытывать со своим Arduino Diecimila:



Удобнее всего его подключать на работе к локалке, благо она под рукой в невероятных количествах ;)



Три коробочки вверху - это мегаизвращение, к которому я прибег при отсутствии под рукой блока питания 9В: берется источник DC 48В (от ~220В), втыкается в PoE-инжектор DLink DWL-P200, который вводит его в кабель Ethernet, затем в PoE-сплиттер, который, наоборот, отделяет питание, но попутно он умеет преобразовывать его при помощи DC-DC в 5 или 12 вольт, как раз под разъем питания для Arduino (2,1 мм, в центре - плюс).

Не пытайтесь повторить ;) лучше купите БП на 9В (от 12В стабилизатор на Arduino довольно сильно греется).

Что дальше?

Запускаем Arduino 0012, говорим "New", затем "Import Library | Ethernet". Появляются инклудники. Можно добавить пустые setup и loop и компильнуть: как видите, sketch занял около 8 Кбайт! (в память ATMEGA8 это уже точно не влезет).

Вернемся к Ethernet. Первым делом, можно попробовать пример Telnet, который есть в дистрибутиве Arduino.

#include <Ethernet.h>

// network configuration.  gateway and subnet are optional.
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 10, 0, 0, 177 };
byte gateway[] = { 10, 0, 0, 1 };
byte subnet[] = { 255, 255, 0, 0 };

// telnet defaults to port 23
Server server = Server(23);

void setup()
{
  // initialize the ethernet device
  Ethernet.begin(mac, ip, gateway, subnet);

  // start listening for clients
  server.begin();
}

void loop()
{
  Client client = server.available();
  if (client) {
    server.write(client.read());
  }
}

Суть примера - после подключения по порту telnet (команда telnet arduino_ip), любой вводимый символ возвращается обратно.

Для того, чтобы попугать коллег, я решил переделать этот пример в имитацию веб-сервера. Поскольку TCP-соединение устанавливается совершенно прозрачно, то меняем порт с 23 на 80, а в обработчике добавляем считывание запроса и вывод HTML-странички.

Поскольку мне было лень считать количество информации на выходе, я ограничился только строкой Content-Type, а Content-Length посылать не стал. Браузеры у коллег наивно пытались дождаться завершения принимаемой информации, но навсегда повисали в этом состоянии. Пришлось добавить несколько команд, чтобы разрушить соединение:

#include <Client.h>
#include <Ethernet.h>
#include <Print.h>
#include <Server.h>

byte mac[] = { 0x00, 0x1D, 0x60, 0xAF, 0x03, 0x30 };
byte ip[] = { 10, 57, 3, 1 };
byte gw[] = { 10, 57, 0, 1 };
byte subnet[] = { 255, 255, 0, 0 };

//Server server = Server(23);
Server server = Server(80);

void setup() {
  Ethernet.begin(mac, ip, gw, subnet);
  server.begin();
  Serial.begin(38400);
}

void loop() {
  Client client = server.available();
  if (client) {
    while (client.available()) {
      Serial.print(client.read(),BYTE);
    }
    client.println("HTTP/1.1 200 OK");
    client.println("Content-type: text/html");
    client.println("");
    client.println("&lt;html&gt;&lt;title&gt;Arduino Ethernet&lt;/title&gt;&lt;body&gt;&lt;h1&gt;Hello, I'm Arduino Ethernet Shield!&lt;/h1&gt;Version 0001 with disconnect!&lt;/body&gt;&lt;/html&gt;");
    client.flush();
    client.stop();
  }
}

На все эксперименты ушло около 15 минут, включая подключение и короткое обдумывание "чего бы такого наваять". Я писал эту статью в блог и делал картинки гораздо дольше ;)