Hackster is hosting Hackster Holidays, Finale: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Tuesday!Stream Hackster Holidays, Finale on Tuesday!
JulienChateau
Published © GPL3+

Spideruino

A Lego arachnid controlled by your smartphone.

IntermediateShowcase (no instructions)58,184
Spideruino

Things used in this project

Story

Read more

Schematics

ArduinoSchematic

Connect your Arduino to the Dual Bridge motor controller and to the bluetooth module.

How it walks

How to assemble the Lego bricks and gears in order to create that silly walk. Each motor drives 4 legs.

Inner gears.

The gear in the middle is the one driving the four other gears of the left side (same thing goes on the right side). to connect it to the motor, I had to cut a bit of the piece and glue it to the motor shaft. Then, you connect the legs to the gears, asynchronously (each on a gear hole) and tadam: silly walk.

Code

Nano Code

Arduino
Upload it to the Nano, it reads the Android orders incomming by bluetooth.
//ARDUINO Hiro NANO

//RXD to TXO (white)
//TXD to RXO (black)  BT adapter

// motor one
int enA = 11; //gris
int in1 = 10; // bleu
int in2 = 9; //vert
// motor two
int enB = 3; // violet
int in3 = 6; // jaune
int in4 = 5; // orange


char command;
String btdata;
int power;
int dir;
// Variables for the duration and the distance
long duration;
int distance;

void setup() {  
 
  pinMode(enA, OUTPUT);
  pinMode(enB, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT);
  pinMode(LED_BUILTIN, OUTPUT);

  Serial.begin(57600); 
  Serial.print("#ihihuuho");
  //MotorsForward();
}


void loop()
{  
  if (Serial.available() > 0)
  {
  }
  while (Serial.available() > 0)
  { command = (Serial.read());
    //Serial.println(" cmdd ");
    //Serial.println(command);

    
    //Serial.println("str: " + btdata);
    if (command == '?')
    {
      //Serial.println();
      //Serial.println("Command: " + btdata);

      delay(1);

     if (btdata.indexOf("forw") >= 0){
        MotorsForward(255);
        }
     if (btdata.indexOf("back") >= 0){
        MotorsBackward(255);
        }
      else{
        Serial.println("Command not recognized: " + btdata);
      }
      

      btdata = "";
      }
    else if (command == '/')
    {
      //Serial.println();
      //Serial.println("Direction: " + btdata);
      dir = btdata.toInt();
      btdata = "";
    }
    else if (command == '%')
    {
      //Serial.println();
      Serial.println("Power: " + btdata);
      power = btdata.toInt();
      btdata = "";
      if ( dir == 1 && power>0) {
        MotorsForward(power);
      }
      else if ( dir == 5 && power>0) {
        MotorsBackward(power);
      }
      else if ( dir == 7 && power>0) {
        MotorsSpinR(power);
      }
      else if ( dir == 3 && power>0) {
        MotorsSpinL(power);
      }
      else if ( dir == 8 && power>0) {
        MotorsFR(power);
      }
      else if ( dir == 2 && power>0) {
        MotorsFL(power);
      }
      else if ( dir == 4 && power>0) {
        MotorsBL(power);
      }
      else if ( dir == 6 && power>0) {
        MotorsBR(power);
      }
      else{
        MotorsStop();
      }
    }
    else{
      btdata = btdata + command;
    }

    
   }
   delay(500);
 }

void LedBlue()
{
  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  //delay(1000);                       // wait for a second
}

void LedRed()
{
  digitalWrite(LED_BUILTIN, LOW);   // turn the LED on (HIGH is the voltage level)
}


void MotorsBackward(int powa)
{
  digitalWrite(in1, HIGH);
  digitalWrite(in2, LOW);
  digitalWrite(in3, HIGH);
  digitalWrite(in4, LOW);
  analogWrite(enA, powa);
  analogWrite(enB, powa);
  
}

void MotorsForward(int powa)
{
  // Serial.println("Forward!");

  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH);
  analogWrite(enA, powa);
  analogWrite(enB, powa);
 
}

void MotorsSpinR(int powa)
{
  digitalWrite(in1, HIGH);
  digitalWrite(in2, LOW);
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH);
  analogWrite(enA, powa);
  analogWrite(enB, powa);
  
}
void MotorsSpinL(int powa)
{
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);
  digitalWrite(in3, HIGH);
  digitalWrite(in4, LOW);
  analogWrite(enA, powa);
  analogWrite(enB, powa);
  
}
void MotorsFL(int powa)
{
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);
  digitalWrite(in3, LOW);
  digitalWrite(in4, LOW);
  analogWrite(enA, powa);  
}
void MotorsFR(int powa)
{
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH);
  analogWrite(enB, powa);  
}
void MotorsBR(int powa)
{
  digitalWrite(in1, HIGH);
  digitalWrite(in2, LOW);
  digitalWrite(in3, LOW);
  digitalWrite(in4, LOW);
  analogWrite(enA, powa);  
}
void MotorsBL(int powa)
{
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);
  digitalWrite(in3, HIGH);
  digitalWrite(in4, LOW);
  analogWrite(enB, powa);  
}

void MotorsStop()
{
  // now turn off motors
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);
  digitalWrite(in3, LOW);
  digitalWrite(in4, LOW);
}

Androidcode

Java
This is the core of the Android application. It uses a virtual Joystick library (zerokol's JoystickView).
package com.pj.hiro.hiro_control;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.os.Handler;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;

import com.zerokol.views.JoystickView;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Set;
import java.util.UUID;


public class MainActivity extends AppCompatActivity {

    //BT
    private final String DEVICE_ADDRESS="Your BT module Mac Adress";
    private final UUID PORT_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");//Serial Port Service ID
    private BluetoothDevice device;
    private BluetoothSocket socket;
    private OutputStream outputStream;
    private InputStream inputStream;
    Button startButton, sendButton,clearButton,stopButton;
    TextView textView;
    EditText editText;
    LinearLayout joystickLayout;
    RelativeLayout bluetoothLayout;
    boolean deviceConnected=false;
    Thread thread;
    FloatingActionButton fab;
    byte buffer[];
    int bufferPosition;
    boolean stopThread;
    //___

    private TextView angleTextView;
    private TextView powerTextView;
    private TextView directionTextView;
    // Importing also other views
    private JoystickView joystick;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        startButton = (Button) findViewById(R.id.buttonStart);
        sendButton = (Button) findViewById(R.id.buttonSend);
        clearButton = (Button) findViewById(R.id.buttonClear);
        stopButton = (Button) findViewById(R.id.buttonStop);
        editText = (EditText) findViewById(R.id.editText);
        textView = (TextView) findViewById(R.id.textView);
        bluetoothLayout = (RelativeLayout) findViewById(R.id.BluetoothLayout);
        joystickLayout = (LinearLayout) findViewById(R.id.JoyStickLayout);
        fab = (FloatingActionButton) findViewById(R.id.hider);
        setUiEnabled(false);



        // Set window fullscreen and remove title bar, and force landscape orientation
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);




        angleTextView = (TextView) findViewById(R.id.angleTextView);
        powerTextView = (TextView) findViewById(R.id.powerTextView);
        directionTextView = (TextView) findViewById(R.id.directionTextView);
        //Referencing also other views
        joystick = (JoystickView) findViewById(R.id.joystickView);

        joystick.setOnJoystickMoveListener(new JoystickView.OnJoystickMoveListener() {

            @Override
            public void onValueChanged(int angle, int power, int direction) {
                // TODO Auto-generated method stub
                angleTextView.setText(" " + String.valueOf(angle) + "°");
                powerTextView.setText(" " + String.valueOf(power) + "%");
                if(outputStream != null) {
                    try {
                        outputStream.write((String.valueOf(direction) + "/" + String.valueOf(Math.round(power * 2.5)) + "%").getBytes());
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                switch (direction) {
                    case JoystickView.FRONT:
                        directionTextView.setText("front_lab" + " " + direction);
                        break;
                    case JoystickView.FRONT_RIGHT:
                        directionTextView.setText("front_right_lab" + " " + direction);
                        break;
                    case JoystickView.RIGHT:
                        directionTextView.setText("right_lab" + " " + direction);
                        break;
                    case JoystickView.RIGHT_BOTTOM:
                        directionTextView.setText("right_bottom_lab" + " " + direction);
                        break;
                    case JoystickView.BOTTOM:
                        directionTextView.setText("bottom_lab" + " " + direction);
                        break;
                    case JoystickView.BOTTOM_LEFT:
                        directionTextView.setText("bottom_left_lab" + " " + direction);
                        break;
                    case JoystickView.LEFT:
                        directionTextView.setText("left_lab" + " " + direction);
                        break;
                    case JoystickView.LEFT_FRONT:
                        directionTextView.setText("left_front_lab" + " " + direction);
                        break;
                    default:
                        directionTextView.setText("center_lab" + " " + direction);
                }

                int polaR = 0;
                int polaL = 0;
                int thrustR = 0;
                int thrustL = 0;

            }
        }, JoystickView.DEFAULT_LOOP_INTERVAL);

        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(bluetoothLayout.getVisibility()==View.GONE){
                    bluetoothLayout.setVisibility(View.VISIBLE);
                }
                else{
                    bluetoothLayout.setVisibility(View.GONE);
                }
            }
        });

        joystickLayout.setVisibility(View.GONE);


    }

    public void setUiEnabled(boolean bool)
    {
        startButton.setEnabled(!bool);
        sendButton.setEnabled(bool);
        stopButton.setEnabled(bool);
        textView.setEnabled(bool);

    }

    public boolean BTinit()
    {
        boolean found=false;
        BluetoothAdapter bluetoothAdapter=BluetoothAdapter.getDefaultAdapter();
        if (bluetoothAdapter == null) {
            Toast.makeText(getApplicationContext(),"Device doesnt Support Bluetooth",Toast.LENGTH_SHORT).show();
        }
        if(!bluetoothAdapter.isEnabled())
        {
            Intent enableAdapter = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableAdapter, 0);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        Set<BluetoothDevice> bondedDevices = bluetoothAdapter.getBondedDevices();
        if(bondedDevices.isEmpty())
        {
            Toast.makeText(getApplicationContext(),"Please Pair the Device first",Toast.LENGTH_SHORT).show();
        }
        else
        {
            for (BluetoothDevice iterator : bondedDevices)
            {
                if(iterator.getAddress().equals(DEVICE_ADDRESS))
                {
                    device=iterator;
                    found=true;
                    break;
                }
            }
        }
        return found;
    }

    public boolean BTconnect()
    {
        boolean connected=true;
        try {
            socket = device.createRfcommSocketToServiceRecord(PORT_UUID);
            socket.connect();
        } catch (IOException e) {
            e.printStackTrace();
            connected=false;
        }
        if(connected)
        {
            try {
                outputStream=socket.getOutputStream();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                inputStream=socket.getInputStream();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }


        return connected;
    }

    public void onClickStart(View view) {
        if(BTinit())
        {
            if(BTconnect())
            {
                setUiEnabled(true);
                deviceConnected=true;
                beginListenForData();
                textView.append("\nConnection Opened!\n");
                if(joystickLayout.getVisibility()==View.GONE){
                    joystickLayout.setVisibility(View.VISIBLE);
                }
            }

        }
    }

    void beginListenForData()
    {
        final Handler handler = new Handler();
        stopThread = false;
        buffer = new byte[1024];
        Thread thread  = new Thread(new Runnable()
        {
            public void run()
            {
                while(!Thread.currentThread().isInterrupted() && !stopThread)
                {
                    try
                    {
                        int byteCount = inputStream.available();
                        if(byteCount > 0)
                        {
                            byte[] rawBytes = new byte[byteCount];
                            inputStream.read(rawBytes);
                            final String string=new String(rawBytes,"UTF-8");
                            handler.post(new Runnable() {
                                public void run()
                                {
                                    textView.append(string);
                                    Toast.makeText(getApplicationContext(), "Reçu" + string, Toast.LENGTH_SHORT).show();
                                }
                            });

                        }
                    }
                    catch (IOException ex)
                    {
                        stopThread = true;
                    }
                }
            }
        });

        thread.start();
    }

    public void onClickSend(View view) {
        String string = editText.getText().toString() + "?";
        try {
            outputStream.write(string.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
        textView.append("\nSent Data:"+string+"\n");

    }

    public void onClickStop(View view) throws IOException {
        stopThread = true;
        outputStream.close();
        inputStream.close();
        socket.close();
        setUiEnabled(false);
        deviceConnected=false;
        textView.append("\nConnection Closed!\n");
        if(joystickLayout.getVisibility()==View.VISIBLE){
            joystickLayout.setVisibility(View.GONE);
        }
    }

    public void onClickClear(View view) {
        textView.setText("");
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    /**
     * A native method that is implemented by the 'native-lib' native library,
     * which is packaged with this application.
     */
    public native String stringFromJNI();

    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("native-lib");
    }
}

Credits

JulienChateau
1 project • 12 followers

Comments