Proyecto I&P2024-1: Robot bailarín / Grupo 2

De Casiopea


TítuloProyecto I&P2024-1: Robot bailarín / Grupo 2
Tipo de ProyectoProyecto de Taller
Palabras Claveproyectoarduino
Período2024-2024
AsignaturaInteracción y Performatividad
Del CursoInteracción y Performatividad 2024-1
CarrerasDiseño
Alumno(s)Catalina España Veas, Constanza Cortes Madrid, Carla Bejares
ProfesorFranco Gnecco

PROYECTO ROBOT BAILARÍN

Proyecto base MiniZowi Bluetooth Dancing Controled Robot

El proyecto consiste en un robot cúbico bípedo, el cual mediante el movimiento de sus piernas asemeje un baile.
Se plantea la posibilidad de reemplazar los sensores que asemejan los ojos, por una matriz LED la cual permita mostrar diferentes expresiones en los ojos.

ESTUDIO PREVIO

Se realiza un estudio inicial del funcionamiento de los elementos que componen el proyecto, probando de esta manera de forma individual cada parte que dará vida al robot.

Servomotor

Códigos base movimiento

Componentes

  • Arduino UNO R3
  • Servomotor x4
  • Protoboard
Grupo 2 IyP 2024-servo prueba 2 03-05-2024.jpg


Diagrama de conexión

Grupo 2 IyP 2024-1 Servomotores.png

Código en arduino

//----------------------------------------------------------------
//-- Otto All moves test
//-- Otto DIY invests time and resources providing open source code and hardware, 
//-- please support by purchasing kits from https://www.ottodiy.com/
//-- Make sure to have installed all libraries: https://github.com/OttoDIY/OttoDIYLib
//-----------------------------------------------------------------
#include <Otto.h>
Otto Otto;  //This is Otto!
#define LeftLeg 2 
#define RightLeg 3
#define LeftFoot 4 
#define RightFoot 5 
#define Buzzer  13 
#define DIN A3 // Data In pin
#define CS A2  // Chip Select pin
#define CLK A1 // Clock pin
#define Orientation 1 // 8x8 LED Matrix orientation  Top  = 1, Bottom = 2, Left = 3, Right = 4 
///////////////////////////////////////////////////////////////////
//-- Setup ------------------------------------------------------//
///////////////////////////////////////////////////////////////////
void setup(){
Otto.init(LeftLeg, RightLeg, LeftFoot, RightFoot, true, Buzzer); //Set the servo pins and Buzzer pin
Otto.initMATRIX( DIN, CS, CLK, Orientation);
Otto.sing(S_connection); //Otto wake up!
Otto.home();
delay(50);
Otto.playGesture(OttoHappy);
}
///////////////////////////////////////////////////////////////////
//-- Principal Loop ---------------------------------------------//
///////////////////////////////////////////////////////////////////
void loop() { 
Otto.walk(2,1000,1); //2 steps, "TIME". IF HIGHER THE VALUE THEN SLOWER (from 600 to 1400), 1 FORWARD
Otto.walk(2,1000,-1); //2 steps, T, -1 BACKWARD 
Otto.turn(2,1000,1);//3 steps turning LEFT
Otto._tone(10, 3, 1);
Otto.bendTones (100, 200, 1.04, 10, 10);
Otto.home();
delay(100);  
Otto.turn(2,1000,-1);//3 steps turning RIGHT 
Otto.bend (1,500,1); //usually steps =1, T=2000
Otto.bend (1,2000,-1);     
Otto.shakeLeg (1,1500, 1);
Otto.home();
delay(100);
Otto.shakeLeg (1,2000,-1);
Otto.moonwalker(3, 1000, 25,1); //LEFT
Otto.moonwalker(3, 1000, 25,-1); //RIGHT  
Otto.crusaito(2, 1000, 20,1);
Otto.crusaito(2, 1000, 20,-1);
delay(100); 
Otto.flapping(2, 1000, 20,1);
Otto.flapping(2, 1000, 20,-1);
delay(100);        
Otto.swing(2, 1000, 20);
Otto.tiptoeSwing(2, 1000, 20);
Otto.jitter(2, 1000, 20); //(small T)
Otto.updown(2, 1500, 20);  // 20 = H "HEIGHT of movement"T 
Otto.ascendingTurn(2, 1000, 50);
Otto.jump(1,500); // It doesn't really jumpl ;P
Otto.home();
delay(100); 
Otto.sing(S_cuddly);
Otto.sing(S_OhOoh);
Otto.sing(S_OhOoh2);
Otto.sing(S_surprise);
Otto.sing(S_buttonPushed);       
Otto.sing(S_mode1);        
Otto.sing(S_mode2);         
Otto.sing(S_mode3);  
Otto.sing(S_sleeping);
Otto.sing(S_fart1);
Otto.sing(S_fart2);
Otto.sing(S_fart3);
Otto.sing(S_happy);
Otto.sing(S_happy_short);                   
Otto.sing(S_superHappy);   
Otto.sing(S_sad);               
Otto.sing(S_confused);
Otto.sing(S_disconnection);
delay(100);  
Otto.playGesture(OttoHappy);
Otto.playGesture(OttoSuperHappy);
Otto.playGesture(OttoSad);
Otto.playGesture(OttoVictory); 
Otto.playGesture(OttoAngry); 
Otto.playGesture(OttoSleeping);
Otto.playGesture(OttoFretful);
Otto.playGesture(OttoLove);
Otto.playGesture(OttoConfused);        
Otto.playGesture(OttoFart);
Otto.playGesture(OttoWave);
Otto.playGesture(OttoMagic);
Otto.playGesture(OttoFail);
Otto.home();
delay(100);  
Otto.putMouth(zero);
delay(100);
Otto.putMouth(one);
delay(100);
Otto.putMouth(two);
delay(100);
Otto.putMouth(three);
delay(100);
Otto.putMouth(four);
delay(100);
Otto.putMouth(five);
delay(100);
Otto.putMouth(6);
delay(100);
Otto.putMouth(7);
delay(100);
Otto.putMouth(8);
delay(100);
Otto.putMouth(9);
delay(100);
Otto.putMouth(smile);
delay(100);
Otto.putMouth(happyOpen);
delay(100);
Otto.putMouth(happyClosed);
delay(100);
Otto.putMouth(heart);
delay(100);
Otto.putMouth(angry);
delay(100);
Otto.putMouth(smallSurprise);
delay(100);
Otto.putMouth(bigSurprise);
delay(100);
Otto.putMouth(tongueOut);
delay(100);
Otto.putMouth(confused);
delay(100);
Otto.putMouth(21); //diagonal
delay(100);
Otto.putMouth(27); //interrogation
delay(100);
Otto.putMouth(23); //sad open
delay(100);
Otto.putMouth(24); //sad closed
delay(100);
Otto.putMouth(vamp1);
delay(100);
Otto.putMouth(vamp2);
delay(100);
Otto.putMouth(xMouth);
delay(100);
Otto.putMouth(okMouth);
delay(100);
Otto.putMouth(thunder);
delay(100);
Otto.putMouth(lineMouth);
delay(100);
Otto.putMouth(culito);
delay(100); 
Otto.putAnimationMouth(littleUuh,0);
delay(1000); 
Otto.putAnimationMouth(dreamMouth, 0);
delay(1000); 
Otto.putAnimationMouth(dreamMouth, 1);
delay(1000); 
Otto.putAnimationMouth(dreamMouth, 2);
delay(1000); 
}

Prueba de movimiento previa

Arduino libraries - Servo

Componentes

  • Arduino UNO R3
  • Servomotor x4
  • Protoboard
Grupo 2 IyP 2024-servo prueba 1 03-05-2024.jpg


Diagrama de conexión

Grupo 2 IyP 2024-1 Servomotores.png

Código en arduino

// C++ code
//
#include <Servo.h>
Servo myservo1;
Servo myservo2;
Servo myservo3;
Servo myservo4;
void setup()
{
myservo1.attach(8);
myservo2.attach(9);
myservo3.attach(10);
myservo4.attach(11);
myservo1.write(45); 
myservo2.write(45); 
myservo3.write(45);
myservo4.write(45);
}
void loop() {
myservo1.write(180);
myservo2.write(0);
myservo3.write(180);
myservo4.write(0);
delay(1500);
myservo1.write(0);
myservo2.write(180);
myservo3.write(0);
myservo4.write(180);
delay(3500);
}

Explicación

  • #include <Servo.h> : Define la librería Servo en la cual se trabajará, bajo esta fila se deben declarar cada uno de los servomotores, en este caso enumerados del 1 al 4.
  • myservo1.attach(8); : Corresponde al servomotor 1 asociado al pin 8.
  • myservo1.write(45); : Posicionamiento del eje a 45°.
  • delay(1500); : Tiempo en que se efectuara el movimiento de los servo, en este caso 1,5s .

Enlace proyecto Tinkercad

Servomotores - Grupo 2

Matriz LED

Movimiento ojos en matriz LED

Componentes

  • Arduino UNO R3
  • Módulo MAX7219 Matriz LED 8x8 Rojo
  • Protoboard

Diagrama de conexión

Grupo 2 IyP 2024-1 Matriz LED.jpeg

Código en arduino

Mediante este código se trabaja la visualización de un ojo en movimiento en la matriz LED.

/*Conecciones
Pines: 11 = DIN  12 =CLK  10 = CS 
5V - GND 
LED Matrix Sprite Generator:https://embed.plnkr.co/3VUsekP3jC5xwSIQDVHx/preview 
*/
#include "LedControl.h" // Libreria
LedControl lc=LedControl(11, 12, 10, 1); //Pines + 2 Matriz "max 8"
#define demora 1000  //1Sg 
byte Ojo_centro[8] = {
B00000000,
B01111110,
B11111111,
B11100111,
B11100111,
B11111111,
B01111110,
B00000000
};  
byte Inferior_derecho[8] = {
B00000000,
B01111110,
B11111001,
B11111001,
B11111111,
B11111111,
B01111110,
B00000000
};
byte Inferior_izquierdo[8] = {
B00000000,
B01111110,
B11111111,
B11111111,
B11110011,
B11110011,
B01111110,
B00000000
};
byte Cento_derecho[8] = {
B00000000,
B01111110,
B11100111,
B11100111,
B11111111,
B11111111,
B01111110,
B00000000
};
byte Cento_izquierdo[8] = {
B00000000,
B01111110,
B11111111,
B11111111,
B11100111,
B11100111,
B01111110,
B00000000
};
byte Inferior_centro[8] = {
B00000000,
B01111110,
B11111111,
B11111001,
B11111001,
B11111111,
B01111110,
B00000000
};
byte superior_derecho[8] = {
B00000000,
B01111110,
B11001111,
B11001111,
B11111111,
B11111111,
B01111110,
B00000000
};
byte superior_izquierdo[8] = {
B00000000,
B01111110,
B11111111,
B11111111,
B11001111,
B11001111,
B01111110,
B00000000
};
byte superior_centro[8] = {
B00000000,
B01111110,
B11111111,
B10011111,
B10011111,
B11111111,
B01111110,
B00000000
};
void setup() {
//Matriz 1  
lc.shutdown(0,false);       // enciende la matriz
lc.setIntensity(0,4);       // establece brillo
lc.clearDisplay(0);         // Se limpia la matriz 
}
void loop() {
mostrar_ojo_centro ();                 //Movimiento 1
delay(demora);               //Tiempo 1000 Milisendos
mostrar_Inferior_derecho();            //Movimiento 2
delay(demora);               //Tiempo 1000 Milisendos
mostrar_Inferior_izquierdo();          //Movimiento 3
delay(demora);               //Tiempo 1000 Milisendos
mostrar_Inferior_centro();             //Movimiento 4
delay(demora);               //Tiempo 1000 Milisendos
mostrar_superior_derecho();            //Movimiento 5
delay(demora);               //Tiempo 1000 Milisendos
mostrar_superior_izquierdo();          //Movimiento 6
delay(demora);               //Tiempo 1000 Milisendos
mostrar_superior_centro();             //Movimiento 7
delay(demora);               //Tiempo 1000 Milisendos
mostrar_Cento_izquierdo();             //Movimiento 8
delay(demora);               //Tiempo 1000 Milisendos
mostrar_Cento_derecho();               //Movimiento 9
delay(demora);               //Tiempo 1000 Milisendos
}
////////////////////////////////////////////////////////////////
//Orden de mostrar en matriz 8x8
void mostrar_ojo_centro() {
for (int i = 0; i < 8; i++) {
lc.setRow(0,i,Ojo_centro[i]);//Matriz 1 
}
}
void mostrar_Inferior_derecho() {
for (int i = 0; i < 8; i++) {
lc.setRow(0,i,Inferior_derecho[i]);//Matriz 1
}
}
void mostrar_Inferior_izquierdo() {
for (int i = 0; i < 8; i++) {
lc.setRow(0,i,Inferior_izquierdo[i]);//Matriz 1
}
}
void mostrar_Inferior_centro() {
for (int i = 0; i < 8; i++) {
lc.setRow(0,i,Inferior_centro[i]);//Matriz 1
}
}
void mostrar_superior_derecho() {
for (int i = 0; i < 8; i++) {
lc.setRow(0,i,superior_derecho[i]);//Matriz 1
}
}
void mostrar_superior_izquierdo() {
for (int i = 0; i < 8; i++) {
lc.setRow(0,i,superior_izquierdo[i]);//Matriz 1
}
}
void mostrar_superior_centro() {
for (int i = 0; i < 8; i++) {
lc.setRow(0,i,superior_centro[i]);//Matriz 1
}
}
void mostrar_Cento_izquierdo() {
for (int i = 0; i < 8; i++) {
lc.setRow(0,i,Cento_izquierdo[i]);//Matriz 1
}
}
void mostrar_Cento_derecho() {
for (int i = 0; i < 8; i++) {
lc.setRow(0,i,Cento_derecho[i]);//Matriz 1
}
}

PROYECTO FINAL

Componentes

  • Arduino UNO R3
  • Servomotor x4
  • Protoboard
  • Módulo MAX7219 Matriz LED 8x8 Rojo
  • Módulo Bluetooth HC-06

Diagrama de conexión

Grupo 2 IyP 2024-1 Diagrama final.jpeg

Código en arduino

El siguiente código permite al robot realizar los movimientos de "baile" asociados a los servomotores, asimismo se permite la visualización del ojo mediante la matriz LED.

Para poder indicar los movimientos a realizar se utiliza un modulo bluetooth el cual se asocia a la aplicación para celular de zowi

//----------------------------------------------------------------
//-- Zowi basic firmware v2
//-- (c) BQ. Released under a GPL licencse
//-- 04 December 2015
//-- Authors:  Anita de Prado: ana.deprado@bq.com
//--           Jose Alberca:   jose.alberca@bq.com
//--           Javier Isabel:  javier.isabel@bq.com
//--           Juan Gonzalez (obijuan): juan.gonzalez@bq.com
//--           Irene Sanz : irene.sanz@bq.com
//-----------------------------------------------------------------
//-- Experiment with all the features that Zowi have!
//-----------------------------------------------------------------
#include <Servo.h> 
#include <Oscillator.h>
#include <EEPROM.h>
#include <BatReader.h>
#include <US.h>
#include <LedMatrix.h>
#include "LedControl.h" // Libreria
//-- Library to manage external interruptions
#include <EnableInterrupt.h> 
//-- Library to manage serial commands
#include <ZowiSerialCommand.h>
ZowiSerialCommand SCmd;  //The SerialCommand object
//-- Zowi Library
#include <Zowi.h>
Zowi zowi;  //This is Zowi!! 
//---------------------------------------------------------
//-- Configuration of pins where the servos are attached
/*
        --------------- 
       |               |
       |     O   O     |
       |               |
YR ==> |               | <== YL
        --------------- 
           ||     ||
           ||     ||
           ||     ||
RR ==>   -----   ------  <== RL
         -----   ------
*/
#define PIN_YL 2 //servo[0]
#define PIN_YR 3 //servo[1]
#define PIN_RL 4 //servo[2]
#define PIN_RR 5 //servo[3] 
//---------------------------------------------------------
//---Zowi Buttons original dos 6 tres 7
#define PIN_SecondButton 14
#define PIN_ThirdButton 7
///////////////////////////////////////////////////////////////////
//-- Global Variables -------------------------------------------//
///////////////////////////////////////////////////////////////////
const char programID[]="ZOWI_BASE_v2"; //Each program will have a ID
const char name_fac='$'; //Factory name
const char name_fir='#'; //First name
//-- Movement parameters
int T=1000;              //Initial duration of movement
int moveId=0;            //Number of movement
int moveSize=15;         //Asociated with the height of some movements
//---------------------------------------------------------
//-- Zowi has 5 modes:
//--    * MODE = 0: Zowi is awaiting  
//--    * MODE = 1: Dancing mode!  
//--    * MODE = 2: Obstacle detector mode  
//--    * MODE = 3: Noise detector mode   
//--    * MODE = 4: ZowiPAD or any Teleoperation mode (listening SerialPort). 
//--
volatile int MODE=0; //State of zowi in the principal state machine. 
//--------------------------------------------------------- 
volatile bool buttonPushed=false;  //Variable to remember when a button has been pushed
volatile bool buttonAPushed=false; //Variable to remember when A button has been pushed
volatile bool buttonBPushed=false; //Variable to remember when B button has been pushed
unsigned long previousMillis=0;
int randomDance=0;
int randomSteps=0;
bool obstacleDetected = false;
///////////////////////////////////////////////////////////////////
//-- Setup ------------------------------------------------------//
///////////////////////////////////////////////////////////////////
LedControl lc=LedControl(11, 12, 10, 1); //Pines + 2 Matriz "max 8"
byte Ojo_centro[8] = {
B00000000,
B01111110,
B11111111,
B11100111,
B11100111,
B11111111,
B01111110,
B00000000
};
void setup(){
//Serial communication initialization
Serial.begin(115200);  
//Matriz 1  
lc.shutdown(0,false);       // enciende la matriz
lc.setIntensity(0,4);       // establece brillo
lc.clearDisplay(0);         // Se limpia la matriz
pinMode(PIN_SecondButton,INPUT);
pinMode(PIN_ThirdButton,INPUT);
//Set the servo pins
zowi.init(PIN_YL,PIN_YR,PIN_RL,PIN_RR,true);
//Uncomment this to set the servo trims manually and save on EEPROM 
//zowi.setTrims(TRIM_YL, TRIM_YR, TRIM_RL, TRIM_RR);
//zowi.saveTrimsOnEEPROM(); //Uncomment this only for one upload when you finaly set the trims.
//Set a random seed
randomSeed(analogRead(A6));
//Interrumptions
enableInterrupt(PIN_SecondButton, secondButtonPushed, RISING);
enableInterrupt(PIN_ThirdButton, thirdButtonPushed, RISING);
//Setup callbacks for SerialCommand commands 
SCmd.addCommand("S", receiveStop);      //  sendAck & sendFinalAck
SCmd.addCommand("L", receiveLED);       //  sendAck & sendFinalAck
SCmd.addCommand("T", recieveBuzzer);    //  sendAck & sendFinalAck
SCmd.addCommand("M", receiveMovement);  //  sendAck & sendFinalAck
SCmd.addCommand("H", receiveGesture);   //  sendAck & sendFinalAck
SCmd.addCommand("K", receiveSing);      //  sendAck & sendFinalAck
SCmd.addCommand("C", receiveTrims);     //  sendAck & sendFinalAck
SCmd.addCommand("G", receiveServo);     //  sendAck & sendFinalAck
SCmd.addCommand("R", receiveName);      //  sendAck & sendFinalAck
SCmd.addCommand("E", requestName);
SCmd.addCommand("D", requestDistance);
SCmd.addCommand("N", requestNoise);
SCmd.addCommand("B", requestBattery);
SCmd.addCommand("I", requestProgramId);
SCmd.addDefaultHandler(receiveStop);
for (int k = 0; k < 8; k++) {
lc.setRow(0,k,Ojo_centro[k]);//Matriz 1 
}
//Zowi wake up!
zowi.sing(S_connection);
zowi.home();
//If Zowi's name is '&' (factory name) means that is the first time this program is executed.
//This first time, Zowi mustn't do anything. Just born at the factory!
//5 = EEPROM address that contains first name character
if (EEPROM.read(5)==name_fac){ 
EEPROM.put(5, name_fir); //From now, the name is '#'
EEPROM.put(6, '\0'); 
zowi.putMouth(culito);
while(true){    
delay(1000);
}
}  
//Send Zowi name, programID & battery level.
requestName();
delay(50);
requestProgramId();
delay(50);
requestBattery();
//Checking battery
ZowiLowBatteryAlarm();
// Animation Uuuuuh - A little moment of initial surprise
//-----
for(int i=0; i<2; i++){
for (int i=0;i<8;i++){
if(buttonPushed){break;}  
zowi.putAnimationMouth(littleUuh,i);
delay(150);
}
}
//-----
//Smile for a happy Zowi :)
if(!buttonPushed){ 
zowi.putMouth(smile);
zowi.sing(S_happy);
delay(200);
}
//If Zowi's name is '#' means that Zowi hasn't been baptized
//In this case, Zowi does a longer greeting
//5 = EEPROM address that contains first name character
if (EEPROM.read(5)==name_fir){ 
if(!buttonPushed){  
zowi.jump(1,700);
delay(200); 
}
if(!buttonPushed){  
zowi.shakeLeg(1,T,1); 
}  
if(!buttonPushed){ 
zowi.putMouth(smallSurprise);
zowi.swing(2,800,20);  
zowi.home();
}  
}
if(!buttonPushed){ 
zowi.putMouth(happyOpen);
}
previousMillis = millis();
}
///////////////////////////////////////////////////////////////////
//-- Principal Loop ---------------------------------------------//
///////////////////////////////////////////////////////////////////
void loop() {
if (Serial.available()>0 && MODE!=4){
MODE=4;
zowi.putMouth(happyOpen);
//Disable Pin Interruptions
disableInterrupt(PIN_SecondButton);
disableInterrupt(PIN_ThirdButton);
buttonPushed=false;
}
//First attemp to initial software
if (buttonPushed){  
zowi.home();
delay(100); //Wait for all buttons 
zowi.sing(S_buttonPushed);
delay(200); //Wait for all buttons 
if      ( buttonAPushed && !buttonBPushed){ MODE=1; zowi.sing(S_mode1);}
else if (!buttonAPushed && buttonBPushed) { MODE=2; zowi.sing(S_mode2);}
else if ( buttonAPushed && buttonBPushed) { MODE=3; zowi.sing(S_mode3);} //else
zowi.putMouth(MODE);
int showTime = 2000;
while((showTime>0)){ //Wait to show the MODE number     
showTime-=10;
delay(10);
}
zowi.putMouth(happyOpen);
buttonPushed=false;
buttonAPushed=false;
buttonBPushed=false;
}else{
switch (MODE) {
//-- MODE 0 - Zowi is awaiting
//---------------------------------------------------------
case 0:
//Every 80 seconds in this mode, Zowi falls asleep 
if (millis()-previousMillis>=80000){
ZowiSleeping_withInterrupts(); //ZZzzzzz...
previousMillis=millis();         
}
break;
//-- MODE 1 - Dance Mode!
//---------------------------------------------------------
case 1:
randomDance=random(5,21); //5,20
if((randomDance>14)&&(randomDance<19)){
randomSteps=1;
T=1600;
}
else{
randomSteps=random(3,6); //3,5
T=1000;
}
zowi.putMouth(random(10,21));
 for (int i=0;i<randomSteps;i++){
move(randomDance);
if(buttonPushed){break;}
}
break;
//-- MODE 2 - Obstacle detector mode
//---------------------------------------------------------
case 2:
if(obstacleDetected){
if(!buttonPushed){
zowi.putMouth(bigSurprise);
zowi.sing(S_surprise);
zowi.jump(5, 500);
}  
if(!buttonPushed){
zowi.putMouth(confused);
zowi.sing(S_cuddly);
}  
//Zowi takes two steps back
for(int i=0;i<3;i++){ 
if(buttonPushed){break;}
zowi.walk(1,1300,-1);
}
delay(100);
obstacleDetector();
delay(100);
//If there are no obstacles and no button is pressed, Zowi shows a smile
if((obstacleDetected==true)||(buttonPushed==true)){break;}            
else{
zowi.putMouth(smile);
delay(50);
obstacleDetector();
} 
//If there are no obstacles and no button is pressed, Zowi shows turns left
for(int i=0; i<3; i++){
if((obstacleDetected==true)||(buttonPushed==true)){break;}            
else{ 
 zowi.turn(1,1000,1); 
obstacleDetector();
} 
}
//If there are no obstacles and no button is pressed, Zowi is happy
if((obstacleDetected==true)||(buttonPushed==true)){break;}           
else{
zowi.home();
zowi.putMouth(happyOpen);
zowi.sing(S_happy_short);
delay(200);
}     
}else{
zowi.walk(1,1000,1); //Zowi walk straight
obstacleDetector();
}   
break;
//-- MODE 3 - Noise detector mode
//---------------------------------------------------------  
case 3:
if (zowi.getNoise()>=650){ //740
delay(50);  //Wait for the possible 'lag' of the button interruptions. 
//Sometimes, the noise sensor detect the button before the interruption takes efect 
if(!buttonPushed){
zowi.putMouth(bigSurprise);
zowi.sing(S_OhOoh);
if(buttonPushed){break;}
zowi.putMouth(random(10,21));
randomDance=random(5,21);
move(randomDance);
zowi.home();
delay(500); //Wait for possible noise of the servos while get home
}
if(!buttonPushed){zowi.putMouth(happyOpen);}
}
break;
//-- MODE 4 - ZowiPAD or any Teleoperation mode (listening SerialPort) 
//---------------------------------------------------------
case 4:
SCmd.readSerial();
//If Zowi is moving yet
if (zowi.getRestState()==false){  
move(moveId);
}
break;      
default:
MODE=4;
break;
}
} 
}  
///////////////////////////////////////////////////////////////////
//-- Functions --------------------------------------------------//
///////////////////////////////////////////////////////////////////
//-- Function executed when second button is pushed
void secondButtonPushed(){ 
buttonAPushed=true;
if(!buttonPushed){
buttonPushed=true;
zowi.putMouth(smallSurprise);
}    
}
//-- Function executed when third button is pushed
void thirdButtonPushed(){ 
buttonBPushed=true;
if(!buttonPushed){
buttonPushed=true;
zowi.putMouth(smallSurprise);
}
}
//-- Function to read distance sensor & to actualize obstacleDetected variable
void obstacleDetector(){
int distance = zowi.getDistance();
if(distance<15){
obstacleDetected = true;
}else{
obstacleDetected = false;
}
}
//-- Function to receive Stop command.
void receiveStop(){
sendAck();
zowi.home();
sendFinalAck();
}
//-- Function to receive LED commands
void receiveLED(){  
//sendAck & stop if necessary
sendAck();
zowi.home();
//Examples of receiveLED Bluetooth commands
//L 000000001000010100100011000000000
//L 001111111111111111111111111111111 (todos los LED encendidos)
unsigned long int matrix;
char *arg;
char *endstr;
arg=SCmd.next();
//Serial.println (arg);
if (arg != NULL) {
matrix=strtoul(arg,&endstr,2);    // Converts a char string to unsigned long integer
zowi.putMouth(matrix,false);
}else{
zowi.putMouth(xMouth);
delay(2000);
zowi.clearMouth();
}
sendFinalAck();
}
//-- Function to receive buzzer commands
void recieveBuzzer(){
//sendAck & stop if necessary
sendAck();
zowi.home(); 
bool error = false; 
int frec;
int duration; 
char *arg; 
arg = SCmd.next(); 
if (arg != NULL) { frec=atoi(arg); }    // Converts a char string to an integer   
else {error=true;}
arg = SCmd.next(); 
if (arg != NULL) { duration=atoi(arg); } // Converts a char string to an integer  
else {error=true;}
if(error==true){
zowi.putMouth(xMouth);
delay(2000);
zowi.clearMouth();
}else{ 
zowi._tone(frec, duration, 1);   
}
sendFinalAck();
}
//-- Function to receive TRims commands
void receiveTrims(){  
//sendAck & stop if necessary
sendAck();
zowi.home(); 
int trim_YL,trim_YR,trim_RL,trim_RR;
//Definition of Servo Bluetooth command
//C trim_YL trim_YR trim_RL trim_RR
//Examples of receiveTrims Bluetooth commands
//C 20 0 -8 3
bool error = false;
char *arg;
arg=SCmd.next();
if (arg != NULL) { trim_YL=atoi(arg); }    // Converts a char string to an integer   
else {error=true;}
arg = SCmd.next(); 
if (arg != NULL) { trim_YR=atoi(arg); }    // Converts a char string to an integer  
else {error=true;}
arg = SCmd.next(); 
if (arg != NULL) { trim_RL=atoi(arg); }    // Converts a char string to an integer  
else {error=true;}
arg = SCmd.next(); 
if (arg != NULL) { trim_RR=atoi(arg); }    // Converts a char string to an integer  
else {error=true;}
if(error==true){
zowi.putMouth(xMouth);
delay(2000);
zowi.clearMouth();
}else{ //Save it on EEPROM
zowi.setTrims(trim_YL, trim_YR, trim_RL, trim_RR);
zowi.saveTrimsOnEEPROM(); //Uncomment this only for one upload when you finaly set the trims.
} 
sendFinalAck();
}
//-- Function to receive Servo commands
void receiveServo(){  
sendAck(); 
moveId = 30;
//Definition of Servo Bluetooth command
//G  servo_YL servo_YR servo_RL servo_RR 
//Example of receiveServo Bluetooth commands
//G 90 85 96 78 
bool error = false;
char *arg;
int servo_YL,servo_YR,servo_RL,servo_RR;
arg=SCmd.next();
if (arg != NULL) { servo_YL=atoi(arg); }    // Converts a char string to an integer   
else {error=true;}
arg = SCmd.next(); 
if (arg != NULL) { servo_YR=atoi(arg); }    // Converts a char string to an integer  
else {error=true;}
arg = SCmd.next(); 
if (arg != NULL) { servo_RL=atoi(arg); }    // Converts a char string to an integer  
else {error=true;}
arg = SCmd.next(); 
if (arg != NULL) { servo_RR=atoi(arg); }    // Converts a char string to an integer  
else {error=true;}
if(error==true){
zowi.putMouth(xMouth);
delay(2000);
zowi.clearMouth();
}else{ //Update Servo:
int servoPos[4]={servo_YL, servo_YR, servo_RL, servo_RR}; 
zowi._moveServos(200, servoPos);   //Move 200ms
}
sendFinalAck();
}
//-- Function to receive movement commands
void receiveMovement(){
sendAck();
if (zowi.getRestState()==true){
zowi.setRestState(false);
}
//Definition of Movement Bluetooth commands
//M  MoveID  T   MoveSize  
char *arg; 
arg = SCmd.next(); 
if (arg != NULL) {moveId=atoi(arg);}
else{
zowi.putMouth(xMouth);
delay(2000);
zowi.clearMouth();
moveId=0; //stop
}
arg = SCmd.next(); 
if (arg != NULL) {T=atoi(arg);}
else{
T=1000;
}
arg = SCmd.next(); 
if (arg != NULL) {moveSize=atoi(arg);}
else{
moveSize =15;
}
}
//-- Function to execute the right movement according the movement command received.
void move(int moveId){
bool manualMode = false;
switch (moveId) {
case 0:
zowi.home();
break;
case 1: //M 1 1000 
zowi.walk(1,T,1);
break;
case 2: //M 2 1000 
zowi.walk(1,T,-1);
break;
case 3: //M 3 1000 
zowi.turn(1,T,1);
break;
case 4: //M 4 1000 
zowi.turn(1,T,-1);
break;
case 5: //M 5 1000 30 
zowi.updown(1,T,moveSize);
break;
case 6: //M 6 1000 30
zowi.moonwalker(1,T,moveSize,1);
break;
case 7: //M 7 1000 30
zowi.moonwalker(1,T,moveSize,-1);
break;
case 8: //M 8 1000 30
zowi.swing(1,T,moveSize);
break;
case 9: //M 9 1000 30 
zowi.crusaito(1,T,moveSize,1);
break;
case 10: //M 10 1000 30 
zowi.crusaito(1,T,moveSize,-1);
break;
case 11: //M 11 1000 
zowi.jump(1,T);
break;
case 12: //M 12 1000 30 
zowi.flapping(1,T,moveSize,1);
break;
case 13: //M 13 1000 30
zowi.flapping(1,T,moveSize,-1);
break;
case 14: //M 14 1000 20
zowi.tiptoeSwing(1,T,moveSize);
break;
case 15: //M 15 500 
zowi.bend(1,T,1);
break;
case 16: //M 16 500 
zowi.bend(1,T,-1);
break;
case 17: //M 17 500 
zowi.shakeLeg(1,T,1);
break;
case 18: //M 18 500 
zowi.shakeLeg(1,T,-1);
break;
case 19: //M 19 500 20
zowi.jitter(1,T,moveSize);
break;
case 20: //M 20 500 15
zowi.ascendingTurn(1,T,moveSize);
break;
default:
manualMode = true;
break;
}
if(!manualMode){
sendFinalAck();
}
}
//-- Function to receive gesture commands
void receiveGesture(){
//sendAck & stop if necessary
sendAck();
zowi.home(); 
//Definition of Gesture Bluetooth commands
//H  GestureID  
int gesture = 0;
char *arg; 
arg = SCmd.next(); 
if (arg != NULL) {gesture=atoi(arg);}
else 
{
zowi.putMouth(xMouth);
delay(2000);
zowi.clearMouth();
}
switch (gesture) {
case 1: //H 1 
zowi.playGesture(ZowiHappy);
break;
case 2: //H 2 
zowi.playGesture(ZowiSuperHappy);
break;
case 3: //H 3 
zowi.playGesture(ZowiSad);
break;
case 4: //H 4 
zowi.playGesture(ZowiSleeping);
break;
case 5: //H 5  
zowi.playGesture(ZowiFart);
break;
case 6: //H 6 
zowi.playGesture(ZowiConfused);
break;
case 7: //H 7 
zowi.playGesture(ZowiLove);
break;
case 8: //H 8 
zowi.playGesture(ZowiAngry);
break;
case 9: //H 9  
zowi.playGesture(ZowiFretful);
break;
case 10: //H 10
zowi.playGesture(ZowiMagic);
break;  
case 11: //H 11
zowi.playGesture(ZowiWave);
break;   
case 12: //H 12
zowi.playGesture(ZowiVictory);
break; 
case 13: //H 13
zowi.playGesture(ZowiFail);
break;         
default:
break;
}
sendFinalAck();
}
//-- Function to receive sing commands
void receiveSing(){
//sendAck & stop if necessary
sendAck();
zowi.home(); 
//Definition of Sing Bluetooth commands
//K  SingID    
int sing = 0;
char *arg; 
arg = SCmd.next(); 
if (arg != NULL) {sing=atoi(arg);}
else 
{
zowi.putMouth(xMouth);
delay(2000);
zowi.clearMouth();
}
switch (sing) {
case 1: //K 1 
zowi.sing(S_connection);
break;
case 2: //K 2 
zowi.sing(S_disconnection);
break;
case 3: //K 3 
zowi.sing(S_surprise);
break;
case 4: //K 4 
zowi.sing(S_OhOoh);
break;
case 5: //K 5  
zowi.sing(S_OhOoh2);
break;
case 6: //K 6 
zowi.sing(S_cuddly);
break;
case 7: //K 7 
zowi.sing(S_sleeping);
break;
case 8: //K 8 
zowi.sing(S_happy);
break;
case 9: //K 9  
zowi.sing(S_superHappy);
break;
case 10: //K 10
zowi.sing(S_happy_short);
break;  
case 11: //K 11
zowi.sing(S_sad);
break;   
case 12: //K 12
zowi.sing(S_confused);
break; 
case 13: //K 13
zowi.sing(S_fart1);
break;
case 14: //K 14
zowi.sing(S_fart2);
break;
case 15: //K 15
zowi.sing(S_fart3);
break;    
case 16: //K 16
zowi.sing(S_mode1);
break; 
case 17: //K 17
zowi.sing(S_mode2);
break; 
case 18: //K 18
zowi.sing(S_mode3);
break;   
case 19: //K 19
zowi.sing(S_buttonPushed);
break;                      
default:
break;
}
sendFinalAck();
}
//-- Function to receive Name command
void receiveName(){
//sendAck & stop if necessary
sendAck();
zowi.home(); 
 char newZowiName[11] = "";  //Variable to store data read from Serial.
int eeAddress = 5;          //Location we want the data to be in EEPROM.
char *arg; 
arg = SCmd.next(); 
if (arg != NULL) {
//Complete newZowiName char string
int k = 0;
while((*arg) && (k<11)){ 
newZowiName[k]=*arg++;
k++;
}
EEPROM.put(eeAddress, newZowiName); 
}
else 
{
zowi.putMouth(xMouth);
delay(2000);
zowi.clearMouth();
}
sendFinalAck();
}
//-- Function to send Zowi's name
void requestName(){
zowi.home(); //stop if necessary
char actualZowiName[11]= "";  //Variable to store data read from EEPROM.
int eeAddress = 5;            //EEPROM address to start reading from
//Get the float data from the EEPROM at position 'eeAddress'
EEPROM.get(eeAddress, actualZowiName);
Serial.print(F("&&"));
Serial.print(F("E "));
Serial.print(actualZowiName);
Serial.println(F("%%"));
Serial.flush();
}
//-- Function to send ultrasonic sensor measure (distance)
void requestDistance(){
zowi.home();  //stop if necessary  
int distance = zowi.getDistance();
Serial.print(F("&&"));
Serial.print(F("D "));
Serial.print(distance);
Serial.println(F("%%"));
Serial.flush();
}
//-- Function to send noise sensor measure
void requestNoise(){
zowi.home();  //stop if necessary
int microphone= zowi.getNoise(); //analogRead(PIN_NoiseSensor);
Serial.print(F("&&"));
Serial.print(F("N "));
Serial.print(microphone);
Serial.println(F("%%"));
Serial.flush();
}
//-- Function to send battery voltage percent
void requestBattery(){
zowi.home();  //stop if necessary
//The first read of the batery is often a wrong reading, so we will discard this value. 
double batteryLevel = zowi.getBatteryLevel();
Serial.print(F("&&"));
Serial.print(F("B "));
Serial.print(batteryLevel);
Serial.println(F("%%"));
Serial.flush();
}
//-- Function to send program ID
void requestProgramId(){
zowi.home();   //stop if necessary
Serial.print(F("&&"));
Serial.print(F("I "));
Serial.print(programID);
Serial.println(F("%%"));
Serial.flush();
}
//-- Function to send Ack comand (A)
void sendAck(){
delay(30);
Serial.print(F("&&"));
Serial.print(F("A"));
Serial.println(F("%%"));
Serial.flush();
}
//-- Function to send final Ack comand (F)
void sendFinalAck(){
delay(30);
Serial.print(F("&&"));
Serial.print(F("F"));
Serial.println(F("%%"));
Serial.flush();
}
//-- Functions with animatics
//--------------------------------------------------------
void ZowiLowBatteryAlarm(){
double batteryLevel = zowi.getBatteryLevel();
if(batteryLevel<45){
while(!buttonPushed){
zowi.putMouth(thunder);
zowi.bendTones (880, 2000, 1.04, 8, 3);  //A5 = 880
delay(30);
zowi.bendTones (2000, 880, 1.02, 8, 3);  //A5 = 880
zowi.clearMouth();
delay(500);
} 
}
}
void ZowiSleeping_withInterrupts(){
int bedPos_0[4]={100, 80, 60, 120}; //{100, 80, 40, 140}
if(!buttonPushed){
zowi._moveServos(700, bedPos_0);  //800  
}
for(int i=0; i<4;i++){
if(buttonPushed){break;}
zowi.putAnimationMouth(dreamMouth,0);
zowi.bendTones (100, 200, 1.04, 10, 10);
if(buttonPushed){break;}
zowi.putAnimationMouth(dreamMouth,1);
zowi.bendTones (200, 300, 1.04, 10, 10);  
if(buttonPushed){break;}
zowi.putAnimationMouth(dreamMouth,2);
zowi.bendTones (300, 500, 1.04, 10, 10);   
delay(500);
if(buttonPushed){break;}
zowi.putAnimationMouth(dreamMouth,1);
zowi.bendTones (400, 250, 1.04, 10, 1); 
if(buttonPushed){break;}
zowi.putAnimationMouth(dreamMouth,0);
zowi.bendTones (250, 100, 1.04, 10, 1); 
delay(500);
} 
if(!buttonPushed){
zowi.putMouth(lineMouth);
zowi.sing(S_cuddly);
}
zowi.home();
if(!buttonPushed){zowi.putMouth(happyOpen);}  
}

DESARROLLO PROYECTO

Piezas

El robot se compone de 6 piezas las cuales se encuentran en MiniZowi robot. Para esta propuesta se editó la cabeza de manera que fuese posible colocar una matriz LED.

Impresión piezas

Caja Vista superior
Base Vista superior
Caja Vista frontal
Base Vista frontal
Base Vista posterior
Base Vista lateral

Proceso armado

FUNCIONAMIENTO

Videos

Video

Video 2