Project tutorial

A DIY Tangible Coding Robot © GPL3+

Tangible Coding provides an opportunity for kids to become involved in programming with no screen used.

  • 2,518 views
  • 1 comment
  • 10 respects

Components and supplies

Necessary tools and machines

3drag
3D Printer (generic)
09507 01
Soldering iron (generic)

Apps and online services

About this project

Introduction

Nowadays, it is absolutely crucial to provide kids with tools and toys that encourage them to step into programming as part of their STEAM curricula. Tangible coding is a new approach to kid’s coding education. It is easy to start and provides kids with early access to programming. Tangible coding takes advantage of the kid’s non-computer knowledge to express language syntax. It also provides an opportunity for kids to become involved in programming with no screen used. The concept of tangible programming is similar to text-based programming languages in terms of sequential execution of instructions. But, instead of typing the instructions, either physical blocks are placed/stacked together or buttons are pressed whereas each object or button represents a coding instruction such as commands and flow-of-control structures. Children can put building blocks together or press push buttons in different orders to create a program.

Tangible coding console usually comes with a robot that executes the coding commands generated by the user (Fig. A). In this project, we called a tangible coding robot. Therefore, kids can easily program their robots to perform a different variety of tasks such as moving on a specific path or doing object manipulation.  If a marker is attached to the robot, kids can program the robot to move on different paths to generate drawing patterns on a paper sheet. They can also create beautiful scenes by having their robot dance.

In the present project, we have made a robot and a remote tangible coding console out of Lego technic, custom-built 3D printed parts, two off-the-shelf DC gear motors, an Arduino board, NRF modules, and five pushbuttons. You can go ahead and program your robot to move on a specific path by pressing the colored push buttons on the coding console (Fig. B).



The coding console and the robot are shown in Fig. B. When a user presses the push buttons on different orders, a program is created and saved in the Arduino board located on the coding console. The coding commands are then sent to the robot using a communication channel established using an NRF module.

In this tutorial, we will make the structure of the body of the robot using Lego Technic parts. Then, two DC gear motors will drive the differential mechanism of the robot to move on any path on the plane (Fig. C).

In the next step, we will add an Arduino Nano board as the brain of the tangible coding robot. Arduino Nano uses a small-size powerful microprocessor that makes it suitable for low-weight and small-size projects (Fig. D).

Various off-the-shelf motors, sensors, LEDs can be easily connected to Arduino boards. This feature enables us to do a variety of tasks with this robot. For instance, you can draw patterns on a paper by attaching a marker (Fig. E) or add RGB LEDs to play around with light colors (Fig. F).

The operator console has five pushbuttons for controlling the robots to go forward (white), backward (green), turn right (red), turn left (blue), and run (yellow) (Fig. G). The command signals are then transmitted to the robot using the NRF module.  The instructions are given in a way that you can easily make one at home.

Materials

  • 2x Breadboard, 83 x 52 x 9mm
  • 2x Arduino Nano
  • 1x Driver Motor
  • 2x NRF 24L01, without Antenna Module
  • 1x Buzzer, Active Type
  • 1x Breadboard, Mini Size
  • 1x Mini Switch, Toggle Type
  • 2x Power Jack, Barrel Type
  • 1x Pushbutton
  • Male to Male Jumper Wire
  • TT Gear Motor
  • 3D Printed Gear Motor Housing
  • Frame, 5x7 module
  • Steel ball & ball bearing
  • Wheel 61.6mm D. x 13.6mm Motorcycle
  • T-Beam, 3x3 module
  • Connector peg with friction, 2-module
  • 3D Printed Lego-Compatible Coupling
  • Beam, 9-module
  • 2x M3 x 16 Machine Screw
  • 1x M3 x 30 Machine Screw
  • Double cross block, 3-module
  • Axle, 2-module
  • Connector peg with friction/axle, 2-module
  • Beam, 7-module
  • 2x M3 Nut
  • 2x M3 Nut

Assembly of mechanical parts

Let’s start off by assembling the body structure of the robot. The body structure holds everything together including the wheels, the casters, and the electronics. Prepare the Lego Technic pieces according to Fig. I, and follow the step-by-step video tutorial below.

3D printed parts

In order to hold the DC gear motors in place and make a proper connection to the Lego pieces, we have used custom-designed, Lego compatible, 3D printed motor housings and shaft couplings (Fig. J). Download and print out the motor housingscouplings. Then prepare the required Lego parts from Fig. I, and follow the step-by-step mechanical assembly tutorial.

Electronics and wiring

For this project, you need to assemble both the robot and the coding console circuits (Figs. K, and L). For assembling the electronic circuits of the tangible coding console and the robot, follow the video instructions and the schematics carefully.

Programming

Double-check the warnings from the previous section and make sure everything is assembled exactly according to the circuit diagrams. Now that you have completed the assembly, it’s time to program your robot. Upload the provided codes to your robot and its coding console.

Robot:

/*
Tangible Coding Robot
The idea:
In this project, we will show you how to make a tangible programmable robot out of Lego Technic pieces,
Arduino boards, off-the-shelf DC motors, and NRF communication modules.
The current project uses two Arduino Nano boards as the main controller of the
robot and the programming console, respectively
The circuit:
- In this circuit, an Arduino Nano is used. Any other types of Arduino
can be used of course but do not forget to change the pin configurations
if you want to change the circuit on your preference.
Visit the Tart Robotics blog for more information:
https://www.tartrobotics.com/blog
*/
#define motorRightA A0
#define motorRightB A1
#define motorRightPWM 6
#define motorLeftA A2
#define motorLeftB A3
#define motorLeftPWM 5
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <Servo.h>
RF24 radio(9, 10); // CE, CSN
// Setup Adafriut Neopixel LED Ring
#include <Adafruit_NeoPixel.h>
#define PIXELSPIN 4
#define NUMPIXELS 16
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIXELSPIN, NEO_GRB + NEO_KHZ800);
const byte address[6] = "00010";
const int motorSpeed = 80, straightTimeDelay = 600, turningTimeDelay = 560;
void setup() {
radio.begin();
radio.openReadingPipe(0, address);
radio.setPALevel(RF24_PA_MIN);
radio.startListening();
pixels.begin(); // Adafriut Neopixel begin
for (int i = 0; i < 17; i++) {
pixels.setPixelColor(i, pixels.Color(0, 0, 0));
pixels.show();
}
}
void loop() {
if (radio.available()) {
// Take and decode instructions
char instructions[50] = "";
radio.read(&instructions, sizeof(instructions));
for (int i = 0; i < sizeof(instructions); i++) {
char message = instructions[i];
stopTheRobot();
delay(200);
if (message == 'f') {
goForward();
} else if (message == 'b') {
goBackward();
} else if (message == 'r') {
goRight();
} else if (message == 'l') {
goLeft();
} else if (message == 's') {
stopTheRobot();
break;
}
}
}
}
void goForward() {
digitalWrite(motorRightA, LOW);
digitalWrite(motorRightB, HIGH);
analogWrite(motorRightPWM, motorSpeed);
digitalWrite(motorLeftA, HIGH);
digitalWrite(motorLeftB, LOW);
analogWrite(motorLeftPWM, motorSpeed);
pixels.setPixelColor(6, pixels.Color(200, 200, 190));
pixels.setPixelColor(7, pixels.Color(200, 200, 190));
pixels.setPixelColor(8, pixels.Color(200, 200, 190));
pixels.setPixelColor(9, pixels.Color(200, 200, 190));
pixels.setPixelColor(10, pixels.Color(200, 200, 190));
pixels.show();
delay(straightTimeDelay);
for (int i = 0; i < 17; i++) {
pixels.setPixelColor(i, pixels.Color(0, 0, 0));
pixels.show();
}
}
void goBackward() {
digitalWrite(motorRightA, HIGH);
digitalWrite(motorRightB, LOW);
analogWrite(motorRightPWM, motorSpeed);
digitalWrite(motorLeftA, LOW);
digitalWrite(motorLeftB, HIGH);
analogWrite(motorLeftPWM, motorSpeed);
pixels.setPixelColor(0, pixels.Color(0, 200, 0));
pixels.setPixelColor(1, pixels.Color(0, 200, 0));
pixels.setPixelColor(2, pixels.Color(0, 200, 0));
pixels.setPixelColor(14, pixels.Color(0, 200, 0));
pixels.setPixelColor(15, pixels.Color(0, 200, 0));
pixels.show();
delay(straightTimeDelay);
for (int i = 0; i < 17; i++) {
pixels.setPixelColor(i, pixels.Color(0, 0, 0));
pixels.show();
}
}
void goLeft() {
digitalWrite(motorRightA, LOW);
digitalWrite(motorRightB, HIGH);
analogWrite(motorRightPWM, motorSpeed);
digitalWrite(motorLeftA, LOW);
digitalWrite(motorLeftB, HIGH);
analogWrite(motorLeftPWM, motorSpeed);
pixels.setPixelColor(2, pixels.Color(0, 0, 210));
pixels.setPixelColor(3, pixels.Color(0, 0, 210));
pixels.setPixelColor(4, pixels.Color(0, 0, 210));
pixels.setPixelColor(5, pixels.Color(0, 0, 210));
pixels.setPixelColor(6, pixels.Color(0, 0, 210));
pixels.show();
delay(straightTimeDelay);
for (int i = 0; i < 17; i++) {
pixels.setPixelColor(i, pixels.Color(0, 0, 0));
pixels.show();
}
}
void goRight() {
digitalWrite(motorRightA, HIGH);
digitalWrite(motorRightB, LOW);
analogWrite(motorRightPWM, motorSpeed);
digitalWrite(motorLeftA, HIGH);
digitalWrite(motorLeftB, LOW);
analogWrite(motorLeftPWM, motorSpeed);
pixels.setPixelColor(10, pixels.Color(200, 0, 0));
pixels.setPixelColor(11, pixels.Color(200, 0, 0));
pixels.setPixelColor(12, pixels.Color(200, 0, 0));
pixels.setPixelColor(13, pixels.Color(200, 0, 0));
pixels.setPixelColor(14, pixels.Color(200, 0, 0));
pixels.show();
delay(straightTimeDelay);
for (int i = 0; i < 17; i++) {
pixels.setPixelColor(i, pixels.Color(0, 0, 0));
pixels.show();
}
}
void stopTheRobot() {
digitalWrite(motorRightA, HIGH);
digitalWrite(motorRightB, HIGH);
analogWrite(motorRightPWM, 0);
digitalWrite(motorLeftA, HIGH);
digitalWrite(motorLeftB, HIGH);
analogWrite(motorLeftPWM, 0);
}

Coding console:

/*
Tangible Coding Console
The idea:
In this project, we will show you how to make a tangible programmable robot out of Lego Technic pieces,
Arduino boards, off-the-shelf DC motors, and NRF communication modules.
The current project uses two Arduino Nano boards as the main controller of the
robot and the programming console, respectively
The circuit:
- In this circuit, an Arduino Nano is used. Any other types of Arduino
can be used of course but do not forget to change the pin configurations
if you want to change the circuit on your preference.
Visit the Tart Robotics blog for more information:
https://www.tartrobotics.com/blog
*/
#define forward_button 8
#define backward_button 4
#define right_button 7
#define left_button 5
#define startstop_button 6
#define buzzerPin A0
#define auxGnd A2 //auxiliary ground pin
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
RF24 radio(9, 10); // CE, CSN
const byte address[6] = "00010";
void setup() {
radio.begin();
radio.openWritingPipe(address);
radio.setPALevel(RF24_PA_MIN);
radio.stopListening();
pinMode(auxGnd, OUTPUT);
pinMode(buzzerPin, OUTPUT);
digitalWrite(auxGnd, LOW);
}
void loop() {
//Take the instructions (50 instructions in a row maximum)
char instructions[50];
for (int i = 0; i < sizeof(instructions); i++)
instructions[i] = NULL;
boolean runTheProgram = false;
int i = 0;
while (i < sizeof(instructions)) {
buzz(100);
while (true) {
if (!digitalRead(forward_button)) {
while (!digitalRead(forward_button));
instructions[i] = 'f';
break;
} else if (!digitalRead(backward_button)) {
while (!digitalRead(backward_button));
instructions[i] = 'b';
break;
} else if (!digitalRead(left_button)) {
while (!digitalRead(left_button));
instructions[i] = 'r';
break;
} else if (!digitalRead(right_button)) {
while (!digitalRead(right_button));
instructions[i] = 'l';
break;
} else if (!digitalRead(startstop_button)) {
while (!digitalRead(startstop_button));
runTheProgram = true;
break;
}
}
i++;
if (runTheProgram)
break;
}
instructions[i] = 's';
buzz(800);
radio.write(&instructions, sizeof(instructions));
}
void buzz(int duration) {
digitalWrite(buzzerPin, HIGH);
delay(duration);
digitalWrite(buzzerPin, LOW);
}

You are all set. Your robot is ready to go.


Code

Tangible Coding RobotC/C++
/*
  Tangible Coding Robot
    The idea:
    In this project, we will show you how to make a tangible programmable robot out of Lego Technic pieces,
    Arduino boards, off-the-shelf DC motors, and NRF communication modules.
    The current project uses two Arduino Nano boards as the main controller of the
    robot and the programming console, respectively
    The circuit:
    - In this circuit, an Arduino Nano is used. Any other types of Arduino
    can be used of course but do not forget to change the pin configurations
    if you want to change the circuit on your preference.
    Visit the Tart Robotics blog for more information:
    https://www.tartrobotics.com/blog
*/

#define motorRightA A0
#define motorRightB A1
#define motorRightPWM 6
#define motorLeftA A2
#define motorLeftB A3
#define motorLeftPWM 5

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <Servo.h>
RF24 radio(9, 10); // CE, CSN

// Setup Adafriut Neopixel LED Ring
#include <Adafruit_NeoPixel.h>
#define PIXELSPIN 4
#define NUMPIXELS 16
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIXELSPIN, NEO_GRB + NEO_KHZ800);

const byte address[6] = "00010";
const int motorSpeed = 80, straightTimeDelay = 600, turningTimeDelay = 560;


void setup() {
  radio.begin();
  radio.openReadingPipe(0, address);
  radio.setPALevel(RF24_PA_MIN);
  radio.startListening();
  pixels.begin(); // Adafriut Neopixel begin
  for (int i = 0; i < 17; i++) {
    pixels.setPixelColor(i, pixels.Color(0, 0, 0));
    pixels.show();
  }
}

void loop() {

  if (radio.available()) {
    // Take and decode instructions
    char instructions[50] = "";
    radio.read(&instructions, sizeof(instructions));

    for (int i = 0; i < sizeof(instructions); i++) {
      char message = instructions[i];
      stopTheRobot();
      delay(200);
      if (message == 'f') {
        goForward();
      } else if (message == 'b') {
        goBackward();
      } else if (message == 'r') {
        goRight();
      } else if (message == 'l') {
        goLeft();
      } else if (message == 's') {
        stopTheRobot();
        break;
      }
    }
  }
}

void goForward() {
  digitalWrite(motorRightA, LOW);
  digitalWrite(motorRightB, HIGH);
  analogWrite(motorRightPWM, motorSpeed);
  digitalWrite(motorLeftA, HIGH);
  digitalWrite(motorLeftB, LOW);
  analogWrite(motorLeftPWM, motorSpeed);

  pixels.setPixelColor(6, pixels.Color(200, 200, 190));
  pixels.setPixelColor(7, pixels.Color(200, 200, 190));
  pixels.setPixelColor(8, pixels.Color(200, 200, 190));
  pixels.setPixelColor(9, pixels.Color(200, 200, 190));
  pixels.setPixelColor(10, pixels.Color(200, 200, 190));
  pixels.show();

  delay(straightTimeDelay);
  for (int i = 0; i < 17; i++) {
    pixels.setPixelColor(i, pixels.Color(0, 0, 0));
    pixels.show();
  }
}
void goBackward() {
  digitalWrite(motorRightA, HIGH);
  digitalWrite(motorRightB, LOW);
  analogWrite(motorRightPWM, motorSpeed);
  digitalWrite(motorLeftA, LOW);
  digitalWrite(motorLeftB, HIGH);
  analogWrite(motorLeftPWM, motorSpeed);

  pixels.setPixelColor(0, pixels.Color(0, 200, 0));
  pixels.setPixelColor(1, pixels.Color(0, 200, 0));
  pixels.setPixelColor(2, pixels.Color(0, 200, 0));
  pixels.setPixelColor(14, pixels.Color(0, 200, 0));
  pixels.setPixelColor(15, pixels.Color(0, 200, 0));
  pixels.show();

  delay(straightTimeDelay);
  for (int i = 0; i < 17; i++) {
    pixels.setPixelColor(i, pixels.Color(0, 0, 0));
    pixels.show();
  }
}
void goLeft() {
  digitalWrite(motorRightA, LOW);
  digitalWrite(motorRightB, HIGH);
  analogWrite(motorRightPWM, motorSpeed);
  digitalWrite(motorLeftA, LOW);
  digitalWrite(motorLeftB, HIGH);
  analogWrite(motorLeftPWM, motorSpeed);

  pixels.setPixelColor(2, pixels.Color(0, 0, 210));
  pixels.setPixelColor(3, pixels.Color(0, 0, 210));
  pixels.setPixelColor(4, pixels.Color(0, 0, 210));
  pixels.setPixelColor(5, pixels.Color(0, 0, 210));
  pixels.setPixelColor(6, pixels.Color(0, 0, 210));
  pixels.show();

  delay(straightTimeDelay);
  for (int i = 0; i < 17; i++) {
    pixels.setPixelColor(i, pixels.Color(0, 0, 0));
    pixels.show();
  }
}
void goRight() {
  digitalWrite(motorRightA, HIGH);
  digitalWrite(motorRightB, LOW);
  analogWrite(motorRightPWM, motorSpeed);
  digitalWrite(motorLeftA, HIGH);
  digitalWrite(motorLeftB, LOW);
  analogWrite(motorLeftPWM, motorSpeed);

  pixels.setPixelColor(10, pixels.Color(200, 0, 0));
  pixels.setPixelColor(11, pixels.Color(200, 0, 0));
  pixels.setPixelColor(12, pixels.Color(200, 0, 0));
  pixels.setPixelColor(13, pixels.Color(200, 0, 0));
  pixels.setPixelColor(14, pixels.Color(200, 0, 0));
  pixels.show();

  delay(straightTimeDelay);
  for (int i = 0; i < 17; i++) {
    pixels.setPixelColor(i, pixels.Color(0, 0, 0));
    pixels.show();
  }
}
void stopTheRobot() {
  digitalWrite(motorRightA, HIGH);
  digitalWrite(motorRightB, HIGH);
  analogWrite(motorRightPWM, 0);
  digitalWrite(motorLeftA, HIGH);
  digitalWrite(motorLeftB, HIGH);
  analogWrite(motorLeftPWM, 0);
}
Tangible Coding ConsoleC/C++
/*
  Tangible Coding Console
    The idea:
    In this project, we will show you how to make a tangible programmable robot out of Lego Technic pieces,
    Arduino boards, off-the-shelf DC motors, and NRF communication modules.
    The current project uses two Arduino Nano boards as the main controller of the
    robot and the programming console, respectively
    The circuit:
    - In this circuit, an Arduino Nano is used. Any other types of Arduino
    can be used of course but do not forget to change the pin configurations
    if you want to change the circuit on your preference.
    Visit the Tart Robotics blog for more information:
    https://www.tartrobotics.com/blog
*/

#define forward_button 8
#define backward_button 4
#define right_button 7
#define left_button 5
#define startstop_button 6
#define buzzerPin A0
#define auxGnd A2 //auxiliary ground pin

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
RF24 radio(9, 10); // CE, CSN

const byte address[6] = "00010";

void setup() {
  radio.begin();
  radio.openWritingPipe(address);
  radio.setPALevel(RF24_PA_MIN);
  radio.stopListening();
  pinMode(auxGnd, OUTPUT);
  pinMode(buzzerPin, OUTPUT);
  digitalWrite(auxGnd, LOW);
}

void loop() {
  //Take the instructions (50 instructions in a row maximum)
  char instructions[50];
  for (int i = 0; i < sizeof(instructions); i++)
    instructions[i] = NULL;

  boolean runTheProgram = false;

  int i = 0;
  while (i < sizeof(instructions)) {
    buzz(100);
    while (true) {
      if (!digitalRead(forward_button)) {
        while (!digitalRead(forward_button));
        instructions[i] = 'f';
        break;
      } else if (!digitalRead(backward_button)) {
        while (!digitalRead(backward_button));
        instructions[i] = 'b';
        break;
      } else if (!digitalRead(left_button)) {
        while (!digitalRead(left_button));
        instructions[i] = 'r';
        break;
      } else if (!digitalRead(right_button)) {
        while (!digitalRead(right_button));
        instructions[i] = 'l';
        break;
      } else if (!digitalRead(startstop_button)) {
        while (!digitalRead(startstop_button));
        runTheProgram = true;
        break;
      }
    }
    i++;
    if (runTheProgram)
      break;
  }
  instructions[i] = 's';
  buzz(800);
  radio.write(&instructions, sizeof(instructions));
}

void buzz(int duration) {
  digitalWrite(buzzerPin, HIGH);
  delay(duration);
  digitalWrite(buzzerPin, LOW);
}

Schematics

Schematic diagram of the robot circuit
Tangible circuit bb   main 8bcfe8t1ym
Schematic diagram of the coding console circuit
Tangible circuit control bb 6jdimoxlcw

Comments

Similar projects you might like

A DIY Remote-Controlled Rescue Robot with Arduino and Lego

Project tutorial by Tart Robotics

  • 3,979 views
  • 2 comments
  • 13 respects

A DIY Zipline Robot with Arduino, Lego, and 3D Printed Parts

Project tutorial by Tart Robotics

  • 4,729 views
  • 2 comments
  • 23 respects

A DIY Biped Robot with Arduino, Lego, and 3D Printed Parts

Project tutorial by Tart Robotics

  • 4,583 views
  • 2 comments
  • 11 respects

Quadruped Robot

Project tutorial by Tart Robotics

  • 7,575 views
  • 2 comments
  • 26 respects

DIY Arduino Robot Arm – Controlled by Hand Gestures

Project tutorial by Eben Kouao

  • 13,905 views
  • 9 comments
  • 46 respects

Amazing 6WD Off-Road Robot | Arduino RC Robot

Project tutorial by Jithin Sanal

  • 21,288 views
  • 1 comment
  • 82 respects
Add projectSign up / Login