Информация к новости
  • Просмотров: 5051
  • Автор: sulicompany
  • Дата: 16-02-2013, 05:10
 (голосов: 0)
16-02-2013, 05:10

Дополнительные материалы

Категория: Электроника » Arduino


  

Мне очень нравятся всякие удобные информеры и шпаргалки и я решил сделать подобную шпаргалку для Arduino :)

Чаще всего я подглядываю нумерацию выводов и . Но решил вывести блоки с основными функциями ардуино. Ну и пример Blink-а — куда же без него? ;)

Ссылки для скачивания:

Книги про Arduino

  •   

Massimo Banzi: 



Brian W. Evans:  (PDF)
 на русский —  (PDF 1.3 Mb)



Mike McRoberts:  (PDF)

Выводы Arduino и Arduino pin mapping

  •   
Для того, чтобы постоянно не лазить в  я вырезал оттуда картинку платы:
 
На самом деле — всё очень просто:

Рядом с аналоговыми портами — порты питания.
Остальное — это всего-лишь блок питания и преобразователь уровней для общения с COM-портом.
Таким образом, можем просто сопоставить порты микроконтроллера и Arduino/Freeduino:





Обратите внимание, что данные схемы годятся только для МК в DIP-корпусе.
Эти картинки потом очень пригодятся ;)

UPD в продолжение темы: 

Ссылки:

Блок питания Arduino...из зарядки сотового телефона

  •   
Как обычно в нужный момент под рукой не оказалось нормального блока питания для свежесобранной ардуинины=( Зато на глаза попалась зарядка от сотика с обгрызеным шнуром:

На шилдике пишут 5V – врут, при замере почти 6. Но на плату надо подавать вольт 8-10. Меньше — нельзя — падение на интегральном стабилизаторе в “ардуине” около 2В, больше тоже нестоит — лишние вольты будут выделяться теплом на том же стабилизаторе — может перегреться =( Т.е. в нашем случае маловато — будем поднимать!
Вскрываем, нещадно ломая клееный корпус и видим вполне приличного вида платку 


видимо собирали фирменные — финские китайцы =)

Приглядевшись, видим на “секондари” стороне стабилитрон на 5,6В… Меняем его на другой повольтистее, ну или подпиваем последовательно ещё один 


Соблюдая меры предосторожности (220 вольт всё-таки!), втыкаем в сеть, меряем — 9.6В – пойдёт! 
Осталось припаять подходящий шнурок со штекером (“+”- внутренний!) и блок питания для первой Arduino готов!


ЗЫ: Поискав потом в интернете нашёл вот такую интересную  — всё уже придумано до нас=(
  •  
    •   
    •  
      •   
    • Прошивка бутлоадера

      Бутлоадер, как уже упоминали, прошивается в  через . Значит, если собрались делать ардуину сами, всё-таки придётся собрать простенький программатор. Чтоб прошить бутлоадер из под ArduinoIDE (а так проще всего) необходим программатор под названием DAPA. 

      Ну чтож попробуем соберём… 
      Вот такой получился
      .
      .
      .
      .
      .
      .
      .
      .
      .
      .
      .
      .
      .

      Запускаем IDE, выбираем тип платы Atmega8,втыкаем шнурок в LPT, Подаём на плату питание, 
      .
      .
      .
      .
      .
      .
      .
      .
      .
      .
      .

      Командуем IDE шить бутлоадер…

      мучительно ждём…ждём ……выскакивает такая штука…

      .
      .
      .
      .
      .
      .

      хм, беру другой шнурок (stk200/300) включаю другую софтину(CodeVisionAVR) – читается/шьётся? а этим шнурком только с 4-5 раза… проверяю всё несколько раз – всё верно… 
      Начинаем эксперименты! Первым делом экранирую шнурок:

      .
      .
      .
      .
      .
      .
      .
      .
      .

      Никакого впечатления… уменьшаем резисторы до 150ом как в обычном — народном программаторе… никаких изменений, убираю резисторы — чуть лучше с 2-3раза шьётся, укоротил провод…ещё…ещё…до предела…есть контакт — 10 из 10!
      Вожделенная надпись и укороченный, но стабильный шнурок — без резисторов=/.

      То что без резисторов — это плохо – LPT жалко. Вот товарищ Илья Данилов
      , что если питать ардуину от того-же LPT то всё прилично работает…но этого мне даже пробовать не хочется. Можно конечно запитаться не от худосочного принтерного порта, а откуда-нибудь с фишки питания, например, флоповода (красный провод +5в) может поможет. Но мы пойдём другим путём! Есть у меня старый проверенный во всех условиях и на всех компах шнурок STK200/300:

      .
      .
      .
      .
      .
      .
      .
      .
      .
      .

      Лучше попробуем его подружить с ArduinoIDE.
      Лезем в arduino-0015\hardware\tools\avr\etc\avrdude.conf 
      вдумчиво читаем, что вначале написано, вникаем, готовимся вписать новый программатор, листаем до “PROGRAMMER DEFINITIONS” ищем куда и что вписать… и с удивлением узнаём что ардуина понимает кучу программаторов и среде них, в секции ”Parallel port programmers” 
      stk200! Просто всё это добро спрятано от народа! Остаётся только вписать в файл “arduino-0015\hardware\programmers.txt” следующее:

      stk200.name=STK200
      stk200
      .protocol=stk200


      И запустить ArduinoIDE:
      Кроме того, пришлось побороть некоторое разнообразие видов разьёмов внутрисхемного программирования 
      .
      .
      .
      .
      .
      .
      .
      .
      .
      .
      .

      И сделать такой переходник
      Всё заработало и весьма стабильно – 10 из 10 раз прошилось успешно!

      .
      .
      .
      .
      .
      .
      .
      .
      .

      И с программатором “4 резистора” тот же эффект!

      .
      .
      .
      .
      .
      .
      .
      .
      .
      .
      .
      .
      .
      .
      .
      .
      .
      .
      Резюмируя: собираем шнурок “5 проводков- 4резистора” (с разьёмом AVR910)
      пишем две строчки в programmers.txt
      шьём и радуемся

      Схемки обоих вариантов STK200 лежат у нас .
      Про источники моей паранойи про прошивку не с первого раза можно почитать .

      Программирование Arduino - Физика процесса

      •   
      Наша свежеслепленная , как и компьютер без софта – просто железо. Чтобы плата ожила и начала делать хоть что-нибудь нужна программа или как часто говорят – прошивка. Написать её под ардуину можно на разных языках — ассемблере, си, паскале, хоть на бейсике, но, обычно, пишут на , из под личной ардуиновской среды разработки —  и загружают (прошивают) оттуда же.

      Как писать прошивки (у ардуино они называется – скетчи) нам подробно  уважаемый admin, а тем кто захочет разобраться с физическим процессом запихивания нашего виртуального творчества в плату поможет (надеюсь) эта серия статей. 

      Загрузить прошивку в МК семейства Mega (а именно такая стоит в ардуине) можно разными способами: 
      Последовательным программатором по интерфейсу SPI
      Через интерфейс JTAG
      Параллельным («высоковольтным») программатором.

      Во всех этих случаях необходим , который надо либо делать, либо где-то покупать (стоят они все прилично), а в ардуино всё шьётся обычным USB-шнурком (ну или com как в случае с хоуммейдовой платой), как же так?! Нет разработчики не стали запихивать на каждую плату по программатору, а использовали одну удобную функцю МК Atmega под названием «самопрограммирование». Если в определённую область памяти программ атмеги прошить специальную программу-загрузчик( далее бутлоадер) то можно заставить её (атмегу) прошивать саму себя по любому имеющемуся на борту интерфейсу – I2C, UART или SPI. В ардуино используется именно UART(com порт практически) — в USB-шных версиях плат стоит преобразователь USB-to-COM (обычно ft232), а на COM-овских — преобразователь уровней COM-to-TTL (max232 или на дискретных транзисторах)

      Работает всё это следующим образом – когда Arduino перезагружается — запускается бутлоадер (если он есть). Он посылает импульсы на цифровой вывод 13 (к данному выводу подключён светодиод — он будет мигать) — это означает, что бутлоадер установлен и работает.
      Далее бутлоадер ждёт команды или данные от компьютера. Обычно, это скетч, который бутлоадер записывает в flash-память МК. Затем, бутлоадер запускает свежезагруженную программу на выполнение.
      Если никаких данных не поступает — бутлоадер запускает предыдущую программу, которая была загружена в микроконтроллер.
      Если же никакой программы нет, то бутлоадер запускает себя снова (цикл повторяется).

      Плату мы , посмотрим что можно в неё загрузить.
      Для загрузки скетчей нужен прямой COM-шнурок папа-мама т.е. просто удлинитель — фактически можно воткнуть плату прямо в COM-порт(без шнурка=)

      Запускаем ArduinoIDE (кто не в курсе — запускать надо файл run.bat из папки arduino-0015, свежую ArduinoIDE можно скачать 
      Выбираем тип нашей платы


      .
      .
      .

      Выбираем COM-порт 

      .
      .
      .
      .
      Выбираем скетч из примеров, например блинк — будем мигать светодиодом- стандартный для МК способ сказать хело волд =)

      .
      .
      .
      .
      .
      .
      .
      .
      .
      .
      .
      .
      .
      .
      .
      .

      Будем хоть немного оригинальны — изменим код=) Помигаем внешним светодиодом (13 пином и так бутоладер мигает)
      int ledPin = 11;                // светодид подключим к 11 выходу

      void setup()                    // запускается единожды когда стартует скетч
      {
        pinMode
      (ledPin, OUTPUT);      // конфигурируем 11 пин как выход
      }

      void loop()                     // будет крутиться в бесконечном цикле
      {
        digitalWrite
      (ledPin, HIGH);   // включим светодиод
        delay
      (500);                   // подождём пол секунды
        digitalWrite
      (ledPin, LOW);    // выключим светодиод
        delay
      (500);                   // подождём пол секунды
      }

      скомпилируем всё это дело — жмём на стрелку, ждём, смотрим на надпись внизу — 790байт из 7168байт, доступных для нашего скетча 

      подадим питание, воткнём шнурок в плату и COM-порт, 

      .
      .
      .
      .
      .
      .
      .
      .
      .

      жмём загрузить


      Ждем…Загрузилось=)

      Втыкаем светодиод в землю и в 11 пин, жмём резет, ждём пока бутлоадер потупит в ожидании нового скетча…мигает!


      далее: 

      Ссылки на использованные материалы:


      По теме:


      книга на русском языке:  (PDF 1.3 Mb)

      Про фьюзы

      •   
      Теперь о том, почему я так загонялся на тему сбоев при прошивке. 
      Дело в том что в памяти атмеги есть ячейки отвечающие за параметры конфигурации всего МК — фьюз-биты. 

      Про фюз-биты, как обычно, можно  у ДиХальта.
      От себя добавлю что фьюз биты МК Atmega8 расположены в два байта – старший фьюз-байт (high _fuses) и младший фьюз-байт ( low_fuses)
      А у Atmega168 есть ещё и дополнительный фьюз-байт(extended_fuses)

      Если при программировании МК произойдёт сбой, то с некоторой долей вероятности (у меня пару раз было =) в эти ячейки может залезть мусор, что приведёт к галюцинированию или неработоспособности. 
      Шьются они специальными командами по 3 байта каждая+1байт данных (“куда писать”+”что писать”) т.е. вероятность, что помеха совпадёт именно с одной из них невелика, однако при прошивке ненадёжным программатором (или в условиях сильных помех) непосредственно фьюз-битов, вероятность попадания в них хлама существенно возрастает (мы сами подаём команду на запись фьюзов и если она каким-то чудом прорвалась сквозь наводки то данные похерить проще (они могут быть произвольными) и МК с радостью схавает шум эфира)

      Наиболее неприятные фьюзы:

      Ячейка RSTDISBL 
      при записи в неё “0” превращает вывод резет в обычную ногу и 
      прошить МК по SPI будет уже невозможно (вначале программирования необходимо “прижать к земле” RESET – подать “0”)

      Ячейка SPIEN 
      при записи в неё “1” запрещено программирование по SPI. Пишут что при 
      программировании по последовательному каналу данная ячейка недоступна, так что нам вроде не грозит, однако проверять нехочется=)

      Ячейки CKOPT и CKSEL
      отвечают за тактирование МК и могут встать в такую позу, что 
      контроллер будет ждать внешнего тактового сигнала или не сможет раскачать ваш кварц.

      Первое и второе лечится только параллельным программатром (может и JTAG поможет)
      Второе лечится “тактированием от пальца” (мне пару раз помогло=). Тыкаете в XTAL1 (у атмеги8 — 9 нога) иголкой (или отвёрткой неизолированной) и шьёте как обычно — через SPI (может не с первого раза получится =) – можно, конечно использовать внешний генератор, но это если он есть или его не лень сделать =)
      Сбои при программировании остальных фьюзов, лок-битов (биты отвечающие за защиту прошивки) и самого бутлоадера могут доставить неприятности лечимые простой (через SPI) перепрошивкой.

      Процесс прошивки бутлодера состоит из четырёх этапов:

      Разблокирование секции загрузчика вообще-то, по умолчанию, вся память атмеги и так 
      доступна для чтения/записи.

      Установка фюз-битов — настраивает МК на работу в ардуине.

      Прошивка собственно бутлодера

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

      Настройки процесса прошивки бутлодера и значеня фьюз- и лок-битов можно просмотреть в arduino-0015\hardware\boards.txt в соотвествующей нашему МК секции (atmega8.bootloader)

      atmega8.bootloader.programmer (по умолчанию: stk500) протокол используемый бутлодером. 

      atmega8.bootloader.path(по умолчанию: atmega8 ) путь где файл бутлодера лежит

      atmega8.bootloader.file(по умолчанию: ATmegaBOOT.hex) собственно, сам бутлоадер

      Теперь самое интересное:

      atmega8.bootloader.unlock_bits (по умолчанию: 0x3F) значение записываемое в лок-байт для разблокирования секции бутлодера. Сбрасывает все лок-биты в 1 т.е. разрешаем любые изменения секции прикладной программы и бутлаодера.

      atmega8.bootloader.high_fuses (по умолчанию: 0xCA) значение записываемое в старший фьюз-байт.

      atmega8.bootloader.low_fuses (по умолчанию: 0xDF) значение записываемое в младший фьюз-байт

      atmega8.bootloader.lock_bits (по умолчанию:0x0F) значение записываемое в лок-байт для блокирования секции бутлодера — запрещается запись/чтение секци бутлоадера (программатором конечно можно, но ни агрессивный скетч ни суицидально настроенный бутлоадер не смогут=)

      Рассмотрим что же именно пишется во фьюз-биты МК:

      Atmega8 

      Младший фьюз-байт


      BODLEVEL  
      1 порог срабатывания схемы BOD 2.7В
      BODEN      
      1 но BOD у нас запрещён=)
      SUT1      
      0 эта пара определяет длительность задержки сигнала RESET после включения
      SUT0      
      1 питания - 16тыс тактов (при 16МГц кварце это 1с)
      CKSEL3    
      1 эти фьюзы
      CKSEL2    
      1 определяют тип
      CKSEL1    
      1 тактирования
      CKSEL0    
      1 кварцевый резонатор >1МГц

      Старший фьюз-байт


      RSTDISBL  
      1 ножка RESET резет
      WDTON      
      1 таймер вочдог запускается программно
      SPIEN      
      0 шить через ISP можно
      CKOPT      
      0 совместно с CKSEL3...0 определяет что усилитель тактового сигнала включен
      EESAVE    
      1 команда “стереть кристалл” стирает также EEPROM
      BOOTSZ1    
      0 размер секции
      BOOTSZ0    
      1 загрузчика 512байт
      BOOTRST    
      0 вектор начального сброса находится в начале секции загрузчика -
                   
      МК при включении питания первым делом запустит бутлоадер


      Atmega168

      Старший фьюз-байт


      RSTDISBL  
      1 ножка RESET резет
      DWEN      
      1 работа отладчного интерфейса DebugWire запрещена
      SPIEN      
      0  шить через ISP можно
      WDTON      
      1  таймер вочдог запускается программно
      EESAVE    
      1 команда “стереть кристалл” стирает также EEPROM
      BODLEVEL2  
      1 порог срабатывания
      BODLEVEL1  
      0 схемы BOD
      BODLEVEL0  
      1  = 2,7В


      Младший фьюз-байт


      CKDIV8    
      1  делитель тактового сигнала выключен
      CKOUT      
      1  Выходной буфер системного тактового сигнала отключен от вывода МК
      SUT1      
      1  эта пара определяет длительность задержки сигнала RESET после вкл.питания
      SUT0      
      1  - 16тыс тактов+14тактов +65мс (при 16МГц кварце это немного больше 1с)
      CKSEL3    
      1  эти фьюзы
      CKSEL2    
      1  определяют тип
      CKSEL1    
      1  тактирования
      CKSEL0    
      1  - кварцевый резонатор >8МГц


      Дополнительный фьюз-байт

      -
      -
      -
      -
      -
      BOOTSZ1    
      0  1024байта размер
      BOOTSZ0    
      0  секции бутлоадера
      BOOTRST    
      0  вектор начального сброса находится в начале секции загрузчика - МК при  
                   
      включении питания первым делом запустит бутлоадер

      Хаки Arduino - Экономим RAM

      •   
      По сравнению с Вашим настольным компьютером – у ардуины очень мало памяти. Очень :) Всего 1Kb ОЗУ (RAM) 
      для Atmega8/Atmega168, для Atmega328 – 2Kb


      Но! Есть небольшой хак, который позволит вызволить Вам для программы дополнительные 100 байт памяти (для 1Kb памяти – это почти 10%!) :)
      Всё очень просто – для работы с последовательным портом через  используется буфер, размер которого определяется в файле: 
      \hardware\cores\arduino\HardwareSerial.cpp
      это в последних версиях Arduino IDE – 0017 (0016), а для более старых IDE нужно редактировать файл:
      \hardware\cores\arduino\wiring_serial.c


      находим строчку
      #define RX_BUFFER_SIZE 128

      Значение буфера можно уменьшить до 32 или 16. Если вашей программе вообще не требуется работать с COM-портом – можете уменьшить это значение настолько на сколько считаете нужным, только оставляйте его больше 0 и кратным степени 2 ;)

      Ссылки по теме:
      •  
        •   
      • ATmega - использование памяти

        Иногда, бывает полезно узнать, сколько памяти использует Ваш скетч.

        Иногда, это очень важно, например, когда Вы достигаете предела. Потому что, могут происходить странные и совершенно непредсказуемые вещи, при достижении программой границ памяти (out of memory).

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

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

        Достижение границы RAM — крайне неприятная проблема. Потому что это может произойти в любое время; не обязательно при запуске, и быть совершенно непредсказуемым, потому что, например, проблемы может вызывать функция-обработчик прерываний.

        В оперативной памяти (RAM), есть три области:
        статических данных, в ней хранятся глобальные переменные и массивы… и строки!
        «куча»(heap), используется, если вы вызываете malloc() и free()
        «cтек»(stack), используется, когда одна функция вызывает другую

        Куча растёт вверх, и используется довольно непредсказуемым образом. Если вы освобождаете области памяти, то они становятся неиспользованными пробелами в куче, которые могут повторно использоваться новым вызовом malloc(), если запрошенный блок вписывается в эти пробелы.

        В любой момент времени, существует высокая точка в оперативной памяти (RAM), занимаемая кучей. Это значение может быть найдено в системной переменной, которая называется __brkval.

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

        т.о. стек растёт навстречу данным! Если он разрастётся, то может достигнуть области данных и записать свои данные вместо ваших значений переменных. Возможна и обратная ситуация — данные разрослись и переписали данные стека. Оба случая крайне неприятны и сложно детектируемы.


        Весь фокус в том, чтобы использовать минимальное количесво оперативной памяти(RAM), потому что это дефицитный ресурс: ATmega имеет всего 2048 байт RAM.

        похоже, имеется в виду ATmega328, у Atmega8/Atmega168 ОЗУ ещё меньше — всего 1024 байта


        Вот небольшая функция функция, которая определяет, сколько оперативной памяти в настоящее время не используется:
        int freeRam () {
         
        extern int __heap_start, *__brkval;
         
        int v;
         
        return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
        }

        И вот скетч, который вызывает данную функцию:
        void setup () {
           
        Serial.begin(57600);
           
        Serial.println("\n[memCheck]");
           
        Serial.println(freeRam());
        }

        void loop () {}

        Результат выполнения:
        [memCheck]
        1846


        Итак, у нас есть около 1.8 Kb доступного ОЗУ в этом крошечном скетче, который почти ничего не делает. Более точно: скетч использует 2048 — 1846 = 202 байта для внутренних нужд и прочего (кстати, 128 байт, используются для входного буфера последовательного порта).

        Когда это значение упадёт до 0, ваш скетч рухнет. Это может выглядеть, как бесконечный цикл, странные расчеты или выход, или постоянная перезагрузка. Не ожидайте, понятных сообщений об ошибке!

        Давайте внесём в скетч незначительные изменения:
        Serial.println("\n[memCheck2]");

        Результат:
        [memCheck2]
        1844


        А?

        Первое — это объясняется тем, что все C-строки также хранятся в оперативной памяти! Это объясняет, почему добавление одного символа в строчке приводит к уменьшению объема доступной памяти.

        Второе — флэш-память организована в слова. Поэтому, иногда, когда вы ожидаете однобайтовый эффект, то можете получить округление из-за того, что объект хранится во флэш-памяти(flash).

        И третье — все C-строки также хранятся во флэш-памяти. Дело в том, что содержимое оперативной памяти не определено при включении питания, поэтому одна из задач, выполняемых при запуске С-кода, состоит в том чтобы скопировать все строки из флэш-памяти в оперативную память.

        Мораль: будьте очень осторожны, когда что-нибудь делаете со строками на ATmega, потому что вы можете обнаружить, что очень быстро достигли границы памяти. Добавление большого количества подробных отладочных сообщений может вызвать больше проблем, чем вы думаете!

        На сайте  отыскалась замечательная картинка, иллюстрирующая AVR RAM:


        Оригинал статьи:


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

        САПР для Arduino :)

        •   
        Меня всё интересовало – как рисуют схемы вроде этой схемы Blink-а:

        И вот я нашёл ответ :) Для этого используется замечательная программа 
         

        Девиз программы – «От прототипа к продукту» (From prototype to product) – полностью оправданный и соответствующий всей философии Arduino!

        На сайте можно  архив с программой, разархивировать её и запустить файл 
        Fritzing.exe

        Появится окно программы:


        Для начала можно посмотреть примеры
        Меню File – Open Example
        Например, тот же стандартный Blink :)
        (File – Open Example – Digital – Output — Blink)


        Откроется уже знакомая схема :)

        Но! Эта программа так же даёт возможность посмотреть принципиальную схему


        и увидеть – какой рисунок нужно изготовить на печатной плате (причём его можно экспортировать в pdf-файл для последующей распечатки и изготовления -ом)


        Как видно – схема формируется в формате шилда для ардуины :)

        Доступ к этим схемам доступен по кнопкам Schematic и PCB ( — печатная плата)
        или через меню View (Show Breadboard/ Show Schematic / Show PCB)

        Примерами дело не ограничивается – в этой программе можно создавать и собственные проекты! Из готовых элементов, список которых можно посмотреть в правом верхнем углу — PARTS 

        , либо из собственных!

        Среди базовых элементов есть не только светодиод, резистор, конденсатор, кнопка, транзистор, но и сама плата Arduino, макетная плата и даже моторчики :) 
        Чтобы поместить их на схему – их достаточно выбрать из списка и перетащить на рабочее пространство левой кнопкой мышки :)

        Рисовать схему можно как в режиме макетной платы – так и в режиме принципиальной схемы. Вторая схема будет строиться автоматически!
        Т.е. набросав схему на макетной плате – она автоматически построится и в виде принципиальной схемы ;)

        Для примера – перетащим на поле светодиод, резистор и блок с батарейками.

        При наведении на контакты элементов указатель превращается в крестик и нажав левую кнопку мышки и протянув до другого контакта – можно соединить их проводом.


        Если щёлкнуть на проводе правой кнопкой мышки – провод можно либо удалить – либо выбрать для него другой цвет :)




        Теперь перейдём в режим Schematic и увидим принципиальную схему нашего соединения:


        Чтобы она стала покрасивее – можно воспользоваться функцией автотрассировки ( голубая кнопка Autoroute)

        Вот! Совсем другое дело :)

        Можно посмотреть как будет выглядеть эта схема – если вдруг захотим перенести её на печатную плату – для это переходим в режим PCB :)


        Теперь можно посмотреть другие примеры, а потом начать рисовать красивые и понятные схемы для Arduino :)

      VirtualBreadboard - эмулятор Arduino

      •   

      Здесь уже рассматривался вариант использования мощного пакета  для симуляции 
      И хотя пользы от освоения PROTEUS-а довольно много, но он платный и монстрообразный.
      И вот нашлась небольшая (всего 19 Mb), простая система для эмуляции Arduino — .
      Программа идёт одним exe-файлом, который можно  и сразу начать работать.
      (если программа не запустилась — значит в системе не установлены некоторые компоненты, которые требуются программе для работы — ссылки на них есть на страничке загрузки программы)


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

       можно посмотреть ролик, показывающий примеры работы с Arduino

      Ссылки:

      Игра "Жизнь" на Arduino :)

      •   
      Обычно, начиная изучать новый язык программирования – я пробовал написать математическую игру Конвея.

      Игра «Жизнь» (англ. Conway's Game of Life) — клеточный автомат(cellular automaton), придуманный английским математиком Джоном Конвеем (англ.) в 1970 году.

      И хотя для ардуино – это не так актуально – программирование ведь идёт на С++.
      Но, всё же, это новая платформа и нужно реализовать эту замечательную игру и для неё :)
      За основу я взял свой  на С++ и просто модифицировал его для Arduino :)

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

      Код скетча получился таким:

      //////////////////////////////////////////////////////////////////////
      //
      //
      // Arduino LIFE GAME
      //
      //
      //
      //   noonv                                                 RoboCraft.ru
      //////////////////////////////////////////////////////////////////////
      // d - will die in next step
      // a - will born in next step

      // size of life-massive
      int L_SIZE = 15;
      int L_SIZEY = 25;

      // variables
      char l_mas[15+2][25+2]; // life-massive//char l_mas[L_SIZE+2][L_SIZEY+2]; // life-massive
      int l_i,l_j; // counter's
      int l_age=0; // age of population
      int l_coef=0; // coefficient for check cell

      void setup()
      {
       
      Serial.begin(9600);
        randomSeed
      (analogRead(0));
        random_mas
      ();
       
      //load_mas(); // not working :(
      }

      void loop()
      {
             
      // print Hello :)
             
      Serial.print("Life  ");

             
      //      
             
      // set border
             
      //
             
      for(l_i=0;l_i<L_SIZEY+2;l_i++)
                      l_mas
      [0][l_i]=l_mas[L_SIZE+1][l_i]='-';
             
      for(l_j=0;l_j<L_SIZE+2;l_j++)
                      l_mas
      [l_j][0]=l_mas[l_j][L_SIZEY+1]='|';
              l_mas
      [L_SIZE+1][0]=l_mas[0][L_SIZEY+1]='+';
              l_mas
      [0][0]=l_mas[L_SIZE+1][L_SIZEY+1]='+';    
             
                     
      Serial.print("Age: ");
                     
      Serial.println(l_age++);
                     
      //
                     
      // print life-massive
                     
      //
                     
      for(l_i=0;l_i<L_SIZE+2;l_i++)
                     
      {
                             
      for(l_j=0;l_j<L_SIZEY+2;l_j++)
                             
      {
                                     
      if(l_mas[l_i][l_j]=='d')
                                              l_mas
      [l_i][l_j]='0'; // amen 8-)
                                     
      if(l_mas[l_i][l_j]=='a')
                                              l_mas
      [l_i][l_j]='*'; // new cell
                                     
      if(l_mas[l_i][l_j]=='0')
                                             
      Serial.print(" ");
                                     
      else
                                             
      Serial.print(l_mas[l_i][l_j]);
                             
      }
                             
      Serial.println();
                     
      }
                     
      //
                     
      // calculate next configuration
                     
      //
                     
      for(l_i=1;l_i<L_SIZE+1;l_i++)
                     
      {
                             
      for(l_j=1;l_j<L_SIZEY+1;l_j++)
                                      calculate
      (l_i,l_j);
                     
      }
             
              delay
      (500);
             
      ////////////
      }

      void calculate(int x,int y)
      {// calculate one cell with x,y
             
      switch(l_mas[x][y])
             
      {
             
      case 'a':
             
      case 'd':
             
      case '+':
             
      case '|':
             
      case '-':
               
      break;
             
      case '0':
             
      case '*':
                     
      //-------------------------------------//
                      l_coef
      =0;
                     
      if(l_mas[x][y-1]=='*'|| l_mas[x][y-1]=='d') // west
                              l_coef
      ++;
                     
      if(l_mas[x-1][y-1]=='*'|| l_mas[x-1][y-1]=='d')// north-west
                              l_coef
      ++;
                     
      if(l_mas[x-1][y]=='*'||l_mas[x-1][y]=='d')// north
                              l_coef
      ++;
                     
      if(l_mas[x-1][y+1]=='*'||l_mas[x-1][y+1]=='d')// north-east
                              l_coef
      ++;
                     
      if(l_mas[x][y+1]=='*'||l_mas[x][y+1]=='d')// east
                              l_coef
      ++;
                     
      if(l_mas[x+1][y+1]=='*'||l_mas[x+1][y+1]=='d')// south-east
                              l_coef
      ++;
                     
      if(l_mas[x+1][y]=='*'||l_mas[x+1][y]=='d')// south
                              l_coef
      ++;
                     
      if(l_mas[x+1][y-1]=='*'||l_mas[x+1][y-1]=='d')// south-west
                              l_coef
      ++;
                     
      switch(l_coef)
                     
      {
                     
      case 0:
                     
      case 1: // will die
                             
      if(l_mas[x][y]=='*')
                                l_mas
      [x][y]='d';
                             
      break;
             
      //      case 2:// stable =)
             
      //              if(l_mas[x][y]=='*')
             
      //                      l_mas[x][y]='*';
             
      //              break;
                     
      case 3: // will born
                             
      if(l_mas[x][y]=='0')
                                      l_mas
      [x][y]='a';
                             
      break;
                     
      case 4: // will die
                     
      case 5:
                     
      case 6:
                     
      case 7:
                     
      case 8:
                             
      if(l_mas[x][y]=='*')
                                      l_mas
      [x][y]='d';
                             
      break;
                     
      default:
                             
      break;
                     
      }
                     
      //-------------------------------------//
                     
      break;
             
      default:
                     
      break;
             
      }

      }

      //
      // set elements of l_mas zero
      //
      void null_mas()
      {
             
      for(l_i=1;l_i<L_SIZE+1;l_i++)
             
      {
                     
      for(l_j=1;l_j<L_SIZEY+1;l_j++)
                              l_mas
      [l_i][l_j]='0';
             
      }
      }

      //
      // set elements of l_mas via random
      //
      void random_mas()
      {

       
      for(l_i=1;l_i<L_SIZE+1;l_i++)
       
      {
       
      for(l_j=1;l_j<L_SIZEY+1;l_j++)
       
      {
           
      if(random(10)>5)
           
      {
              l_mas
      [l_i][l_j]='*';
             
      //Serial.print(l_mas[l_i][l_j]);
           
      }
           
      else
           
      {
              l_mas
      [l_i][l_j]='0';
           
      }
         
      }
         
      //Serial.println("");
       
      }
      }

      Загружаем в МК и смотрим, что нам выдаёт монитор COM-порта :)

      Живём :)

      Разумеется код можно (и нужно) оптимизировать – например, не тратить на клетку целый байт, а использовать один бит ;)


      В дальнейшем – можно попробовать подключить к ардуине светодиодную матрицу и выводить информацию туда ;)

      Ссылки:



      Самодельный датчик цвета

      •   

      Идея состоит в использовании цветных  для поочерёдного освещения объекта, при этом считывается уровень напряжения на  и выбирается наилучшый отклик. 

      схема:

      Для объединения светодиодов и фотодиода в один удобный модуль можно использовать либо термоклей, либо ;)

      код  для :
      //Pins
      int photoResistor = 0;

      int b = 2;
      int r = 3;
      int g = 4;
      int y = 5;

      //Calibration
      // AKA Terrible software solution to a hardware problem....
      double bAdj = 1.0;
      double rAdj = 1.02;
      double gAdj = 1.0;
      double yAdj = 1.17;
      double ambientAdj = 1.0;

      void setup()
      {
        pinMode
      (g, OUTPUT);
        pinMode
      (y, OUTPUT);
        pinMode
      (b, OUTPUT);
        pinMode
      (r, OUTPUT);
        pinMode
      (photoResistor, OUTPUT);
       
      Serial.begin(9600);
      }

      void loop()
      {  
          allOff
      ();
          delay
      (100);
          asses
      (100,100);
      }

      void allOff()
      {
          digitalWrite
      (g, LOW);
          digitalWrite
      (y, LOW);
          digitalWrite
      (r, LOW);
          digitalWrite
      (b, LOW);
      }

      void allOn()
      {
          digitalWrite
      (g, HIGH);
          digitalWrite
      (y, HIGH);
          digitalWrite
      (r, HIGH);
          digitalWrite
      (b, HIGH);
      }

      void pulse(int colour)
      {
         
      for(int i=0;i<3;i++)
         
      {
            digitalWrite
      (colour, HIGH);
            delay
      (100);
            digitalWrite
      (colour, LOW);
            delay
      (100);
         
      }
      }

      void asses(int colldownTime, int saturationTime)
      {
       
          delay
      (500);
         
      double ambient = analogRead(photoResistor);
         
      Serial.print("Ambient: ");
         
      Serial.println(ambient*ambientAdj);
         
          digitalWrite
      (g, HIGH);
          delay
      (saturationTime);
         
      double green = analogRead(photoResistor);
         
      Serial.print("Green: ");
         
      Serial.println(green*gAdj);
          digitalWrite
      (g, LOW);
          delay
      (colldownTime);
         
          digitalWrite
      (r, HIGH);
          delay
      (saturationTime);
         
      double red = analogRead(photoResistor);
         
      Serial.print("Red: ");
         
      Serial.println(red*rAdj);
          digitalWrite
      (r, LOW);
          delay
      (colldownTime);
         
          digitalWrite
      (b, HIGH);
          delay
      (saturationTime);
         
      double blue = analogRead(photoResistor);
         
      Serial.print("Blue: ");
         
      Serial.println(blue*bAdj);
          digitalWrite
      (b, LOW);
          delay
      (colldownTime);
         
          digitalWrite
      (y, HIGH);
          delay
      (saturationTime);
         
      double yellow = analogRead(photoResistor);
         
      Serial.print("Yellow: ");
         
      Serial.println(yellow*yAdj);
          digitalWrite
      (y, LOW);
          delay
      (colldownTime);
         
         
      double rawData[] = {(green*gAdj), (red*rAdj), (blue*bAdj), (yellow*yAdj)};
         
      double maximum = ambient*ambientAdj;
         
      int decision;
         
         
      for (int i=0; i<4; i++)  
         
      {
             
      if (maximum<rawData[i])
           
      {
                maximum
      = rawData[i];
                decision
      = i+1;
           
      }
         
      }
               
         
      Serial.println("");
         
         
      if(decision == 0)
         
      {
             
      Serial.println("No object detected.");
             allOn
      ();
             delay
      (1000);
             allOff
      ();
         
      }
         
      else if(decision == 1)
         
      {
             
      Serial.println("I think its green.");
             pulse
      (g);
         
      }
         
      else if(decision == 2)
         
      {
             
      Serial.println("Looks red to me.");
             pulse
      (r);
         
      }
         
      else if(decision == 3)
         
      {
             
      Serial.println("Blue for sure!");
             pulse
      (b);
         
      }
         
      else if(decision == 4)
         
      {
             
      Serial.println("Booring old yellow.");
             pulse
      (y);
         
      }
         
      Serial.println("");

      }

      видео с описанием и примером работы датчика:


      кстати, ведь совсем необязательно использовать 4 цветных светодиода, а можно ограничиться одним  ;)

      Далее: 

      Ссылки:
      источник — 


  • Программаторы

    Загрузить прошивку в МК AVR семейства Mega (а именно такой стоит в ардуине) можно разными способами(тремя видами программаторов): 

    Последовательным программатором по интерфейсу SPI
    Через интерфейс JTAG
    Параллельным (“высоковольтным”) программатором

    Теперь по порядку. 

    SPI или ISP — внутрисхемное последовательное программирование(In-cirсuit Serial Programming).
    Самый простой и распространённый, покрайней мере у любителей, метод. 
    Как следует из названия — не нужно вынимать МК из платы — прошивка происходит прямо в схеме, через специальный разьём, что довольно удобно =) да и программатор довольно прост (естественно его можно просто купить):

    STK200/300 — Наверное самый распространённый SPI-программатор для AVR. Это его буферизованная версия т.е LPT-порт компа защищён буферными элементами микросхемы 74LS244 от каких-либо непредвиденностей. Можно ещё добавить резисторы по 100-200ом между портом и микросхемой

    вот попроще
    , а вот знаменитые “пять проводков” проще некуда=), но и LPT ничто не спасёт в случае чего=) 
    .
    .
    .
    .
    .
    .
    .
    .
    .
    .
    .
    .
    .
    .
    .
    .
    .
    .
    .
    .

    Также есть COM-версия (прогромматор Громова) 

    Есть еще куча разных вариаций последовательных программаторов, через USB в том числе. 

    JTAG это собственно интерфейc (последовательный) для внутрисхемной отладки 
    (разработанный группой ведущих специалистов по проблемам тестирования электроннх компонентов Joint Test Action Group), то есть прям почти находу можно в самые недра МК заглянуть — посмотреть что там во всех регистрах творится, ну и прошить можно заодно=) Но программатор относительно сложен (и весьма дорог) так что в любительских условиях это скорее экзотика.
    Например  
    .
    .
    .
    .
    .
    .
    .
    .
    .
    .
    .
    .
    Параллельный “высоковольтный” программатор стоит гораздо дороже, шьёт быстрее, и может помочь 
    “оживить” программно убитые МК. 
    Как, опять же, следует из названия данные в МК передаются параллельно т.е. требуется большое количество выводов МК, также требуется источник “высокого” напряжения 12в. Основное применение этого режима — массовая прошивка МК перед установкой в устройства в промышленных масштабах/условиях.
    То есть схема посложнее будет=) 
    Вот например “” ну и конечно тут придётся МК из панельки выковыривать=)

    DAPA
    Ну а бутлоадер прошивается в ардуину через SPI. 
    Причём разработчики соригинальничали и придумали для этого свой программатор =)

    Да ещё и периодически обзывают его ParallelProgrammer,(это у них сокращение такое — так он Parallel Port Programmer), а вообще зовётся онDAPA.

    Про загрузку бутлодера и мои приключения с DAPA можно почитать .