Arduino Pro Mini + куча запчастей = самое бесполезное устройство


Arduino + два сервопривода + плата зарядки + плата повышающего преобразователя + старый аккумулятор + кучка радиодеталей + кусок фанеры + тумблер = сбылась мечта идиота!
Много текста, для тех, кто любит читать. Много спойлеров, для тех, кто любит читать «по диагонали». Видео, для тех, кто любит видео. Скетч, для тех, кто любит сразу скопировать и запустить «на коленке». Фото, фото, фото. Кот, для любителей котов.

Не совсем дисклеймер
Это мой первый проект, не считая мигания светодиодом, Hello world и т.п. По традиции надо предварительно посыпать голову пеплом, на предмет того, что код далек от совершенства и обязательно ввязаться в спор по этому поводу. А также по поводу частичной скопированности кода у другого проекта, попросить не бить сильно и т.д. Но этого не будет. Код идеален! Потому что работает, нравится мне и сделан для себя.
Интересующимся дам совет: не бойтесь, вступайте в бой, лопатьте горы кода, стройте свои мегапирамиды из разных операторов. Со временем придет и стиль, и утонченность, и идеал.
Пока в памяти контроллера есть место — вам ни чего не страшно. Упретесь в стену — будете оптимизировать. И это тоже развитие. Оно важно.
Большая книга по программированию на С — да, полезно. Но, на первых порах, гораздо полезнее иметь под рукой краткий справочник по командам и держать в закладках несколько ссылок на работу с простыми примерами, библиотеками и т.п., вроде arduino-diy.com, cxem.net или той же Амперки.
И еще, мне очень помогают блок-схемы. Прямоугольник, ромбик, овал. Кто сталкивался — понимает. Делаю сейчас один проект — без блок-схемы никак. Для меня, лучше несколько дней рисовать — перерисовывать на бумаге, чтобы яснее представить себе весь ход работы программы, чем набросать кучу кода и зашиться в нем, т.к. я не обладаю умением охватить весь код силой своей программистской мысли, в виду малого опыта.
Желающим повторить или сделать по-своему – отвечу на все вопросы.
В пустые споры по моей письменной грамотности, стилю, дизайну, коду и нужности изделия и т.п., вступать не буду. Если допустил где-то в обзоре суровый косяк – исправлю или допишу.


Что такое «Самое бесполезное устройство» можете загуглить сами. Я натолкнулся на него случайно здесь. Этот код и был взят за основу, т.к. сам по себе он не запустился, да и сценарии хотелось сделать свои.

Лирическое отступление
Говорят, после сорока, особенно, когда уже очень после сорока, нужно стараться «разминать» мозги. И что изучение языков — лучшая разминка. И не только в таком возрасте. К языкам я не очень, а журнал «Здоровье» как бы советует… В общем, решил я изучить что-то новое для себя. Электроника для меня не в новинку, хоть и забыл я ее уже по большей части, но вот программирование ни когда не было родным. Я его побаивался. Но тут совпало много знаков свыше: журнал «Здоровье», который рекомендует изучить что-то новое, давняя мечта разобраться (хоть немного) в программировании (хоть чего) и youtube, в котором только ленивый не рассказывает про то, как мигать светодиодом с помощью умной платы за доллар с копейками.
До этого я неплохо управлял миганием светодиода с помощью двух транзисторов, конденсатора и пары сопротивлений, но теперь, говорят, это не комильфо. Значит надо быть в тренде.



Очень мне понравилось это бесполезное, в прямом смысле слова, устройство. Увидел – влюбился. Хочу, и всё! Как детская мечта! Но возраст внес свои коррективы. Хочу именно сам сделать, а не купить. Тем более, что в продаже простые устройства. Я же натолкнулся на «интеллектуальное», а таких в продаже я не нашел. Тем более – надо делать!
И опять, Arduino. А я в нем ни бум-бум. Значит надо разбираться. Алиэкспресс в помощь. Начал с Ардуин. Понимал, что путь к изучению будет тернист и жертвы неизбежны. Поэтому заказал пять разных. Пусть себе горят, если что. Отладка схемы происходила на Uno от другого продавца. Но, так как в конечном устройстве оказалась именно эта плата — ее и вынес в заглавие.
Кроме ардуинок, заказал огромное количество всякого разного барахла, как ардуиносовместимого, так и околоардуинового. Здесь расскажу только о том, что пригодилось в данном изделии.
Arduino Pro Mini

Доставка быстрая, упаковка в виде стандартного антистатического пакета и конверта с внутренней пупырчатой поверхностью. Продавец общительный, русскоязычный.
На 328 чипе. 3,3 вольта, 8МГц. Почему именно так? Да по ошибке. Хотел на 5 вольт, 16МГц, а купил эту. Сам виноват. Впрочем, для данного проекта не критично — поставил лишний преобразователь напряжения. Собственно и всё. Огромных отличий от других Mini я не нашел. Фирменное отличие — черный текстолит(?) Из косяков: на плате не работает пин RAW. Но и это не остановило. Хотя, с ним мог бы сэкономить преобразователь на 3,3 В. гребенки не распаяны. Плата сделана добротно.
Почему так кратко? Потому что про этого продавца и его платы уже есть пристрастный обзор (п.18). Желающие найдут легко. Пересказывать его не имеет смысла. Я в комментах к нему тоже вставил свои пять копеек. И с продавцом напереписывался вдоволь.

Сервопривод SG90

Магазин
$3.2 за партию две штуки.
Описывать особенно нечего. Слабый сервопривод со средней точностью позиционирования, которая сильно зависит от скорости перемещения. Зато копеечный. Для привода крышки — с лихвой, для «руки» — на грани возможностей. Для работы нужно 5 вольт, но для управления достаточно и 3,3. Пробовал управлять через преобразователь и напрямую от ардуино — разницы нет. Поэтому преобразователь уровней сэкономил.

Контроллер зарядки и преобразователь питания

Магазин
$2.28 за пять штук. С защитой. Пока заряжается — горит красный светодиод, окончание зарядки — синий светодиод. Обзор здесь был.

Магазин
$0.50 за штуку. Доставка, правда, платная, но я брал в этом магазе еще целый ворох всякой всячины, поэтому доставка не напрягла. USB гнездо выпаял для облегчения веса))) На выходе выдает 5,12 вольт.


Тумблер

Магазин
Брал в оффлайне. Немного туговат. Для облегчения работы сервы, можно было его разобрать, укоротить пружину или заменить на более слабую. Но лень победила. Поставил так. Правда пришлось в коде прописывать добавки к углу поворота сервы на больших скоростях.

TTL преобразователь

Магазин
$1.5 за штуку. Вообще-то я заказал сначала такой. Он в два раза дешевле. Но, по каким-то странным причинам, он пал смертью храбрых. Я так и не понял, чем я его убил. По этой причине проект застопорился на месяц, пока не пришел новый, более продвинутый — не надо давить reset. Это ли не прогресс?

Остальное из запасников
Регулятор напряжения1117Т-3,3V в корпусе TO220, конденсаторы 1500,0х6,3 и 470,0х16, два конденсатора по 0,1 мкФ, белый светодиод и микропереключатель от детской машинки, резистор 220 Ом. Аккумулятор валялся несколько лет без дела. Когда-то я разобрал сгоревший (в прямом смысле) портативный DVD-проигрыватель. Из хорошего там только аккумуляторы и уцелели. Вот один из них и пригодился. Вольтаж 3,7 V, емкости я в маркировке не нашел.
Клеевой пистолет, резинка для денег, два крючка от… лифчика (спасибо супруге. Дорогая, я тебя люблю!), два мебельных шканта, четыре шурупа, четыре клейких отбойника для мебельных дверей, кусок макетной платы, провода, разъемы.

Сложнее обстояло дело с корпусом. Было перепробовано множество коробок. Коробка из пластика от часов Tissot оказалась хрупкой, частично картонной. Но металлические завесы от нее подошли. Одна даже в запасе осталась. Пробовал готовые корпуса от парфюма, коробку от вина, от конфет. В итоге, решил сделать сам.
Качественная фанера, скорее всего березовая, нашлась в детском наборе для выжигания. Ребенок вырос — набор остался. С одной стороны был нанесен рисунок, зато другая сторона выглядела прямо-таки сказать, отлично
Прямо-таки сказать, отлично
В школе у нас был трудовик. В возрасте. В общем и целом — замечательный человек. Его уважали. Когда мы проходили электричество, на примере батарейки, лампочки и ключа, он прочитал нам лекцию.
«В батарейке живет ток. Вот выходит он из плюса и пошел по проводам. Идет, идет, вдруг бац — ключ на пути. И ключ разомкнут. Ток понимает, что дальше идти некуда. Он развернулся и ушел в батарейку. И лампочка не горит. Замыкаем ключ. Ток опять пошел, дошел до ключа, прошел через него, прошел через лампочку и вернулся в батарейку. И лампочка горит, прямо-таки сказать, отлично.» С тех пор и есть такая фраза в лексиконе, как синоним чего-то неожиданно удачного.


Пробовал резать фанеру ножовкой, лобзиком — всё не то. Сколы, которые потом трудно убрать, не ровная кромка. Нашел выход — острый канцелярский нож. Замечательно прорезает половину фанеры с одной стороны, и половину с другой. Потом чуть-чуть наждачкой и всё в ажуре. Зато, при хорошей металлической линейке и постоянно остром лезвии, получается идеальный срез и ровная линия.
Конечно, не без косяков — под наклейкой Hand made скрывается банальная дырка. Просверлил по центру, для тумблера. А серва не влезла. Пришлось смещать тумблер в бок и закрывать дырку. Меня такие трудности не пугают.
Описывать каждый свой чих по изготовлению устройства не вижу смысла. Я опишу некоторые моменты. А уж имеющий руки — да сделает.
Коробку собрал на термоклей. Самого клея не жалел. Держится отменно. Не скрипит, не люфтит. Быстро, дешево и сердито. Да и вообще, как вы заметили, практически всё держится на этом клее. Рекомендую. Очень ускоряет процесс сборки. Микрик выключения приклеил изнутри на левую стенку — виднеется на фото немного.
Крышку прикрепил на завесу.

С завесой намучился. Много экспериментировал. Хотел, чтобы крышка располагалась именно сверху коробки, а не внутри. Даже согнул несколько вариантов скоб-завес из скрепок. По потом вспомнил, что в процессе экспериментов на глаза попались завесы из коробки часов Tissot. Такие добротные, швейцарские (китайские?).
Завеса вещь важная. Ее качество очень важно для общей внешней красоты устройства.
Основной тумблер нужен помягШе, тогда и работать будет полегШе.
Крышку возвращает в закрытое положение резинка. Ее не нужно выбирать очень жесткой — серва справится, но, при центральном расположении завесы, крышку будет перекашивать.
В случае с фанерой, покрытие лаком обязательно — пачкается сильно. Я применил бесцветный цапон-лак. Просто потому, что другого под рукой не оказалось.
Серву, которая управляет «рукой» лучше расположить по-другому. Не сбоку, а спереди от тумблера. Тогда «рука» может быть попроще в изготовлении — г-образная, вместо п-образной. Ширину коробки можно уменьшить и тумблер расположить по центру.
Серву крышки лучше развернуть на 180 градусов, тогда в коде проще будет ассоциировать градусы этой сервы с работой крышки. У меня наоборот, поэтому открывание — это уменьшение градусов. А у «руки» наоборот. И правильнее толкать крышку с той же стороны, с которой ее тянет назад резинка.
Коробку не стоит делать слишком маленькой. Будет не удобно пользоваться. А вот более плоской — допустимо. Коробка легкая и если она будет площе, будет устойчивее. Удобнее будет толкать тумблер пальцем не придерживая коробку.
Из двух кусков макетной платы сделал что-то типа шилда. Ардуину впаял без разъемов. Намертво. Мне не жалко.

А вот всю периферию сделал на разъемах. Так удобнее.
Конденсатор большой емкости по питанию ардуины (3,3 вольт) обязателен. Без него ардуина «виснет».
У меня нет сборочных чертежей устройства. Оно на столько простое, что можно применить много других простых решений, на которых строится вся механика. На видео, как моем, так и других подобных устройств, можно видеть применяемые варианты приводов.

Скетч
#include <Bounce.h>
#include <Servo.h>
Servo doorServo; //сервопривод крышки
Servo handServo; //сервопривод руки
Bounce bouncer = Bounce(12, 40); //создаем экземпляр класса Bounce для 12 вывода тумблера
int pos = 0; //переменная начальной позиции
int pos1door = 70; //начальное положение сервопривода крышки
int pos2door = 30;  //конечное положение сервопривода крышки
int pos1hand = 10;  //начальное положение сервопривода руки
int pos2hand = 160;  //конечное положение сервопривода руки
int r; //случайное число, от которого зависит вариант выключения тумблера
#define LED_PIN  11      // номер выхода,подключенного к светодиоду
int ledState = LOW;             // этой переменной устанавливаем состояние светодиода
long previousMillis = 0;        // храним время последнего переключения светодиода
#define  INTERVAL  30UL           // интервал между включение/выключением светодиода

void setup()
{
  pinMode(LED_PIN, OUTPUT); 
  pinMode(12, INPUT);   //переключаем 12 вывод в режим входа
  digitalWrite(12, 1);  //включаем на нем подтягивающий резистор
  Serial.begin(9600);  //установка порта на скорость 9600 бит/сек. Для отладки. Потом можно убрать.
  doorServo.attach(9);           //назначаем сервопривод крышки на пин 9
  handServo.attach(10);          //назначаем сервопривод руки на пин 10
  doorServo.write(pos1door);           //устанавливаем в начальную позицию сервопривод крышки
  handServo.write(pos1hand);            //устанавливаем в начальную позицию сервопривод руки
}

void loop()
{
  if (bouncer.update()) {     
    if (bouncer.read()==0) {    //если кнопка нажата
{  

   
 r = random(0,11); //генерируем случайное число jn 0 до 10
  Serial.println®;
  if (r == 0) { move_0(); }  //вызов функции по случайному числу
  else if (r == 1) { move_1(); }  
  else if (r == 2) { move_2(); }
  else if (r == 3) { move_3(); }
  else if (r == 4) { move_4(); }
  else if (r == 5) { move_5(); }
  else if (r == 6) { move_0(); }
  else if (r == 7) { move_1(); }
  else if (r == 8) { move_4(); }
  else if (r == 9) { move_3(); }
  else if (r == 10) { move_0(); }
}
    }
  } 
}
// Библиотека функций. Общий принцип: открыть крышку - высунуть руку и выключить тумблер - убрать руку - закрыть крышку
//а уж вариантов как это красиво обставить................

void move_0(){ //простой вариант: открыли-выключили-закрыли
//открываем крышку
    for(pos = pos1door; pos >= pos2door; pos -=3)  
    {                                  
    doorServo.write(pos);             
    delay(15);                      
    }
//высовываем руку
    for(pos = pos1hand; pos <= pos2hand; pos +=3) 
    {                                  
    handServo.write(pos);              
    delay(15);                      
    } 
//убираем руку
    for(pos = pos2hand; pos >= pos1hand; pos -=3)     
    {                               
    handServo.write(pos);              
    delay(15);                       
    }
//закрываем крышку
    for(pos = pos2door; pos <= pos1door; pos +=3)    
    {                               
    doorServo.write(pos);             
    delay(15);                     
    }
   }

void move_1(){ //простой вариант 2: открыли-выключили-закрыли
//открываем крышку
    for(pos = pos1door; pos >= pos2door; pos -=1)  
    {                                  
    doorServo.write(pos);             
    delay(15);                      
    }
    delay(1000);
//высовываем руку
    for(pos = pos1hand; pos <= pos2hand; pos +=1) 
    {                                  
    handServo.write(pos);              
    delay(15);                      
    } 
//убираем руку
    for(pos = pos2hand; pos >= pos1hand; pos -=5)     
    {                               
    handServo.write(pos);              
    delay(15);                       
    }
//закрываем крышку
    for(pos = pos2door; pos <= pos1door; pos +=5)    
    {                               
    doorServo.write(pos);             
    delay(15);                     
    }
   }

void move_2(){ //задумчивый вариант 2: приоткрыли-закрыли-открыли-выключили-закрыли
//открываем крышку
    for(pos = pos1door; pos >= pos2door+15; pos -=5)  
    {                                  
    doorServo.write(pos);             
    delay(15);                      
    }
    delay(1000);
//закрываем крышку
    for(pos = pos2door+15; pos <= pos1door; pos +=5)    
    {                               
    doorServo.write(pos);             
    delay(15);                     
    }
    delay(1000);
//открываем крышку
    for(pos = pos1door; pos >= pos2door; pos -=5)  
    {                                  
    doorServo.write(pos);             
    delay(15);                      
    }
//высовываем руку
    for(pos = pos1hand; pos <= pos2hand+2; pos +=5) 
    {                                  
    handServo.write(pos);              
    delay(15);                      
    } 
//убираем руку
    for(pos = pos2hand+2; pos >= pos1hand; pos -=5)     
    {                               
    handServo.write(pos);              
    delay(15);                       
    }
//закрываем крышку
    for(pos = pos2door; pos <= pos1door; pos +=5)    
    {                               
    doorServo.write(pos);             
    delay(15);                     
    }
   }

void move_3(){ //дерганый вариант: приоткрыли-подергали - закрыли-открыли-выключили-закрыли
//открываем крышку
    for(pos = pos1door; pos >= pos2door+15; pos -=1)  
    {                                  
    doorServo.write(pos);             
    delay(50);                      
    }
    delay(500);
//дергаем крышку
    for(int i=1; i <=8; i ++)  
    {                                  
    doorServo.write(pos2door+18);             
    delay(80);    
    doorServo.write(pos2door+15);
     delay(80); 
           
           static unsigned long previousMillis = 0;
           if(millis() - previousMillis > INTERVAL) {
           previousMillis = millis(); 
           digitalWrite(LED_PIN,!digitalRead(LED_PIN));
           }  
    }
    delay(500);
//закрываем крышку
    for(pos = pos2door+15; pos <= pos1door; pos +=1)    
    {                               
    doorServo.write(pos);             
    delay(50);                     
    }
    delay(1000);
//открываем крышку
    for(pos = pos1door; pos >= pos2door; pos -=5)  
    {                                  
    doorServo.write(pos);             
    delay(15);                      
    }
//высовываем руку
    for(pos = pos1hand; pos <= pos2hand+2; pos +=5) 
    {                                  
    handServo.write(pos);              
    delay(15);                      
    } 
//убираем руку
    for(pos = pos2hand+2; pos >= pos1hand; pos -=5)     
    {                               
    handServo.write(pos);              
    delay(15);                       
    }
//закрываем крышку
    for(pos = pos2door; pos <= pos1door; pos +=5)    
    {                               
    doorServo.write(pos);             
    delay(15);                     
    }
   }

void move_4(){
   //открываем крышку
    delay(2000);
    for(pos = pos1door; pos >= pos2door+15; pos -=5)  
    {                                  
    doorServo.write(pos);             
    delay(50);                      
    }
    delay(500);
    digitalWrite(LED_PIN,!digitalRead(LED_PIN));
    delay(2000);
    digitalWrite(LED_PIN,!digitalRead(LED_PIN));
    delay(500);
//закрываем крышку
    for(pos = pos2door+15; pos <= pos1door; pos +=5)  
    {                                  
    doorServo.write(pos);             
    delay(50);    
    }
    delay(1000);
//открываем крышку не полностью
    for(pos = pos1door; pos >= pos2door+15; pos -=1)  
    {                                  
    doorServo.write(pos);             
    delay(50);                      
    }
    delay(2000);
//открываем крышку полностью
    for(pos = pos2door+15; pos >= pos2door; pos -=1)  
    {                                  
    doorServo.write(pos);             
    delay(15);                      
    }
//высовываем руку
    for(pos = pos1hand; pos <= pos2hand-35; pos +=1) 
    {                                  
    handServo.write(pos);              
    delay(35);                      
    } 
    delay(1000);
//высовываем руку
    for(pos = pos2hand-35; pos <= pos2hand+3; pos +=4) 
    {                                  
    handServo.write(pos);              
    delay(15);                      
    } 
//убираем руку
    for(pos = pos2hand+3; pos >= pos1hand; pos -=7)     
    {                               
    handServo.write(pos);              
    delay(15);                       
    }
//закрываем крышку
    for(pos = pos2door; pos <= pos1door; pos +=7)    
    {                               
    doorServo.write(pos);             
    delay(15);                     
    }
    delay(500);
//открываем крышку
    for(pos = pos1door; pos >= pos2door+20; pos -=5)  
    {                                  
    doorServo.write(pos);             
    delay(50);                      
    }
    delay(300);
    digitalWrite(LED_PIN,!digitalRead(LED_PIN));
    delay(500);
    digitalWrite(LED_PIN,!digitalRead(LED_PIN));
    delay(100);
//закрываем крышку
    for(pos = pos2door+20; pos <= pos1door; pos +=1)  
    {                                  
    doorServo.write(pos);             
    delay(50);    
    } 
   }

void move_5(){
   //возня
for(int i=1; i <=2; i ++)  
    {    
    for(pos = pos1door; pos <= pos1door+45; pos +=5)  
    {                                  
    doorServo.write(pos);             
    delay(50);                      
    }
    for(pos = pos1door+45; pos >= pos1door; pos -=5)  
    {                                  
    doorServo.write(pos);             
    delay(50);                      
    }
    delay(100);
    }
//дергаем крышку
    for(int i=1; i <=3; i ++)  
    {                                  
    doorServo.write(pos1door-6);             
    delay(80);    
    doorServo.write(pos1door-3);
     delay(80);
    }
     delay(300);  
 //открываем крышку
    digitalWrite(LED_PIN,!digitalRead(LED_PIN));
    for(pos = pos1door; pos >= pos2door+25; pos -=5)  
    {                                  
    doorServo.write(pos);             
    delay(50);                      
    }
    delay(500);
 //открываем крышку
    digitalWrite(LED_PIN,!digitalRead(LED_PIN));
    for(pos = pos2door+25; pos >= pos2door+10; pos -=5)  
    {                                  
    doorServo.write(pos);             
    delay(50);                      
    }  
//открываем крышку
    digitalWrite(LED_PIN,!digitalRead(LED_PIN));
    for(pos = pos2door+10; pos >= pos2door-5; pos -=2)  
    {                                  
    doorServo.write(pos);             
    delay(50);                      
    }  
  //высовываем руку
    for(pos = pos1hand; pos <= pos2hand-35; pos +=9) 
    {                                  
    handServo.write(pos);              
    delay(35);                      
    } 
    delay(1000);
 //убираем руку
    for(pos = pos2hand-35; pos >= pos2hand-70; pos -=1)     
    {                               
    handServo.write(pos);              
    delay(15);                       
    } 
    delay(1000);
//высовываем руку
    for(pos = pos2hand-70; pos <= pos2hand+3; pos +=9) 
    {                                  
    handServo.write(pos);              
    delay(15);                      
    } 
    delay(50);
//убираем руку
    for(pos = pos2hand+3; pos >= pos1hand; pos -=7)     
    {                               
    handServo.write(pos);              
    delay(15);                       
    }
//закрываем крышку
    digitalWrite(LED_PIN,!digitalRead(LED_PIN));
    for(pos = pos2door-5; pos <= pos1door+3; pos +=5)  
    {                                  
    doorServo.write(pos);             
    delay(50);    
    } 
   }



Скетч, предлагаемый автором из ссылки в начале обзора, у меня не запустился. А я еще был не тот профи, каковым являюсь сейчас )))))))
В общем, начал разбираться. В итоге, на основе чужого, сделал свой скетч. Добавил защиту от дребезга. Проще, конечно, было поставить резистор с конденсатором, но уж очень хотелось попрограммировать.

Схема

В принципе, схема понятна из скетча. Но я ее все-таки приведу. Уж простите за качество — как смог. Плату преобразователя взял немного другую — в «анфас» не нашел нужной.

Особых пояснений по скетчу нет. Разве что момент добавления угла поворота на несколько градусов, когда скорость сервы большая. Заметил, что если «рука» выскакивает резко, то она не выключает тумблер. Явно это от низкого качества сервоприводов. Поэтому нужно добавить немного к углу вылета «руки». Подозреваю, что при повторении эти добавочные градусы могут быть у вас другими. Зависит от плеча «руки».
И про программы. Пока шесть программ. Вызываются через генерацию случайного числа. Причем простые программы (0, 1 и 2) вызываются чаще обычных. Всем моим тестировщикам показалось, что более навороченные программы должны быть редким приятным бонусом, тогда появляется некая интрига. Так и сделал.
Для любителей цифр — размер коробки: длина — 150мм, высота — 70мм, ширина — 65мм.
Видео
Youtube сильно ухудшил качество. Если нужно глянуть в оригинале — качайте. 21 МБ.
Здесь в скетч внесено изменение, позволяющее увидеть все шесть программ по очереди, чтобы вы имели представление обо всех. В жизни, как я писал, у них псевдо-случайный порядок.


Зарядка производится через микро-USB обычным зарядником от мобильного. Автономность сильно зависит от частоты использования. Иногда несколько суток, а иногда за день «убиваю».

Напоследок.
Проект, тем не менее, вполне можно дорабатывать и дорабатывать. Можно придумывать новые сценарии. Можно добавить пищалку и озвучить устройство. Например пусть «рычит», типа злится, если время между выключением и включением тумблера очень короткое. Можно, как в исходном проекте, добавить перемещение коробочки в разные стороны.
Можно встроить проверку случая, когда «рука», по какой-то причине, не выключила тумблер (например на холоде, серва не дотягивает до нужного угла совсем немного) и скорректировать угол на один раз, написав специально для такого случая какую-нибудь «нервную» программу выключения. Можно поставить Nano и программировать через USB, не разбирая каждый раз устройство.

Да и вообще – можно сделать аккуратнее. Много всяких можно. Собственно именно этим я и предлагаю заняться тем, кого это заинтересовало.
Может я упустил что-то. Крупноват обзор получился для такого простого устройства. Вот за это могу извиниться.
Теперь кот и спасибо за то, что дочитали до конца.
Летняя фотосессия домашнего мышееда

Планирую купить +79 Добавить в избранное +123 +232
+
avatar
  • ABATAPA
  • 29 февраля 2016, 16:39
+21
Автор ограничил доступ к видео.
Сожалеем об этом.
+
avatar
  • vanenzo
  • 29 февраля 2016, 17:09
+1
Автор знатный извращенец )
+
avatar
+2
Извините. Открыл доступ. Закрывал на время редактирования обзора, чтобы добавить в него ссылки на скетч и этот обзор.
А с другой стороны, не специально, но знатно получилось)))
+
avatar
  • Minin
  • 07 апреля 2020, 21:24
0
Скетч не работает, при компиляции выдаёт кучу ошибок, как быть? очень надо.
+
avatar
  • Imho
  • 29 февраля 2016, 16:44
+14
Из названия подумал, что это Arduino Pro Mini — самое бесполезное устройство )
+
avatar
  • nevsky
  • 29 февраля 2016, 16:49
+1
Да, отсутствие кавычек вводит в заблуждение.
+
avatar
  • Kartus
  • 29 февраля 2016, 17:19
+3
Это просто констатация факта)))
+
avatar
  • sergk
  • 29 февраля 2016, 20:19
+1
Я честно говоря так и не понял что там автор себе ваял на ардуинке.
Продраться сквозь не смог…
+
avatar
  • kn_dima
  • 29 февраля 2016, 17:01
+5
Плюс уже за первый абзац :)
+
avatar
  • Sanja
  • 29 февраля 2016, 17:02
+5
Серво SG-90 — печаль. Грохочет пластиковой начинкой, силёнок никаких.

В коде в setup() напрашивается INPUT_PULLUP

Составляющие движений в функциях move_XX() у вас описаны однотипно. Просятся в отдельную функцию, чтобы у вас были пачки инструкций в одну строку, например,

step(from;to;increment);
step(from;to;increment);
step(from;to;increment);

так дебажить проще. Одинаковые значения (например, паузы между движениями) — в константы надо бы убрать, чтобы можно было поправить в одном месте.
+
avatar
  • sir0ta
  • 29 февраля 2016, 19:30
+5
Серво SG-90 — печаль.
Ну да. Я после нее взял металлических MG996R по 280 рябчиков на 10Кг… вот это струя. Я сервами кран полуоборотный кручю и… крепеж погнулся. Смотрю, серва по монитору вроде вдижется, потребление есть, а воды нет. Прихожу, а серва двигает, только не кран, а себя. Хватило же дури направляйку с аккуатора двери вывернуть.
+
avatar
+2
А что за кран? или любой крутит? Я тож собираюсь на сервах электрокраны сделать, ибо фабричные с приводами или совсем неприличных денег стоят, или краны на них сомнительные, и где искать в случае поломки самого крана — непонятно
+
avatar
0
на даче для автоматического полива использую вот такие, aliexpress.com/item/Free-Shipping-G1-Solenoid-Valve-normally-closed-copper-valve-2w250-25-12VDC-24VDC-110VAC-220VAC/1476985553.html
Сезон отработали 8 штук — все норм.
+
avatar
+2
Да, но это клапан а не кран. Я с такими работал — сопротивление потоку они всё-же оказывают намного большее, нежели шаровый кран, жрут много в открытом режиме… Есть «правильные» клапаны — там и тарелка больше, а электромагнит меньше. Там тарелку в закрытом состоянии подпирает сам поток воды, а открывается она снятием этого водяного подпора — маленьким электромагнитом. www.heat-cool.com.ua/img/item/2586/imgdescr.jpg
такой клапан у меня один есть, сопротивление потоку у него меньше, чем у тех, которые с «прямым приводом», но всё-же шаровый это шаровый… один минус — дёргать его надо периодически, чтоб не закисал. Но это уже программная проблема.
И, кстати, по цене. Если надо много (10), то клапаны выйдут в ~22000 р., и жрать будут все разом открытые ампер 10-15. А с сервами выйдет 300 р. серва + кран (300-500), итого 6000-8000 р. если к каждой мелкую тиньку добавить. чтобы получить просто «открыть закрыть» то будет на 100 р. дороже каждая.
+
avatar
  • sir0ta
  • 06 марта 2016, 08:17
0
Полуоборотный. У меня это краны воды и газа на колонке. При чем если газа еще как-то крутил SG-90, то воду ну ни как. Кручу через коромысла (на крану и на серве по рейке, края рейки соеденены через стальную проволоку где-то 1мм в диаметре.\)
+
avatar
0
Спасибо за информацию!
Как-то боретесь с закисаниями кранов? Я читал что их надо хотя б раз в пол годика дергать, чтоб не закисли… Хотя если у вас на колонке — то наверное они чаще перемещаются, чем если делать защиту от протеканий на вводе…
+
avatar
  • sir0ta
  • 08 марта 2016, 08:52
0
Часто ими пользуюсь. На улице полуоборотный (итальнский какой-то) всю зиму простоял, вчерап росто повернул его и все.
+
avatar
  • Berebes
  • 02 декабря 2016, 14:22
0
А можете фото показать как закреплено всё?
+
avatar
  • sir0ta
  • 02 декабря 2016, 16:12
0
Старую конструкцию нет, разобрана. Был смысл такой = — коромысла | — тяги о — кран О — двигатель — - просто заполнитель для движка сайта, он 2 пробела заменяет на 1
======о======
|-------------------|
======O=====
Т.е. верхее коромысло на кран на штуцер закрепляется, нижнее коромысло на двигатель, по края тяги. У меня там краны на 60 градусов, вполне себе хватало.
Сейчас имея 3D принтер все переделано и ось сервы соосна с краном и просто проставка.
+
avatar
  • Berebes
  • 03 декабря 2016, 21:41
0
А может фото как сейчас сделано, с применением зд принтера?
+
avatar
  • sir0ta
  • 04 декабря 2016, 07:03
0
Как на месте не пойду, холодина на улице. Это перед монтажем на пк нашел фотки.

+
avatar
  • Yaguar
  • 29 февраля 2016, 22:00
+2
Тоже интересует какой кран Вы применяете. Модель, ссылку или фото плиз.
+
avatar
  • sir0ta
  • 04 декабря 2016, 08:28
0
Ну пол дюймовый вертит только в путь. 3/4 тоже. Дюймовых у меня нет.
+
avatar
  • ShadowHD
  • 29 февраля 2016, 20:21
0
Захотелось уточнить, как я понял INPUT_PULLUP — позволяет не ставить на контакт подтягивающий резистор? В статье написано, что это фича новых (с поправкой на 2 года давности) версий ардуины, какая вероятность, что китайские будут это поддерживать?
+
avatar
  • ksiman
  • 29 февраля 2016, 20:26
+4
какая вероятность, что китайские будут это поддерживать?
Это фича самого контроллера
+
avatar
  • ShadowHD
  • 29 февраля 2016, 21:18
0
интересная штука, надо будет не забыть попробовать
+
avatar
  • sav13
  • 01 марта 2016, 06:13
+1
Это поддерживают все микроконтроллеры Atmega328. НО
1. Встроенные резисторы довольного большого номинала и поэтому довольно помехонеустойчивые
2. Встроенные резисторы, бывают, сгорают. И об этом вы не узнаете.

Так что для надежности лучше проверенные 10к на VCC
+
avatar
0
Спасибо. В целом не удивительно, но для тестов будет удобно использовать, главное не забыть исправить в «продакшене»
+
avatar
+1
молодец, руки из нужного места растут, а я так и не осилил как гуманитарии ардуино, зато «осилил» esp8286, похоже на esp не так много некачественных «изделий», вот отличий от ардуино, хотя сами модули ардуины активно использую, а вот сами платы ардуины не пошли… мистика
+
avatar
  • udavst
  • 29 февраля 2016, 17:56
0
ардуин заказывал много и разных, по такой цене удобно получить разведённый контроллер и не травить плату, ну и плюсом стабилизатор и ненужный кварц. Ниразу не попадал на «некачественно», тк не понятно чему там быть некачественному, там же примитив, а контроллер неплохой для простых задач, разве что дорабатывать приходится, если электричество нужно экономить.
+
avatar
0
соглашусь по аппаратной части может и примитив, а вот программно подбирать библиотеки это не очень, тот же печальный для меня «етхернет» модуль на enc28j60, дешевый вроде, а библиотеку подобрать что бы работало стабильно с моим роутером так и не смог, пришлось покупать «дорогой» и проверенный модуль на Wiznet W5100...(((
+
avatar
0
ESP-шек заказано три штуки. Мне понравилась идея этих модулей. Есть пара задумок… Но это позже. Пока еще на ардуино не наигрался всё сделано. И три GSM-модуля ждут своего часа. Пока только поигрался с смс-ками и отложил. Торопиться не надо.
+
avatar
  • Pigmat
  • 29 февраля 2016, 17:26
+1
Простите ламера), но что конкретно делает данное устройство?)
+
avatar
+1
Выключает себя.
Типа, работать не хочет.
+
avatar
+9
Стоит оно на моем рабочем столе. Когда меня «берет», я поиграюсь с ним, и меня отпускает. Что-то вроде антистресса.
+
avatar
0
Выключатель питания стоит установить до преобразователя напряжения 5в, иначе постоянное, хотя и небольшое
потребление батареи
+
avatar
  • Myx
  • 29 февраля 2016, 17:27
+2
Как там на ЯПе говорят: однозначно зелень! ))
+
avatar
  • krysa
  • 29 февраля 2016, 17:28
+3
у кота зубы растут из правильного места
+
avatar
  • serg_mur
  • 29 февраля 2016, 17:34
+2
Автор, Вы молодец! Тоже далеко за 40, и тоже осваиваю Ардуино. Да, мозги нужно тренировать и развивать. Плюс и плюс.
+
avatar
  • DDimann
  • 29 февраля 2016, 17:50
+2
А шо? Весьма полезная штука получилась.
Нет ничего полезнее бесполезных вещей, потому как только бесполезные вещи делаются исключительно для души, так что + явно заслужен :)
+
avatar
  • Bhakti
  • 29 февраля 2016, 18:02
0
что оно делает? крышку коробки открывает и закрывает? видео нет, непонятно) а все глянул. устройство похоже на копилку,там монетку кладешь и лапа кота ее забирает )
+
avatar
0
Видео уже есть. Исправился.
+
avatar
  • Aloha_
  • 29 февраля 2016, 18:15
+12
Вероятно идея почерпнута отсюда

Так что автору есть куда стремиться =)
+
avatar
+2
Я побаиваюсь японцев…
+
avatar
  • Nkk
  • 01 марта 2016, 22:16
+1
онто ни ковай десу нэ
+
avatar
  • Nkk
  • 01 марта 2016, 22:55
+1
в конце ролика она спрашивает «выключатель, где выключатель?», т.к. выключатель перемещается и ручка по нему не попадает
+
avatar
  • Yuu
  • 02 марта 2016, 01:02
0
Спасибо, поржал!
+
avatar
0
Вот что значит правильно растущие руки и генератор безумных идей в дополнение.
+ однозначно.
+
avatar
0
Плюс за стремление к творчеству.
Замечание за знание английского. «Useless» пишется немного не так, как вы написали.
Лайфхак: пожно написать кирилицей «бесполезная коробка». Ютуб от этого не сломается.
+
avatar
0
Точно. Даже не заметил! Исправил.
+
avatar
  • li4nost
  • 29 февраля 2016, 18:53
0
не умею, но хочу такое же…
спасибо за желание начать разбираться!
+
avatar
  • sir0ta
  • 29 февраля 2016, 19:17
+7
Коли уж начали учить, учите сразу правильно, потому переучиваться сложнее. Начнем:
int pos1door = 70; //начальное положение сервопривода крышки
int pos2door = 30;  //конечное положение сервопривода крышки
int pos1hand = 10;  //начальное положение сервопривода руки
int pos2hand = 160;  //конечное положение сервопривода руки

заменить на #define pos1door 70
Следом использование типов переменных. uint16_t там где это не надо не следует. Есть uint8_t.
Все используемые пины описывайте
#define servo1 5

Так в случае если пин переедет не надо его искать.
//открываем крышку
    for(pos = pos1door; pos >= pos2door+15; pos -=5)  
    {                                  
    doorServo.write(pos);             
    delay(15);                      
    }
    delay(1000);
//закрываем крышку
    for(pos = pos2door+15; pos <= pos1door; pos +=5)    
    {                               
    doorServo.write(pos);             
    delay(15);                     
    }
    delay(1000);
//открываем крышку
    for(pos = pos1door; pos >= pos2door; pos -=5)  
    {                                  
    doorServo.write(pos);             
    delay(15);                      
    }
//высовываем руку
    for(pos = pos1hand; pos <= pos2hand+2; pos +=5) 
    {                                  
    handServo.wr

Описываем как отдельные функции:
void moveServo(int8_t znak) {
 for(pos = pos1door; pos >= pos2door; pos +=(znak*5))  
    {                                  
    doorServo.write(pos);             
    delay(15);                      
    }
}

Вызываем скажем так:
moveServo(-1);
moveServo(1);
Если добавить ссылки и указатели, то можно еще и для всех серв 1 функцию намаслякать.

Пользоваться random() без randomSeed() не интересно, ибо всегда генерируется одна последовательность по дефолту.
И подтягивающие резистры желательно юзать внешние. Внутренние хоть и есть, но если он умрет — будет не айс…
+
avatar
  • BeJIuk
  • 29 февраля 2016, 21:15
0
Есть uint8_t.
А для чего используют uint8_t? Почему не unsigned char?
+
avatar
  • dts
  • 29 февраля 2016, 21:23
0
а в чем различие uint16_t, uint8_t и int8_t от просто int?
+
avatar
+2
Не знаю, как в ардуино, в C и C++ размер целочисленных типов не задан жёстко и зависит от платформы. Просто соблюдается соотношение char <= int <= long. Для x86 int 32 бита, x64 — 64 бита. В обычных атмегах int 16 бит, если ничего не путаю. Размер uint16_t будет всегда 16 бит, независимо от компилятора.

«u» в начале означает unsigned — беззнаковый, то есть int8_t может быть от -128 до 127, uint8_t от 0 до 255. Помните стишок про 10 программистов? :)
+
avatar
  • dts
  • 29 февраля 2016, 21:50
0
стало понятнее, а long это для чего?
+
avatar
+2
это когда диапазона int не хватает :) Кстати, ещё бывает long long!

А вообще все эти _t нафиг не нужны, пока вас не беспокоят проблемы портируемости и кроссплатформенности.
+
avatar
  • dts
  • 29 февраля 2016, 22:54
0
а если нужно не целое, а дробное записать, то float int8_t, например?
+
avatar
  • Bacchus
  • 29 февраля 2016, 22:57
+2
Я может отстал от жизни но float int у меня вызвал когнитивный диссонанс :-)
+
avatar
  • yurok
  • 29 февраля 2016, 23:50
0
да уж… сладкая соль )
+
avatar
  • sav13
  • 01 марта 2016, 06:15
-1
Интересно как у компилятора крыша не съехала?
+
avatar
0
На самом деле float это не дробное число а целое число с подвижной запятой. Истинное дробное число будет состоять из двух целых чисел представляющих собой числитель и знаменатель, но математика с такими числами становится нетривиальной.
+
avatar
  • sir0ta
  • 29 февраля 2016, 21:58
0
Размерность. msdn.microsoft.com/ru-ru/library/s3f49ktz.aspx
int16_t — 2 байта -32 768 до 32 767
uint8_t — 1 байт — 0 до 255
а скажем int8_t — 1 байт — -128 до 127
int — челых 4 байта! -2 147 483 648 до 2 147 483 647 (он же int32_t)
u — unsigned — т.е. без знака
Скажем мы знаем что положение сервы может меняться только от 0 до 180. Значит нам вполне хватает uint8_t
+
avatar
  • yurok
  • 29 февраля 2016, 22:09
+1
ну вы нашли куда ссылаться, микрософтовцы пусть там читают )
habrahabr.ru/post/156593/ — вот популярно
тут кратко и таблично применительно к AVR (а значит к ардуино):
digitalchip.ru/skolko-vesyat-tipyi-dannyih

кратко:
char 1 (8) -128… 127
unsigned char 1 (8) 0… 255
signed char 1 (8) -128… 127
int 2 (16) -32768… 32767
unsigned int 2 (16) 0… 65535
signed int 2 (16) -32768… 32767
short int 2 (16) -32768… 32767
unsigned short int 2 (16) 0… 65535
signed short int 2 (16) -32768… 32767
long int 4 (32) -2147483648… 2147483647
unsigned long int 4 (32) 0… 4294967295
signed long int 4 (32) -2147483648… 2147483647
float 4 (32) 3.4Е-38… 3.4Е+38
double 4 (32) 3.4Е-38… 3.4Е+38
long double 10 (80) 3.4Е-4932… 3.4Е+4932

производные:
int8_t signed char
uint8_t unsigned char
int16_t signed int
uint16_t unsigned int
int32_t signed long int
uint32_t unsigned long int
int64_t signed long long int
uint64_t unsigned long long int
+
avatar
  • sir0ta
  • 29 февраля 2016, 22:17
0
А что не так? у майкросовтовцев есть таблица, в ней все написано. Более читать там не чего.
+
avatar
  • yurok
  • 29 февраля 2016, 22:25
+2
__int16 у них и int16_t — ни о чем не говорит?

__int16 работает в Visual Studio 2015 — там так и написано
табличка для тех кто там пишет, а остальные, в том числе и автор обзора, пишут не там

у майкрософт свои стандарты — отличающиеся от других, туда нужно ссылаться если разработка идет в той среде
+
avatar
  • Sanja
  • 29 февраля 2016, 22:45
0
Ардуину, к слову, очень приятно программировать в Visual Studio…
+
avatar
  • yurok
  • 29 февраля 2016, 22:46
0
приятно? :)
+
avatar
  • sir0ta
  • 29 февраля 2016, 23:28
0
Ну понятно что кого-то надо ткнуть носом, но для общего взора на типы данных в принципе хватает. А уж если голова на плечах есть, то додумать не велика проблема. Если уж не хватает, я бы не советовал садится за программирование. так светиками помигать, чужой код по копипастить, но не более.
+
avatar
  • Antares
  • 01 марта 2016, 13:21
+1
Человек про отличия «просто int» спросил, а вы ему «int — челых 4 байта! -2 147 483 648 до 2 147 483 647»,
хотя в AVR GCC int 2 байта -32768… 32767.
Так и представляю: автор написал программу для Arduino Mini, которая ждет условия (переменная_int>100000), спрашивает «почему не работает?» на той же амперке, ему намекают на тип данных, а он — вот же, сам Майкрософт написал!
Иногда лучше отсутствие данных (тогда человек на оф.сайте найдет правильные), чем ложная уверенность в неправильных данных.
+
avatar
  • sir0ta
  • 01 марта 2016, 14:05
0
Матюк назад. Я виндовый программист привык что int это uint32_t (хотя я вообще делфятник и у меня integer, real и прочие)
А тут для себя понял что чтобы не теряться надо юзать XintN_t и все сразу становится предельно ясно )
+
avatar
  • Bacchus
  • 29 февраля 2016, 21:59
+1
Когда не надо экономить память — ничем :-)
+
avatar
  • sir0ta
  • 29 февраля 2016, 22:16
0
культура программирования… Я вот полтора года назад по необходимости достал старый проект. Он лопатил 2 базы и вставлял в 3-ю. В общем на скоряк я обработал ей данные, ушло на это 3 часа. Потом дня 3 я оптимизировал код и менял алгоритмы так что бы работало быстрее и красивее. Итог — те же действия программа делает пол часа. С того момента до сегодняшнего дня я пользовался обработкой порядка 10 раз. Это 25 часов экономии времени. С учетом того что мой рабочий день продуктивный где-то 4-5 часов — я отбил это время,
+
avatar
  • Bacchus
  • 29 февраля 2016, 22:25
0
Мне по наследству достался один проект. В котором в том числе производился расчет ликвидности. Он проходил около 2, потом 3, потом 4х :-).
Добавлением одного (ОДНОГО, КАРЛ!) индекса я свел его до получаса
+
avatar
  • sir0ta
  • 29 февраля 2016, 23:23
0
Оптимизация чистой воды ) Почему так не было сделано сразу? Не знание? Отсутствие желания? Может не хватило смекалки?
+
avatar
  • Bacchus
  • 29 февраля 2016, 23:42
+2
Тут много нюансов.
Если в табличках 100 записей то это будет отлично работать и без него. даже быстрее чем с ним.
Потом таблички некисло разрастаются и почему-то без него начинает работать хреново :-)
Ну и самый главный принцип: Ты сделай, чтоб хоть как-то работало, потому что завтра вчера нам надо это сдавать :-)
+
avatar
0
заменить на #define pos1door 70
Можно просто const добавить. Ещё могу ошибаться, но константы и макроподстановки вроде традиционно пишут большими буквами.
+
avatar
  • Bacchus
  • 29 февраля 2016, 22:03
0
это зависит от языка и культуры написания
+
avatar
  • sir0ta
  • 29 февраля 2016, 22:09
0
Ну я сам всего ни чего как в С перешел. так что много что сам еще учу. И вот все время хотел почитаь по поводу отличия дефайн и констант. И тут вы меня сподвигли. И вот что я выяснил для себя:
const uint8_t n1=1;
uint8_t n2=2;
n2+=n1 //тут мы обращаемся к ячейке памяти где хранится n1
n2+=n1 //и тут мы обращаемся к ячейке памяти где хранится n1
а с #define… Смотрите сами:
#define n1 1
uint8_t n2=2;
n2+=n1 //тут мы обращаемся к ячейке памяти где хранится 1
n2+=n1 //а тут мы обращаемся к другой ячейке памяти где хранится 1
Выходит define ложная катавасия в плане экономии ресурсов
Плюс (нам это не грозит) при отладке скажем при #define test 123 в случае если будет проблема с этими 123, то отладчик покажет 123, а не test и получистя не будет известно от куда взялось это 123. Т.е. скажем когда

uint8_t n1=0;
#define test 5/n1

мы не будем знать где произошло это деление на 0 точно. В таком случае в C++ (в С нет) inline функции. Блин… я программист, меня год учили C++, а я сдал последнюю лабу за 1 месяц и не ходил на занятия целый курс… Я много пропустил )
+
avatar
+2
Директивы препроцессора это страшная вещь… :)
Если интересно, вот большая статья про них.
Удивительно, но в плюсах тоже частенько можно встретить, причём не только в роли #include guard. Последний особенно впечатливший меня пример — это реализация исключений в Poco. Нет, я всё понимаю, но взять и настрогать классов дефайнами…

Насчёт памяти вы правы, хотя мне кажется, что компилятор должен уметь оптимизировать такие вещи.
+
avatar
  • sir0ta
  • 29 февраля 2016, 23:40
0
Ну я читал что вроде бы у стокового компилятора не все гладко с этим. Хотя я пройдясь по uint16_t и переписав местами const в #define, местами прикрутив макросы вместо функций (теперь знаю что надо делать inline), и отказавшись от либо явного указания переменных с плавающими точками либо вообще от их использования с 80% памяти съехал до 50. А глобальным перемнным вообще норм, с 80% до 30%. Долго тужился с отказом от string, но выходило слишком громоздко и нудно (utf8...) и обратно ввел и все что я наоптимизировал все ушло в string (
+
avatar
+1
#define n1 1
uint8_t n2=2;
n2+=n1;

«1» нигде не хранится, в том смысле в каком это понимаете вы — эта константа будет непосредственно в коде.

А вот если у нас n1 — это const uint8_t, тогда в коде у нас будет другая константа: адрес той ячейки памяти, в которой лежит значение «1». И добавится лишняя операция — чтение по данному адресу.

Хотя, компилятор может и соптимизировать это, сведя ситуацию к предыдущей. Кстати, интересный вопрос, каковы дефолтные опции компилятора в среде ардуино. Надо б посмотреть… :)
+
avatar
  • sir0ta
  • 01 марта 2016, 05:55
+1
Но весь код лежит в адресном пространстве. И эта 1 занимает там место.
+
avatar
  • Antares
  • 01 марта 2016, 13:52
+2
В микроконтроллере гарвардской архитектуры (в т.ч. ATmega328P в Arduino Mini) не одно адресное пространство. Отдельно — память команд, отдельно — данных.
Константа непосредственно в коде (#define) — инструкция LDI www.gaw.ru/html.cgi/txt/doc/micros/avr/asm/ldi.htm — занимает 2 байта памяти программ и исполняется за 1 цикл, константа в оперативной памяти (const) — LDS www.gaw.ru/html.cgi/txt/doc/micros/avr/asm/lds.htm — 4 байта и 3 цикла + место в памяти данных под эту константу, константа в памяти программ (PROGMEM const) — LDM www.gaw.ru/html.cgi/txt/doc/micros/avr/asm/lpm.htm — 2 байта и 3 цикла (и еще команда загрузки в Z) + занимаемая под константу память программ. Так что если константа не более 255 — #define оптимален и с точки зрения экономии памяти программ, и памяти данных, и быстродействия.
+
avatar
  • yurok
  • 01 марта 2016, 14:16
0
в программах для большого брата препроцессор выглядит устаревшим и не желателен к использованию (в первую очередь из-за непрозрачного сопровождения кода), в атмегах — он вполне работает и позволяет экономить ресурсы
+
avatar
  • sir0ta
  • 01 марта 2016, 14:16
0
Буду знать. Спасибо.
+
avatar
0
По-моему, вы зря лезете в эти дебри. Если уж так важны эти такты, то надо отказываться от ардуино и писать под голый контроллер на ассемблере, которого я, например, не знаю и не горю особым желанием учить.
+
avatar
  • sir0ta
  • 01 марта 2016, 14:24
0
Ну есть культура написания кода. Т.е. какие-то правила которые позволяют код сделать изначально оптимальным и красивым. Вот эти дебри и позволяют где-то заюзать define, а гдето inline, а где-то функцию, а где-то константу. Вот сегодня оптимизировал код одного паренька. В принципе после оптимизатора мой код выигрывал у оригинала порядка 30% программного кода и 50% глобальных переменных. СРазу я начал переписывать (читай исправлять) код, ушло на это 2 часа и я прошел только 1/3 всего кода. Потом я плюнул на все, и написал весь код заного учитывая мои познания. Ушло порядка 2-х часов, но результаты я вам уже представил.
+
avatar
  • Bacchus
  • 01 марта 2016, 14:34
+1
Ну вам ли не знать культуру кода дельфистов :-)
+
avatar
0
Константы это числовые подстановки, константа может содержать только число. А дефайн вещь более гибкая и мощная. Это текстовая подстановка на уровне исходника. Использование дефайна в качестве константы это лишь частный случай, надо отдавать себе отчёт что это будет просто подстановка в исходнике, а по нему уже ПОТОМ пройдётся компилятор. Чтобы не забыть что есть что к дефайнам обычно добавляют подчеркивание в начале имени, вроде как грязный гаечный ключ лежащий в машинном отделении.
+
avatar
  • sir0ta
  • 06 марта 2016, 08:21
0
Мы уже установили это. Вопрос стоял в другом — оптимизация. Скажем используя const uint_t n=5; мы использовали 2 байта в global variables, в то время как #define n 5 в именно кодинге ни чем не отличается кроме того что количество циклов обращений сводится к 1 и не занимает места в памяти кроме своего места в коде.
+
avatar
  • spc
  • 29 февраля 2016, 19:36
+11
Шикарно! А вот мой кумир:

+
avatar
0
Классно! Моё творение закончилось на этом. Всё никак руки не доходят доделать)
+
avatar
  • plashkin
  • 29 февраля 2016, 20:09
0
unleses box
имели в виду useless?
+
avatar
0
Исправил)) Мне ближе было бы написать Die nutzlos box.
+
avatar
  • Sanja
  • 29 февраля 2016, 22:55
0
Der nutzlose Kasten.
+
avatar
0
Geeignet. Но немецкие песни я не люблю.
+
avatar
  • yurok
  • 29 февраля 2016, 20:18
+6
хорошая поделка и ее описание!

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

однозначно плюс…

а главное, когда пишешь — вроде и писать особо нечего — все очевидно (поле граблей после изготовления готового устройства — кажется только твоим, и у других, опять же ощущение, его не возникнет)
+
avatar
  • Herts
  • 29 февраля 2016, 20:50
+3
поржал с видео. теперь хочу эту фигню)
+
avatar
  • IVF
  • 29 февраля 2016, 21:00
+2
Я, как начинающий ардуинщик (ардуиновод? ардуинофил?), задумался. Надо будет сделать нечто подобное, хотя бы для тренировки мозгов и рук.
+
avatar
  • ksiman
  • 29 февраля 2016, 21:01
+2
Я, как начинающий ардуинщик (ардуиновод? ардуинофил?)
А в дальнейшем ардуинофоб :)
+
avatar
  • OkeaH
  • 29 февраля 2016, 21:07
+6
Мне на арудинке такие роботы импонируют. Надо будет как-нибудь заказать арудинку и смастерить такого же.
+
avatar
  • ksiman
  • 29 февраля 2016, 21:21
0
Ресурсов ардуины тут не хватит
+
avatar
  • zavulonq
  • 29 февраля 2016, 21:40
+1
Тут минимум малину нужно использовать:-)
+
avatar
  • Sanja
  • 29 февраля 2016, 23:11
+2
цилиндр сверху — это LIDAR, он быстро вращается и создаёт трёхмерную картину местности. Не всякий десктопный компьютер такое осилит.

Посмотрите лучше в сторону гексаподов:

+
avatar
  • sav13
  • 01 марта 2016, 06:18
+4
Тоже смотрю за этим проектом. Прямоходящий тоже очень нравится
+
avatar
  • bdos
  • 29 февраля 2016, 21:35
0
Идеальный обзор — есть все!
+
avatar
  • Bacchus
  • 29 февраля 2016, 21:50
0
Пришел с работы, посмотрел видео. Обалденная штука! Будет время — слабаю такую себе
Плюсанул
+
avatar
  • dts
  • 29 февраля 2016, 22:00
0
круто было бы найти список использованного железа, которое есть на али, и выкройки корпуса и «пальцев» для сервов, чтобы повторить такую коробку, не заморачиваясь.
+
avatar
+1
Всё «железо» в статье. Добавить можно разве дюпон-соединители. Брал здесь. Но их использовано несколько штук, и заказывать много не стОит. Также использованы разъемы от старого системника (female) для светодиода и тумблера. Клей и пистолет куплены так давно, что даже не помню где. Но не на Али.
Выкройка корпуса проста — простые формы. Размер не проектировался специально. Были листы фанеры, формата 200х315 толщиной 3 мм. Я его обрезал до размера 150х315 мм. Потом покромсал на полоски двух ширин: одна полоса шириной 59мм и четыре полосы шириной 64мм. Верхняя, нижняя и боковые крышки абсолютно одинаковые, 150х64мм. Зад и перед вырезаны из одной полосы, их размер 64х59мм. Крышка формируется легко — распиливаем одну полосу ножовкой по металлу. Ее толщина и есть зазор между подвижной и неподвижной крышками. Толкатель крышки в моем примере имеет размер 28х9мм с закругленными углами. «Руку» вырезал так. Приклеил серву на тонкий двусторонний скотч. Взял кусок толстого картона и накидал выкройку. Привинтил ее винтами и правил ножницами. Без подключения сервы. Просто двигал рукой. Центр отверстия для тумблера расположен на расстоянии 21мм от края, из-за которого вылетает рука. Размер руки нужно подбирать исходя из высоты тумблера и хода его рычажка.
У меня «рука» имеет такие размеры:

Поверьте, из картона заготовка вырезается на раз.
В моем случае, я ошибся с расположением сервы. Правильнее было бы установить не сбоку, а перед тумблером, вытянув ее вертикально. Тогда можно упростить «руку» до г-образной, и сделать ее тоньше.
Если захотите прикрепить какую-то нашлепку, для пущего дизайна, обязательно просверлите под ней дырку. Тогда у этой детали появится еще и сугубо практическое назначение.
+
avatar
  • opposite
  • 29 февраля 2016, 22:14
0
Собственно, такую штуку можно было сделать и без Ардуино:)
+
avatar
  • sir0ta
  • 29 февраля 2016, 22:19
0
С генератором без мк было бы туго. Вы бы на логике все собирали? Удачи.
+
avatar
0
Не «собирал бы», а собирал всего лишь на моторе с редуктором, батарейках и выключателе. Ардуина здесь — как из пушки по воробьям
+
avatar
  • sir0ta
  • 01 марта 2016, 07:30
0
На моторе с редуктором вы могли использовать ик датчик расстояния? Или рандомное время когда вылезет рука. Или движения туда/сюда? Ардуина — это всего лишь МК с обвязом готовая к употреблению и способная в любой момент времени быть прошита новой прошивки без мучений с фьюзами и прочим. Так что на одном моторе вы бы ни уехали.
+
avatar
0
Я знаю, что такое Ардуино. И без неё сделал уже больше десятка самых бесполезных устройств на подарки, в которых не было Ардуино, только моторчик, который работает от батареек
+
avatar
  • sir0ta
  • 01 марта 2016, 14:01
+1
Покажите нам. ПОжалуйста. Я не против узнать что-то новое.
+
avatar
0
Хорошо, как раз нужно ещё одну сделать
В принципе, моторы у меня тоже с Али, могу и обзор запилить:)
+
avatar
  • sir0ta
  • 01 марта 2016, 15:04
0
Давайте! Если не тут, то мне ссылку в личку пожалуйста ) Буду ждать!
+
avatar
  • bigvlad
  • 29 февраля 2016, 22:51
+6
А мне вот такой понравился
+
avatar
  • Lithe
  • 29 февраля 2016, 22:56
0
А что за синяя бирка на коробке?
+
avatar
+1
В тексте есть описание. Это очень непростая бирка!
+
avatar
  • vismyk
  • 01 марта 2016, 06:22
0
Кто, интересно, придумал название «Самое бесполезное устройство»? Раз оно развлекает пользователя — оно уже всяко не бесполезное! Сам Клод Шеннон назвал это своё изобретение «Абсолютной машиной». Говорят, что когда он показал свою абсолютную машину Артуру Кларку, у того случился культурный шок… ;)
+
avatar
  • Nkk
  • 01 марта 2016, 17:24
0
Подскажите, пожалуйста, будет ли достаточно производительности и разъемов Atmega328 для чтения NMEA-сообщений из GPS-модуля и записи их на карту памяти? Сколько примерно будет потреблять, есть ли разница между 5-и и 3-вольтной версиями?
Находил описание, как писать на карту, но хотелось бы изучить девайс последовательно. С чего начать, желательно на русском языке.
+
avatar
0
Хватит с головой. GPS-модуль будет в 10 раз больше потреблять.
А 3 или 5В версия надо подбирать под GPS-модуль чтобы потом не добавлять согласование уровней. Скорей всего нужно будет 3-х вольтовую версию.
+
avatar
  • manatu
  • 02 марта 2016, 01:09
0
ОГРОМНОЕ спасибо за обзор этой «бесполезной вещи»! Ну а каменты как всегда очень полезные, поэтому комментаторам отдельное спасибо!
+
avatar
  • Tuks
  • 02 марта 2016, 07:45
0
Большое спасибо автору, очень крутая статья. Загорелся покупкой ардуины и изготовлением такого девайса.
Может знающие подскажут, что лучше взять — arduino nano или micro?.. И еще вопрос — выдержат ли эти ардуино мощность серв? Это нужно в даташите на ардуино смотреть?
+
avatar
  • vismyk
  • 03 марта 2016, 06:21
0
Если выбирать между нано и микро, то лучше микро, но они и дороже. Если гнаться за рекордом по цене, то лучше про-мини на АТМеге168 вместо 328, для многих применений этого вполне достаточно. ;) По мощности: насколько помню, нагрузочная способность ардуины — до 40мА на ногу и то желательно поменьше нагружать, поэтому для сервоприводов нужны драйверы.
+
avatar
  • Tuks
  • 03 марта 2016, 21:44
0
Спасибо. Буду пробовать. Уже представляю восторг дочки от такой игрушки.
+
avatar
0
Вообще сервам драйверы не нужны, они управляются слаботочкой а большой ток потребления у них по шине питания что уже собственно выходов контроллера не касается и проблемы могут возникнуть только при неудачной разводке шин питания.
+
avatar
  • scorpid
  • 02 марта 2016, 11:09
0
Плюс за кота :)
+
avatar
  • A11
  • 09 марта 2016, 09:40
0
Вещица забавная!
А если бы еще динамик с «рычанием» «гавканьем» и жалобными звуками добавили… ребетенка было бы не оторвать)))

Если бы наш дед соорудил такую штуку своему внуку… то привил бы страсть к такому творчеству надолго)))
+
avatar
0
Забавная штука! Дочка впечатлилась вашим творением — пришлось делать заказ на ардуино и сервы. Правда в ардуино я полный ноль. А TTL преобразователь для чего? Программировать?
+
avatar
  • ganzubas
  • 25 сентября 2016, 21:18
0
Отличная работа. Было бы не плохо добавить МР3 шильд для озвучивания действий. Записать недовольное рычание и всякие прикольные звуки…
+
avatar
  • serg3d
  • 30 января 2018, 19:27
0
Очень понравилось данное устройством. Решил сделать свой вариант www.youtube.com/watch?v=ytywdSoROJM&t=1s
+
avatar
  • Klinskyi
  • 07 августа 2018, 09:08
0
На Arduino Pro Mini что то не заработало, на Nano пошло. Проблема с дребезгом приводов в режиме ожидания. Что делать?
+
avatar
  • Bash
  • 24 декабря 2018, 22:55
0
при компиляции ругается на строку Serial.println®, параметр ( r) видимо скопировался некорректно)