Показаны сообщения с ярлыком Software. Показать все сообщения
Показаны сообщения с ярлыком Software. Показать все сообщения

30.03.2015

LiquidCrystalRus для 1.6.1

Недавно вышла очередная ArduinoIDE 1.6.1, одним из новшеств которой выступил новый gcc версии 3.4.5. И поскольку с каждой версией gcc синтаксис становится всё строже и строже - без неприятностей не обошлось.

В частности, перестала компилироваться библиотека поддержки вывода русского языка LiquidCrystalRus, из-за неверного (с точки зрения gcc) использования директивы PROGMEM, о чем ко мне посыпались сообщения от уважаемых пользователей (за что им хочу выразить особую благодарность).

Изменения там совсем крошечные, но если после установки новой ArduinoIDE ваш проект с LiquidCrystalRus в составе перестал компилироваться, не паникуйте, а скачайте и установите LiquidCrystalRus-1.6.0.zip.

Напоминаю, что проект также доступен на GitHub: https://github.com/mk90/LiquidCrystalRus.

UPDATE: подобно оригинальному LiquidCrystal, LiquidCrystalRus не умеет работать с дисплеями, подключенными как-то иначе, чем к пинам Arduino (например, по I2C), но зато и не требует для работы дополнительных библиотек: и в результате поддержка русского языка обходится дополнительно в 500 байт flash и 7 байт SRAM. 

30.12.2013

Freeduino wireless (2)

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

Довольно давно на рынке существует микросхема nRF24L01+, выпускаемая фирмой Nordic Semiconductors. Она обеспечивает возможность приема или передачи информации на несущей 2,4 ГГц (полоса ISM), методом частотной манипуляции GFSK. Для Arduino это решение удобно не только в силу низкой стоимости чипа, но и по причине подключения через SPI.

Для экспериментов нам понадобится какой-либо беспроводной модуль на основе nRF24L01+, например такой:



Его можно купить практически где угодно, стоить больше 160 рублей он не должен. Следует заметить, что 90% таких модулей ничем друг от друга не отличаются - схема скопирована из реф-дизайна evolution-кита к nRF24L01+, опубликованному производителем. Антенна расположена прямо на печатной плате, что при такой длине волны вполне допустимо и обещает максимальное расстояние до 100 метров (разумеется, с оговоркой про "идеальные условия", в реальности оно будет меньше - сколько именно, придется проверять экспериментально). К слову, существует две версии чипа - nRF24L01 и nRF24L01+, отличающиеся совсем ненамного и совместимые друг с другом (просто имейте ввиду, что если ваш модуль с nRF24L01 - к нему эта статья применима в полном объеме).

Назначение контактов на вилке должно быть следующим (вид сверху):



У модулей с вилкой 2x4 есть одно существенное неудобство - невозможно воткнуть в беспаечную макетку: расположенные в два ряда контакты, увы, будут закорочены попарно. Остается только позавидовать счастливым обладателям модуля от SparkFun, не поскупившимся отдать за это чудо 19.95 USD:

Посмотрим, какие выводы и куда подключать:
  • GND - земля, соединяем с одним из пинов GND на Arduino;
  • VCC - питание модуля,  внимательно - соединяем с пином 3.3В - модуль питается от напряжений 1,9..3,6В, хотя при этом отлично умеет работать с логическими уровнями +5В;
  • CE - расшифровывается как Chip Enable, но речь не про работу всего чипа, а лишь про его радиоинтерфейс - в режиме приема заставляет модуль "прослушивать" эфир в поисках предназначенного ему пакета, в режиме передачи кратковременный импульс CE передает в эфир содержимое буфера FIFO.  Подключим его к пину D8;
  • CSN - SPI: Chip select not, выбор Slave-устройства на шине SPI низким уровнем, подключаем к пину D7;
  • SCK - SPI: Clock, подключаем к пину D13;
  • MOSI - SPI: Master Out, Slave In - подключаем к пину D11;
  • MISO - SPI: Master In, Slave Out - подключаем к пину D12;
  • IRQ - прерывание, пока никуда не подключаем :(
Пины с аппаратной поддержкой SPI (SCK, MOSI, MISO) гарантированно можно найти на шестиконтактной ISP-вилке Arduino:


Если же будете подключаться к боковым гребенкам, учитывайте, что аппаратная поддержка SPI у Mega находится на пинах 50 (MISO), 51 (MOSI), 52 (SCK) и 53 (SS).

Переходник для установки в беспаечную макетку можно соорудить из разъемов PBD08 и PLS8, на кусочке обрезка обычной макетной платы (под пайку):



Итак, паяльник можно откладывать в сторону. Однако прежде чем приступать к написанию скетчей, познакомимся с документацией на чип и поподробней разберемся в том, что он умеет (и что не умеет - разумеется, тоже).

nRF24L01+ способен работать приемником или передатчиком на частотах 2400..2525 МГц, конкретная частота определяется номером частотного канала от 1 до 126, задаваемым через регистр RF_CH. Чтобы приемник и передатчик смогли обмениваться между собой, они обязательно должны быть сконфигурированы для одного и того же канала. Скорость обмена по умолчанию - 2 Мбит/с, но при необходимости ее можно снизить до 1 Мбит/с - в основном это делается для совместимости с ранними версиями чипов Nordec (вот одно из отличий nRF24L01 от nRF24L01+: последний умеет работать еще и на пониженной скорости 250 Кбит/с).

Данные передаются пакетами. Пользовательская часть (в документации называется "Payload") может занимать до 32 байт, остальные поля - служебные:


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

В какой-то конкретный момент времени чип может быть либо передатчиком, либо приемником - либо передавать, либо принимать: по-очереди, но не одновременно. Для контроля можно организовать смену режимов - одной стороне даете команду передать сообщение и перейти в режим приема, другой - принять сообщение, проверить его корректность с помощью поля CRC, затем перейти в режим передачи и "отстучать" передавшему подтверждение.

Но, к счастью, существует специальный встроенный протокол Enhanced Shockburst (tm), который берет на себя все заботы о гарантированной доставке сообщения между двумя nRF24L01+. Это включает в себя не только прием, проверку правильности и отсылку подтверждающего пакета приемником, но и повторную перепосылку пакета передатчиком. Не правда ли, инженеры Nordic Semiconductors поработали на славу? ;) Для работы протокол использует поле управления пакетом.

В довершение существует специальный режим Multiceiver, в котором приемник может быть настроен на получение данных от шести передатчиков, и опять же, с возможностью работы по Enhanced Shockburst. Иными словами - один приемник может "тянуть" данные из шести передатчиков с аппаратным подтверждением и перепосылкой. Правда, есть некоторые ограничения - все устройства надо сконфигурировать на работу в одном частотном канале, с одинаковой скоростью,  длиной адреса и способом формирования CRC. Один адрес передатчика можно выбрать произвольно, а вот остальные пять должны совпадать во всех байтах адреса, кроме последнего (например, 0x1234567801, 0x12345678D5, 0x12345678AA, 0x1234567855, и так далее).

Адрес задает пользователь, и, строго говоря, он может быть произвольным. Но располагается он в самом начале пакета, сразу после преамбулы, которая выглядит в двоичном представлении как 01010101 или 10101010 - такая комбинация не случайна и нужна для правильного пробуждения приемника и его подстройки к частоте передатчика. Чтобы было меньше ложных "отбраковываний" пакетов приемной частью, надо стараться избегать как адресов, похожих на преамбулу (например - 0xAAAAAA или 0x555555), так и адресов, состоящих из вообще одних нулей и единиц (еще два плохих примера - 0xFFFFFF или 0x000000).

Пример схемы (допустим, Freeduino Nano):



Какие библиотеки  для Arduino существуют для работы с nRF24L01+?


Самый простой вариант - библиотека Mirf, которая предоставляет минимальную обвязку (её даже адаптировали для ATtiny). Скачайте последнюю версию библиотеки:
  • на странице Arduino playground, посвященной nRF24L01+;
  • непосредственно из gitHub.
Перед началом работы надо задать пины, к которым подключены CE и CSN, собственный адрес как приемника, длину пользовательской части (payload) и вызывать пару функций. По умолчанию предполагается, что CE подключен к D8, CSN - к D7 (ровно так мы уже и сделали), работа будет идти по каналу 1, длина пакета - 16 байт. Если что-то из перечисленного не совпадает с вашими потребностями, необходимо установить соответствующие значения полей до вызова init() и config(), например: Mirf.cePIN = 10;  в случае, если CE подключен к D10.

В основном, последовательность инициализации выглядит так:
  1. Mirf.spi = &MirfHardwareSpi;
  2. Mirf.init();
  3. Mirf.setRADDR((byte *)"12345");
  4. Mirf.payload = 4;
  5. Mirf.config();

Первая строчка - установление "правильного" алгоритма работы с SPI, носит скорее исторический характер. Сейчас всё равно вся работа осуществляется через встроенную в ArduinoIDE библиотку SPI, но ведь не всегда было так ;) Второй строчкой происходит инициализация пинов и SPI, в третьей мы устанавливаем собственный адрес приемника, длиной 5 байт (символьная строка "12345" дана исключительно для наглядности, на самом деле это 0x3132333435 ;) В четвертой - мы устанавливаем длину пакета 4 байта, и, наконец-то, в пятой конфигурируем чип NRF24L01 и переводим его в режим приема.

Дальше можно принимать и передавать данные.

Прием:

 if(Mirf.dataReady()){
  Mirf.getData((byte *) &packet); 
}
Сначала дожидаемся прихода пакета в буфер, затем считываем его в переменную packet (ее размер должен соответствовать текущей длине payload).

Передача:

Mirf.setTADDR((byte *)"12345");
Mirf.send((byte *)&packet);
while(Mirf.isSending()){
}

Устанавливаем адрес получателя, затем отсылаем packet и при помощи isSending дожидаемся завершения отправки.

К библиотеке прилагаются примеры ping_client и ping_server, которые обмениваются пакетами друг с другом. Чуть интереснее изучить пример  ping_server_interrupt, демонстрирующий работу по прерыванию в режиме энергосбережения: пока нет данных, Arduino пребывает в режиме сна. Однако, как только фиксируется прием нового пакета, он просыпается, принимает пакет из nRF24L01+, отсылает ответный пакет и снова "засыпает". Для корректной работы потребуется подключить ранее неиспользованный пин IRQ на плате радиомодуля - к пину D2 Arduino.

В каких случаях генерируется прерывание от nRF24L01+?


Это происходит в трех ситуациях и отображается в регистре STATUS при помощи соответствующих битовых полей:
  1. TX_DS - передающая сторона получила от встречной стороны информацию (ACK-пакет), подтверждающую успешный прием;
  2. RX_DR - приемная сторона получила новый пакет данных (и с правильным CRC, и не дубль уже полученного ранее пакета);
  3. MAX_RT - передающая сторона попыталась передать пакет максимально разрешенное количество раз, но так и не получила подтверждения о приеме.  
И, самое важное - после того, как любой из перечисленных битов был установлен, для дальнейшей работы его необходимо сбросить - записать единицу. Обычно, об этом заботится библиотека ;)

Функция Mirf.isSending() как раз и проверяет факт завершения передачи по установке TX_DS или MAX_RT. Но имейте ввиду, что она не отвечает на вопрос о том, был ли пакет благополучно принят на противоположной стороне. После того, как Mirf.isSending() вернет true, чтение регистра STATUS становится бессмысленным - перед выходом функция сбрасывает биты TX_DS и MAX_RT. К счастью, при каждом возникновении MAX_RT увеличивается счетчик PLOS_CNT в специальном регистре OBSERVE_TX, поэтому проверку благополучной доставки можно организовать так:

int readPLOS_CNT() {
  byte reg;
  Mirf.readRegister(OBSERVE_TX,&reg,1);
  return (reg >> PLOS_CNT) & B1111;
}

void loop() {
  
  int prev_plos_cnt = readPLOS_CNT();

  /* ... */
  Mirf.send((byte *)&packet);
  while(Mirf.isSending()){
  }

  if (readPLOS_CNT() != prev_plos_cnt) {
   /* failed :( */else {
   /* success! */
  }
}

Еще можно вообще отказаться от использования Mirf.isSending(), и проверять биты TX_DS и MSX_RT непосредственно чтением регистра STATUS. Но тогда не забывайте сбрасывать их после установки, иначе процесс передачи встанет после первого же пакета.

Как я уже упоминал в самом начале - библиотека реализует действительно минимально необходимый набор функционала. За это приходится расплатиться следующим:
  • длина адресного поля - всегда 5 байт;
  • CRC всегда однобайтовый;
  • длина payload всегда фиксирована;
  • нет поддержки режима multiceiver (прием данных от шести передатчиков).
Что-то решается простейшим исправлением кода библиотеки, что-то можно сделать через запись и чтение управляющих регистров nRF24L01+, что-то (multiceiver или динамическая длина payload) добавить уже и вовсе непросто.

Однако, если у вас возникает слишком много претензий к функционалу Mirf, можно попробовать альтернативу - RF24. В ней конфигурируется буквально всё, в том числе автоматически учитываются различия между nRF24L01 и nRF24L01+. Идеологически библиотека ближе к стандартам Arduino и интуитивно понятнее, особенно начинающим. Например, по аналогии с Mirf есть функция RF24::startWrite, а в дополнение к ней - RF24::send, которая блокирует ход скетча до завершения процесса передачи, чтобы стало понятно - передан пакет успешно или нет, что и сообщается в возвращаемом значении типа bool (прямая замена вышеприведенному коду, который пришлось добавлять для аналогичного контроля в Mirf). 

В комплекте с библиотекой RF24 много полезных примеров, которые демонстрируют использование irq, отправку пользовательских данных в ACK-пакете и прочее. Есть даже примитивный сканер эфира ;)

Куда двигаться дальше? 


Например, по каким-то причинам не устраивает дальность приема: то ли расстояние велико, то ли стен многовато. В этом случае надо брать модуль nRF24L01+ с PA/LNA (Power Amplifier и Low Noise Amplifier):


Этот модуль будет стоить чуть дороже, около 10 USD. В его основе nRF24L01+ с точно такой же вилкой, но у него непосредственно к выходным каскадам вместо антенны подключен усилитель, повышающий мощность передатчика и чувствительность приемника. К SMA-коннектору необходимо подключить стандартную антенну для диапазона 2,4 ГГц (можно скрутить с нерабочего WiFi роутера) и правильно сориентировать - получите диапазон до 1000 метров. Правда, сразу вырастут запросы по питанию: модулю потребуются не десятки, а сотни mA, напряжение питания должно быть в диапазоне 3,0..3,6В. В этом случае может уже не получиться питать его от Arduino - если не помогает конденсатор 10 мкФ между 3,3В и землей, просто подключите модуль к отдельному источнику питания.

Да, и еще одно: не исключено пересечение по частотным каналам с другими беспроводными устройствами. Если у вас есть беспроводная клавиатура или мышь на 2,4 ГГц, с очень большой долей вероятности есть шанс разобрав ее увидеть нашего старого знакомого ;) 

Ссылки по теме:



07.06.2013

TV-out для Arduino

Если вы когда-нибудь почувствуете, что вашему Arduino-проекту стало тесно на алфавитно-цифровом дисплее 1602, обязательно обратите внимание на проект TellyMate Shield. Он позволяет выводить ту же алфавитно-цифровую информацию на обычный телевизор, через видео-вход.

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


Обычный ATmega8 на тактовой частоте 16 МГц формирует два компонента видеосигнала, которые смешиваются нехитрой схемой из двух резисторов и двух диодов. Группой переключателей S1 устанавливаются режимы работы; согласующий резистор 75 Ом подключается через перемычку и добавлен, скорее, для универсальности (думаю, в большинстве случаев не понадобится).



Arduino выводит информацию для отображения через последовательный порт - пины RX/TX. Если вас смущает, что по ним же происходит загузка скетча и во время этого процесса на экране появляется некая "ерунда", можно уйти на любой пин с помощью библиотеки SoftwareSerial. Поддерживаются разные скорости, а также есть возможность автоопределения. Простейший скетч выглядит так:


        Serial.begin(57600); //57k6 baud
        Serial.println("Hello, world!");


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


Вы, наверное, заметили, что для вывода видео использован аудио-разъем 3,5мм. На самом деле, это не казус, а вполне осознанный выбор, ограничивающий высоту элементов и делающий возможным стекирование шилдов:


Кроме вывода обычных символов, поддерживаются так называемые ESCAPE-последовательности, которые управляют курсором, удваивавают высоту и/или ширину символов и даже переключают банки шрифтов и переопределяют символы (что, впрочем, возможно только на ATmega328P, где памяти гораздо больше, чем у ATmega8). Таким же образом можно получить версию прошивки и прочую диагностическую информацию.

Чем-то все это напоминает LoL-Shield, особенно приложениями - взгляните на список доступных .ino. Здесь найдется не только классика Life и Snake, но и более изощренные - Maze и даже простейший "графический редактор"!

Поскольку все материалы доступны и открыты для доработки, мы решили немного поэкспериментировать и создать на базе этого шилда русифицированный вариант. Имя "TellyMate", подобно Arduino, является торговой маркой - поэтому пришлось назвать наш вариант Freeduino Teleсhat:


Все детали - PTH, поскольку шилд задумывался изначально в формате кита для самостоятельной сборки - и что может быть лучше, чем собрать всё самостоятельно? ;) Пины RX/TX имеют перемычки под пайку с обратной стороны платы, так что при желании их можно перерезать и подпаять к любым другим пинам. Аналогичным способом  отключается и кнопка сброса - если не хотите, чтобы МК шилда сбрасывался синхронно со  скетчем Arduino.

Краткое руководство по сборке шилда:


Шутка, конечно ;) просто там действительно все элементарно. На howtomakekit.blogspot.ru, как всегда, выложена подробная пошаговая инструкция.

Русифицированный шрифт мы разместили точно таким же способом, что и автор - в виде ссылки на документ в GDocs, копию которого при необходимости можно сохранить у себя. В открытом документе надо зайти на последнюю закладку, генерирующую hex, и скопировать ее содержимое в файл  fontbank0.c, подменив его в исходниках (можно скачать со страницы проекта). После компиляции получите прошивку c поддержкой кодовой страницы 866. Именно она и зашивается в ATmega8, входящие в комплект наборов Freeduino TeleChat. 

Для вывода русского текста потребуется еще кое-что сделать. Как известно, ArduinoIDE хранит все символы в кодировке UTF-8, и для нормальной работы потребуется их транслировать в кодировку 866. Делать это в оригинальной прошивке нам показалось святотатством - авторы очень скрупулезно рассчитали все задержки в коде. Предлагаем самый простой вариант перекодирующей функции:

byte c1 = 0;

void tele_print_char(char cd) {
  byte c = cd;
  if (  c >= 0x80) { // UTF-8 handling
    if (!c1) {
      c1 = c;
    } else {
      if (c1 == 0xd0) { 
       if (c == 0x81) Serial.print(char(0xf0)); // Ё
        else Serial.print( (char) (c - 0x10));
      }
      if (c1 == 0xd1) {
       if (c == 0x91) Serial.print(char(0xf1)); // ё
        else Serial.print( (char) (c + 0x60));
      }
      c1 = 0;
    }
  } else Serial.print(cd);
} 

void tele_print_str(char *s) {
  for(int i=0;i<strlen(s);i++) tele_print_char(s[i]);
}

void setup()
{
  char letter[]="АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ";
  Serial.begin( 57600 ) ;
  Serial.println( "Hello World!" ) ;
  tele_print_str( "Привет, мир!\n\r" ) ;
  tele_print_str( letter );
}

void loop()
{
    // do nothing!
}


Купить шилд в собранном виде или в виде комплекта деталей можно здесь.

Для тех, кто любит почитать оффлайн - про TellyMate упоминается в книге У. Соммера "Программирование микроконтроллерных плат Arduino/Freeduino".

07.05.2013

Web-термометр

"Погодная станция своими руками" - вот как можно было бы назвать статью, но я решил пока просто рассказать о том, как соорудить web-термометр, подключить его к домашней LAN  и наблюдать показания через браузер ;)

Для этого нам потребуется Arduino-совместимая плата, поддержка Ethernet и несколько температурных датчиков.


17.04.2013

ArduinoIDE 1.0.4

Новая ArduinoIDE 1.0.4 вышла 11.03.2013, и почти весь ее смысл - исправление ошибок.

Лично мне видится три главных момента:

  • Добавлена новая библиотека GSM, для работы с Arduino GSM Shield. С ее помощью можно не только передавать данные с использованием конструкции Client/Server по аналогии с Ethernet, но и отправлять/получать SMS-сообщения, а также голосовые вызовы;
  • Все драйверы собраны в один пакет, с цифровой подписью для Windows 8. По идее, это упрощает процесс установки, избавляя вас от лишних вопросов и подозрений со стороны операционной системы;
  • Официально исправлены накопившиеся (видимо, за все время) ошибки в бутлоадере Mega2560. Ошибки это были знаменитые, ко многим давно существовали патчи - взять, например, ошибку с незагрузкой скетча, в котором встречается комбинация "!!!". Разумеется, аналогичные изменения войдут и в бутлоадер, прошитый во Freeduino Mega2560.
Впереди - слияние ветки 1.5.x и 1.0.x, но когда именно оно произойдет, пока сказать трудно...

01.02.2013

Ethernet Shield своими руками

Классический Ethernet Shield от Arduino на микросхеме Wiznet W5100 появился одним из первых, перенес уже как минимум три существенных ревизии, а также интегрирован в плату Arduino Ethernet.



Тем не менее, использование W5100 - вовсе не единственный способ добавить немного LAN в ваше устройство на основе Arduino. Давным-давно фирма Microchip выпустила Ethernet-контроллер ENC28J60, который изготавливается не только в SMD-исполнении, но и в DIP-корпусе, что сделало его незаменимым для DIY-любителей. От себя замечу, что это единственный Ethernet-контроллер в DIP-е, который вообще попадал мне в руки.



Если сравнивать W5100 и ENC28J60, сразу же выяснится, что их основная общая черта - способность работать по шине SPI и тем самым экономить пины микроконтроллера для других задач. Но по техническим характеристикам ENC28J60 уступает - он не может пощеголять ни аппаратной поддержкой TCP, ни скоростью 100 Мбит.

Но, быть может, вашему проекту оно и не надо?

Когда говорят о скорости 100 Мбит/с, подразумевают скорость работы физического интерфейса (а не скорость поступления полезных данных, которая всегда меньше). К сожалению, Arduino UNO/Mega работает на тактовой частоте 16 МГц и способен выполнять только 16 000 000 операций в секунду (одна инструкция за такт - на то он и RISC ;). Вероятно, он не справится со сложным потоком медиаданных, зато на обмен небольшими порциями управляющей информации - вполне способен. Скорее всего, вы не почувствуете разницу между 10 и 100 Мбит/с, если будете считывать состояние датчиков или давать управляющие команды. Сетевые интерфейсы, способные работать на 100 Мбит/с, как правило, поддерживают и 10 Мбит/с - если только эта скорость не будет запрещена в конфигурации сетевого устройства принудительно каким-то злым маньяком системным администратором.

Что касается аппаратной поддержки TCP, который обеспечивает гарантированную доставку данных для многих протоколов, включая http, то здесь тоже все относительно просто: микросхема W5100 работает с четырьмя соединениями одновременно, обрабатывая перезапросы; в микросхеме ENC28J60 такой возможности нет (хотя она и поддерживает подсчет контрольной суммы, а также имеет буфер на 8 килобайт). То, что не делается аппаратно - приходится реализовывать программно, хоть и нагружая МК Arduino. Для программиста прикладного уровня (читаем - для рядового Arduino-пользователя типа нас с вами) это решается использованием соответствующей библиотеки, с оглядкой на свободную память микроконтроллера. Опытным путем я установил, что разница по объему скетчей хоть и есть, но не такая драматически большая, как мне показалось с первого взгляда.

Что нужно для того, чтобы состыковать ENC28J60 с Arduino? Да практически тоже самое, что и W5100:
  • схема тактирования (кварц 25 МГц + емкости);
  • питание +3,3В;
  • шина SPI c согласованием уровней логических сигналов  (+5В у Arduino и +3,3В у контроллера Ethernet);
  • развязка с линией (трансформатор, разрядник и резисторы - желательно 1%-ые);
  • внешний "точный" (1%-ый) резистор для работы опорного источника напряжения.
Собственно, все эти компоненты вполне реально существуют в выводном исполнении - так почему бы не воспользоваться? Схемы можно найти в изобилие в интернете, например - вот вариант из Instructables.



Автономные модули и шилд-платы с ENC28J60 в SMD-исполнении давно доступны на EBay и у  прочих интернет-магазинов (в особенности, конечно же, в китайских) - но это всего лишь железо, реализация одной и той же, по сути, схемы. Программная часть наиболее грамотно разрабатывается JeeLabs, можно даже найти инструкции по миграции с EthernetShield на EtherCard (так называется их вариант кита для самостоятельной сборки). Идея же представить набор для самостоятельной сборки по праву принадлежит Open Electronics, а библиотеку можно скачать на GitHub.



Основываясь на этой разработке, свет увидела Freeduino EtherCard R1:




Схема оставлена практически без изменений. Вот несколько моментов, которые их отличают:
  1. Шилд подключается по SPI, но через проходную вилку - таким образом, к нему можно подключить еще один SPI-шилд, например MicroSD shield;
  2. Все резисторы, которые требуют повышенной точности, взяты действительно 1%-ые;
  3. Шилд стыкуется с платой максимально компактно - обратите внимание, что в отличие от оригинала, он полностью "сел" на плату (обратите внимание на разъем USB и край печатной платы шилда, чтобы понять, о чем я говорю);
  4. Бочкообразные электролиты несоразмерной емкости 470 мкФ заменены на низкопрофильные.
Купить шилд в собранном виде или в виде kit-а можно здесь, пошаговая инструкция по сборке доступна здесь.

При использовании библиотеки, не забывайте в инициализации ether.begin дописывать третий параметр - номер пина, к которому подключено разрешение работы. Библиотека по умолчанию предполагает D8, но в этом шилде - D10

Возьмите прилагающийся к библиотеке пример testDHCP и найдите строчки:

  if (ether.begin(sizeof Ethernet::buffer, mymac) == 0) 
    Serial.println( "Failed to access Ethernet controller");

Впишите номер пина в конце следующим образом:

  if (ether.begin(sizeof Ethernet::buffer, mymac, 10) == 0) 
    Serial.println( "Failed to access Ethernet controller");

И все тут же заработает (при наличии подключенной сетки с DHCP-сервером, конечно же ;)

15.12.2012

Температура и Влажность

Из серии статей про измерения температуры незаслуженно выпал сенсор DHT11, представляющий собой недорогой цифровой датчик температуры и влажности в одном корпусе:



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

Насколько важна влажность в помещении? Считается, что оптимум лежит около 50% - именно при такой влажности растения, люди и животные будут чувствовать себя комфортно. В частности - люди меньше болеют вирусными заболеваниями, а растения не рискуют превратиться в экибану.

Вот так устроен этот датчик внутри (а ведь он заменяет собой целый психрометр):


С одной стороны микроплатки - аналоговый сенсор, с другой - микросхема, оцифровывающая измерения и реализующая интерфейс с MCU. 

Протокол обмена - однопроводный, по структуре сильно похож на DS18B20, но с важными оговорками:
  • DHT11 не умеет работать в "паразитном" режиме (питание по линии данных);
  • каждый DS18B20 имеет персональный идентификатор, что дает возможность подключения нескольких таких датчиков к одному пину Arduino - у DHT11 такой возможности нет - один датчик будет использовать строго один цифровой пин.
DHT11 медленнее конвертирует измеренные значения - считывать их можно не чаще, чем раз в секунду. Погрешность у него тоже больше:

ПоказательDS18B20DHT11
Допустимый диапазон t,°C-55..+1250..+50
Погрешность измерения t, min±0.5°C@-10..+85°C±2°C@0..+50°C
Погрешность измерения t, max±2°C±2°C
Разрешение шкалы t,°C0.5/0.25/0.125,/0.06251
Допустимый диапазон RH, %-20..95
Погрешность измерения RH, min-±4% +25°C
Погрешность измерения RH, max-±5%
Разрешение шкалы RH, %-1

(для тех, кто склонен путать разрешающую способность и точность: хотя DS18B20 можно настроить таким образом, чтобы он отдавал 12-битные значения с разрешением 0,0625 градуса, его точность не станет лучше 0.5С. Но можно сделать "более живой" дисплей с отображением двух знаков после запятой ;)

Из характеристик видно невооруженным глазом, что DHT11 практически идеально подходит для жилых помещений и комнатных температур. Если датчик попадает в условия, выходящие за допустимые пределы, он начинает врать (попутно ускорится процесс старения аналогового сенсора), после чего требуется несложный процесс восстановления. Более подробно про это можно прочесть в описании: DHT11.pdf.

Как подключить DHT11 к Arduino? Начнем с расположения его пинов:


(третий пин не надо никуда подключать)

Рекомендуемая схема подключения содержит обязательный для однопроводных линий резистор-подтяжку к VCC и, в качестве опции, рекомендуется конденсатор (фильтр по питанию между VCC и GND):


На макетке это выглядит так (сенсор подключен к цифровому пину D8 платы Freeduino Nano):



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


Разберемся, как происходит обмен DHT11 с Arduino. Логически, это представляется такой последовательностью:
  1. Arduino запускает считывание показаний, переводя свой пин в режим выхода - как минимум на 18 миллисекунд переводит его в LOW, затем на 40 мкс в HIGH - и, после этого, переключает его в режим входа;
  2. Через 20..40 мкс DHT11 отвечает подтверждением, также сначала переводя шину в LOW на 80 мкс, а затем в HIGH на 80 мкс;
  3. DHT11 начинает побитную передачу информации, каждый бит начинается с уровня LOW в течение 50 мкс, и затем HIGH разной продолжительности: если 26-28 мкс, то это ноль, если же 70 мкс - единица;
  4. По окончании передачи 40 бит информации DHT11 "на прощание" еще раз переводит шину в LOW на 50 мкс и освобождает ее.
Полученная от DHT11 пачка из 40 бит представляется в виде последовательности из 5 байт следующего содержания:
  1. Целая часть значения влажности;
  2. Дробная часть значения влажности;
  3. Целая часть значения температуры;
  4. Дробная часть значения температуры;
  5. Контрольная сумма.
Как всегда, можно воспользоваться готовой библиотекой, которая считывает показания и вычисляет контрольную сумму для проверки. Что характерно, байты с дробной частью приходят всегда нулевые - пусть вас это не смущает, так и задумано ;)

Примеры использования DHT11 с Arduino: во-первых, данные можно выводить в последовательный порт и наблюдать на Serial Monitor:

#include <dht11.h>

dht11 sensor;

#define DHT11PIN 8

void setup()
{
  Serial.begin(115200);
  Serial.println("DHT11 TEST PROGRAM ");
  Serial.print("LIBRARY VERSION: ");
  Serial.println(DHT11LIB_VERSION);
  Serial.println();
}

void loop()
{
  Serial.println("\n");

  int chk = sensor.read(DHT11PIN);

  Serial.print("Read sensor: ");
  switch (chk)
  {
    case DHTLIB_OK: 
         Serial.println("OK"); 
         break;
    case DHTLIB_ERROR_CHECKSUM: 
         Serial.println("Checksum error"); 
         break;
    case DHTLIB_ERROR_TIMEOUT: 
         Serial.println("Time out error"); 
         break;
    default: 
         Serial.println("Unknown error"); 
         break;
  }

  Serial.print("Humidity (%): ");
  Serial.println(sensor.humidity);

  Serial.print("Temperature (oC): ");
  Serial.println(sensor.temperature);
  
  delay(2000);
}



Во-вторых, немного усложнив схему, можно выводить данные на LCD-дисплей:





#include <LiquidCrystalRus.h>
#include <dht11.h>

LiquidCrystalRus lcd(12, 11, 5, 4, 3, 2);
dht11 sensor;

#define DHT11PIN 8

void setup() {
  lcd.begin(16, 2);
  lcd.clear();
}

void loop() {
  switch (sensor.read(DHT11PIN)) {
    case DHTLIB_OK: 
                break;
    case DHTLIB_ERROR_CHECKSUM: 
                lcd.print("Checksum error");
                delay(2000);
                return;
    case DHTLIB_ERROR_TIMEOUT: 
                lcd.print("Time out error"); 
                delay(2000);
                return;
    default: 
                lcd.print("Unknown error"); 
                delay(2000);
                return;
  }
  lcd.setCursor(0, 0);
  lcd.print("Влажность,%:");
  lcd.print(sensor.humidity);
  lcd.setCursor(0, 1);
  lcd.print("Температура,C:");
  lcd.print(sensor.temperature);
  delay(2000);
  
}


Куда двигаться дальше? 

Если стремиться к увеличению точности, можно найти достаточное количество датчиков, наиболее близкие по исполнению - DHT21/22. Они же, соответственно, и более дороги.

Купить DHT11 можно, например, здесь.

Ссылки по теме:

01.12.2012

ArduinoIDE 1.0.2

В конце октября - начале ноября произошло сразу несколько событий: была официально выпущена в продажу и почти сразу же распродана Arduino Due, вышла ArduinoIDE 1.5 специально для поддержки этой самой Due, затем вышла ArduinoIDE 1.0.2 - не поддерживающая Due, но содержащая много полезных фиксов для платы Leonardo.

26.06.2012

Leonardo официальный

Вместе с выходом ArduinoIDE 1.0.1 нас посетила и "новая" плата Leonardo, выпуск которой был настолько основательно задержан, что она уже успела обзавестись массой клонов:



В официальном магазине Arduino ее можно приобрести за 18 EUR со всеми разъемами  или же, немного сэкономив, за 16 EUR, но уже без них:

Изучая схему, можно найти испытанный не одним поколением плат Arduino узел автоматического выбора питания на основе LM358 и полевого транзистора. Цепь питания +3.3В выполнена на отдельном регуляторе LP2985A-33, как и во всех платах, в которых нет USB-TTL моста FTDI232RL.

Есть и некоторые нововведения - впервые в этой серии видим разъем microUSB. Колодки выводов расположены согласно последнему стандарту arduino pinoout 1.0 - с фиксированной позицией SCL, SDA и IOREF. Скопированы и спорные с моей точки зрения "усовершенствования" в виде резистора 1М между ножками кварца, диода в цепи сброса и включенного в параллель внешнему источнику питания диода, лихо закорачивающего источник с неверной полярностью.

Таким образом, никаких сюрпризов в схеме нет - всё самое интересное происходит в программной части (напоминаю, что до момента выхода ArduinoIDE 1.0.1 код ATmega32u4 был практически неработоспособен из коробки - например, чтобы работать с Freeduino 32u4 надо было установить пропатченное ядро).

Бутлоадер

Изменен полностью - ранее он основывался на коде Peter Barrett-а и назывался DiskLoader, теперь же мы имеем модифицированный вариант CDC-бутлоадера из LUFA, под кодовым названием Caterina. Единственное предположение по поводу цели такого перехода - новый код лучше поддерживается - других внятных объяснений я пока не подыскал, особенно в свете удвоившегося размера bootloader-а. Звучит особенно грустно, если вспомнить, что поддержка USB неявно подключается к каждому компилируемому под Leonardo скетчу, для поддержания возможности программного сброса через USB. И вот уже blink занимает 4850 байт (против 1084 при компиляции под UNO!). Невольно вспоминается teensy с его закрытым от общественного взора кодом, но зато и с впечатляющим 512-байтным размером...

Как и раньше, процедура заливки скетча начинается со сброса, и сигналом к этому служит закрытие виртуального COM-порта Leonardo, до этого открытого на скорости 1200. Изменился, впрочем, сам подход к запуску бутлоадера - если раньше управление ему передавалось немедленно, то теперь это происходит через 120 мс, путем установки watchdog-а. Полагаю, авторы стремились дать корректно завершиться собственно процедуре закрытия порта, чтобы она не провоцировала ситуацию с таймаутом на хосте.

Таймаут ожидания заливки скетча в бутлоадере увеличили до 8 секунд! Практика показала, что это действительно правильно: время от времени получаю письма от пользователей Freeduino 32u4, что их плата перестала принимать скетчи по USB. Добиться этого нетрудно - достаточно залить в плату скетч, который ее полностью завешивает, и ArduinoIDE сбросить ее программно уже не сможет. Но когда пользователь нажимает кнопку сброса на плате, и лишь затем - Ctr+U в ArduinoIDE, процесс компиляции и ликновки не успевает уложиться в заданные 6 секунд, и плата вновь зависает. Я всегда рекомендую изменить последовательность - сначала нажимать Ctrl+U и только потом - сброс на плате (ну, или нажать и удерживать сброс, а потом отпустить его - надо просто прицелиться поточнее, и это всегда помогает :) 

Если раньше и бутлоадер, и ядро имели один и тот же PID комбинированного USB-устройства, новый бутлоадер представляется только CDC-устройством, зато имеющим свой собственный PID. Таким образом, Windows попросит установить драйвера дважды - сначала для бутлоадера, затем для скетча.

Ну и последнее изменение - протокол общения с бутлоадером сменился с  'arduino' на 'avr109'. В этом тоже не стоит искать скрытого смысла, поскольку именно avr109 поддерживает CDC-бутлоадер из LUFA.

Ядро

Arduino Leonardo по-прежнему уверенно изображает из себя комбинированное USB-устройство (CDC-модем, мышь и клавиатура - три в одном). 

С точки зрения API все осталось прежним - использовать это многообразие функциональности вы можете  через соответствующие классы Serial, Mouse, Keyboard. Причем интерфейс общения с клавиатурой обогатился функциями-членами press() и release(), которые великолепно понимают "непечатные" символы, и поэтому редактировать исходники ядра, чтобы сделать sendReport публичным (как это, например, потребовалось здесь) отныне не нужно.

Наконец-то пофикшена инициализация таймеров - аппаратный ШИМ одинаково корректно работает на всех выходах.

К сожалению, в ядре по-прежнему есть и недоделки:
  • попытка использовать встроенную функцию tone, скорее всего, вызовет повисание скетча, запущенного на ATmega32u4;
  • не работают назначаемые пользователем прерывания - через attachInterrupt, это Issue714. Справедливости ради стоит заметить, что работа в этом направлении все-таки ведется, но пока - увы, прерывания в для ATmega32u4 реализованы.

Freeduino 32u4 в ArduinoIDE 1.0.1

Для того, чтобы Freeduino32u4 можно было использовать с ArduinoIDE 1.0.1, потребуется замена бутлоадера - увы, подружить с ней старый вариант на базе DiskLoader мне пока не удалось.

С другой стороны, новый бутлоадер основан на Caterina и позволяет добиться максимальной совместимости с оригинальным Leonardo - изменения касаются только VID/PID и мигания встроенным светодиодом L. Ядро в этом случае тоже остается неизменным - добавляется лишь variant-файл для правильной трансляции номеров пинов.

Расплачиваемся за все это двумя килобайтами памяти программ... если решились - скачайте и распакуйте в каталог с ArduinoIDE 1.0.1 архив, в котором вы найдете:
  • готовый hex, для заливания в плату при помощи программатора;
  • файл-вариант Arduino-нумерации пинов Freeduino 32u4;
  • .inf-файл для Windows (новому бутлоадеру - новы PID :);
  • boards.txt.add: секция для добавления к boards.txt;
  • Makefile.freeduino32u4 для сборки hex-файла с правильными VID/PID.
Прошивать можно либо из ArduinoIDE, либо из командной строки (например, если у вас AVRDoper):

avrdude -c stk500v2 -P avrdoper -B 3 -p atmega32u4 -F -e -u -U lock:w:0x3f:m -U efuse:w:0xcb:m -U hfuse:w:0xd8:m -U lfuse:w:0xff:m
avrdude -c stk500v2 -P avrdoper -B 1.1 -p atmega32u4 -F -U flash:w:Caterina-Freeduino32u4.hex -U lock:w:0x2f:m


Саму плату можно купить здесь.