Jan Ingo Haller и Lorin Samija в рамках семинара по вычислительному дизайну и цифровому производству в магистерской программе «Интеграционные технологии и исследования архитектурного дизайна» (ITECH) в Штутгартском университете создали необычного робота-питомца, которого назвали mOLOID.
mOLOID (moving OLOID) — двигается очень необычным образом. Когда внутреннее устройство робота спрятано под тканевым покрытием, то кажется, что робот сам собой перекатывается, словно какое-то непонятное существо.
В основе этого необычного робота-питомца лежит оригинальный геометрический объект — олоид.
Олоид — трёхмерный криволинейный геометрический объект, открытый Paul Schatz в 1929 году. Это выпуклая оболочка каркаса, сделанного из двух соединённых конгруэнтных окружностей в перпендикулярных плоскостях, так что центр каждой окружности лежит на другой окружности. Расстояние между центрами окружностей равно радиусу окружностей. Одна треть периметра каждого круга лежит внутри выпуклой оболочки, поэтому одна и та же форма может быть также сформирована как выпуклая оболочка двух оставшихся круглых дуг, каждая из которых охватывает угол 4π/3.
Подобная структура, состоящая из двух окружностей, расположенных под углом 90° к друг-другу, приходит в движение при помощи двух сервомашинок, которые перемещают грузы по периметру каждого круга, что изменяет центр тяжести робота и заставляет его катиться вперёд или назад.
Мозг робота — контроллер Arduino Uno, к которому подключены не только сервомашинки, но и инфракрасный датчик движения HC-SR501 (позволяет роботу реагировать на окружающую среду), Bluetooth-модуль HC-05 (через него осуществляется управление роботом через SerialPortPorfile (SPP)) и небольшой динамик (обеспечивает звуковую обратную связь).
Код скетча — 200713_mOLOID.ino
///Libraries
#include <SoftwareSerial.h>
#include <Servo.h>
#include <pitches.h>
////
/// Custom Functions
//Smooth servo movement
void MoveCts(Servo serv, int aim, int delayTime){
int stepSize = 1;
//int delayT = 20;
int delayT = delayTime;
int current = serv.read();
int diff = aim - current;
if (diff < 0) diff = -1*diff;
int steps = diff/stepSize;
if(aim > current){
for(int i = 1; i < steps + 1; i++){
serv.write(current + i * stepSize);
delay(delayT);
}
}
else if (aim < current){
for(int i = 1; i < steps + 1; i++){
serv.write(current - i * stepSize);
delay(delayT);
}
}
}
//Making the OLOID move, i.e. into an mOLOID
void Move(bool dir, int velocity, Servo serv1, Servo serv2){
int vel = 0;
vel = velocity;
if (dir == 0){
MoveCts(serv1,0, vel);
delay(vel);
MoveCts(serv2,90, vel);
MoveCts(serv2,180, vel);
delay(vel);
MoveCts(serv1,90, vel);
MoveCts(serv1,180, vel);
delay(vel);
MoveCts(serv2,90, vel);
MoveCts(serv2,0, vel);
delay(vel);
MoveCts(serv1,90, vel);
delay(vel);
}
else {
MoveCts(serv1,180, vel);
delay(vel);
MoveCts(serv2,90, vel);
MoveCts(serv2,180, vel);
delay(vel);
MoveCts(serv1,90, vel);
MoveCts(serv1,0, vel);
delay(vel);
MoveCts(serv2,90, vel);
MoveCts(serv2,0, vel);
delay(vel);
MoveCts(serv1,90, vel);
delay(vel);
}
}
////
///Variables
#define rxPin 11 ///blue
#define txPin 12 ///green
#define buzz 7 //buzzer
#define sens 13 //sensor
bool power = 0;
bool dir = 0;
int motState = LOW;
int sensVal = 0;
Servo serv1;
Servo serv2;
int delayT = 10;
SoftwareSerial btSerial(rxPin, txPin);
String btData;
// Sound Setup
int melody1[] = {
NOTE_G7, NOTE_G7, NOTE_AS7, NOTE_G7
}; //switch on
int melody2[] = {
NOTE_AS7, NOTE_AS7, NOTE_G7, NOTE_AS7
}; //sensor triggered movement
int melody0[] = {
NOTE_AS7, NOTE_AS7, NOTE_G7
}; //switch off
int durations1[] = {
4,4,8,8
};
int durations2[] = {
4,4,8,8
};
int durations0[] = {
4,4,4
};
int songLength1 = sizeof(melody1)/sizeof(melody1[0]);
int songLength2 = sizeof(melody2)/sizeof(melody2[0]);
int songLength0 = sizeof(melody0)/sizeof(melody0[0]);
////
///Setup
void setup() {
serv1.attach(6);
serv2.attach(8);
pinMode(buzz, OUTPUT);
pinMode(sens, INPUT);
btSerial.begin(9600);
btSerial.println("bluetooth available");
}
////
///Loop
void loop() {
if (btSerial.available()) {
btData = btSerial.readString();
if(btData == "off") {
power = 0;
for (int thisNote = 0; thisNote < songLength0; thisNote++){
int duration = 3000/ durations0[thisNote];
tone(buzz, melody0[thisNote], duration);
// pause between notes
int pause = duration * 0.3;
delay(pause);
// stop the tone
noTone(buzz);
}
MoveCts(serv1, 90, delayT);
MoveCts(serv2, 0, delayT);
btSerial.println("Device is off.");
//serv1.write(90);
//serv2.write(0);
}
else if (btData == "on") {
power = 1;
for (int thisNote = 0; thisNote < songLength1; thisNote++){
int duration = 3000/ durations1[thisNote];
tone(buzz, melody1[thisNote], duration);
// pause between notes
int pause = duration * 0.3;
delay(pause);
// stop the tone
noTone(buzz);
}
MoveCts(serv1, 90, delayT);
MoveCts(serv2, 0, delayT);
btSerial.println("Device is on.");
//serv1.write(90);
//serv2.write(0);
}
else {
int btNumb = btData.toInt();
if (btNumb == 0) btNumb = 10;
if (btNumb < 0) {
dir = 1;
delayT = -btNumb;
}
else {
delayT = btNumb;
dir = 0;
}
//btSerial.println("Input unknown. Only on/off.");
}
}
if (power){
sensVal = digitalRead(sens);
if (sensVal == HIGH){
if (motState == LOW){
btSerial.println("Motion detected!");
motState = HIGH;
for (int thisNote = 0; thisNote < songLength2; thisNote++){
int duration = 3000/ durations2[thisNote];
tone(buzz, melody2[thisNote], duration);
// pause between notes
int pause = duration * 0.3;
delay(pause);
// stop the tone
noTone(buzz);
}
for(int i = 0; i < 3; i++){
Move(dir, delayT, serv1, serv2);
}
}
}
else{
MoveCts(serv1, 90, delayT);
MoveCts(serv2, 0, delayT);
//serv1.write(90);
//serv2.write(0);
if (motState == HIGH){
btSerial.println("Motion ended!");
motState = LOW;
}
}
}
}
////
Ссылки
The Moving OLOID - a Different Pet in Different Times
По теме
Sneaky - интерактивный змееподобный робот
MORPH - робот гуляющий по парку
Робот-червяк на базе Arduino
Halfbug - ползающий робот на Arduino
