В первой статье про принтер 3D MC3 Мастер v1.1 я описал первый опыт сборки 3D принтера из готового набора. С тех пор прошло немало времени, я извел немало пластикового прутка, обучаясь тонкостям 3d печати. Накопил немного личного опыта и хочу рассказать о методах повышения точности при печати на конкретно взятом примере. Во второй части статьи расскажу об изделии, которое напечатал, собрал и усовершенствовал — автономных ушках, о которых говорилось здесь и здесь.
Поразвлекавшись с печатью стандартных кубиков, решено было напечатать что-то побольше и функциональнее. В процессе эксплуатации всплыла проблема следующего толка: слои ложились небольшой гребенкой, а иногда стол смещался в стороны из-за быстрого перемещения по осям X и Y. Методов решения этой проблемы целых два:
- Жестко зафиксировать стол в креплениях. Так как стекло очень гладкое, а пластик не фиксирует стол жестко, то проще всего стекло приклеить к ножкам термоклеем, который легко снимается впоследствии, или скотчем. Так мы избавимся от движения стола.
- Также заметные искажения может вносить небольшой люфт оси Z. В официальной поставке двигатель этой оси со шпилькой объединен пластиковой деталью и она не всегда идеально отцентрирована по центрам осей. Поэтому я перешел к надежной металлической втулке с фиксацией болтами и гарантированной центровкой. Небольшой люфт пропал и качество печати заметно улучшилось.
Сама деталь выглядит следующим образом:
Результатом таких улучшений стало возможным напечатать такие детали:
Тут можно переходить ко второй части улучшений. Мне давно нравились движущиеся ушки и я прочел пару материалов, как они создавались и как их усовершенствовали. Но каждый раз словно спотыкался обо что-то. В конце концов, я понял, чего лично мне не хватает в этом проекте и что заставляет задуматься: необходимость в действиях человека для активации движения. Выход прост: надо автоматизировать работу аниматроники. Самое простое — это написать цикл, в котором рандомно будут запускаться те или иные процедуры шевеления ушами, но это ведь не наш метод!
Решение пришло быстро: все дело в звуке. В закромах сайта masterkit.ru обнаружился вот такой модуль:
Прелесть его в том, что он является законченным решением, а значит можно избежать работы с паяльником и просто подключить к разъемам Arduino. Минус конкретно этого модуля — он имеет два логических положения: вкл и выкл. То есть он не выдает величину сигнала. Таким образом, не удастся привязаться к громкости говорящего, а только к наличию звука.
Идея заключается в следующем:
1. Звука нет — уши вращаются какое-то время, а после складываются в «сон»;
2. Звук появляется — уши дрожат и поднимаются;
3. Звук продолжается — уши крутятся и попеременно складываются;
4. Звук исчезает — см пункт 1.
Возможность доработки:
1. Если с микрофона снимать не дискретный сигнал с двумя положениями, а аналоговый, когда громкость звука разная, то можно добавить количество эффектов: громкий хлопок — и уши складываются в испуге.
2. Добавить второй микрофон и расположить их по сторонам — можно поворачивать уши в сторону говорящего.
3. С двумя микрофонами каждое ухо может «жить своей жизнью»
Ну а пока вернемся к блогу, где рассказывалось про питание без шлейфа проводов и вместо bluetooth адаптера добавим имеющийся микрофон. Далее модифицируем имеющийся код и поучаем уши, работающие по звуку. Самым длительным в этой истории стала подстройка громкости звука резистором, при котором блок микрофона будет выдавать сигнал на микроконтроллер — тут все устанавливается только опытным путем.
Servo LeftVer;
Servo LeftAng;
Servo RightVer;
Servo RightAng;
const byte LeftVerPin = 2;
const byte LeftAngPin = 3;
const byte RightVerPin = 4;
const byte RightAngPin = 5;
const int SensorPin = 9; //микрофон
int ledPin = 13; // светодиод
const byte Button_1 = 6;
const byte Button_2 = 7;
const byte Button_3 = 8;
const byte Button_4 = 11;
const byte Button_5 = 10;
int i=0;
int pos = 0;
int SensorState = 0;
boolean BowFlag = 0;
boolean RearBowFlag = 0;
void setup()
{
pinMode(ledPin, OUTPUT); // initialize the Sensor pin as an input:
pinMode(SensorPin, INPUT); // разъем ушей устанавливаем, как вход
LeftVer.attach(LeftVerPin);
LeftAng.attach(LeftAngPin);
RightVer.attach(RightVerPin);
RightAng.attach(RightAngPin);
pinMode(Button_1, INPUT);
pinMode(Button_2, INPUT);
pinMode(Button_3, INPUT);
pinMode(Button_4, INPUT);
pinMode(Button_5, INPUT);
digitalWrite(Button_1, HIGH);
digitalWrite(Button_2, HIGH);
digitalWrite(Button_3, HIGH);
digitalWrite(Button_4, HIGH);
digitalWrite(Button_5, HIGH);
InitState();
delay(1000);
}
//------------------------------------------------------
void loop()
{
SensorState = digitalRead(SensorPin); // check if the Sensor is close. // if it is, the SensorState is HIGH:
if (SensorState == HIGH)
{
digitalWrite(ledPin, HIGH);
i=i++;
}
if (i==6)
{
i=1;
}
if (i=1)
{
if (!BowFlag)
{
FrontBow();
BowFlag = 1;
}
else
{
InitState();
BowFlag = 0;
delay(200);
}
}
if (i=2)
{
LeftEarBow();
InitState();
}
if (i=3)
{
RightEarBow();
InitState();
}
if (i=4)
{
TwoEarsBow();
InitState();
}
if (i=5)
{
if (!RearBowFlag)
{
RearBow();
RearBowFlag = 1;
}
else
{
InitState();
RearBowFlag = 0;
}
delay(200);
}
}
//------------------------------------------------------
void FrontBow()
{
byte Max = 90;
byte Min = 70;
unsigned int MoveDelay = 5;
unsigned int PosDelay = 500;
for(byte i=0; i <= (Max — Min) + 15; i++)
{
LeftAng.write(Min + i);
RightAng.write(Max — i);
delay(MoveDelay);
}
// delay(PosDelay);
for(byte i=0; i <= 3*(Max — Min) + 17; i++)
{
LeftAng.write(Max — i);
RightAng.write(Min + i);
delay(3*MoveDelay);
}
delay(PosDelay);
}
//------------------------------------------------------
void InitState()
{
LeftVer.write(90);
LeftAng.write(90);
RightVer.write(90);
RightAng.write(90);
}
//------------------------------------------------------
void RearBow()
{
byte Max = 90;
byte Min = 70;
unsigned int MoveDelay = 5;
unsigned int PosDelay = 500;
/*
for(byte i=0; i <= (Max — Min) + 10; i++)
{
LeftAng.write(Max — i);
RightAng.write(Min + i);
delay(MoveDelay);
}
delay(PosDelay);
*/
for(byte i=0; i <= (Max — Min) + 15; i++)
{
LeftAng.write(Min + i);
RightAng.write(Max — i);
delay(MoveDelay);
}
for(byte i=0; i <= 10; i++)
{
LeftVer.write(Max + i);
RightVer.write(Max — i);
delay(1);
}
delay(PosDelay);
}
//------------------------------------------------------
void LeftEarBow()
{
byte Max = 90;
unsigned int MoveDelay = 7;
byte AnglePos = Max;
for(byte i=0; i <= 80; i++)
{
LeftVer.write(Max + i);
delay(1);
}
for(byte i=0; i <= 75; i++)
{
LeftAng.write(AnglePos);
AnglePos = Max — i;
delay(MoveDelay);
}
for(byte i=0; i <= 10; i++)
{
LeftAng.write(AnglePos);
AnglePos += i;
delay(MoveDelay);
}
for(byte j=0; j<5; j++)
{
for(byte i=0; i <= 10; i++)
{
LeftAng.write(AnglePos);
AnglePos -= i;
delay(MoveDelay);
}
for(byte i=0; i <= 10; i++)
{
LeftAng.write(AnglePos);
AnglePos += i;
delay(MoveDelay);
}
}
}
//------------------------------------------------------
void RightEarBow()
{
byte Max = 90;
unsigned int MoveDelay = 7;
byte AnglePos = Max;
for(byte i=0; i <= 80; i++)
{
RightVer.write(Max — i);
delay(1);
}
for(byte i=0; i <= 75; i++)
{
RightAng.write(AnglePos);
AnglePos = Max + i;
delay(MoveDelay);
}
for(byte i=0; i <= 10; i++)
{
RightAng.write(AnglePos);
AnglePos -= i;
delay(MoveDelay);
}
for(byte j=0; j<5; j++)
{
for(byte i=0; i <= 10; i++)
{
RightAng.write(AnglePos);
AnglePos += i;
delay(MoveDelay);
}
for(byte i=0; i <= 10; i++)
{
RightAng.write(AnglePos);
AnglePos -= i;
delay(MoveDelay);
}
}
}
//------------------------------------------------------
void TwoEarsBow()
{
byte Max = 90;
unsigned int MoveDelay = 7;
byte AnglePosLeft = Max;
byte AnglePosRight = Max;
for(byte i=0; i <= 80; i++)
{
LeftVer.write(Max + i);
RightVer.write(Max — i);
delay(1);
}
for(byte i=0; i <= 75; i++)
{
LeftAng.write(AnglePosLeft);
RightAng.write(AnglePosRight);
AnglePosLeft = Max — i;
AnglePosRight = Max + i;
delay(MoveDelay);
}
for(byte i=0; i <= 10; i++)
{
LeftAng.write(AnglePosLeft);
RightAng.write(AnglePosRight);
AnglePosLeft += i;
AnglePosRight -= i;
delay(MoveDelay);
}
for(byte j=0; j<5; j++)
{
for(byte i=0; i <= 10; i++)
{
LeftAng.write(AnglePosLeft);
RightAng.write(AnglePosRight);
AnglePosLeft -= i;
AnglePosRight += i;
delay(MoveDelay);
}
for(byte i=0; i <= 10; i++)
{
LeftAng.write(AnglePosLeft);
RightAng.write(AnglePosRight);
AnglePosLeft += i;
AnglePosRight -= i;
delay(MoveDelay);
}
}
}
Итогом этой работы стали уши без проводов, которые работают автономно и реагируют на окружающие звуки. Таким образом, мы приблизились к оригинальному варианту, который придумали японцы:
Ну а у нас есть свой путь и можно сделать костюм медведя, добавить звук рыка или музыку балалайки. На этом заканчиваем повествование о тестовой печати и переходим к более серьезному проекту — сборке собственного робота-пылесоса на базе Ардуино, о котором будет написано чуть позже.
Автор: shuvaevgl