В этой статье мы расскажем вам как собрать музыкального робота Мариачи, который умеет подключаться к разным веб-серверам, считывать данные и в зависимости от заданных условий играть на маракасах. А условия могут быть самыми разнообразными:
В нашем случае Мариачи будет оповещать нас о новых заказах в магазине Амперка.
8
и 9
пину Troyka Shield соответственно.5
и 6
пину Troyka Shield. Установите верхнюю панель куба (7x7) на левую и правую панели.5V
. Для этого возьмите гнездо питания 2,1 мм и с помощью проводов «папа-папа» через верхнюю панель куба соедините пин 5V
Arduino с плюсом
клеммника, а пин GND
Arduino с минусом
клеммника. В результате должна получиться такая схема:Из за конфликта между Arduino LLC и Arduino SRL для работы платы Arduino Leonardo ETH в стандартной Arduino IDE от Arduino.cc, надо выполнить некоторые настройки.
C:\Program Files\Arduino\
.\hardware\arduino\avr\
.boards.txt
и откройте его с помощью любого текстового редактора.############################################################## leonardoeth.name=Arduino Leonardo ETH leonardoeth.vid.0=0x2a03 leonardoeth.pid.0=0x0040 leonardoeth.vid.1=0x2a03 leonardoeth.pid.1=0x8040 leonardoeth.upload.tool=avrdude leonardoeth.upload.protocol=avr109 leonardoeth.upload.maximum_size=28672 leonardoeth.upload.maximum_data_size=2560 leonardoeth.upload.speed=57600 leonardoeth.upload.disable_flushing=true leonardoeth.upload.use_1200bps_touch=true leonardoeth.upload.wait_for_upload_port=true leonardoeth.bootloader.tool=avrdude leonardoeth.bootloader.low_fuses=0xff leonardoeth.bootloader.high_fuses=0xd8 leonardoeth.bootloader.extended_fuses=0xcb leonardoeth.bootloader.file=caterina/Caterina-LeonardoEthernet.hex leonardoeth.bootloader.unlock_bits=0x3F leonardoeth.bootloader.lock_bits=0x2F leonardoeth.build.mcu=atmega32u4 leonardoeth.build.f_cpu=16000000L leonardoeth.build.vid=0x2a03 leonardoeth.build.pid=0x8040 leonardoeth.build.usb_product="Arduino Leonardo ETH" leonardoeth.build.board=AVR_LEONARDO leonardoeth.build.core=arduino leonardoeth.build.variant=leonardo leonardoeth.build.extra_flags={build.usb_flags} ##############################################################
В данном проекте мы используем метод GET
на URL Амперки. Пример ответа сервиса приведён ниже.
HTTP/1.1 200 OK Server: nginx/1.6.0 Date: Fri, 10 Jul 2015 14:27:55 GMT Content-Type: text/html; charset=utf-8 Content-Length: 1 Connection: close 2
Цифра 2
— это количество необработанных заказов. Наша задача отлавливать эту цифру в приходящих данных с сервера и фиксировать её изменения каждую минуту.
Для работы ниже приведённого скетча вам понадобиться скачать и подключить библиотеку Ethernet2.
#include <SPI.h> // библиотека для подсоединения Arduino Leonardo ETH к Интернету #include <Ethernet2.h> // библиотека для работы с сервоприводами #include <Servo.h> // интервал между отправками HTTP-запроса в миллисекундах #define INTERVAL 60000 // даём разумное имя пинам к которым подключены светодиоды #define LED_1 5 #define LED_2 6 // даём разумное имя пинам к которым подключены сервомоторы #define SERV_L 8 #define SERV_R 9 // создадим два объекта для управления сервоприводами // левая и правая рука робота Servo myservo_L; Servo myservo_R; // MAC-адрес контроллера, напечатан на обратной стороне платы byte mac[] = { 0x90, 0xA2, 0xDA, 0x10, 0x01, 0x00 }; // впишите сюда адрес вашего сервера char server[] = "your.server.ru"; // переменная для хранения последнего состояния подключения boolean lastConnected = false; // количество заказов char buff[5] = {0}; // индекс массива buff[] int i = 0; // первый для проверки первый ли раз был запуск программы boolean flag = 0; // состояние работы программы int state = 0; // переменная для хранения времени работы программы // с последней отправки HTTP-запроса long previousMillis = 0; // переменная для хранения времени работы программы // с момента запуска функции движения руками long robotTime = 0; // текущее количество заказов int value = 0; // предыдущее количество заказов int previous_value = 0; // задаем статический IP-адрес // на тот случай, если у DHCP выдать IP-адрес не получится IPAddress ip(192, 168, 0, 177); // создаём клиента, который будет подключаться // к необходимому для нас серверу и порту // портом по умолчанию для HTTP является 80 EthernetClient client; void setup() { // очищаем буфер clearbuff(); // настраиваем пины светодиодов в режим выхода pinMode(LED_1, OUTPUT); pinMode(LED_2, OUTPUT); // открываем последовательный порт для мониторинга действий в программе Serial.begin(9600); // запускаем Ethernet-соединение: if (Ethernet.begin(mac) == 0) { // если не удалось сконфигурировать Ethernet при помощи DHCP Serial.println("Failed to configure Ethernet using DHCP"); // продолжать дальше смысла нет, поэтому вместо DHCP // попытаемся сделать это при помощи IP-адреса: Ethernet.begin(mac, ip); } // даем Ethernet 3 секунды на инициализацию delay(3000); // получаем и выводим локальный IP адрес Serial.print("My IP address: "); Serial.println(Ethernet.localIP()); // отправляем HTTP-запрос httpRequest(); } void loop() { // если от сервера есть какие-нибудь байты, // считываем их и выводим в Serial-порт if (client.available()) { char c = client.read(); Serial.print(c); // отслеживаем в пришедших байтах // данных которые показывают количество необработанных заказов // в нашем случае пустой строки testSymbol(c); } // если сервер отключился и последнее состояние подключение истинно if (!client.connected() && lastConnected) { // останавливаем работу клиента client.stop(); lastConnected = false; Serial.println(); Serial.println("Disconnect"); Serial.println(); buff[i]='\0'; value = atoi(buff); state = 0; // очищаем буфер clearbuff(); // если программа выполняется впервые, то // записываем текущее количества заказов if (flag == 0) { previous_value = value; flag = 1; } // если текущее количество заказов больше предыдущего // вызываем функцию движения руками робота if (value > previous_value) { robotHands(); } // если текущее количество заказов больше 0 if (value > 0) { // зажгём светодиоды digitalWrite(LED_1, HIGH); digitalWrite(LED_2, HIGH); } else { // погасим светодиоды digitalWrite(LED_1, LOW); digitalWrite(LED_2, LOW); } // записываем текущее количество заказов previous_value = value; } // проверяем не прошел ли нужный интервал времени if (millis() - previousMillis > INTERVAL) { // отправляем HTTP-запрос httpRequest(); // сохраняем текущее время previousMillis = millis(); } } // функция отправки HTTP-запроса void httpRequest() { // если подключение установлено, сообщаем об этом на Serial-порт: if (client.connect(server, 80)) { Serial.println("Connected"); // делаем HTTP-запрос: // сюда вписывайте свои данные client.println("GET /yourorders/ HTTP/1.1"); client.println("Host: your.server.ru"); // если ваш сервер не требует авторизации, следующую строчку можете пропустить client.println("Authorization: your basic access authentication"); client.println("Connection: close"); client.println(); lastConnected = true; } else { // если соединения с сервером нет, пишем об этом на Serial-порт: Serial.println("Connection failed"); } } // функция очистки буфера void clearbuff() { for (int t = 0; t < 5; t++) { // очищаем буфер, // присваивая всем индексам массива значение 0 buff[t] = 0; } // для записи с 0 индекса массива // после очистки массива i = 0; } // функция отслеживания пустой строки void testSymbol(char c) { if (c == '\n' && state == 0) { // если новый символ «перевод строки» // и программа находится в нулевом состоянии // переходим в первое состояние state = 1; } else if (c == '\r' && state == 1) { // если новый символ «возврат каретки» // и программа находится в первом состоянии // переходим во второе состояние state = 2; } else if (c == '\n' && state == 2) { // если новый символ «перевод строки» // и программа находится во втором состоянии // переходим в третье состояние state = 3; } else if (state == 3) { // если программа в третьем состоянии // это значит что пришедшие данные // будут содержать информацию о количестве заказов // считываем их в массив buff[i] = c; i++; } else { state = 0; } } void robotHands() { // сохраняем текущее время работы программы robotTime = millis(); // покаместь не прошла 1 секунда while (millis() - robotTime < 5000) { // подключаем сервоприводы myservo_L.attach(SERV_L); myservo_R.attach(SERV_R); // зажигаем светодиоды digitalWrite(LED_1, HIGH); digitalWrite(LED_2, HIGH); // устанавливаем угол 120 градусов myservo_L.write(120); myservo_R.write(120); // ждём 300 миллисекунд delay(300); // гасим светодиоды digitalWrite(LED_1, LOW); digitalWrite(LED_2, LOW); // устанавливаем угол 60 градусов myservo_L.write(60); myservo_R.write(60); // ждём 300 миллисекунд delay(300); } // останавливаем сервомоторы myservo_L.detach(); myservo_R.detach(); }
В данном проекте можно использовать любую другую плату с выходом в интернет. Если у вас, например, уже есть Iskra Neo, можно добавить к ней Ethernet Shield 2 или даже GPRS Shield, немного изменив скетч. Так как светодиоды подключены к пинам, поддерживающим ШИМ, вы можете плавно регулировать их яркость в зависимости от вашей задачи. А добавив ещё один сервопривод можно заставить робота вращать головой.